xref: /linux/drivers/clocksource/em_sti.c (revision b9dbf9517784084ee9496f9f17f9754c1d021a9e)
1*b9dbf951SMagnus Damm /*
2*b9dbf951SMagnus Damm  * Emma Mobile Timer Support - STI
3*b9dbf951SMagnus Damm  *
4*b9dbf951SMagnus Damm  *  Copyright (C) 2012 Magnus Damm
5*b9dbf951SMagnus Damm  *
6*b9dbf951SMagnus Damm  * This program is free software; you can redistribute it and/or modify
7*b9dbf951SMagnus Damm  * it under the terms of the GNU General Public License as published by
8*b9dbf951SMagnus Damm  * the Free Software Foundation; either version 2 of the License
9*b9dbf951SMagnus Damm  *
10*b9dbf951SMagnus Damm  * This program is distributed in the hope that it will be useful,
11*b9dbf951SMagnus Damm  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*b9dbf951SMagnus Damm  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*b9dbf951SMagnus Damm  * GNU General Public License for more details.
14*b9dbf951SMagnus Damm  *
15*b9dbf951SMagnus Damm  * You should have received a copy of the GNU General Public License
16*b9dbf951SMagnus Damm  * along with this program; if not, write to the Free Software
17*b9dbf951SMagnus Damm  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18*b9dbf951SMagnus Damm  */
19*b9dbf951SMagnus Damm 
20*b9dbf951SMagnus Damm #include <linux/init.h>
21*b9dbf951SMagnus Damm #include <linux/platform_device.h>
22*b9dbf951SMagnus Damm #include <linux/spinlock.h>
23*b9dbf951SMagnus Damm #include <linux/interrupt.h>
24*b9dbf951SMagnus Damm #include <linux/ioport.h>
25*b9dbf951SMagnus Damm #include <linux/io.h>
26*b9dbf951SMagnus Damm #include <linux/clk.h>
27*b9dbf951SMagnus Damm #include <linux/irq.h>
28*b9dbf951SMagnus Damm #include <linux/err.h>
29*b9dbf951SMagnus Damm #include <linux/delay.h>
30*b9dbf951SMagnus Damm #include <linux/clocksource.h>
31*b9dbf951SMagnus Damm #include <linux/clockchips.h>
32*b9dbf951SMagnus Damm #include <linux/slab.h>
33*b9dbf951SMagnus Damm #include <linux/module.h>
34*b9dbf951SMagnus Damm 
35*b9dbf951SMagnus Damm enum { USER_CLOCKSOURCE, USER_CLOCKEVENT, USER_NR };
36*b9dbf951SMagnus Damm 
37*b9dbf951SMagnus Damm struct em_sti_priv {
38*b9dbf951SMagnus Damm 	void __iomem *base;
39*b9dbf951SMagnus Damm 	struct clk *clk;
40*b9dbf951SMagnus Damm 	struct platform_device *pdev;
41*b9dbf951SMagnus Damm 	unsigned int active[USER_NR];
42*b9dbf951SMagnus Damm 	unsigned long rate;
43*b9dbf951SMagnus Damm 	raw_spinlock_t lock;
44*b9dbf951SMagnus Damm 	struct clock_event_device ced;
45*b9dbf951SMagnus Damm 	struct clocksource cs;
46*b9dbf951SMagnus Damm };
47*b9dbf951SMagnus Damm 
48*b9dbf951SMagnus Damm #define STI_CONTROL 0x00
49*b9dbf951SMagnus Damm #define STI_COMPA_H 0x10
50*b9dbf951SMagnus Damm #define STI_COMPA_L 0x14
51*b9dbf951SMagnus Damm #define STI_COMPB_H 0x18
52*b9dbf951SMagnus Damm #define STI_COMPB_L 0x1c
53*b9dbf951SMagnus Damm #define STI_COUNT_H 0x20
54*b9dbf951SMagnus Damm #define STI_COUNT_L 0x24
55*b9dbf951SMagnus Damm #define STI_COUNT_RAW_H 0x28
56*b9dbf951SMagnus Damm #define STI_COUNT_RAW_L 0x2c
57*b9dbf951SMagnus Damm #define STI_SET_H 0x30
58*b9dbf951SMagnus Damm #define STI_SET_L 0x34
59*b9dbf951SMagnus Damm #define STI_INTSTATUS 0x40
60*b9dbf951SMagnus Damm #define STI_INTRAWSTATUS 0x44
61*b9dbf951SMagnus Damm #define STI_INTENSET 0x48
62*b9dbf951SMagnus Damm #define STI_INTENCLR 0x4c
63*b9dbf951SMagnus Damm #define STI_INTFFCLR 0x50
64*b9dbf951SMagnus Damm 
65*b9dbf951SMagnus Damm static inline unsigned long em_sti_read(struct em_sti_priv *p, int offs)
66*b9dbf951SMagnus Damm {
67*b9dbf951SMagnus Damm 	return ioread32(p->base + offs);
68*b9dbf951SMagnus Damm }
69*b9dbf951SMagnus Damm 
70*b9dbf951SMagnus Damm static inline void em_sti_write(struct em_sti_priv *p, int offs,
71*b9dbf951SMagnus Damm 				unsigned long value)
72*b9dbf951SMagnus Damm {
73*b9dbf951SMagnus Damm 	iowrite32(value, p->base + offs);
74*b9dbf951SMagnus Damm }
75*b9dbf951SMagnus Damm 
76*b9dbf951SMagnus Damm static int em_sti_enable(struct em_sti_priv *p)
77*b9dbf951SMagnus Damm {
78*b9dbf951SMagnus Damm 	int ret;
79*b9dbf951SMagnus Damm 
80*b9dbf951SMagnus Damm 	/* enable clock */
81*b9dbf951SMagnus Damm 	ret = clk_enable(p->clk);
82*b9dbf951SMagnus Damm 	if (ret) {
83*b9dbf951SMagnus Damm 		dev_err(&p->pdev->dev, "cannot enable clock\n");
84*b9dbf951SMagnus Damm 		return ret;
85*b9dbf951SMagnus Damm 	}
86*b9dbf951SMagnus Damm 
87*b9dbf951SMagnus Damm 	/* configure channel, periodic mode and maximum timeout */
88*b9dbf951SMagnus Damm 	p->rate = clk_get_rate(p->clk);
89*b9dbf951SMagnus Damm 
90*b9dbf951SMagnus Damm 	/* reset the counter */
91*b9dbf951SMagnus Damm 	em_sti_write(p, STI_SET_H, 0x40000000);
92*b9dbf951SMagnus Damm 	em_sti_write(p, STI_SET_L, 0x00000000);
93*b9dbf951SMagnus Damm 
94*b9dbf951SMagnus Damm 	/* mask and clear pending interrupts */
95*b9dbf951SMagnus Damm 	em_sti_write(p, STI_INTENCLR, 3);
96*b9dbf951SMagnus Damm 	em_sti_write(p, STI_INTFFCLR, 3);
97*b9dbf951SMagnus Damm 
98*b9dbf951SMagnus Damm 	/* enable updates of counter registers */
99*b9dbf951SMagnus Damm 	em_sti_write(p, STI_CONTROL, 1);
100*b9dbf951SMagnus Damm 
101*b9dbf951SMagnus Damm 	return 0;
102*b9dbf951SMagnus Damm }
103*b9dbf951SMagnus Damm 
104*b9dbf951SMagnus Damm static void em_sti_disable(struct em_sti_priv *p)
105*b9dbf951SMagnus Damm {
106*b9dbf951SMagnus Damm 	/* mask interrupts */
107*b9dbf951SMagnus Damm 	em_sti_write(p, STI_INTENCLR, 3);
108*b9dbf951SMagnus Damm 
109*b9dbf951SMagnus Damm 	/* stop clock */
110*b9dbf951SMagnus Damm 	clk_disable(p->clk);
111*b9dbf951SMagnus Damm }
112*b9dbf951SMagnus Damm 
113*b9dbf951SMagnus Damm static cycle_t em_sti_count(struct em_sti_priv *p)
114*b9dbf951SMagnus Damm {
115*b9dbf951SMagnus Damm 	cycle_t ticks;
116*b9dbf951SMagnus Damm 	unsigned long flags;
117*b9dbf951SMagnus Damm 
118*b9dbf951SMagnus Damm 	/* the STI hardware buffers the 48-bit count, but to
119*b9dbf951SMagnus Damm 	 * break it out into two 32-bit access the registers
120*b9dbf951SMagnus Damm 	 * must be accessed in a certain order.
121*b9dbf951SMagnus Damm 	 * Always read STI_COUNT_H before STI_COUNT_L.
122*b9dbf951SMagnus Damm 	 */
123*b9dbf951SMagnus Damm 	raw_spin_lock_irqsave(&p->lock, flags);
124*b9dbf951SMagnus Damm 	ticks = (cycle_t)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32;
125*b9dbf951SMagnus Damm 	ticks |= em_sti_read(p, STI_COUNT_L);
126*b9dbf951SMagnus Damm 	raw_spin_unlock_irqrestore(&p->lock, flags);
127*b9dbf951SMagnus Damm 
128*b9dbf951SMagnus Damm 	return ticks;
129*b9dbf951SMagnus Damm }
130*b9dbf951SMagnus Damm 
131*b9dbf951SMagnus Damm static cycle_t em_sti_set_next(struct em_sti_priv *p, cycle_t next)
132*b9dbf951SMagnus Damm {
133*b9dbf951SMagnus Damm 	unsigned long flags;
134*b9dbf951SMagnus Damm 
135*b9dbf951SMagnus Damm 	raw_spin_lock_irqsave(&p->lock, flags);
136*b9dbf951SMagnus Damm 
137*b9dbf951SMagnus Damm 	/* mask compare A interrupt */
138*b9dbf951SMagnus Damm 	em_sti_write(p, STI_INTENCLR, 1);
139*b9dbf951SMagnus Damm 
140*b9dbf951SMagnus Damm 	/* update compare A value */
141*b9dbf951SMagnus Damm 	em_sti_write(p, STI_COMPA_H, next >> 32);
142*b9dbf951SMagnus Damm 	em_sti_write(p, STI_COMPA_L, next & 0xffffffff);
143*b9dbf951SMagnus Damm 
144*b9dbf951SMagnus Damm 	/* clear compare A interrupt source */
145*b9dbf951SMagnus Damm 	em_sti_write(p, STI_INTFFCLR, 1);
146*b9dbf951SMagnus Damm 
147*b9dbf951SMagnus Damm 	/* unmask compare A interrupt */
148*b9dbf951SMagnus Damm 	em_sti_write(p, STI_INTENSET, 1);
149*b9dbf951SMagnus Damm 
150*b9dbf951SMagnus Damm 	raw_spin_unlock_irqrestore(&p->lock, flags);
151*b9dbf951SMagnus Damm 
152*b9dbf951SMagnus Damm 	return next;
153*b9dbf951SMagnus Damm }
154*b9dbf951SMagnus Damm 
155*b9dbf951SMagnus Damm static irqreturn_t em_sti_interrupt(int irq, void *dev_id)
156*b9dbf951SMagnus Damm {
157*b9dbf951SMagnus Damm 	struct em_sti_priv *p = dev_id;
158*b9dbf951SMagnus Damm 
159*b9dbf951SMagnus Damm 	p->ced.event_handler(&p->ced);
160*b9dbf951SMagnus Damm 	return IRQ_HANDLED;
161*b9dbf951SMagnus Damm }
162*b9dbf951SMagnus Damm 
163*b9dbf951SMagnus Damm static int em_sti_start(struct em_sti_priv *p, unsigned int user)
164*b9dbf951SMagnus Damm {
165*b9dbf951SMagnus Damm 	unsigned long flags;
166*b9dbf951SMagnus Damm 	int used_before;
167*b9dbf951SMagnus Damm 	int ret = 0;
168*b9dbf951SMagnus Damm 
169*b9dbf951SMagnus Damm 	raw_spin_lock_irqsave(&p->lock, flags);
170*b9dbf951SMagnus Damm 	used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT];
171*b9dbf951SMagnus Damm 	if (!used_before)
172*b9dbf951SMagnus Damm 		ret = em_sti_enable(p);
173*b9dbf951SMagnus Damm 
174*b9dbf951SMagnus Damm 	if (!ret)
175*b9dbf951SMagnus Damm 		p->active[user] = 1;
176*b9dbf951SMagnus Damm 	raw_spin_unlock_irqrestore(&p->lock, flags);
177*b9dbf951SMagnus Damm 
178*b9dbf951SMagnus Damm 	return ret;
179*b9dbf951SMagnus Damm }
180*b9dbf951SMagnus Damm 
181*b9dbf951SMagnus Damm static void em_sti_stop(struct em_sti_priv *p, unsigned int user)
182*b9dbf951SMagnus Damm {
183*b9dbf951SMagnus Damm 	unsigned long flags;
184*b9dbf951SMagnus Damm 	int used_before, used_after;
185*b9dbf951SMagnus Damm 
186*b9dbf951SMagnus Damm 	raw_spin_lock_irqsave(&p->lock, flags);
187*b9dbf951SMagnus Damm 	used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT];
188*b9dbf951SMagnus Damm 	p->active[user] = 0;
189*b9dbf951SMagnus Damm 	used_after = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT];
190*b9dbf951SMagnus Damm 
191*b9dbf951SMagnus Damm 	if (used_before && !used_after)
192*b9dbf951SMagnus Damm 		em_sti_disable(p);
193*b9dbf951SMagnus Damm 	raw_spin_unlock_irqrestore(&p->lock, flags);
194*b9dbf951SMagnus Damm }
195*b9dbf951SMagnus Damm 
196*b9dbf951SMagnus Damm static struct em_sti_priv *cs_to_em_sti(struct clocksource *cs)
197*b9dbf951SMagnus Damm {
198*b9dbf951SMagnus Damm 	return container_of(cs, struct em_sti_priv, cs);
199*b9dbf951SMagnus Damm }
200*b9dbf951SMagnus Damm 
201*b9dbf951SMagnus Damm static cycle_t em_sti_clocksource_read(struct clocksource *cs)
202*b9dbf951SMagnus Damm {
203*b9dbf951SMagnus Damm 	return em_sti_count(cs_to_em_sti(cs));
204*b9dbf951SMagnus Damm }
205*b9dbf951SMagnus Damm 
206*b9dbf951SMagnus Damm static int em_sti_clocksource_enable(struct clocksource *cs)
207*b9dbf951SMagnus Damm {
208*b9dbf951SMagnus Damm 	int ret;
209*b9dbf951SMagnus Damm 	struct em_sti_priv *p = cs_to_em_sti(cs);
210*b9dbf951SMagnus Damm 
211*b9dbf951SMagnus Damm 	ret = em_sti_start(p, USER_CLOCKSOURCE);
212*b9dbf951SMagnus Damm 	if (!ret)
213*b9dbf951SMagnus Damm 		__clocksource_updatefreq_hz(cs, p->rate);
214*b9dbf951SMagnus Damm 	return ret;
215*b9dbf951SMagnus Damm }
216*b9dbf951SMagnus Damm 
217*b9dbf951SMagnus Damm static void em_sti_clocksource_disable(struct clocksource *cs)
218*b9dbf951SMagnus Damm {
219*b9dbf951SMagnus Damm 	em_sti_stop(cs_to_em_sti(cs), USER_CLOCKSOURCE);
220*b9dbf951SMagnus Damm }
221*b9dbf951SMagnus Damm 
222*b9dbf951SMagnus Damm static void em_sti_clocksource_resume(struct clocksource *cs)
223*b9dbf951SMagnus Damm {
224*b9dbf951SMagnus Damm 	em_sti_clocksource_enable(cs);
225*b9dbf951SMagnus Damm }
226*b9dbf951SMagnus Damm 
227*b9dbf951SMagnus Damm static int em_sti_register_clocksource(struct em_sti_priv *p)
228*b9dbf951SMagnus Damm {
229*b9dbf951SMagnus Damm 	struct clocksource *cs = &p->cs;
230*b9dbf951SMagnus Damm 
231*b9dbf951SMagnus Damm 	memset(cs, 0, sizeof(*cs));
232*b9dbf951SMagnus Damm 	cs->name = dev_name(&p->pdev->dev);
233*b9dbf951SMagnus Damm 	cs->rating = 200;
234*b9dbf951SMagnus Damm 	cs->read = em_sti_clocksource_read;
235*b9dbf951SMagnus Damm 	cs->enable = em_sti_clocksource_enable;
236*b9dbf951SMagnus Damm 	cs->disable = em_sti_clocksource_disable;
237*b9dbf951SMagnus Damm 	cs->suspend = em_sti_clocksource_disable;
238*b9dbf951SMagnus Damm 	cs->resume = em_sti_clocksource_resume;
239*b9dbf951SMagnus Damm 	cs->mask = CLOCKSOURCE_MASK(48);
240*b9dbf951SMagnus Damm 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
241*b9dbf951SMagnus Damm 
242*b9dbf951SMagnus Damm 	dev_info(&p->pdev->dev, "used as clock source\n");
243*b9dbf951SMagnus Damm 
244*b9dbf951SMagnus Damm 	/* Register with dummy 1 Hz value, gets updated in ->enable() */
245*b9dbf951SMagnus Damm 	clocksource_register_hz(cs, 1);
246*b9dbf951SMagnus Damm 	return 0;
247*b9dbf951SMagnus Damm }
248*b9dbf951SMagnus Damm 
249*b9dbf951SMagnus Damm static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced)
250*b9dbf951SMagnus Damm {
251*b9dbf951SMagnus Damm 	return container_of(ced, struct em_sti_priv, ced);
252*b9dbf951SMagnus Damm }
253*b9dbf951SMagnus Damm 
254*b9dbf951SMagnus Damm static void em_sti_clock_event_mode(enum clock_event_mode mode,
255*b9dbf951SMagnus Damm 				    struct clock_event_device *ced)
256*b9dbf951SMagnus Damm {
257*b9dbf951SMagnus Damm 	struct em_sti_priv *p = ced_to_em_sti(ced);
258*b9dbf951SMagnus Damm 
259*b9dbf951SMagnus Damm 	/* deal with old setting first */
260*b9dbf951SMagnus Damm 	switch (ced->mode) {
261*b9dbf951SMagnus Damm 	case CLOCK_EVT_MODE_ONESHOT:
262*b9dbf951SMagnus Damm 		em_sti_stop(p, USER_CLOCKEVENT);
263*b9dbf951SMagnus Damm 		break;
264*b9dbf951SMagnus Damm 	default:
265*b9dbf951SMagnus Damm 		break;
266*b9dbf951SMagnus Damm 	}
267*b9dbf951SMagnus Damm 
268*b9dbf951SMagnus Damm 	switch (mode) {
269*b9dbf951SMagnus Damm 	case CLOCK_EVT_MODE_ONESHOT:
270*b9dbf951SMagnus Damm 		dev_info(&p->pdev->dev, "used for oneshot clock events\n");
271*b9dbf951SMagnus Damm 		em_sti_start(p, USER_CLOCKEVENT);
272*b9dbf951SMagnus Damm 		clockevents_config(&p->ced, p->rate);
273*b9dbf951SMagnus Damm 		break;
274*b9dbf951SMagnus Damm 	case CLOCK_EVT_MODE_SHUTDOWN:
275*b9dbf951SMagnus Damm 	case CLOCK_EVT_MODE_UNUSED:
276*b9dbf951SMagnus Damm 		em_sti_stop(p, USER_CLOCKEVENT);
277*b9dbf951SMagnus Damm 		break;
278*b9dbf951SMagnus Damm 	default:
279*b9dbf951SMagnus Damm 		break;
280*b9dbf951SMagnus Damm 	}
281*b9dbf951SMagnus Damm }
282*b9dbf951SMagnus Damm 
283*b9dbf951SMagnus Damm static int em_sti_clock_event_next(unsigned long delta,
284*b9dbf951SMagnus Damm 				   struct clock_event_device *ced)
285*b9dbf951SMagnus Damm {
286*b9dbf951SMagnus Damm 	struct em_sti_priv *p = ced_to_em_sti(ced);
287*b9dbf951SMagnus Damm 	cycle_t next;
288*b9dbf951SMagnus Damm 	int safe;
289*b9dbf951SMagnus Damm 
290*b9dbf951SMagnus Damm 	next = em_sti_set_next(p, em_sti_count(p) + delta);
291*b9dbf951SMagnus Damm 	safe = em_sti_count(p) < (next - 1);
292*b9dbf951SMagnus Damm 
293*b9dbf951SMagnus Damm 	return !safe;
294*b9dbf951SMagnus Damm }
295*b9dbf951SMagnus Damm 
296*b9dbf951SMagnus Damm static void em_sti_register_clockevent(struct em_sti_priv *p)
297*b9dbf951SMagnus Damm {
298*b9dbf951SMagnus Damm 	struct clock_event_device *ced = &p->ced;
299*b9dbf951SMagnus Damm 
300*b9dbf951SMagnus Damm 	memset(ced, 0, sizeof(*ced));
301*b9dbf951SMagnus Damm 	ced->name = dev_name(&p->pdev->dev);
302*b9dbf951SMagnus Damm 	ced->features = CLOCK_EVT_FEAT_ONESHOT;
303*b9dbf951SMagnus Damm 	ced->rating = 200;
304*b9dbf951SMagnus Damm 	ced->cpumask = cpumask_of(0);
305*b9dbf951SMagnus Damm 	ced->set_next_event = em_sti_clock_event_next;
306*b9dbf951SMagnus Damm 	ced->set_mode = em_sti_clock_event_mode;
307*b9dbf951SMagnus Damm 
308*b9dbf951SMagnus Damm 	dev_info(&p->pdev->dev, "used for clock events\n");
309*b9dbf951SMagnus Damm 
310*b9dbf951SMagnus Damm 	/* Register with dummy 1 Hz value, gets updated in ->set_mode() */
311*b9dbf951SMagnus Damm 	clockevents_config_and_register(ced, 1, 2, 0xffffffff);
312*b9dbf951SMagnus Damm }
313*b9dbf951SMagnus Damm 
314*b9dbf951SMagnus Damm static int __devinit em_sti_probe(struct platform_device *pdev)
315*b9dbf951SMagnus Damm {
316*b9dbf951SMagnus Damm 	struct em_sti_priv *p;
317*b9dbf951SMagnus Damm 	struct resource *res;
318*b9dbf951SMagnus Damm 	int irq, ret;
319*b9dbf951SMagnus Damm 
320*b9dbf951SMagnus Damm 	p = kzalloc(sizeof(*p), GFP_KERNEL);
321*b9dbf951SMagnus Damm 	if (p == NULL) {
322*b9dbf951SMagnus Damm 		dev_err(&pdev->dev, "failed to allocate driver data\n");
323*b9dbf951SMagnus Damm 		ret = -ENOMEM;
324*b9dbf951SMagnus Damm 		goto err0;
325*b9dbf951SMagnus Damm 	}
326*b9dbf951SMagnus Damm 
327*b9dbf951SMagnus Damm 	p->pdev = pdev;
328*b9dbf951SMagnus Damm 	platform_set_drvdata(pdev, p);
329*b9dbf951SMagnus Damm 
330*b9dbf951SMagnus Damm 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
331*b9dbf951SMagnus Damm 	if (!res) {
332*b9dbf951SMagnus Damm 		dev_err(&pdev->dev, "failed to get I/O memory\n");
333*b9dbf951SMagnus Damm 		ret = -EINVAL;
334*b9dbf951SMagnus Damm 		goto err0;
335*b9dbf951SMagnus Damm 	}
336*b9dbf951SMagnus Damm 
337*b9dbf951SMagnus Damm 	irq = platform_get_irq(pdev, 0);
338*b9dbf951SMagnus Damm 	if (irq < 0) {
339*b9dbf951SMagnus Damm 		dev_err(&pdev->dev, "failed to get irq\n");
340*b9dbf951SMagnus Damm 		ret = -EINVAL;
341*b9dbf951SMagnus Damm 		goto err0;
342*b9dbf951SMagnus Damm 	}
343*b9dbf951SMagnus Damm 
344*b9dbf951SMagnus Damm 	/* map memory, let base point to the STI instance */
345*b9dbf951SMagnus Damm 	p->base = ioremap_nocache(res->start, resource_size(res));
346*b9dbf951SMagnus Damm 	if (p->base == NULL) {
347*b9dbf951SMagnus Damm 		dev_err(&pdev->dev, "failed to remap I/O memory\n");
348*b9dbf951SMagnus Damm 		ret = -ENXIO;
349*b9dbf951SMagnus Damm 		goto err0;
350*b9dbf951SMagnus Damm 	}
351*b9dbf951SMagnus Damm 
352*b9dbf951SMagnus Damm 	/* get hold of clock */
353*b9dbf951SMagnus Damm 	p->clk = clk_get(&pdev->dev, "sclk");
354*b9dbf951SMagnus Damm 	if (IS_ERR(p->clk)) {
355*b9dbf951SMagnus Damm 		dev_err(&pdev->dev, "cannot get clock\n");
356*b9dbf951SMagnus Damm 		ret = PTR_ERR(p->clk);
357*b9dbf951SMagnus Damm 		goto err1;
358*b9dbf951SMagnus Damm 	}
359*b9dbf951SMagnus Damm 
360*b9dbf951SMagnus Damm 	if (request_irq(irq, em_sti_interrupt,
361*b9dbf951SMagnus Damm 			IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
362*b9dbf951SMagnus Damm 			dev_name(&pdev->dev), p)) {
363*b9dbf951SMagnus Damm 		dev_err(&pdev->dev, "failed to request low IRQ\n");
364*b9dbf951SMagnus Damm 		ret = -ENOENT;
365*b9dbf951SMagnus Damm 		goto err2;
366*b9dbf951SMagnus Damm 	}
367*b9dbf951SMagnus Damm 
368*b9dbf951SMagnus Damm 	raw_spin_lock_init(&p->lock);
369*b9dbf951SMagnus Damm 	em_sti_register_clockevent(p);
370*b9dbf951SMagnus Damm 	em_sti_register_clocksource(p);
371*b9dbf951SMagnus Damm 	return 0;
372*b9dbf951SMagnus Damm 
373*b9dbf951SMagnus Damm err2:
374*b9dbf951SMagnus Damm 	clk_put(p->clk);
375*b9dbf951SMagnus Damm err1:
376*b9dbf951SMagnus Damm 	iounmap(p->base);
377*b9dbf951SMagnus Damm err0:
378*b9dbf951SMagnus Damm 	kfree(p);
379*b9dbf951SMagnus Damm 	return ret;
380*b9dbf951SMagnus Damm }
381*b9dbf951SMagnus Damm 
382*b9dbf951SMagnus Damm static int __devexit em_sti_remove(struct platform_device *pdev)
383*b9dbf951SMagnus Damm {
384*b9dbf951SMagnus Damm 	return -EBUSY; /* cannot unregister clockevent and clocksource */
385*b9dbf951SMagnus Damm }
386*b9dbf951SMagnus Damm 
387*b9dbf951SMagnus Damm static struct platform_driver em_sti_device_driver = {
388*b9dbf951SMagnus Damm 	.probe		= em_sti_probe,
389*b9dbf951SMagnus Damm 	.remove		= __devexit_p(em_sti_remove),
390*b9dbf951SMagnus Damm 	.driver		= {
391*b9dbf951SMagnus Damm 		.name	= "em_sti",
392*b9dbf951SMagnus Damm 	}
393*b9dbf951SMagnus Damm };
394*b9dbf951SMagnus Damm 
395*b9dbf951SMagnus Damm module_platform_driver(em_sti_device_driver);
396*b9dbf951SMagnus Damm 
397*b9dbf951SMagnus Damm MODULE_AUTHOR("Magnus Damm");
398*b9dbf951SMagnus Damm MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver");
399*b9dbf951SMagnus Damm MODULE_LICENSE("GPL v2");
400