2 * H8/300 16bit Timer driver
4 * Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp>
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>
21 #include <asm/segment.h>
38 #define FLAG_REPROGRAM (1 << 0)
39 #define FLAG_SKIPEVENT (1 << 1)
40 #define FLAG_IRQCONTEXT (1 << 2)
41 #define FLAG_STARTED (1 << 3)
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
;
58 unsigned short cs_enabled
;
67 static unsigned long timer16_get_counter(struct timer16_priv
*p
)
69 unsigned long v1
, v2
, v3
;
72 o1
= ctrl_inb(p
->mapcommon
+ TISRC
) & p
->ovf
;
74 /* Make sure the timer value is stable. Stolen from acpi_pm.c */
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
)));
89 static irqreturn_t
timer16_interrupt(int irq
, void *dev_id
)
91 struct timer16_priv
*p
= (struct timer16_priv
*)dev_id
;
93 ctrl_outb(ctrl_inb(p
->mapcommon
+ TISRA
) & ~p
->imfa
,
94 p
->mapcommon
+ TISRA
);
95 p
->total_cycles
+= 0x10000;
100 static inline struct timer16_priv
*cs_to_priv(struct clocksource
*cs
)
102 return container_of(cs
, struct timer16_priv
, cs
);
105 static cycle_t
timer16_clocksource_read(struct clocksource
*cs
)
107 struct timer16_priv
*p
= cs_to_priv(cs
);
108 unsigned long flags
, raw
;
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
);
119 static int timer16_enable(struct clocksource
*cs
)
121 struct timer16_priv
*p
= cs_to_priv(cs
);
123 WARN_ON(p
->cs_enabled
);
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
);
131 p
->cs_enabled
= true;
135 static void timer16_disable(struct clocksource
*cs
)
137 struct timer16_priv
*p
= cs_to_priv(cs
);
139 WARN_ON(!p
->cs_enabled
);
141 ctrl_outb(ctrl_inb(p
->mapcommon
+ TSTR
) & ~p
->enb
,
142 p
->mapcommon
+ TSTR
);
144 p
->cs_enabled
= false;
150 static int timer16_setup(struct timer16_priv
*p
, struct platform_device
*pdev
)
152 struct resource
*res
[2];
156 memset(p
, 0, sizeof(*p
));
159 res
[REG_CH
] = platform_get_resource(p
->pdev
,
160 IORESOURCE_MEM
, REG_CH
);
161 res
[REG_COMM
] = platform_get_resource(p
->pdev
,
162 IORESOURCE_MEM
, REG_COMM
);
163 if (!res
[REG_CH
] || !res
[REG_COMM
]) {
164 dev_err(&p
->pdev
->dev
, "failed to get I/O memory\n");
167 irq
= platform_get_irq(p
->pdev
, 0);
169 dev_err(&p
->pdev
->dev
, "failed to get irq\n");
173 p
->clk
= clk_get(&p
->pdev
->dev
, "fck");
174 if (IS_ERR(p
->clk
)) {
175 dev_err(&p
->pdev
->dev
, "can't get clk\n");
176 return PTR_ERR(p
->clk
);
178 of_property_read_u32(p
->pdev
->dev
.of_node
, "renesas,channel", &ch
);
181 p
->mapbase
= res
[REG_CH
]->start
;
182 p
->mapcommon
= res
[REG_COMM
]->start
;
185 p
->imiea
= 1 << (4 + ch
);
186 p
->cs
.name
= pdev
->name
;
188 p
->cs
.read
= timer16_clocksource_read
;
189 p
->cs
.enable
= timer16_enable
;
190 p
->cs
.disable
= timer16_disable
;
191 p
->cs
.mask
= CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
192 p
->cs
.flags
= CLOCK_SOURCE_IS_CONTINUOUS
;
194 ret
= request_irq(irq
, timer16_interrupt
,
195 IRQF_TIMER
, pdev
->name
, p
);
197 dev_err(&p
->pdev
->dev
, "failed to request irq %d\n", irq
);
201 clocksource_register_hz(&p
->cs
, clk_get_rate(p
->clk
) / 8);
206 static int timer16_probe(struct platform_device
*pdev
)
208 struct timer16_priv
*p
= platform_get_drvdata(pdev
);
211 dev_info(&pdev
->dev
, "kept as earlytimer\n");
215 p
= devm_kzalloc(&pdev
->dev
, sizeof(*p
), GFP_KERNEL
);
219 return timer16_setup(p
, pdev
);
222 static int timer16_remove(struct platform_device
*pdev
)
227 static const struct of_device_id timer16_of_table
[] = {
228 { .compatible
= "renesas,16bit-timer" },
231 static struct platform_driver timer16_driver
= {
232 .probe
= timer16_probe
,
233 .remove
= timer16_remove
,
235 .name
= "h8300h-16timer",
236 .of_match_table
= of_match_ptr(timer16_of_table
),
240 static int __init
timer16_init(void)
242 return platform_driver_register(&timer16_driver
);
245 static void __exit
timer16_exit(void)
247 platform_driver_unregister(&timer16_driver
);
250 subsys_initcall(timer16_init
);
251 module_exit(timer16_exit
);
252 MODULE_AUTHOR("Yoshinori Sato");
253 MODULE_DESCRIPTION("H8/300H 16bit Timer Driver");
254 MODULE_LICENSE("GPL v2");