1*e842f1c8SRichard Purdie /* 2*e842f1c8SRichard Purdie * Real Time Clock interface for StrongARM SA1x00 and XScale PXA2xx 3*e842f1c8SRichard Purdie * 4*e842f1c8SRichard Purdie * Copyright (c) 2000 Nils Faerber 5*e842f1c8SRichard Purdie * 6*e842f1c8SRichard Purdie * Based on rtc.c by Paul Gortmaker 7*e842f1c8SRichard Purdie * 8*e842f1c8SRichard Purdie * Original Driver by Nils Faerber <nils@kernelconcepts.de> 9*e842f1c8SRichard Purdie * 10*e842f1c8SRichard Purdie * Modifications from: 11*e842f1c8SRichard Purdie * CIH <cih@coventive.com> 12*e842f1c8SRichard Purdie * Nicolas Pitre <nico@cam.org> 13*e842f1c8SRichard Purdie * Andrew Christian <andrew.christian@hp.com> 14*e842f1c8SRichard Purdie * 15*e842f1c8SRichard Purdie * Converted to the RTC subsystem and Driver Model 16*e842f1c8SRichard Purdie * by Richard Purdie <rpurdie@rpsys.net> 17*e842f1c8SRichard Purdie * 18*e842f1c8SRichard Purdie * This program is free software; you can redistribute it and/or 19*e842f1c8SRichard Purdie * modify it under the terms of the GNU General Public License 20*e842f1c8SRichard Purdie * as published by the Free Software Foundation; either version 21*e842f1c8SRichard Purdie * 2 of the License, or (at your option) any later version. 22*e842f1c8SRichard Purdie */ 23*e842f1c8SRichard Purdie 24*e842f1c8SRichard Purdie #include <linux/platform_device.h> 25*e842f1c8SRichard Purdie #include <linux/module.h> 26*e842f1c8SRichard Purdie #include <linux/rtc.h> 27*e842f1c8SRichard Purdie #include <linux/init.h> 28*e842f1c8SRichard Purdie #include <linux/fs.h> 29*e842f1c8SRichard Purdie #include <linux/interrupt.h> 30*e842f1c8SRichard Purdie #include <linux/string.h> 31*e842f1c8SRichard Purdie #include <linux/pm.h> 32*e842f1c8SRichard Purdie 33*e842f1c8SRichard Purdie #include <asm/bitops.h> 34*e842f1c8SRichard Purdie #include <asm/hardware.h> 35*e842f1c8SRichard Purdie #include <asm/irq.h> 36*e842f1c8SRichard Purdie #include <asm/rtc.h> 37*e842f1c8SRichard Purdie 38*e842f1c8SRichard Purdie #ifdef CONFIG_ARCH_PXA 39*e842f1c8SRichard Purdie #include <asm/arch/pxa-regs.h> 40*e842f1c8SRichard Purdie #endif 41*e842f1c8SRichard Purdie 42*e842f1c8SRichard Purdie #define TIMER_FREQ CLOCK_TICK_RATE 43*e842f1c8SRichard Purdie #define RTC_DEF_DIVIDER 32768 - 1 44*e842f1c8SRichard Purdie #define RTC_DEF_TRIM 0 45*e842f1c8SRichard Purdie 46*e842f1c8SRichard Purdie static unsigned long rtc_freq = 1024; 47*e842f1c8SRichard Purdie static struct rtc_time rtc_alarm; 48*e842f1c8SRichard Purdie static spinlock_t sa1100_rtc_lock = SPIN_LOCK_UNLOCKED; 49*e842f1c8SRichard Purdie 50*e842f1c8SRichard Purdie static int rtc_update_alarm(struct rtc_time *alrm) 51*e842f1c8SRichard Purdie { 52*e842f1c8SRichard Purdie struct rtc_time alarm_tm, now_tm; 53*e842f1c8SRichard Purdie unsigned long now, time; 54*e842f1c8SRichard Purdie int ret; 55*e842f1c8SRichard Purdie 56*e842f1c8SRichard Purdie do { 57*e842f1c8SRichard Purdie now = RCNR; 58*e842f1c8SRichard Purdie rtc_time_to_tm(now, &now_tm); 59*e842f1c8SRichard Purdie rtc_next_alarm_time(&alarm_tm, &now_tm, alrm); 60*e842f1c8SRichard Purdie ret = rtc_tm_to_time(&alarm_tm, &time); 61*e842f1c8SRichard Purdie if (ret != 0) 62*e842f1c8SRichard Purdie break; 63*e842f1c8SRichard Purdie 64*e842f1c8SRichard Purdie RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); 65*e842f1c8SRichard Purdie RTAR = time; 66*e842f1c8SRichard Purdie } while (now != RCNR); 67*e842f1c8SRichard Purdie 68*e842f1c8SRichard Purdie return ret; 69*e842f1c8SRichard Purdie } 70*e842f1c8SRichard Purdie 71*e842f1c8SRichard Purdie static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id, 72*e842f1c8SRichard Purdie struct pt_regs *regs) 73*e842f1c8SRichard Purdie { 74*e842f1c8SRichard Purdie struct platform_device *pdev = to_platform_device(dev_id); 75*e842f1c8SRichard Purdie struct rtc_device *rtc = platform_get_drvdata(pdev); 76*e842f1c8SRichard Purdie unsigned int rtsr; 77*e842f1c8SRichard Purdie unsigned long events = 0; 78*e842f1c8SRichard Purdie 79*e842f1c8SRichard Purdie spin_lock(&sa1100_rtc_lock); 80*e842f1c8SRichard Purdie 81*e842f1c8SRichard Purdie rtsr = RTSR; 82*e842f1c8SRichard Purdie /* clear interrupt sources */ 83*e842f1c8SRichard Purdie RTSR = 0; 84*e842f1c8SRichard Purdie RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); 85*e842f1c8SRichard Purdie 86*e842f1c8SRichard Purdie /* clear alarm interrupt if it has occurred */ 87*e842f1c8SRichard Purdie if (rtsr & RTSR_AL) 88*e842f1c8SRichard Purdie rtsr &= ~RTSR_ALE; 89*e842f1c8SRichard Purdie RTSR = rtsr & (RTSR_ALE | RTSR_HZE); 90*e842f1c8SRichard Purdie 91*e842f1c8SRichard Purdie /* update irq data & counter */ 92*e842f1c8SRichard Purdie if (rtsr & RTSR_AL) 93*e842f1c8SRichard Purdie events |= RTC_AF | RTC_IRQF; 94*e842f1c8SRichard Purdie if (rtsr & RTSR_HZ) 95*e842f1c8SRichard Purdie events |= RTC_UF | RTC_IRQF; 96*e842f1c8SRichard Purdie 97*e842f1c8SRichard Purdie rtc_update_irq(&rtc->class_dev, 1, events); 98*e842f1c8SRichard Purdie 99*e842f1c8SRichard Purdie if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) 100*e842f1c8SRichard Purdie rtc_update_alarm(&rtc_alarm); 101*e842f1c8SRichard Purdie 102*e842f1c8SRichard Purdie spin_unlock(&sa1100_rtc_lock); 103*e842f1c8SRichard Purdie 104*e842f1c8SRichard Purdie return IRQ_HANDLED; 105*e842f1c8SRichard Purdie } 106*e842f1c8SRichard Purdie 107*e842f1c8SRichard Purdie static int rtc_timer1_count; 108*e842f1c8SRichard Purdie 109*e842f1c8SRichard Purdie static irqreturn_t timer1_interrupt(int irq, void *dev_id, 110*e842f1c8SRichard Purdie struct pt_regs *regs) 111*e842f1c8SRichard Purdie { 112*e842f1c8SRichard Purdie struct platform_device *pdev = to_platform_device(dev_id); 113*e842f1c8SRichard Purdie struct rtc_device *rtc = platform_get_drvdata(pdev); 114*e842f1c8SRichard Purdie 115*e842f1c8SRichard Purdie /* 116*e842f1c8SRichard Purdie * If we match for the first time, rtc_timer1_count will be 1. 117*e842f1c8SRichard Purdie * Otherwise, we wrapped around (very unlikely but 118*e842f1c8SRichard Purdie * still possible) so compute the amount of missed periods. 119*e842f1c8SRichard Purdie * The match reg is updated only when the data is actually retrieved 120*e842f1c8SRichard Purdie * to avoid unnecessary interrupts. 121*e842f1c8SRichard Purdie */ 122*e842f1c8SRichard Purdie OSSR = OSSR_M1; /* clear match on timer1 */ 123*e842f1c8SRichard Purdie 124*e842f1c8SRichard Purdie rtc_update_irq(&rtc->class_dev, rtc_timer1_count, RTC_PF | RTC_IRQF); 125*e842f1c8SRichard Purdie 126*e842f1c8SRichard Purdie if (rtc_timer1_count == 1) 127*e842f1c8SRichard Purdie rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))); 128*e842f1c8SRichard Purdie 129*e842f1c8SRichard Purdie return IRQ_HANDLED; 130*e842f1c8SRichard Purdie } 131*e842f1c8SRichard Purdie 132*e842f1c8SRichard Purdie static int sa1100_rtc_read_callback(struct device *dev, int data) 133*e842f1c8SRichard Purdie { 134*e842f1c8SRichard Purdie if (data & RTC_PF) { 135*e842f1c8SRichard Purdie /* interpolate missed periods and set match for the next */ 136*e842f1c8SRichard Purdie unsigned long period = TIMER_FREQ/rtc_freq; 137*e842f1c8SRichard Purdie unsigned long oscr = OSCR; 138*e842f1c8SRichard Purdie unsigned long osmr1 = OSMR1; 139*e842f1c8SRichard Purdie unsigned long missed = (oscr - osmr1)/period; 140*e842f1c8SRichard Purdie data += missed << 8; 141*e842f1c8SRichard Purdie OSSR = OSSR_M1; /* clear match on timer 1 */ 142*e842f1c8SRichard Purdie OSMR1 = osmr1 + (missed + 1)*period; 143*e842f1c8SRichard Purdie /* Ensure we didn't miss another match in the mean time. 144*e842f1c8SRichard Purdie * Here we compare (match - OSCR) 8 instead of 0 -- 145*e842f1c8SRichard Purdie * see comment in pxa_timer_interrupt() for explanation. 146*e842f1c8SRichard Purdie */ 147*e842f1c8SRichard Purdie while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) { 148*e842f1c8SRichard Purdie data += 0x100; 149*e842f1c8SRichard Purdie OSSR = OSSR_M1; /* clear match on timer 1 */ 150*e842f1c8SRichard Purdie OSMR1 = osmr1 + period; 151*e842f1c8SRichard Purdie } 152*e842f1c8SRichard Purdie } 153*e842f1c8SRichard Purdie return data; 154*e842f1c8SRichard Purdie } 155*e842f1c8SRichard Purdie 156*e842f1c8SRichard Purdie static int sa1100_rtc_open(struct device *dev) 157*e842f1c8SRichard Purdie { 158*e842f1c8SRichard Purdie int ret; 159*e842f1c8SRichard Purdie 160*e842f1c8SRichard Purdie ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT, 161*e842f1c8SRichard Purdie "rtc 1Hz", dev); 162*e842f1c8SRichard Purdie if (ret) { 163*e842f1c8SRichard Purdie printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz); 164*e842f1c8SRichard Purdie goto fail_ui; 165*e842f1c8SRichard Purdie } 166*e842f1c8SRichard Purdie ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT, 167*e842f1c8SRichard Purdie "rtc Alrm", dev); 168*e842f1c8SRichard Purdie if (ret) { 169*e842f1c8SRichard Purdie printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm); 170*e842f1c8SRichard Purdie goto fail_ai; 171*e842f1c8SRichard Purdie } 172*e842f1c8SRichard Purdie ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT, 173*e842f1c8SRichard Purdie "rtc timer", dev); 174*e842f1c8SRichard Purdie if (ret) { 175*e842f1c8SRichard Purdie printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1); 176*e842f1c8SRichard Purdie goto fail_pi; 177*e842f1c8SRichard Purdie } 178*e842f1c8SRichard Purdie return 0; 179*e842f1c8SRichard Purdie 180*e842f1c8SRichard Purdie fail_pi: 181*e842f1c8SRichard Purdie free_irq(IRQ_RTCAlrm, NULL); 182*e842f1c8SRichard Purdie fail_ai: 183*e842f1c8SRichard Purdie free_irq(IRQ_RTC1Hz, NULL); 184*e842f1c8SRichard Purdie fail_ui: 185*e842f1c8SRichard Purdie return ret; 186*e842f1c8SRichard Purdie } 187*e842f1c8SRichard Purdie 188*e842f1c8SRichard Purdie static void sa1100_rtc_release(struct device *dev) 189*e842f1c8SRichard Purdie { 190*e842f1c8SRichard Purdie spin_lock_irq(&sa1100_rtc_lock); 191*e842f1c8SRichard Purdie RTSR = 0; 192*e842f1c8SRichard Purdie OIER &= ~OIER_E1; 193*e842f1c8SRichard Purdie OSSR = OSSR_M1; 194*e842f1c8SRichard Purdie spin_unlock_irq(&sa1100_rtc_lock); 195*e842f1c8SRichard Purdie 196*e842f1c8SRichard Purdie free_irq(IRQ_OST1, dev); 197*e842f1c8SRichard Purdie free_irq(IRQ_RTCAlrm, dev); 198*e842f1c8SRichard Purdie free_irq(IRQ_RTC1Hz, dev); 199*e842f1c8SRichard Purdie } 200*e842f1c8SRichard Purdie 201*e842f1c8SRichard Purdie 202*e842f1c8SRichard Purdie static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, 203*e842f1c8SRichard Purdie unsigned long arg) 204*e842f1c8SRichard Purdie { 205*e842f1c8SRichard Purdie switch(cmd) { 206*e842f1c8SRichard Purdie case RTC_AIE_OFF: 207*e842f1c8SRichard Purdie spin_lock_irq(&sa1100_rtc_lock); 208*e842f1c8SRichard Purdie RTSR &= ~RTSR_ALE; 209*e842f1c8SRichard Purdie spin_unlock_irq(&sa1100_rtc_lock); 210*e842f1c8SRichard Purdie return 0; 211*e842f1c8SRichard Purdie case RTC_AIE_ON: 212*e842f1c8SRichard Purdie spin_lock_irq(&sa1100_rtc_lock); 213*e842f1c8SRichard Purdie RTSR |= RTSR_ALE; 214*e842f1c8SRichard Purdie spin_unlock_irq(&sa1100_rtc_lock); 215*e842f1c8SRichard Purdie return 0; 216*e842f1c8SRichard Purdie case RTC_UIE_OFF: 217*e842f1c8SRichard Purdie spin_lock_irq(&sa1100_rtc_lock); 218*e842f1c8SRichard Purdie RTSR &= ~RTSR_HZE; 219*e842f1c8SRichard Purdie spin_unlock_irq(&sa1100_rtc_lock); 220*e842f1c8SRichard Purdie return 0; 221*e842f1c8SRichard Purdie case RTC_UIE_ON: 222*e842f1c8SRichard Purdie spin_lock_irq(&sa1100_rtc_lock); 223*e842f1c8SRichard Purdie RTSR |= RTSR_HZE; 224*e842f1c8SRichard Purdie spin_unlock_irq(&sa1100_rtc_lock); 225*e842f1c8SRichard Purdie return 0; 226*e842f1c8SRichard Purdie case RTC_PIE_OFF: 227*e842f1c8SRichard Purdie spin_lock_irq(&sa1100_rtc_lock); 228*e842f1c8SRichard Purdie OIER &= ~OIER_E1; 229*e842f1c8SRichard Purdie spin_unlock_irq(&sa1100_rtc_lock); 230*e842f1c8SRichard Purdie return 0; 231*e842f1c8SRichard Purdie case RTC_PIE_ON: 232*e842f1c8SRichard Purdie if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE)) 233*e842f1c8SRichard Purdie return -EACCES; 234*e842f1c8SRichard Purdie spin_lock_irq(&sa1100_rtc_lock); 235*e842f1c8SRichard Purdie OSMR1 = TIMER_FREQ/rtc_freq + OSCR; 236*e842f1c8SRichard Purdie OIER |= OIER_E1; 237*e842f1c8SRichard Purdie rtc_timer1_count = 1; 238*e842f1c8SRichard Purdie spin_unlock_irq(&sa1100_rtc_lock); 239*e842f1c8SRichard Purdie return 0; 240*e842f1c8SRichard Purdie case RTC_IRQP_READ: 241*e842f1c8SRichard Purdie return put_user(rtc_freq, (unsigned long *)arg); 242*e842f1c8SRichard Purdie case RTC_IRQP_SET: 243*e842f1c8SRichard Purdie if (arg < 1 || arg > TIMER_FREQ) 244*e842f1c8SRichard Purdie return -EINVAL; 245*e842f1c8SRichard Purdie if ((arg > 64) && (!capable(CAP_SYS_RESOURCE))) 246*e842f1c8SRichard Purdie return -EACCES; 247*e842f1c8SRichard Purdie rtc_freq = arg; 248*e842f1c8SRichard Purdie return 0; 249*e842f1c8SRichard Purdie } 250*e842f1c8SRichard Purdie return -EINVAL; 251*e842f1c8SRichard Purdie } 252*e842f1c8SRichard Purdie 253*e842f1c8SRichard Purdie static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) 254*e842f1c8SRichard Purdie { 255*e842f1c8SRichard Purdie rtc_time_to_tm(RCNR, tm); 256*e842f1c8SRichard Purdie return 0; 257*e842f1c8SRichard Purdie } 258*e842f1c8SRichard Purdie 259*e842f1c8SRichard Purdie static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) 260*e842f1c8SRichard Purdie { 261*e842f1c8SRichard Purdie unsigned long time; 262*e842f1c8SRichard Purdie int ret; 263*e842f1c8SRichard Purdie 264*e842f1c8SRichard Purdie ret = rtc_tm_to_time(tm, &time); 265*e842f1c8SRichard Purdie if (ret == 0) 266*e842f1c8SRichard Purdie RCNR = time; 267*e842f1c8SRichard Purdie return ret; 268*e842f1c8SRichard Purdie } 269*e842f1c8SRichard Purdie 270*e842f1c8SRichard Purdie static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 271*e842f1c8SRichard Purdie { 272*e842f1c8SRichard Purdie memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); 273*e842f1c8SRichard Purdie alrm->pending = RTSR & RTSR_AL ? 1 : 0; 274*e842f1c8SRichard Purdie return 0; 275*e842f1c8SRichard Purdie } 276*e842f1c8SRichard Purdie 277*e842f1c8SRichard Purdie static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 278*e842f1c8SRichard Purdie { 279*e842f1c8SRichard Purdie int ret; 280*e842f1c8SRichard Purdie 281*e842f1c8SRichard Purdie spin_lock_irq(&sa1100_rtc_lock); 282*e842f1c8SRichard Purdie ret = rtc_update_alarm(&alrm->time); 283*e842f1c8SRichard Purdie if (ret == 0) { 284*e842f1c8SRichard Purdie memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time)); 285*e842f1c8SRichard Purdie 286*e842f1c8SRichard Purdie if (alrm->enabled) 287*e842f1c8SRichard Purdie enable_irq_wake(IRQ_RTCAlrm); 288*e842f1c8SRichard Purdie else 289*e842f1c8SRichard Purdie disable_irq_wake(IRQ_RTCAlrm); 290*e842f1c8SRichard Purdie } 291*e842f1c8SRichard Purdie spin_unlock_irq(&sa1100_rtc_lock); 292*e842f1c8SRichard Purdie 293*e842f1c8SRichard Purdie return ret; 294*e842f1c8SRichard Purdie } 295*e842f1c8SRichard Purdie 296*e842f1c8SRichard Purdie static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) 297*e842f1c8SRichard Purdie { 298*e842f1c8SRichard Purdie seq_printf(seq, "trim/divider\t: 0x%08x\n", RTTR); 299*e842f1c8SRichard Purdie seq_printf(seq, "alarm_IRQ\t: %s\n", 300*e842f1c8SRichard Purdie (RTSR & RTSR_ALE) ? "yes" : "no" ); 301*e842f1c8SRichard Purdie seq_printf(seq, "update_IRQ\t: %s\n", 302*e842f1c8SRichard Purdie (RTSR & RTSR_HZE) ? "yes" : "no"); 303*e842f1c8SRichard Purdie seq_printf(seq, "periodic_IRQ\t: %s\n", 304*e842f1c8SRichard Purdie (OIER & OIER_E1) ? "yes" : "no"); 305*e842f1c8SRichard Purdie seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq); 306*e842f1c8SRichard Purdie 307*e842f1c8SRichard Purdie return 0; 308*e842f1c8SRichard Purdie } 309*e842f1c8SRichard Purdie 310*e842f1c8SRichard Purdie static struct rtc_class_ops sa1100_rtc_ops = { 311*e842f1c8SRichard Purdie .open = sa1100_rtc_open, 312*e842f1c8SRichard Purdie .read_callback = sa1100_rtc_read_callback, 313*e842f1c8SRichard Purdie .release = sa1100_rtc_release, 314*e842f1c8SRichard Purdie .ioctl = sa1100_rtc_ioctl, 315*e842f1c8SRichard Purdie .read_time = sa1100_rtc_read_time, 316*e842f1c8SRichard Purdie .set_time = sa1100_rtc_set_time, 317*e842f1c8SRichard Purdie .read_alarm = sa1100_rtc_read_alarm, 318*e842f1c8SRichard Purdie .set_alarm = sa1100_rtc_set_alarm, 319*e842f1c8SRichard Purdie .proc = sa1100_rtc_proc, 320*e842f1c8SRichard Purdie }; 321*e842f1c8SRichard Purdie 322*e842f1c8SRichard Purdie static int sa1100_rtc_probe(struct platform_device *pdev) 323*e842f1c8SRichard Purdie { 324*e842f1c8SRichard Purdie struct rtc_device *rtc; 325*e842f1c8SRichard Purdie 326*e842f1c8SRichard Purdie /* 327*e842f1c8SRichard Purdie * According to the manual we should be able to let RTTR be zero 328*e842f1c8SRichard Purdie * and then a default diviser for a 32.768KHz clock is used. 329*e842f1c8SRichard Purdie * Apparently this doesn't work, at least for my SA1110 rev 5. 330*e842f1c8SRichard Purdie * If the clock divider is uninitialized then reset it to the 331*e842f1c8SRichard Purdie * default value to get the 1Hz clock. 332*e842f1c8SRichard Purdie */ 333*e842f1c8SRichard Purdie if (RTTR == 0) { 334*e842f1c8SRichard Purdie RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); 335*e842f1c8SRichard Purdie printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n"); 336*e842f1c8SRichard Purdie /* The current RTC value probably doesn't make sense either */ 337*e842f1c8SRichard Purdie RCNR = 0; 338*e842f1c8SRichard Purdie } 339*e842f1c8SRichard Purdie 340*e842f1c8SRichard Purdie rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, 341*e842f1c8SRichard Purdie THIS_MODULE); 342*e842f1c8SRichard Purdie 343*e842f1c8SRichard Purdie if (IS_ERR(rtc)) { 344*e842f1c8SRichard Purdie dev_err(&pdev->dev, "Unable to register the RTC device\n"); 345*e842f1c8SRichard Purdie return PTR_ERR(rtc); 346*e842f1c8SRichard Purdie } 347*e842f1c8SRichard Purdie 348*e842f1c8SRichard Purdie platform_set_drvdata(pdev, rtc); 349*e842f1c8SRichard Purdie 350*e842f1c8SRichard Purdie dev_info(&pdev->dev, "SA11xx/PXA2xx RTC Registered\n"); 351*e842f1c8SRichard Purdie 352*e842f1c8SRichard Purdie return 0; 353*e842f1c8SRichard Purdie } 354*e842f1c8SRichard Purdie 355*e842f1c8SRichard Purdie static int sa1100_rtc_remove(struct platform_device *pdev) 356*e842f1c8SRichard Purdie { 357*e842f1c8SRichard Purdie struct rtc_device *rtc = platform_get_drvdata(pdev); 358*e842f1c8SRichard Purdie 359*e842f1c8SRichard Purdie if (rtc) 360*e842f1c8SRichard Purdie rtc_device_unregister(rtc); 361*e842f1c8SRichard Purdie 362*e842f1c8SRichard Purdie return 0; 363*e842f1c8SRichard Purdie } 364*e842f1c8SRichard Purdie 365*e842f1c8SRichard Purdie static struct platform_driver sa1100_rtc_driver = { 366*e842f1c8SRichard Purdie .probe = sa1100_rtc_probe, 367*e842f1c8SRichard Purdie .remove = sa1100_rtc_remove, 368*e842f1c8SRichard Purdie .driver = { 369*e842f1c8SRichard Purdie .name = "sa1100-rtc", 370*e842f1c8SRichard Purdie }, 371*e842f1c8SRichard Purdie }; 372*e842f1c8SRichard Purdie 373*e842f1c8SRichard Purdie static int __init sa1100_rtc_init(void) 374*e842f1c8SRichard Purdie { 375*e842f1c8SRichard Purdie return platform_driver_register(&sa1100_rtc_driver); 376*e842f1c8SRichard Purdie } 377*e842f1c8SRichard Purdie 378*e842f1c8SRichard Purdie static void __exit sa1100_rtc_exit(void) 379*e842f1c8SRichard Purdie { 380*e842f1c8SRichard Purdie platform_driver_unregister(&sa1100_rtc_driver); 381*e842f1c8SRichard Purdie } 382*e842f1c8SRichard Purdie 383*e842f1c8SRichard Purdie module_init(sa1100_rtc_init); 384*e842f1c8SRichard Purdie module_exit(sa1100_rtc_exit); 385*e842f1c8SRichard Purdie 386*e842f1c8SRichard Purdie MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); 387*e842f1c8SRichard Purdie MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)"); 388*e842f1c8SRichard Purdie MODULE_LICENSE("GPL"); 389