root/drivers/clocksource/h8300_timer16.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. timer16_get_counter
  2. timer16_interrupt
  3. cs_to_priv
  4. timer16_clocksource_read
  5. timer16_enable
  6. timer16_disable
  7. h8300_16timer_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  H8/300 16bit Timer driver
   4  *
   5  *  Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp>
   6  */
   7 
   8 #include <linux/interrupt.h>
   9 #include <linux/init.h>
  10 #include <linux/clocksource.h>
  11 #include <linux/clk.h>
  12 #include <linux/io.h>
  13 #include <linux/of.h>
  14 #include <linux/of_address.h>
  15 #include <linux/of_irq.h>
  16 
  17 #define TSTR    0
  18 #define TISRC   6
  19 
  20 #define TCR     0
  21 #define TCNT    2
  22 
  23 #define bset(b, a) iowrite8(ioread8(a) | (1 << (b)), (a))
  24 #define bclr(b, a) iowrite8(ioread8(a) & ~(1 << (b)), (a))
  25 
  26 struct timer16_priv {
  27         struct clocksource cs;
  28         unsigned long total_cycles;
  29         void __iomem *mapbase;
  30         void __iomem *mapcommon;
  31         unsigned short cs_enabled;
  32         unsigned char enb;
  33         unsigned char ovf;
  34         unsigned char ovie;
  35 };
  36 
  37 static unsigned long timer16_get_counter(struct timer16_priv *p)
  38 {
  39         unsigned short v1, v2, v3;
  40         unsigned char  o1, o2;
  41 
  42         o1 = ioread8(p->mapcommon + TISRC) & p->ovf;
  43 
  44         /* Make sure the timer value is stable. Stolen from acpi_pm.c */
  45         do {
  46                 o2 = o1;
  47                 v1 = ioread16be(p->mapbase + TCNT);
  48                 v2 = ioread16be(p->mapbase + TCNT);
  49                 v3 = ioread16be(p->mapbase + TCNT);
  50                 o1 = ioread8(p->mapcommon + TISRC) & p->ovf;
  51         } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
  52                           || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
  53 
  54         if (likely(!o1))
  55                 return v2;
  56         else
  57                 return v2 + 0x10000;
  58 }
  59 
  60 
  61 static irqreturn_t timer16_interrupt(int irq, void *dev_id)
  62 {
  63         struct timer16_priv *p = (struct timer16_priv *)dev_id;
  64 
  65         bclr(p->ovf, p->mapcommon + TISRC);
  66         p->total_cycles += 0x10000;
  67 
  68         return IRQ_HANDLED;
  69 }
  70 
  71 static inline struct timer16_priv *cs_to_priv(struct clocksource *cs)
  72 {
  73         return container_of(cs, struct timer16_priv, cs);
  74 }
  75 
  76 static u64 timer16_clocksource_read(struct clocksource *cs)
  77 {
  78         struct timer16_priv *p = cs_to_priv(cs);
  79         unsigned long raw, value;
  80 
  81         value = p->total_cycles;
  82         raw = timer16_get_counter(p);
  83 
  84         return value + raw;
  85 }
  86 
  87 static int timer16_enable(struct clocksource *cs)
  88 {
  89         struct timer16_priv *p = cs_to_priv(cs);
  90 
  91         WARN_ON(p->cs_enabled);
  92 
  93         p->total_cycles = 0;
  94         iowrite16be(0x0000, p->mapbase + TCNT);
  95         iowrite8(0x83, p->mapbase + TCR);
  96         bset(p->ovie, p->mapcommon + TISRC);
  97         bset(p->enb, p->mapcommon + TSTR);
  98 
  99         p->cs_enabled = true;
 100         return 0;
 101 }
 102 
 103 static void timer16_disable(struct clocksource *cs)
 104 {
 105         struct timer16_priv *p = cs_to_priv(cs);
 106 
 107         WARN_ON(!p->cs_enabled);
 108 
 109         bclr(p->ovie, p->mapcommon + TISRC);
 110         bclr(p->enb, p->mapcommon + TSTR);
 111 
 112         p->cs_enabled = false;
 113 }
 114 
 115 static struct timer16_priv timer16_priv = {
 116         .cs = {
 117                 .name = "h8300_16timer",
 118                 .rating = 200,
 119                 .read = timer16_clocksource_read,
 120                 .enable = timer16_enable,
 121                 .disable = timer16_disable,
 122                 .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8),
 123                 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
 124         },
 125 };
 126 
 127 #define REG_CH   0
 128 #define REG_COMM 1
 129 
 130 static int __init h8300_16timer_init(struct device_node *node)
 131 {
 132         void __iomem *base[2];
 133         int ret, irq;
 134         unsigned int ch;
 135         struct clk *clk;
 136 
 137         clk = of_clk_get(node, 0);
 138         if (IS_ERR(clk)) {
 139                 pr_err("failed to get clock for clocksource\n");
 140                 return PTR_ERR(clk);
 141         }
 142 
 143         ret = -ENXIO;
 144         base[REG_CH] = of_iomap(node, 0);
 145         if (!base[REG_CH]) {
 146                 pr_err("failed to map registers for clocksource\n");
 147                 goto free_clk;
 148         }
 149 
 150         base[REG_COMM] = of_iomap(node, 1);
 151         if (!base[REG_COMM]) {
 152                 pr_err("failed to map registers for clocksource\n");
 153                 goto unmap_ch;
 154         }
 155 
 156         ret = -EINVAL;
 157         irq = irq_of_parse_and_map(node, 0);
 158         if (!irq) {
 159                 pr_err("failed to get irq for clockevent\n");
 160                 goto unmap_comm;
 161         }
 162 
 163         of_property_read_u32(node, "renesas,channel", &ch);
 164 
 165         timer16_priv.mapbase = base[REG_CH];
 166         timer16_priv.mapcommon = base[REG_COMM];
 167         timer16_priv.enb = ch;
 168         timer16_priv.ovf = ch;
 169         timer16_priv.ovie = 4 + ch;
 170 
 171         ret = request_irq(irq, timer16_interrupt,
 172                           IRQF_TIMER, timer16_priv.cs.name, &timer16_priv);
 173         if (ret < 0) {
 174                 pr_err("failed to request irq %d of clocksource\n", irq);
 175                 goto unmap_comm;
 176         }
 177 
 178         clocksource_register_hz(&timer16_priv.cs,
 179                                 clk_get_rate(clk) / 8);
 180         return 0;
 181 
 182 unmap_comm:
 183         iounmap(base[REG_COMM]);
 184 unmap_ch:
 185         iounmap(base[REG_CH]);
 186 free_clk:
 187         clk_put(clk);
 188         return ret;
 189 }
 190 
 191 TIMER_OF_DECLARE(h8300_16bit, "renesas,16bit-timer",
 192                            h8300_16timer_init);

/* [<][>][^][v][top][bottom][index][help] */