]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/clocksource/h8300_timer16.c
Merge branch 'sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / drivers / clocksource / h8300_timer16.c
1 /*
2  *  H8/300 16bit Timer driver
3  *
4  *  Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp>
5  */
6
7 #include <linux/errno.h>
8 #include <linux/kernel.h>
9 #include <linux/param.h>
10 #include <linux/string.h>
11 #include <linux/slab.h>
12 #include <linux/interrupt.h>
13 #include <linux/init.h>
14 #include <linux/platform_device.h>
15 #include <linux/clocksource.h>
16 #include <linux/module.h>
17 #include <linux/clk.h>
18 #include <linux/io.h>
19 #include <linux/of.h>
20
21 #include <asm/segment.h>
22 #include <asm/irq.h>
23
24 #define TSTR    0
25 #define TSNC    1
26 #define TMDR    2
27 #define TOLR    3
28 #define TISRA   4
29 #define TISRB   5
30 #define TISRC   6
31
32 #define TCR     0
33 #define TIOR    1
34 #define TCNT    2
35 #define GRA     4
36 #define GRB     6
37
38 #define FLAG_REPROGRAM (1 << 0)
39 #define FLAG_SKIPEVENT (1 << 1)
40 #define FLAG_IRQCONTEXT (1 << 2)
41 #define FLAG_STARTED (1 << 3)
42
43 #define ONESHOT  0
44 #define PERIODIC 1
45
46 #define RELATIVE 0
47 #define ABSOLUTE 1
48
49 struct timer16_priv {
50         struct platform_device *pdev;
51         struct clocksource cs;
52         struct irqaction irqaction;
53         unsigned long total_cycles;
54         unsigned long mapbase;
55         unsigned long mapcommon;
56         unsigned long flags;
57         unsigned short gra;
58         unsigned short cs_enabled;
59         unsigned char enb;
60         unsigned char imfa;
61         unsigned char imiea;
62         unsigned char ovf;
63         raw_spinlock_t lock;
64         struct clk *clk;
65 };
66
67 static unsigned long timer16_get_counter(struct timer16_priv *p)
68 {
69         unsigned long v1, v2, v3;
70         int o1, o2;
71
72         o1 = ctrl_inb(p->mapcommon + TISRC) & p->ovf;
73
74         /* Make sure the timer value is stable. Stolen from acpi_pm.c */
75         do {
76                 o2 = o1;
77                 v1 = ctrl_inw(p->mapbase + TCNT);
78                 v2 = ctrl_inw(p->mapbase + TCNT);
79                 v3 = ctrl_inw(p->mapbase + TCNT);
80                 o1 = ctrl_inb(p->mapcommon + TISRC) & p->ovf;
81         } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
82                           || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
83
84         v2 |= 0x10000;
85         return v2;
86 }
87
88
89 static irqreturn_t timer16_interrupt(int irq, void *dev_id)
90 {
91         struct timer16_priv *p = (struct timer16_priv *)dev_id;
92
93         ctrl_outb(ctrl_inb(p->mapcommon + TISRA) & ~p->imfa,
94                   p->mapcommon + TISRA);
95         p->total_cycles += 0x10000;
96
97         return IRQ_HANDLED;
98 }
99
100 static inline struct timer16_priv *cs_to_priv(struct clocksource *cs)
101 {
102         return container_of(cs, struct timer16_priv, cs);
103 }
104
105 static cycle_t timer16_clocksource_read(struct clocksource *cs)
106 {
107         struct timer16_priv *p = cs_to_priv(cs);
108         unsigned long flags, raw;
109         unsigned long value;
110
111         raw_spin_lock_irqsave(&p->lock, flags);
112         value = p->total_cycles;
113         raw = timer16_get_counter(p);
114         raw_spin_unlock_irqrestore(&p->lock, flags);
115
116         return value + raw;
117 }
118
119 static int timer16_enable(struct clocksource *cs)
120 {
121         struct timer16_priv *p = cs_to_priv(cs);
122
123         WARN_ON(p->cs_enabled);
124
125         p->total_cycles = 0;
126         ctrl_outw(0x0000, p->mapbase + TCNT);
127         ctrl_outb(0x83, p->mapbase + TCR);
128         ctrl_outb(ctrl_inb(p->mapcommon + TSTR) | p->enb,
129                   p->mapcommon + TSTR);
130
131         p->cs_enabled = true;
132         return 0;
133 }
134
135 static void timer16_disable(struct clocksource *cs)
136 {
137         struct timer16_priv *p = cs_to_priv(cs);
138
139         WARN_ON(!p->cs_enabled);
140
141         ctrl_outb(ctrl_inb(p->mapcommon + TSTR) & ~p->enb,
142                   p->mapcommon + TSTR);
143
144         p->cs_enabled = false;
145 }
146
147 #define REG_CH   0
148 #define REG_COMM 1
149
150 static int timer16_setup(struct timer16_priv *p, struct platform_device *pdev)
151 {
152         struct resource *res[2];
153         int ret, irq;
154         unsigned int ch;
155
156         p->pdev = pdev;
157
158         res[REG_CH] = platform_get_resource(p->pdev,
159                                             IORESOURCE_MEM, REG_CH);
160         res[REG_COMM] = platform_get_resource(p->pdev,
161                                               IORESOURCE_MEM, REG_COMM);
162         if (!res[REG_CH] || !res[REG_COMM]) {
163                 dev_err(&p->pdev->dev, "failed to get I/O memory\n");
164                 return -ENXIO;
165         }
166         irq = platform_get_irq(p->pdev, 0);
167         if (irq < 0) {
168                 dev_err(&p->pdev->dev, "failed to get irq\n");
169                 return irq;
170         }
171
172         p->clk = clk_get(&p->pdev->dev, "fck");
173         if (IS_ERR(p->clk)) {
174                 dev_err(&p->pdev->dev, "can't get clk\n");
175                 return PTR_ERR(p->clk);
176         }
177         of_property_read_u32(p->pdev->dev.of_node, "renesas,channel", &ch);
178
179         p->pdev = pdev;
180         p->mapbase = res[REG_CH]->start;
181         p->mapcommon = res[REG_COMM]->start;
182         p->enb = 1 << ch;
183         p->imfa = 1 << ch;
184         p->imiea = 1 << (4 + ch);
185         p->cs.name = pdev->name;
186         p->cs.rating = 200;
187         p->cs.read = timer16_clocksource_read;
188         p->cs.enable = timer16_enable;
189         p->cs.disable = timer16_disable;
190         p->cs.mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
191         p->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
192
193         ret = request_irq(irq, timer16_interrupt,
194                           IRQF_TIMER, pdev->name, p);
195         if (ret < 0) {
196                 dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
197                 return ret;
198         }
199
200         clocksource_register_hz(&p->cs, clk_get_rate(p->clk) / 8);
201
202         return 0;
203 }
204
205 static int timer16_probe(struct platform_device *pdev)
206 {
207         struct timer16_priv *p = platform_get_drvdata(pdev);
208
209         if (p) {
210                 dev_info(&pdev->dev, "kept as earlytimer\n");
211                 return 0;
212         }
213
214         p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
215         if (!p)
216                 return -ENOMEM;
217
218         return timer16_setup(p, pdev);
219 }
220
221 static int timer16_remove(struct platform_device *pdev)
222 {
223         return -EBUSY;
224 }
225
226 static const struct of_device_id timer16_of_table[] = {
227         { .compatible = "renesas,16bit-timer" },
228         { }
229 };
230 static struct platform_driver timer16_driver = {
231         .probe          = timer16_probe,
232         .remove         = timer16_remove,
233         .driver         = {
234                 .name   = "h8300h-16timer",
235                 .of_match_table = of_match_ptr(timer16_of_table),
236         }
237 };
238
239 static int __init timer16_init(void)
240 {
241         return platform_driver_register(&timer16_driver);
242 }
243
244 static void __exit timer16_exit(void)
245 {
246         platform_driver_unregister(&timer16_driver);
247 }
248
249 subsys_initcall(timer16_init);
250 module_exit(timer16_exit);
251 MODULE_AUTHOR("Yoshinori Sato");
252 MODULE_DESCRIPTION("H8/300H 16bit Timer Driver");
253 MODULE_LICENSE("GPL v2");