1b9dbf951SMagnus Damm /* 2b9dbf951SMagnus Damm * Emma Mobile Timer Support - STI 3b9dbf951SMagnus Damm * 4b9dbf951SMagnus Damm * Copyright (C) 2012 Magnus Damm 5b9dbf951SMagnus Damm * 6b9dbf951SMagnus Damm * This program is free software; you can redistribute it and/or modify 7b9dbf951SMagnus Damm * it under the terms of the GNU General Public License as published by 8b9dbf951SMagnus Damm * the Free Software Foundation; either version 2 of the License 9b9dbf951SMagnus Damm * 10b9dbf951SMagnus Damm * This program is distributed in the hope that it will be useful, 11b9dbf951SMagnus Damm * but WITHOUT ANY WARRANTY; without even the implied warranty of 12b9dbf951SMagnus Damm * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13b9dbf951SMagnus Damm * GNU General Public License for more details. 14b9dbf951SMagnus Damm * 15b9dbf951SMagnus Damm * You should have received a copy of the GNU General Public License 16b9dbf951SMagnus Damm * along with this program; if not, write to the Free Software 17b9dbf951SMagnus Damm * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18b9dbf951SMagnus Damm */ 19b9dbf951SMagnus Damm 20b9dbf951SMagnus Damm #include <linux/init.h> 21b9dbf951SMagnus Damm #include <linux/platform_device.h> 22b9dbf951SMagnus Damm #include <linux/spinlock.h> 23b9dbf951SMagnus Damm #include <linux/interrupt.h> 24b9dbf951SMagnus Damm #include <linux/ioport.h> 25b9dbf951SMagnus Damm #include <linux/io.h> 26b9dbf951SMagnus Damm #include <linux/clk.h> 27b9dbf951SMagnus Damm #include <linux/irq.h> 28b9dbf951SMagnus Damm #include <linux/err.h> 29b9dbf951SMagnus Damm #include <linux/delay.h> 30b9dbf951SMagnus Damm #include <linux/clocksource.h> 31b9dbf951SMagnus Damm #include <linux/clockchips.h> 32b9dbf951SMagnus Damm #include <linux/slab.h> 33b9dbf951SMagnus Damm #include <linux/module.h> 34b9dbf951SMagnus Damm 35b9dbf951SMagnus Damm enum { USER_CLOCKSOURCE, USER_CLOCKEVENT, USER_NR }; 36b9dbf951SMagnus Damm 37b9dbf951SMagnus Damm struct em_sti_priv { 38b9dbf951SMagnus Damm void __iomem *base; 39b9dbf951SMagnus Damm struct clk *clk; 40b9dbf951SMagnus Damm struct platform_device *pdev; 41b9dbf951SMagnus Damm unsigned int active[USER_NR]; 42b9dbf951SMagnus Damm unsigned long rate; 43b9dbf951SMagnus Damm raw_spinlock_t lock; 44b9dbf951SMagnus Damm struct clock_event_device ced; 45b9dbf951SMagnus Damm struct clocksource cs; 46b9dbf951SMagnus Damm }; 47b9dbf951SMagnus Damm 48b9dbf951SMagnus Damm #define STI_CONTROL 0x00 49b9dbf951SMagnus Damm #define STI_COMPA_H 0x10 50b9dbf951SMagnus Damm #define STI_COMPA_L 0x14 51b9dbf951SMagnus Damm #define STI_COMPB_H 0x18 52b9dbf951SMagnus Damm #define STI_COMPB_L 0x1c 53b9dbf951SMagnus Damm #define STI_COUNT_H 0x20 54b9dbf951SMagnus Damm #define STI_COUNT_L 0x24 55b9dbf951SMagnus Damm #define STI_COUNT_RAW_H 0x28 56b9dbf951SMagnus Damm #define STI_COUNT_RAW_L 0x2c 57b9dbf951SMagnus Damm #define STI_SET_H 0x30 58b9dbf951SMagnus Damm #define STI_SET_L 0x34 59b9dbf951SMagnus Damm #define STI_INTSTATUS 0x40 60b9dbf951SMagnus Damm #define STI_INTRAWSTATUS 0x44 61b9dbf951SMagnus Damm #define STI_INTENSET 0x48 62b9dbf951SMagnus Damm #define STI_INTENCLR 0x4c 63b9dbf951SMagnus Damm #define STI_INTFFCLR 0x50 64b9dbf951SMagnus Damm 65b9dbf951SMagnus Damm static inline unsigned long em_sti_read(struct em_sti_priv *p, int offs) 66b9dbf951SMagnus Damm { 67b9dbf951SMagnus Damm return ioread32(p->base + offs); 68b9dbf951SMagnus Damm } 69b9dbf951SMagnus Damm 70b9dbf951SMagnus Damm static inline void em_sti_write(struct em_sti_priv *p, int offs, 71b9dbf951SMagnus Damm unsigned long value) 72b9dbf951SMagnus Damm { 73b9dbf951SMagnus Damm iowrite32(value, p->base + offs); 74b9dbf951SMagnus Damm } 75b9dbf951SMagnus Damm 76b9dbf951SMagnus Damm static int em_sti_enable(struct em_sti_priv *p) 77b9dbf951SMagnus Damm { 78b9dbf951SMagnus Damm int ret; 79b9dbf951SMagnus Damm 80b9dbf951SMagnus Damm /* enable clock */ 813814ae09SNicolai Stange ret = clk_enable(p->clk); 82b9dbf951SMagnus Damm if (ret) { 83b9dbf951SMagnus Damm dev_err(&p->pdev->dev, "cannot enable clock\n"); 84b9dbf951SMagnus Damm return ret; 85b9dbf951SMagnus Damm } 86b9dbf951SMagnus Damm 87b9dbf951SMagnus Damm /* reset the counter */ 88b9dbf951SMagnus Damm em_sti_write(p, STI_SET_H, 0x40000000); 89b9dbf951SMagnus Damm em_sti_write(p, STI_SET_L, 0x00000000); 90b9dbf951SMagnus Damm 91b9dbf951SMagnus Damm /* mask and clear pending interrupts */ 92b9dbf951SMagnus Damm em_sti_write(p, STI_INTENCLR, 3); 93b9dbf951SMagnus Damm em_sti_write(p, STI_INTFFCLR, 3); 94b9dbf951SMagnus Damm 95b9dbf951SMagnus Damm /* enable updates of counter registers */ 96b9dbf951SMagnus Damm em_sti_write(p, STI_CONTROL, 1); 97b9dbf951SMagnus Damm 98b9dbf951SMagnus Damm return 0; 99b9dbf951SMagnus Damm } 100b9dbf951SMagnus Damm 101b9dbf951SMagnus Damm static void em_sti_disable(struct em_sti_priv *p) 102b9dbf951SMagnus Damm { 103b9dbf951SMagnus Damm /* mask interrupts */ 104b9dbf951SMagnus Damm em_sti_write(p, STI_INTENCLR, 3); 105b9dbf951SMagnus Damm 106b9dbf951SMagnus Damm /* stop clock */ 1073814ae09SNicolai Stange clk_disable(p->clk); 108b9dbf951SMagnus Damm } 109b9dbf951SMagnus Damm 110a5a1d1c2SThomas Gleixner static u64 em_sti_count(struct em_sti_priv *p) 111b9dbf951SMagnus Damm { 112a5a1d1c2SThomas Gleixner u64 ticks; 113b9dbf951SMagnus Damm unsigned long flags; 114b9dbf951SMagnus Damm 115b9dbf951SMagnus Damm /* the STI hardware buffers the 48-bit count, but to 116b9dbf951SMagnus Damm * break it out into two 32-bit access the registers 117b9dbf951SMagnus Damm * must be accessed in a certain order. 118b9dbf951SMagnus Damm * Always read STI_COUNT_H before STI_COUNT_L. 119b9dbf951SMagnus Damm */ 120b9dbf951SMagnus Damm raw_spin_lock_irqsave(&p->lock, flags); 121a5a1d1c2SThomas Gleixner ticks = (u64)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32; 122b9dbf951SMagnus Damm ticks |= em_sti_read(p, STI_COUNT_L); 123b9dbf951SMagnus Damm raw_spin_unlock_irqrestore(&p->lock, flags); 124b9dbf951SMagnus Damm 125b9dbf951SMagnus Damm return ticks; 126b9dbf951SMagnus Damm } 127b9dbf951SMagnus Damm 128a5a1d1c2SThomas Gleixner static u64 em_sti_set_next(struct em_sti_priv *p, u64 next) 129b9dbf951SMagnus Damm { 130b9dbf951SMagnus Damm unsigned long flags; 131b9dbf951SMagnus Damm 132b9dbf951SMagnus Damm raw_spin_lock_irqsave(&p->lock, flags); 133b9dbf951SMagnus Damm 134b9dbf951SMagnus Damm /* mask compare A interrupt */ 135b9dbf951SMagnus Damm em_sti_write(p, STI_INTENCLR, 1); 136b9dbf951SMagnus Damm 137b9dbf951SMagnus Damm /* update compare A value */ 138b9dbf951SMagnus Damm em_sti_write(p, STI_COMPA_H, next >> 32); 139b9dbf951SMagnus Damm em_sti_write(p, STI_COMPA_L, next & 0xffffffff); 140b9dbf951SMagnus Damm 141b9dbf951SMagnus Damm /* clear compare A interrupt source */ 142b9dbf951SMagnus Damm em_sti_write(p, STI_INTFFCLR, 1); 143b9dbf951SMagnus Damm 144b9dbf951SMagnus Damm /* unmask compare A interrupt */ 145b9dbf951SMagnus Damm em_sti_write(p, STI_INTENSET, 1); 146b9dbf951SMagnus Damm 147b9dbf951SMagnus Damm raw_spin_unlock_irqrestore(&p->lock, flags); 148b9dbf951SMagnus Damm 149b9dbf951SMagnus Damm return next; 150b9dbf951SMagnus Damm } 151b9dbf951SMagnus Damm 152b9dbf951SMagnus Damm static irqreturn_t em_sti_interrupt(int irq, void *dev_id) 153b9dbf951SMagnus Damm { 154b9dbf951SMagnus Damm struct em_sti_priv *p = dev_id; 155b9dbf951SMagnus Damm 156b9dbf951SMagnus Damm p->ced.event_handler(&p->ced); 157b9dbf951SMagnus Damm return IRQ_HANDLED; 158b9dbf951SMagnus Damm } 159b9dbf951SMagnus Damm 160b9dbf951SMagnus Damm static int em_sti_start(struct em_sti_priv *p, unsigned int user) 161b9dbf951SMagnus Damm { 162b9dbf951SMagnus Damm unsigned long flags; 163b9dbf951SMagnus Damm int used_before; 164b9dbf951SMagnus Damm int ret = 0; 165b9dbf951SMagnus Damm 166b9dbf951SMagnus Damm raw_spin_lock_irqsave(&p->lock, flags); 167b9dbf951SMagnus Damm used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; 168b9dbf951SMagnus Damm if (!used_before) 169b9dbf951SMagnus Damm ret = em_sti_enable(p); 170b9dbf951SMagnus Damm 171b9dbf951SMagnus Damm if (!ret) 172b9dbf951SMagnus Damm p->active[user] = 1; 173b9dbf951SMagnus Damm raw_spin_unlock_irqrestore(&p->lock, flags); 174b9dbf951SMagnus Damm 175b9dbf951SMagnus Damm return ret; 176b9dbf951SMagnus Damm } 177b9dbf951SMagnus Damm 178b9dbf951SMagnus Damm static void em_sti_stop(struct em_sti_priv *p, unsigned int user) 179b9dbf951SMagnus Damm { 180b9dbf951SMagnus Damm unsigned long flags; 181b9dbf951SMagnus Damm int used_before, used_after; 182b9dbf951SMagnus Damm 183b9dbf951SMagnus Damm raw_spin_lock_irqsave(&p->lock, flags); 184b9dbf951SMagnus Damm used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; 185b9dbf951SMagnus Damm p->active[user] = 0; 186b9dbf951SMagnus Damm used_after = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; 187b9dbf951SMagnus Damm 188b9dbf951SMagnus Damm if (used_before && !used_after) 189b9dbf951SMagnus Damm em_sti_disable(p); 190b9dbf951SMagnus Damm raw_spin_unlock_irqrestore(&p->lock, flags); 191b9dbf951SMagnus Damm } 192b9dbf951SMagnus Damm 193b9dbf951SMagnus Damm static struct em_sti_priv *cs_to_em_sti(struct clocksource *cs) 194b9dbf951SMagnus Damm { 195b9dbf951SMagnus Damm return container_of(cs, struct em_sti_priv, cs); 196b9dbf951SMagnus Damm } 197b9dbf951SMagnus Damm 198a5a1d1c2SThomas Gleixner static u64 em_sti_clocksource_read(struct clocksource *cs) 199b9dbf951SMagnus Damm { 200b9dbf951SMagnus Damm return em_sti_count(cs_to_em_sti(cs)); 201b9dbf951SMagnus Damm } 202b9dbf951SMagnus Damm 203b9dbf951SMagnus Damm static int em_sti_clocksource_enable(struct clocksource *cs) 204b9dbf951SMagnus Damm { 205b9dbf951SMagnus Damm struct em_sti_priv *p = cs_to_em_sti(cs); 206b9dbf951SMagnus Damm 207*4e53aa2fSNicolai Stange return em_sti_start(p, USER_CLOCKSOURCE); 208b9dbf951SMagnus Damm } 209b9dbf951SMagnus Damm 210b9dbf951SMagnus Damm static void em_sti_clocksource_disable(struct clocksource *cs) 211b9dbf951SMagnus Damm { 212b9dbf951SMagnus Damm em_sti_stop(cs_to_em_sti(cs), USER_CLOCKSOURCE); 213b9dbf951SMagnus Damm } 214b9dbf951SMagnus Damm 215b9dbf951SMagnus Damm static void em_sti_clocksource_resume(struct clocksource *cs) 216b9dbf951SMagnus Damm { 217b9dbf951SMagnus Damm em_sti_clocksource_enable(cs); 218b9dbf951SMagnus Damm } 219b9dbf951SMagnus Damm 220b9dbf951SMagnus Damm static int em_sti_register_clocksource(struct em_sti_priv *p) 221b9dbf951SMagnus Damm { 222b9dbf951SMagnus Damm struct clocksource *cs = &p->cs; 223b9dbf951SMagnus Damm 224b9dbf951SMagnus Damm cs->name = dev_name(&p->pdev->dev); 225b9dbf951SMagnus Damm cs->rating = 200; 226b9dbf951SMagnus Damm cs->read = em_sti_clocksource_read; 227b9dbf951SMagnus Damm cs->enable = em_sti_clocksource_enable; 228b9dbf951SMagnus Damm cs->disable = em_sti_clocksource_disable; 229b9dbf951SMagnus Damm cs->suspend = em_sti_clocksource_disable; 230b9dbf951SMagnus Damm cs->resume = em_sti_clocksource_resume; 231b9dbf951SMagnus Damm cs->mask = CLOCKSOURCE_MASK(48); 232b9dbf951SMagnus Damm cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 233b9dbf951SMagnus Damm 234b9dbf951SMagnus Damm dev_info(&p->pdev->dev, "used as clock source\n"); 235b9dbf951SMagnus Damm 236*4e53aa2fSNicolai Stange clocksource_register_hz(cs, p->rate); 237b9dbf951SMagnus Damm return 0; 238b9dbf951SMagnus Damm } 239b9dbf951SMagnus Damm 240b9dbf951SMagnus Damm static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced) 241b9dbf951SMagnus Damm { 242b9dbf951SMagnus Damm return container_of(ced, struct em_sti_priv, ced); 243b9dbf951SMagnus Damm } 244b9dbf951SMagnus Damm 24575f94061SViresh Kumar static int em_sti_clock_event_shutdown(struct clock_event_device *ced) 24675f94061SViresh Kumar { 24775f94061SViresh Kumar struct em_sti_priv *p = ced_to_em_sti(ced); 24875f94061SViresh Kumar em_sti_stop(p, USER_CLOCKEVENT); 24975f94061SViresh Kumar return 0; 25075f94061SViresh Kumar } 25175f94061SViresh Kumar 25275f94061SViresh Kumar static int em_sti_clock_event_set_oneshot(struct clock_event_device *ced) 253b9dbf951SMagnus Damm { 254b9dbf951SMagnus Damm struct em_sti_priv *p = ced_to_em_sti(ced); 255b9dbf951SMagnus Damm 256b9dbf951SMagnus Damm dev_info(&p->pdev->dev, "used for oneshot clock events\n"); 257b9dbf951SMagnus Damm em_sti_start(p, USER_CLOCKEVENT); 25875f94061SViresh Kumar return 0; 259b9dbf951SMagnus Damm } 260b9dbf951SMagnus Damm 261b9dbf951SMagnus Damm static int em_sti_clock_event_next(unsigned long delta, 262b9dbf951SMagnus Damm struct clock_event_device *ced) 263b9dbf951SMagnus Damm { 264b9dbf951SMagnus Damm struct em_sti_priv *p = ced_to_em_sti(ced); 265a5a1d1c2SThomas Gleixner u64 next; 266b9dbf951SMagnus Damm int safe; 267b9dbf951SMagnus Damm 268b9dbf951SMagnus Damm next = em_sti_set_next(p, em_sti_count(p) + delta); 269b9dbf951SMagnus Damm safe = em_sti_count(p) < (next - 1); 270b9dbf951SMagnus Damm 271b9dbf951SMagnus Damm return !safe; 272b9dbf951SMagnus Damm } 273b9dbf951SMagnus Damm 274b9dbf951SMagnus Damm static void em_sti_register_clockevent(struct em_sti_priv *p) 275b9dbf951SMagnus Damm { 276b9dbf951SMagnus Damm struct clock_event_device *ced = &p->ced; 277b9dbf951SMagnus Damm 278b9dbf951SMagnus Damm ced->name = dev_name(&p->pdev->dev); 279b9dbf951SMagnus Damm ced->features = CLOCK_EVT_FEAT_ONESHOT; 280b9dbf951SMagnus Damm ced->rating = 200; 2812199a557SMagnus Damm ced->cpumask = cpu_possible_mask; 282b9dbf951SMagnus Damm ced->set_next_event = em_sti_clock_event_next; 28375f94061SViresh Kumar ced->set_state_shutdown = em_sti_clock_event_shutdown; 28475f94061SViresh Kumar ced->set_state_oneshot = em_sti_clock_event_set_oneshot; 285b9dbf951SMagnus Damm 286b9dbf951SMagnus Damm dev_info(&p->pdev->dev, "used for clock events\n"); 287b9dbf951SMagnus Damm 288*4e53aa2fSNicolai Stange clockevents_config_and_register(ced, p->rate, 2, 0xffffffff); 289b9dbf951SMagnus Damm } 290b9dbf951SMagnus Damm 2911850514bSGreg Kroah-Hartman static int em_sti_probe(struct platform_device *pdev) 292b9dbf951SMagnus Damm { 293b9dbf951SMagnus Damm struct em_sti_priv *p; 294b9dbf951SMagnus Damm struct resource *res; 2951745e696SLaurent Pinchart int irq; 2963814ae09SNicolai Stange int ret; 297b9dbf951SMagnus Damm 2981745e696SLaurent Pinchart p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); 29939dd5677SJingoo Han if (p == NULL) 3001745e696SLaurent Pinchart return -ENOMEM; 301b9dbf951SMagnus Damm 302b9dbf951SMagnus Damm p->pdev = pdev; 303b9dbf951SMagnus Damm platform_set_drvdata(pdev, p); 304b9dbf951SMagnus Damm 305b9dbf951SMagnus Damm irq = platform_get_irq(pdev, 0); 306b9dbf951SMagnus Damm if (irq < 0) { 307b9dbf951SMagnus Damm dev_err(&pdev->dev, "failed to get irq\n"); 3081745e696SLaurent Pinchart return -EINVAL; 309b9dbf951SMagnus Damm } 310b9dbf951SMagnus Damm 311b9dbf951SMagnus Damm /* map memory, let base point to the STI instance */ 3121745e696SLaurent Pinchart res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 3131745e696SLaurent Pinchart p->base = devm_ioremap_resource(&pdev->dev, res); 3141745e696SLaurent Pinchart if (IS_ERR(p->base)) 3151745e696SLaurent Pinchart return PTR_ERR(p->base); 316b9dbf951SMagnus Damm 3173814ae09SNicolai Stange if (devm_request_irq(&pdev->dev, irq, em_sti_interrupt, 3183814ae09SNicolai Stange IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, 3193814ae09SNicolai Stange dev_name(&pdev->dev), p)) { 3203814ae09SNicolai Stange dev_err(&pdev->dev, "failed to request low IRQ\n"); 3213814ae09SNicolai Stange return -ENOENT; 3223814ae09SNicolai Stange } 3233814ae09SNicolai Stange 324b9dbf951SMagnus Damm /* get hold of clock */ 3251745e696SLaurent Pinchart p->clk = devm_clk_get(&pdev->dev, "sclk"); 326b9dbf951SMagnus Damm if (IS_ERR(p->clk)) { 327b9dbf951SMagnus Damm dev_err(&pdev->dev, "cannot get clock\n"); 3281745e696SLaurent Pinchart return PTR_ERR(p->clk); 329b9dbf951SMagnus Damm } 330b9dbf951SMagnus Damm 3313814ae09SNicolai Stange ret = clk_prepare(p->clk); 3323814ae09SNicolai Stange if (ret < 0) { 3333814ae09SNicolai Stange dev_err(&pdev->dev, "cannot prepare clock\n"); 3343814ae09SNicolai Stange return ret; 335b9dbf951SMagnus Damm } 336b9dbf951SMagnus Damm 337*4e53aa2fSNicolai Stange ret = clk_enable(p->clk); 338*4e53aa2fSNicolai Stange if (ret < 0) { 339*4e53aa2fSNicolai Stange dev_err(&p->pdev->dev, "cannot enable clock\n"); 340*4e53aa2fSNicolai Stange clk_unprepare(p->clk); 341*4e53aa2fSNicolai Stange return ret; 342*4e53aa2fSNicolai Stange } 343*4e53aa2fSNicolai Stange p->rate = clk_get_rate(p->clk); 344*4e53aa2fSNicolai Stange clk_disable(p->clk); 345*4e53aa2fSNicolai Stange 346b9dbf951SMagnus Damm raw_spin_lock_init(&p->lock); 347b9dbf951SMagnus Damm em_sti_register_clockevent(p); 348b9dbf951SMagnus Damm em_sti_register_clocksource(p); 349b9dbf951SMagnus Damm return 0; 350b9dbf951SMagnus Damm } 351b9dbf951SMagnus Damm 3521850514bSGreg Kroah-Hartman static int em_sti_remove(struct platform_device *pdev) 353b9dbf951SMagnus Damm { 354b9dbf951SMagnus Damm return -EBUSY; /* cannot unregister clockevent and clocksource */ 355b9dbf951SMagnus Damm } 356b9dbf951SMagnus Damm 3571850514bSGreg Kroah-Hartman static const struct of_device_id em_sti_dt_ids[] = { 358fc0830feSMagnus Damm { .compatible = "renesas,em-sti", }, 359fc0830feSMagnus Damm {}, 360fc0830feSMagnus Damm }; 361fc0830feSMagnus Damm MODULE_DEVICE_TABLE(of, em_sti_dt_ids); 362fc0830feSMagnus Damm 363b9dbf951SMagnus Damm static struct platform_driver em_sti_device_driver = { 364b9dbf951SMagnus Damm .probe = em_sti_probe, 3651850514bSGreg Kroah-Hartman .remove = em_sti_remove, 366b9dbf951SMagnus Damm .driver = { 367b9dbf951SMagnus Damm .name = "em_sti", 368fc0830feSMagnus Damm .of_match_table = em_sti_dt_ids, 369b9dbf951SMagnus Damm } 370b9dbf951SMagnus Damm }; 371b9dbf951SMagnus Damm 37209acc3a1SSimon Horman static int __init em_sti_init(void) 37309acc3a1SSimon Horman { 37409acc3a1SSimon Horman return platform_driver_register(&em_sti_device_driver); 37509acc3a1SSimon Horman } 37609acc3a1SSimon Horman 37709acc3a1SSimon Horman static void __exit em_sti_exit(void) 37809acc3a1SSimon Horman { 37909acc3a1SSimon Horman platform_driver_unregister(&em_sti_device_driver); 38009acc3a1SSimon Horman } 38109acc3a1SSimon Horman 38209acc3a1SSimon Horman subsys_initcall(em_sti_init); 38309acc3a1SSimon Horman module_exit(em_sti_exit); 384b9dbf951SMagnus Damm 385b9dbf951SMagnus Damm MODULE_AUTHOR("Magnus Damm"); 386b9dbf951SMagnus Damm MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); 387b9dbf951SMagnus Damm MODULE_LICENSE("GPL v2"); 388