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