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];
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");
166 irq
= platform_get_irq(p
->pdev
, 0);
168 dev_err(&p
->pdev
->dev
, "failed to get irq\n");
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
);
177 of_property_read_u32(p
->pdev
->dev
.of_node
, "renesas,channel", &ch
);
180 p
->mapbase
= res
[REG_CH
]->start
;
181 p
->mapcommon
= res
[REG_COMM
]->start
;
184 p
->imiea
= 1 << (4 + ch
);
185 p
->cs
.name
= pdev
->name
;
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
;
193 ret
= request_irq(irq
, timer16_interrupt
,
194 IRQF_TIMER
, pdev
->name
, p
);
196 dev_err(&p
->pdev
->dev
, "failed to request irq %d\n", irq
);
200 clocksource_register_hz(&p
->cs
, clk_get_rate(p
->clk
) / 8);
205 static int timer16_probe(struct platform_device
*pdev
)
207 struct timer16_priv
*p
= platform_get_drvdata(pdev
);
210 dev_info(&pdev
->dev
, "kept as earlytimer\n");
214 p
= devm_kzalloc(&pdev
->dev
, sizeof(*p
), GFP_KERNEL
);
218 return timer16_setup(p
, pdev
);
221 static int timer16_remove(struct platform_device
*pdev
)
226 static const struct of_device_id timer16_of_table
[] = {
227 { .compatible
= "renesas,16bit-timer" },
230 static struct platform_driver timer16_driver
= {
231 .probe
= timer16_probe
,
232 .remove
= timer16_remove
,
234 .name
= "h8300h-16timer",
235 .of_match_table
= of_match_ptr(timer16_of_table
),
239 static int __init
timer16_init(void)
241 return platform_driver_register(&timer16_driver
);
244 static void __exit
timer16_exit(void)
246 platform_driver_unregister(&timer16_driver
);
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");