blob: cdf0d83a91be965932fccdca78534b179ca5fda5 [file] [log] [blame]
Yoshinori Sato618b9022015-01-28 02:52:42 +09001/*
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>
Yoshinori Sato4633f4c2015-11-07 01:31:44 +090020#include <linux/of_address.h>
21#include <linux/of_irq.h>
Yoshinori Sato618b9022015-01-28 02:52:42 +090022
23#include <asm/segment.h>
24#include <asm/irq.h>
25
26#define TSTR 0
27#define TSNC 1
28#define TMDR 2
29#define TOLR 3
30#define TISRA 4
31#define TISRB 5
32#define TISRC 6
33
34#define TCR 0
35#define TIOR 1
36#define TCNT 2
37#define GRA 4
38#define GRB 6
39
40#define FLAG_REPROGRAM (1 << 0)
41#define FLAG_SKIPEVENT (1 << 1)
42#define FLAG_IRQCONTEXT (1 << 2)
43#define FLAG_STARTED (1 << 3)
44
45#define ONESHOT 0
46#define PERIODIC 1
47
48#define RELATIVE 0
49#define ABSOLUTE 1
50
51struct timer16_priv {
Yoshinori Sato618b9022015-01-28 02:52:42 +090052 struct clocksource cs;
Yoshinori Sato618b9022015-01-28 02:52:42 +090053 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
67static 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
89static 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
100static inline struct timer16_priv *cs_to_priv(struct clocksource *cs)
101{
102 return container_of(cs, struct timer16_priv, cs);
103}
104
105static 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
119static 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
135static 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
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900147static struct timer16_priv timer16_priv = {
148 .cs = {
149 .name = "h8300_16timer",
150 .rating = 200,
151 .read = timer16_clocksource_read,
152 .enable = timer16_enable,
153 .disable = timer16_disable,
154 .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8),
155 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
156 },
157};
158
Yoshinori Sato618b9022015-01-28 02:52:42 +0900159#define REG_CH 0
160#define REG_COMM 1
161
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900162static void __init h8300_16timer_init(struct device_node *node)
Yoshinori Sato618b9022015-01-28 02:52:42 +0900163{
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900164 void __iomem *base[2];
Yoshinori Sato618b9022015-01-28 02:52:42 +0900165 int ret, irq;
166 unsigned int ch;
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900167 struct clk *clk;
Yoshinori Sato618b9022015-01-28 02:52:42 +0900168
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900169 clk = of_clk_get(node, 0);
170 if (IS_ERR(clk)) {
171 pr_err("failed to get clock for clocksource\n");
172 return;
Yoshinori Sato618b9022015-01-28 02:52:42 +0900173 }
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900174
175 base[REG_CH] = of_iomap(node, 0);
176 if (!base[REG_CH]) {
177 pr_err("failed to map registers for clocksource\n");
178 goto free_clk;
179 }
180
181 base[REG_COMM] = of_iomap(node, 1);
182 if (!base[REG_COMM]) {
183 pr_err("failed to map registers for clocksource\n");
184 goto unmap_ch;
185 }
186
187 irq = irq_of_parse_and_map(node, 0);
Yoshinori Sato618b9022015-01-28 02:52:42 +0900188 if (irq < 0) {
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900189 pr_err("failed to get irq for clockevent\n");
190 goto unmap_comm;
Yoshinori Sato618b9022015-01-28 02:52:42 +0900191 }
192
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900193 of_property_read_u32(node, "renesas,channel", &ch);
Yoshinori Sato618b9022015-01-28 02:52:42 +0900194
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900195 timer16_priv.mapbase = (unsigned long)base[REG_CH];
196 timer16_priv.mapcommon = (unsigned long)base[REG_COMM];
197 timer16_priv.enb = 1 << ch;
198 timer16_priv.imfa = 1 << ch;
199 timer16_priv.imiea = 1 << (4 + ch);
Yoshinori Sato618b9022015-01-28 02:52:42 +0900200
201 ret = request_irq(irq, timer16_interrupt,
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900202 IRQF_TIMER, timer16_priv.cs.name, &timer16_priv);
Yoshinori Sato618b9022015-01-28 02:52:42 +0900203 if (ret < 0) {
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900204 pr_err("failed to request irq %d of clocksource\n", irq);
205 goto unmap_comm;
Yoshinori Sato618b9022015-01-28 02:52:42 +0900206 }
207
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900208 clocksource_register_hz(&timer16_priv.cs,
209 clk_get_rate(timer16_priv.clk) / 8);
210 return;
Yoshinori Sato618b9022015-01-28 02:52:42 +0900211
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900212unmap_comm:
213 iounmap(base[REG_COMM]);
214unmap_ch:
215 iounmap(base[REG_CH]);
216free_clk:
217 clk_put(clk);
Yoshinori Sato618b9022015-01-28 02:52:42 +0900218}
219
Yoshinori Sato4633f4c2015-11-07 01:31:44 +0900220CLOCKSOURCE_OF_DECLARE(h8300_16bit, "renesas,16bit-timer", h8300_16timer_init);