diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 19 | ||||
| -rw-r--r-- | drivers/rtc/Makefile | 2 | ||||
| -rw-r--r-- | drivers/rtc/interface.c | 10 | ||||
| -rw-r--r-- | drivers/rtc/rtc-at91rm9200.c | 18 | ||||
| -rw-r--r-- | drivers/rtc/rtc-at91sam9.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-bfin.c | 105 | ||||
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 294 | ||||
| -rw-r--r-- | drivers/rtc/rtc-dev.c | 72 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1305.c | 847 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ep93xx.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-isl1208.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-m41t80.c | 20 | ||||
| -rw-r--r-- | drivers/rtc/rtc-m41t94.c | 173 | ||||
| -rw-r--r-- | drivers/rtc/rtc-omap.c | 21 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf8583.c | 129 | ||||
| -rw-r--r-- | drivers/rtc/rtc-s3c.c | 91 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sa1100.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-vr41xx.c | 65 |
18 files changed, 1439 insertions, 439 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index fc85bf2e4a97..90ab73825401 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -273,6 +273,25 @@ comment "SPI RTC drivers" | |||
| 273 | 273 | ||
| 274 | if SPI_MASTER | 274 | if SPI_MASTER |
| 275 | 275 | ||
| 276 | config RTC_DRV_M41T94 | ||
| 277 | tristate "ST M41T94" | ||
| 278 | help | ||
| 279 | If you say yes here you will get support for the | ||
| 280 | ST M41T94 SPI RTC chip. | ||
| 281 | |||
| 282 | This driver can also be built as a module. If so, the module | ||
| 283 | will be called rtc-m41t94. | ||
| 284 | |||
| 285 | config RTC_DRV_DS1305 | ||
| 286 | tristate "Dallas/Maxim DS1305/DS1306" | ||
| 287 | help | ||
| 288 | Select this driver to get support for the Dallas/Maxim DS1305 | ||
| 289 | and DS1306 real time clock chips. These support a trickle | ||
| 290 | charger, alarms, and NVRAM in addition to the clock. | ||
| 291 | |||
| 292 | This driver can also be built as a module. If so, the module | ||
| 293 | will be called rtc-ds1305. | ||
| 294 | |||
| 276 | config RTC_DRV_MAX6902 | 295 | config RTC_DRV_MAX6902 |
| 277 | tristate "Maxim MAX6902" | 296 | tristate "Maxim MAX6902" |
| 278 | help | 297 | help |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index b5d9d67df887..18622ef84cab 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -24,6 +24,7 @@ obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | |||
| 24 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 24 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
| 25 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 25 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
| 26 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | 26 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o |
| 27 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o | ||
| 27 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 28 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
| 28 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o | 29 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o |
| 29 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | 30 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o |
| @@ -34,6 +35,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | |||
| 34 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 35 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
| 35 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 36 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
| 36 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 37 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
| 38 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | ||
| 37 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | 39 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o |
| 38 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 40 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
| 39 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 41 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index d397fa5f3a91..7af60b98d8a4 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
| @@ -20,7 +20,7 @@ int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
| 20 | 20 | ||
| 21 | err = mutex_lock_interruptible(&rtc->ops_lock); | 21 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 22 | if (err) | 22 | if (err) |
| 23 | return -EBUSY; | 23 | return err; |
| 24 | 24 | ||
| 25 | if (!rtc->ops) | 25 | if (!rtc->ops) |
| 26 | err = -ENODEV; | 26 | err = -ENODEV; |
| @@ -46,7 +46,7 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
| 46 | 46 | ||
| 47 | err = mutex_lock_interruptible(&rtc->ops_lock); | 47 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 48 | if (err) | 48 | if (err) |
| 49 | return -EBUSY; | 49 | return err; |
| 50 | 50 | ||
| 51 | if (!rtc->ops) | 51 | if (!rtc->ops) |
| 52 | err = -ENODEV; | 52 | err = -ENODEV; |
| @@ -66,7 +66,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) | |||
| 66 | 66 | ||
| 67 | err = mutex_lock_interruptible(&rtc->ops_lock); | 67 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 68 | if (err) | 68 | if (err) |
| 69 | return -EBUSY; | 69 | return err; |
| 70 | 70 | ||
| 71 | if (!rtc->ops) | 71 | if (!rtc->ops) |
| 72 | err = -ENODEV; | 72 | err = -ENODEV; |
| @@ -106,7 +106,7 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al | |||
| 106 | 106 | ||
| 107 | err = mutex_lock_interruptible(&rtc->ops_lock); | 107 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 108 | if (err) | 108 | if (err) |
| 109 | return -EBUSY; | 109 | return err; |
| 110 | 110 | ||
| 111 | if (rtc->ops == NULL) | 111 | if (rtc->ops == NULL) |
| 112 | err = -ENODEV; | 112 | err = -ENODEV; |
| @@ -293,7 +293,7 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
| 293 | 293 | ||
| 294 | err = mutex_lock_interruptible(&rtc->ops_lock); | 294 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 295 | if (err) | 295 | if (err) |
| 296 | return -EBUSY; | 296 | return err; |
| 297 | 297 | ||
| 298 | if (!rtc->ops) | 298 | if (!rtc->ops) |
| 299 | err = -ENODEV; | 299 | err = -ENODEV; |
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 9c3db934cc24..4e888cc8be5b 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
| 30 | 30 | ||
| 31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
| 32 | #include <asm/arch/at91_rtc.h> | 32 | #include <mach/at91_rtc.h> |
| 33 | 33 | ||
| 34 | 34 | ||
| 35 | #define AT91_RTC_FREQ 1 | 35 | #define AT91_RTC_FREQ 1 |
| @@ -171,8 +171,10 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 171 | | BIN2BCD(tm.tm_mday) << 24 | 171 | | BIN2BCD(tm.tm_mday) << 24 |
| 172 | | AT91_RTC_DATEEN | AT91_RTC_MTHEN); | 172 | | AT91_RTC_DATEEN | AT91_RTC_MTHEN); |
| 173 | 173 | ||
| 174 | if (alrm->enabled) | 174 | if (alrm->enabled) { |
| 175 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | ||
| 175 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); | 176 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); |
| 177 | } | ||
| 176 | 178 | ||
| 177 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 179 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
| 178 | at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, | 180 | at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, |
| @@ -191,28 +193,22 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
| 191 | 193 | ||
| 192 | pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg); | 194 | pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg); |
| 193 | 195 | ||
| 196 | /* important: scrub old status before enabling IRQs */ | ||
| 194 | switch (cmd) { | 197 | switch (cmd) { |
| 195 | case RTC_AIE_OFF: /* alarm off */ | 198 | case RTC_AIE_OFF: /* alarm off */ |
| 196 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); | 199 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); |
| 197 | break; | 200 | break; |
| 198 | case RTC_AIE_ON: /* alarm on */ | 201 | case RTC_AIE_ON: /* alarm on */ |
| 202 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | ||
| 199 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); | 203 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); |
| 200 | break; | 204 | break; |
| 201 | case RTC_UIE_OFF: /* update off */ | 205 | case RTC_UIE_OFF: /* update off */ |
| 202 | case RTC_PIE_OFF: /* periodic off */ | ||
| 203 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV); | 206 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV); |
| 204 | break; | 207 | break; |
| 205 | case RTC_UIE_ON: /* update on */ | 208 | case RTC_UIE_ON: /* update on */ |
| 206 | case RTC_PIE_ON: /* periodic on */ | 209 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_SECEV); |
| 207 | at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV); | 210 | at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV); |
| 208 | break; | 211 | break; |
| 209 | case RTC_IRQP_READ: /* read periodic alarm frequency */ | ||
| 210 | ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg); | ||
| 211 | break; | ||
| 212 | case RTC_IRQP_SET: /* set periodic alarm frequency */ | ||
| 213 | if (arg != AT91_RTC_FREQ) | ||
| 214 | ret = -EINVAL; | ||
| 215 | break; | ||
| 216 | default: | 212 | default: |
| 217 | ret = -ENOIOCTLCMD; | 213 | ret = -ENOIOCTLCMD; |
| 218 | break; | 214 | break; |
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index f0246ef413a4..2133f37906f2 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c | |||
| @@ -19,8 +19,8 @@ | |||
| 19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 20 | #include <linux/ioctl.h> | 20 | #include <linux/ioctl.h> |
| 21 | 21 | ||
| 22 | #include <asm/arch/board.h> | 22 | #include <mach/board.h> |
| 23 | #include <asm/arch/at91_rtt.h> | 23 | #include <mach/at91_rtt.h> |
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | /* | 26 | /* |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 8624f55d0560..a1af4c27939b 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
| 3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] | 3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] |
| 4 | * | 4 | * |
| 5 | * Copyright 2004-2007 Analog Devices Inc. | 5 | * Copyright 2004-2008 Analog Devices Inc. |
| 6 | * | 6 | * |
| 7 | * Enter bugs at http://blackfin.uclinux.org/ | 7 | * Enter bugs at http://blackfin.uclinux.org/ |
| 8 | * | 8 | * |
| @@ -32,6 +32,15 @@ | |||
| 32 | * writes to clear status registers complete immediately. | 32 | * writes to clear status registers complete immediately. |
| 33 | */ | 33 | */ |
| 34 | 34 | ||
| 35 | /* It may seem odd that there is no SWCNT code in here (which would be exposed | ||
| 36 | * via the periodic interrupt event, or PIE). Since the Blackfin RTC peripheral | ||
| 37 | * runs in units of seconds (N/HZ) but the Linux framework runs in units of HZ | ||
| 38 | * (2^N HZ), there is no point in keeping code that only provides 1 HZ PIEs. | ||
| 39 | * The same exact behavior can be accomplished by using the update interrupt | ||
| 40 | * event (UIE). Maybe down the line the RTC peripheral will suck less in which | ||
| 41 | * case we can re-introduce PIE support. | ||
| 42 | */ | ||
| 43 | |||
| 35 | #include <linux/bcd.h> | 44 | #include <linux/bcd.h> |
| 36 | #include <linux/completion.h> | 45 | #include <linux/completion.h> |
| 37 | #include <linux/delay.h> | 46 | #include <linux/delay.h> |
| @@ -144,14 +153,13 @@ static void bfin_rtc_sync_pending(struct device *dev) | |||
| 144 | * Initialize the RTC. Enable pre-scaler to scale RTC clock | 153 | * Initialize the RTC. Enable pre-scaler to scale RTC clock |
| 145 | * to 1Hz and clear interrupt/status registers. | 154 | * to 1Hz and clear interrupt/status registers. |
| 146 | */ | 155 | */ |
| 147 | static void bfin_rtc_reset(struct device *dev) | 156 | static void bfin_rtc_reset(struct device *dev, u16 rtc_ictl) |
| 148 | { | 157 | { |
| 149 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 158 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
| 150 | dev_dbg_stamp(dev); | 159 | dev_dbg_stamp(dev); |
| 151 | bfin_rtc_sync_pending(dev); | 160 | bfin_rtc_sync_pending(dev); |
| 152 | bfin_write_RTC_PREN(0x1); | 161 | bfin_write_RTC_PREN(0x1); |
| 153 | bfin_write_RTC_ICTL(RTC_ISTAT_WRITE_COMPLETE); | 162 | bfin_write_RTC_ICTL(rtc_ictl); |
| 154 | bfin_write_RTC_SWCNT(0); | ||
| 155 | bfin_write_RTC_ALARM(0); | 163 | bfin_write_RTC_ALARM(0); |
| 156 | bfin_write_RTC_ISTAT(0xFFFF); | 164 | bfin_write_RTC_ISTAT(0xFFFF); |
| 157 | rtc->rtc_wrote_regs = 0; | 165 | rtc->rtc_wrote_regs = 0; |
| @@ -194,14 +202,6 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
| 194 | } | 202 | } |
| 195 | } | 203 | } |
| 196 | 204 | ||
| 197 | if (rtc_ictl & RTC_ISTAT_STOPWATCH) { | ||
| 198 | if (rtc_istat & RTC_ISTAT_STOPWATCH) { | ||
| 199 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); | ||
| 200 | events |= RTC_PF | RTC_IRQF; | ||
| 201 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | if (rtc_ictl & RTC_ISTAT_SEC) { | 205 | if (rtc_ictl & RTC_ISTAT_SEC) { |
| 206 | if (rtc_istat & RTC_ISTAT_SEC) { | 206 | if (rtc_istat & RTC_ISTAT_SEC) { |
| 207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); |
| @@ -226,7 +226,7 @@ static int bfin_rtc_open(struct device *dev) | |||
| 226 | 226 | ||
| 227 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); | 227 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); |
| 228 | if (!ret) | 228 | if (!ret) |
| 229 | bfin_rtc_reset(dev); | 229 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); |
| 230 | 230 | ||
| 231 | return ret; | 231 | return ret; |
| 232 | } | 232 | } |
| @@ -234,16 +234,16 @@ static int bfin_rtc_open(struct device *dev) | |||
| 234 | static void bfin_rtc_release(struct device *dev) | 234 | static void bfin_rtc_release(struct device *dev) |
| 235 | { | 235 | { |
| 236 | dev_dbg_stamp(dev); | 236 | dev_dbg_stamp(dev); |
| 237 | bfin_rtc_reset(dev); | 237 | bfin_rtc_reset(dev, 0); |
| 238 | free_irq(IRQ_RTC, dev); | 238 | free_irq(IRQ_RTC, dev); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | static void bfin_rtc_int_set(struct bfin_rtc *rtc, u16 rtc_int) | 241 | static void bfin_rtc_int_set(u16 rtc_int) |
| 242 | { | 242 | { |
| 243 | bfin_write_RTC_ISTAT(rtc_int); | 243 | bfin_write_RTC_ISTAT(rtc_int); |
| 244 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); | 244 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); |
| 245 | } | 245 | } |
| 246 | static void bfin_rtc_int_clear(struct bfin_rtc *rtc, u16 rtc_int) | 246 | static void bfin_rtc_int_clear(u16 rtc_int) |
| 247 | { | 247 | { |
| 248 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); | 248 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); |
| 249 | } | 249 | } |
| @@ -252,7 +252,7 @@ static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc) | |||
| 252 | /* Blackfin has different bits for whether the alarm is | 252 | /* Blackfin has different bits for whether the alarm is |
| 253 | * more than 24 hours away. | 253 | * more than 24 hours away. |
| 254 | */ | 254 | */ |
| 255 | bfin_rtc_int_set(rtc, (rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY)); | 255 | bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY); |
| 256 | } | 256 | } |
| 257 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 257 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
| 258 | { | 258 | { |
| @@ -264,23 +264,13 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar | |||
| 264 | bfin_rtc_sync_pending(dev); | 264 | bfin_rtc_sync_pending(dev); |
| 265 | 265 | ||
| 266 | switch (cmd) { | 266 | switch (cmd) { |
| 267 | case RTC_PIE_ON: | ||
| 268 | dev_dbg_stamp(dev); | ||
| 269 | bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH); | ||
| 270 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | ||
| 271 | break; | ||
| 272 | case RTC_PIE_OFF: | ||
| 273 | dev_dbg_stamp(dev); | ||
| 274 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_STOPWATCH); | ||
| 275 | break; | ||
| 276 | |||
| 277 | case RTC_UIE_ON: | 267 | case RTC_UIE_ON: |
| 278 | dev_dbg_stamp(dev); | 268 | dev_dbg_stamp(dev); |
| 279 | bfin_rtc_int_set(rtc, RTC_ISTAT_SEC); | 269 | bfin_rtc_int_set(RTC_ISTAT_SEC); |
| 280 | break; | 270 | break; |
| 281 | case RTC_UIE_OFF: | 271 | case RTC_UIE_OFF: |
| 282 | dev_dbg_stamp(dev); | 272 | dev_dbg_stamp(dev); |
| 283 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_SEC); | 273 | bfin_rtc_int_clear(~RTC_ISTAT_SEC); |
| 284 | break; | 274 | break; |
| 285 | 275 | ||
| 286 | case RTC_AIE_ON: | 276 | case RTC_AIE_ON: |
| @@ -289,7 +279,7 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar | |||
| 289 | break; | 279 | break; |
| 290 | case RTC_AIE_OFF: | 280 | case RTC_AIE_OFF: |
| 291 | dev_dbg_stamp(dev); | 281 | dev_dbg_stamp(dev); |
| 292 | bfin_rtc_int_clear(rtc, ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 282 | bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); |
| 293 | break; | 283 | break; |
| 294 | 284 | ||
| 295 | default: | 285 | default: |
| @@ -371,30 +361,14 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) | |||
| 371 | seq_printf(seq, | 361 | seq_printf(seq, |
| 372 | "alarm_IRQ\t: %s\n" | 362 | "alarm_IRQ\t: %s\n" |
| 373 | "wkalarm_IRQ\t: %s\n" | 363 | "wkalarm_IRQ\t: %s\n" |
| 374 | "seconds_IRQ\t: %s\n" | 364 | "seconds_IRQ\t: %s\n", |
| 375 | "periodic_IRQ\t: %s\n", | ||
| 376 | yesno(ictl & RTC_ISTAT_ALARM), | 365 | yesno(ictl & RTC_ISTAT_ALARM), |
| 377 | yesno(ictl & RTC_ISTAT_ALARM_DAY), | 366 | yesno(ictl & RTC_ISTAT_ALARM_DAY), |
| 378 | yesno(ictl & RTC_ISTAT_SEC), | 367 | yesno(ictl & RTC_ISTAT_SEC)); |
| 379 | yesno(ictl & RTC_ISTAT_STOPWATCH)); | ||
| 380 | return 0; | 368 | return 0; |
| 381 | #undef yesno | 369 | #undef yesno |
| 382 | } | 370 | } |
| 383 | 371 | ||
| 384 | /** | ||
| 385 | * bfin_irq_set_freq - make sure hardware supports requested freq | ||
| 386 | * @dev: pointer to RTC device structure | ||
| 387 | * @freq: requested frequency rate | ||
| 388 | * | ||
| 389 | * The Blackfin RTC can only generate periodic events at 1 per | ||
| 390 | * second (1 Hz), so reject any attempt at changing it. | ||
| 391 | */ | ||
| 392 | static int bfin_irq_set_freq(struct device *dev, int freq) | ||
| 393 | { | ||
| 394 | dev_dbg_stamp(dev); | ||
| 395 | return -ENOTTY; | ||
| 396 | } | ||
| 397 | |||
| 398 | static struct rtc_class_ops bfin_rtc_ops = { | 372 | static struct rtc_class_ops bfin_rtc_ops = { |
| 399 | .open = bfin_rtc_open, | 373 | .open = bfin_rtc_open, |
| 400 | .release = bfin_rtc_release, | 374 | .release = bfin_rtc_release, |
| @@ -404,7 +378,6 @@ static struct rtc_class_ops bfin_rtc_ops = { | |||
| 404 | .read_alarm = bfin_rtc_read_alarm, | 378 | .read_alarm = bfin_rtc_read_alarm, |
| 405 | .set_alarm = bfin_rtc_set_alarm, | 379 | .set_alarm = bfin_rtc_set_alarm, |
| 406 | .proc = bfin_rtc_proc, | 380 | .proc = bfin_rtc_proc, |
| 407 | .irq_set_freq = bfin_irq_set_freq, | ||
| 408 | }; | 381 | }; |
| 409 | 382 | ||
| 410 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) | 383 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) |
| @@ -423,10 +396,14 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
| 423 | ret = PTR_ERR(rtc->rtc_dev); | 396 | ret = PTR_ERR(rtc->rtc_dev); |
| 424 | goto err; | 397 | goto err; |
| 425 | } | 398 | } |
| 426 | rtc->rtc_dev->irq_freq = 1; | 399 | |
| 400 | /* see comment at top of file about stopwatch/PIE */ | ||
| 401 | bfin_write_RTC_SWCNT(0); | ||
| 427 | 402 | ||
| 428 | platform_set_drvdata(pdev, rtc); | 403 | platform_set_drvdata(pdev, rtc); |
| 429 | 404 | ||
| 405 | device_init_wakeup(&pdev->dev, 1); | ||
| 406 | |||
| 430 | return 0; | 407 | return 0; |
| 431 | 408 | ||
| 432 | err: | 409 | err: |
| @@ -445,6 +422,32 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) | |||
| 445 | return 0; | 422 | return 0; |
| 446 | } | 423 | } |
| 447 | 424 | ||
| 425 | #ifdef CONFIG_PM | ||
| 426 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 427 | { | ||
| 428 | if (device_may_wakeup(&pdev->dev)) { | ||
| 429 | enable_irq_wake(IRQ_RTC); | ||
| 430 | bfin_rtc_sync_pending(&pdev->dev); | ||
| 431 | } else | ||
| 432 | bfin_rtc_int_clear(-1); | ||
| 433 | |||
| 434 | return 0; | ||
| 435 | } | ||
| 436 | |||
| 437 | static int bfin_rtc_resume(struct platform_device *pdev) | ||
| 438 | { | ||
| 439 | if (device_may_wakeup(&pdev->dev)) | ||
| 440 | disable_irq_wake(IRQ_RTC); | ||
| 441 | else | ||
| 442 | bfin_write_RTC_ISTAT(-1); | ||
| 443 | |||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | #else | ||
| 447 | # define bfin_rtc_suspend NULL | ||
| 448 | # define bfin_rtc_resume NULL | ||
| 449 | #endif | ||
| 450 | |||
| 448 | static struct platform_driver bfin_rtc_driver = { | 451 | static struct platform_driver bfin_rtc_driver = { |
| 449 | .driver = { | 452 | .driver = { |
| 450 | .name = "rtc-bfin", | 453 | .name = "rtc-bfin", |
| @@ -452,6 +455,8 @@ static struct platform_driver bfin_rtc_driver = { | |||
| 452 | }, | 455 | }, |
| 453 | .probe = bfin_rtc_probe, | 456 | .probe = bfin_rtc_probe, |
| 454 | .remove = __devexit_p(bfin_rtc_remove), | 457 | .remove = __devexit_p(bfin_rtc_remove), |
| 458 | .suspend = bfin_rtc_suspend, | ||
| 459 | .resume = bfin_rtc_resume, | ||
| 455 | }; | 460 | }; |
| 456 | 461 | ||
| 457 | static int __init bfin_rtc_init(void) | 462 | static int __init bfin_rtc_init(void) |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index d7bb9bac71df..6ea349aba3ba 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
| @@ -36,25 +36,9 @@ | |||
| 36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
| 37 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
| 38 | 38 | ||
| 39 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
| 40 | #include <asm/hpet.h> | ||
| 41 | #endif | ||
| 42 | |||
| 43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 39 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
| 44 | #include <asm-generic/rtc.h> | 40 | #include <asm-generic/rtc.h> |
| 45 | 41 | ||
| 46 | #ifndef CONFIG_HPET_EMULATE_RTC | ||
| 47 | #define is_hpet_enabled() 0 | ||
| 48 | #define hpet_set_alarm_time(hrs, min, sec) do { } while (0) | ||
| 49 | #define hpet_set_periodic_freq(arg) 0 | ||
| 50 | #define hpet_mask_rtc_irq_bit(arg) do { } while (0) | ||
| 51 | #define hpet_set_rtc_irq_bit(arg) do { } while (0) | ||
| 52 | #define hpet_rtc_timer_init() do { } while (0) | ||
| 53 | #define hpet_register_irq_handler(h) 0 | ||
| 54 | #define hpet_unregister_irq_handler(h) do { } while (0) | ||
| 55 | extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); | ||
| 56 | #endif | ||
| 57 | |||
| 58 | struct cmos_rtc { | 42 | struct cmos_rtc { |
| 59 | struct rtc_device *rtc; | 43 | struct rtc_device *rtc; |
| 60 | struct device *dev; | 44 | struct device *dev; |
| @@ -93,6 +77,72 @@ static inline int is_intr(u8 rtc_intr) | |||
| 93 | 77 | ||
| 94 | /*----------------------------------------------------------------*/ | 78 | /*----------------------------------------------------------------*/ |
| 95 | 79 | ||
| 80 | /* Much modern x86 hardware has HPETs (10+ MHz timers) which, because | ||
| 81 | * many BIOS programmers don't set up "sane mode" IRQ routing, are mostly | ||
| 82 | * used in a broken "legacy replacement" mode. The breakage includes | ||
| 83 | * HPET #1 hijacking the IRQ for this RTC, and being unavailable for | ||
| 84 | * other (better) use. | ||
| 85 | * | ||
| 86 | * When that broken mode is in use, platform glue provides a partial | ||
| 87 | * emulation of hardware RTC IRQ facilities using HPET #1. We don't | ||
| 88 | * want to use HPET for anything except those IRQs though... | ||
| 89 | */ | ||
| 90 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
| 91 | #include <asm/hpet.h> | ||
| 92 | #else | ||
| 93 | |||
| 94 | static inline int is_hpet_enabled(void) | ||
| 95 | { | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | static inline int hpet_mask_rtc_irq_bit(unsigned long mask) | ||
| 100 | { | ||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | static inline int hpet_set_rtc_irq_bit(unsigned long mask) | ||
| 105 | { | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static inline int | ||
| 110 | hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec) | ||
| 111 | { | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | static inline int hpet_set_periodic_freq(unsigned long freq) | ||
| 116 | { | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline int hpet_rtc_dropped_irq(void) | ||
| 121 | { | ||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | static inline int hpet_rtc_timer_init(void) | ||
| 126 | { | ||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | extern irq_handler_t hpet_rtc_interrupt; | ||
| 131 | |||
| 132 | static inline int hpet_register_irq_handler(irq_handler_t handler) | ||
| 133 | { | ||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | static inline int hpet_unregister_irq_handler(irq_handler_t handler) | ||
| 138 | { | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | #endif | ||
| 143 | |||
| 144 | /*----------------------------------------------------------------*/ | ||
| 145 | |||
| 96 | static int cmos_read_time(struct device *dev, struct rtc_time *t) | 146 | static int cmos_read_time(struct device *dev, struct rtc_time *t) |
| 97 | { | 147 | { |
| 98 | /* REVISIT: if the clock has a "century" register, use | 148 | /* REVISIT: if the clock has a "century" register, use |
| @@ -185,11 +235,56 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 185 | return 0; | 235 | return 0; |
| 186 | } | 236 | } |
| 187 | 237 | ||
| 238 | static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control) | ||
| 239 | { | ||
| 240 | unsigned char rtc_intr; | ||
| 241 | |||
| 242 | /* NOTE after changing RTC_xIE bits we always read INTR_FLAGS; | ||
| 243 | * allegedly some older rtcs need that to handle irqs properly | ||
| 244 | */ | ||
| 245 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | ||
| 246 | |||
| 247 | if (is_hpet_enabled()) | ||
| 248 | return; | ||
| 249 | |||
| 250 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
| 251 | if (is_intr(rtc_intr)) | ||
| 252 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | ||
| 253 | } | ||
| 254 | |||
| 255 | static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask) | ||
| 256 | { | ||
| 257 | unsigned char rtc_control; | ||
| 258 | |||
| 259 | /* flush any pending IRQ status, notably for update irqs, | ||
| 260 | * before we enable new IRQs | ||
| 261 | */ | ||
| 262 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
| 263 | cmos_checkintr(cmos, rtc_control); | ||
| 264 | |||
| 265 | rtc_control |= mask; | ||
| 266 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
| 267 | hpet_set_rtc_irq_bit(mask); | ||
| 268 | |||
| 269 | cmos_checkintr(cmos, rtc_control); | ||
| 270 | } | ||
| 271 | |||
| 272 | static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) | ||
| 273 | { | ||
| 274 | unsigned char rtc_control; | ||
| 275 | |||
| 276 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
| 277 | rtc_control &= ~mask; | ||
| 278 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
| 279 | hpet_mask_rtc_irq_bit(mask); | ||
| 280 | |||
| 281 | cmos_checkintr(cmos, rtc_control); | ||
| 282 | } | ||
| 283 | |||
| 188 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | 284 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) |
| 189 | { | 285 | { |
| 190 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 286 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
| 191 | unsigned char mon, mday, hrs, min, sec; | 287 | unsigned char mon, mday, hrs, min, sec; |
| 192 | unsigned char rtc_control, rtc_intr; | ||
| 193 | 288 | ||
| 194 | if (!is_valid_irq(cmos->irq)) | 289 | if (!is_valid_irq(cmos->irq)) |
| 195 | return -EIO; | 290 | return -EIO; |
| @@ -213,17 +308,10 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 213 | sec = t->time.tm_sec; | 308 | sec = t->time.tm_sec; |
| 214 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; | 309 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; |
| 215 | 310 | ||
| 216 | hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); | ||
| 217 | spin_lock_irq(&rtc_lock); | 311 | spin_lock_irq(&rtc_lock); |
| 218 | 312 | ||
| 219 | /* next rtc irq must not be from previous alarm setting */ | 313 | /* next rtc irq must not be from previous alarm setting */ |
| 220 | rtc_control = CMOS_READ(RTC_CONTROL); | 314 | cmos_irq_disable(cmos, RTC_AIE); |
| 221 | rtc_control &= ~RTC_AIE; | ||
| 222 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
| 223 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | ||
| 224 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
| 225 | if (is_intr(rtc_intr)) | ||
| 226 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | ||
| 227 | 315 | ||
| 228 | /* update alarm */ | 316 | /* update alarm */ |
| 229 | CMOS_WRITE(hrs, RTC_HOURS_ALARM); | 317 | CMOS_WRITE(hrs, RTC_HOURS_ALARM); |
| @@ -237,14 +325,13 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 237 | CMOS_WRITE(mon, cmos->mon_alrm); | 325 | CMOS_WRITE(mon, cmos->mon_alrm); |
| 238 | } | 326 | } |
| 239 | 327 | ||
| 240 | if (t->enabled) { | 328 | /* FIXME the HPET alarm glue currently ignores day_alrm |
| 241 | rtc_control |= RTC_AIE; | 329 | * and mon_alrm ... |
| 242 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 330 | */ |
| 243 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 331 | hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); |
| 244 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 332 | |
| 245 | if (is_intr(rtc_intr)) | 333 | if (t->enabled) |
| 246 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | 334 | cmos_irq_enable(cmos, RTC_AIE); |
| 247 | } | ||
| 248 | 335 | ||
| 249 | spin_unlock_irq(&rtc_lock); | 336 | spin_unlock_irq(&rtc_lock); |
| 250 | 337 | ||
| @@ -267,8 +354,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
| 267 | f = 16 - f; | 354 | f = 16 - f; |
| 268 | 355 | ||
| 269 | spin_lock_irqsave(&rtc_lock, flags); | 356 | spin_lock_irqsave(&rtc_lock, flags); |
| 270 | if (!hpet_set_periodic_freq(freq)) | 357 | hpet_set_periodic_freq(freq); |
| 271 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | 358 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); |
| 272 | spin_unlock_irqrestore(&rtc_lock, flags); | 359 | spin_unlock_irqrestore(&rtc_lock, flags); |
| 273 | 360 | ||
| 274 | return 0; | 361 | return 0; |
| @@ -277,26 +364,17 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
| 277 | static int cmos_irq_set_state(struct device *dev, int enabled) | 364 | static int cmos_irq_set_state(struct device *dev, int enabled) |
| 278 | { | 365 | { |
| 279 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 366 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
| 280 | unsigned char rtc_control, rtc_intr; | ||
| 281 | unsigned long flags; | 367 | unsigned long flags; |
| 282 | 368 | ||
| 283 | if (!is_valid_irq(cmos->irq)) | 369 | if (!is_valid_irq(cmos->irq)) |
| 284 | return -ENXIO; | 370 | return -ENXIO; |
| 285 | 371 | ||
| 286 | spin_lock_irqsave(&rtc_lock, flags); | 372 | spin_lock_irqsave(&rtc_lock, flags); |
| 287 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
| 288 | 373 | ||
| 289 | if (enabled) | 374 | if (enabled) |
| 290 | rtc_control |= RTC_PIE; | 375 | cmos_irq_enable(cmos, RTC_PIE); |
| 291 | else | 376 | else |
| 292 | rtc_control &= ~RTC_PIE; | 377 | cmos_irq_disable(cmos, RTC_PIE); |
| 293 | |||
| 294 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
| 295 | |||
| 296 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | ||
| 297 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
| 298 | if (is_intr(rtc_intr)) | ||
| 299 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | ||
| 300 | 378 | ||
| 301 | spin_unlock_irqrestore(&rtc_lock, flags); | 379 | spin_unlock_irqrestore(&rtc_lock, flags); |
| 302 | return 0; | 380 | return 0; |
| @@ -308,7 +386,6 @@ static int | |||
| 308 | cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 386 | cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
| 309 | { | 387 | { |
| 310 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 388 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
| 311 | unsigned char rtc_control, rtc_intr; | ||
| 312 | unsigned long flags; | 389 | unsigned long flags; |
| 313 | 390 | ||
| 314 | switch (cmd) { | 391 | switch (cmd) { |
| @@ -316,51 +393,29 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
| 316 | case RTC_AIE_ON: | 393 | case RTC_AIE_ON: |
| 317 | case RTC_UIE_OFF: | 394 | case RTC_UIE_OFF: |
| 318 | case RTC_UIE_ON: | 395 | case RTC_UIE_ON: |
| 319 | case RTC_PIE_OFF: | ||
| 320 | case RTC_PIE_ON: | ||
| 321 | if (!is_valid_irq(cmos->irq)) | 396 | if (!is_valid_irq(cmos->irq)) |
| 322 | return -EINVAL; | 397 | return -EINVAL; |
| 323 | break; | 398 | break; |
| 399 | /* PIE ON/OFF is handled by cmos_irq_set_state() */ | ||
| 324 | default: | 400 | default: |
| 325 | return -ENOIOCTLCMD; | 401 | return -ENOIOCTLCMD; |
| 326 | } | 402 | } |
| 327 | 403 | ||
| 328 | spin_lock_irqsave(&rtc_lock, flags); | 404 | spin_lock_irqsave(&rtc_lock, flags); |
| 329 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
| 330 | switch (cmd) { | 405 | switch (cmd) { |
| 331 | case RTC_AIE_OFF: /* alarm off */ | 406 | case RTC_AIE_OFF: /* alarm off */ |
| 332 | rtc_control &= ~RTC_AIE; | 407 | cmos_irq_disable(cmos, RTC_AIE); |
| 333 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
| 334 | break; | 408 | break; |
| 335 | case RTC_AIE_ON: /* alarm on */ | 409 | case RTC_AIE_ON: /* alarm on */ |
| 336 | rtc_control |= RTC_AIE; | 410 | cmos_irq_enable(cmos, RTC_AIE); |
| 337 | hpet_set_rtc_irq_bit(RTC_AIE); | ||
| 338 | break; | 411 | break; |
| 339 | case RTC_UIE_OFF: /* update off */ | 412 | case RTC_UIE_OFF: /* update off */ |
| 340 | rtc_control &= ~RTC_UIE; | 413 | cmos_irq_disable(cmos, RTC_UIE); |
| 341 | hpet_mask_rtc_irq_bit(RTC_UIE); | ||
| 342 | break; | 414 | break; |
| 343 | case RTC_UIE_ON: /* update on */ | 415 | case RTC_UIE_ON: /* update on */ |
| 344 | rtc_control |= RTC_UIE; | 416 | cmos_irq_enable(cmos, RTC_UIE); |
| 345 | hpet_set_rtc_irq_bit(RTC_UIE); | ||
| 346 | break; | ||
| 347 | case RTC_PIE_OFF: /* periodic off */ | ||
| 348 | rtc_control &= ~RTC_PIE; | ||
| 349 | hpet_mask_rtc_irq_bit(RTC_PIE); | ||
| 350 | break; | ||
| 351 | case RTC_PIE_ON: /* periodic on */ | ||
| 352 | rtc_control |= RTC_PIE; | ||
| 353 | hpet_set_rtc_irq_bit(RTC_PIE); | ||
| 354 | break; | 417 | break; |
| 355 | } | 418 | } |
| 356 | if (!is_hpet_enabled()) | ||
| 357 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
| 358 | |||
| 359 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | ||
| 360 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
| 361 | if (is_intr(rtc_intr)) | ||
| 362 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | ||
| 363 | |||
| 364 | spin_unlock_irqrestore(&rtc_lock, flags); | 419 | spin_unlock_irqrestore(&rtc_lock, flags); |
| 365 | return 0; | 420 | return 0; |
| 366 | } | 421 | } |
| @@ -502,27 +557,29 @@ static irqreturn_t cmos_interrupt(int irq, void *p) | |||
| 502 | u8 rtc_control; | 557 | u8 rtc_control; |
| 503 | 558 | ||
| 504 | spin_lock(&rtc_lock); | 559 | spin_lock(&rtc_lock); |
| 505 | /* | 560 | |
| 506 | * In this case it is HPET RTC interrupt handler | 561 | /* When the HPET interrupt handler calls us, the interrupt |
| 507 | * calling us, with the interrupt information | 562 | * status is passed as arg1 instead of the irq number. But |
| 508 | * passed as arg1, instead of irq. | 563 | * always clear irq status, even when HPET is in the way. |
| 564 | * | ||
| 565 | * Note that HPET and RTC are almost certainly out of phase, | ||
| 566 | * giving different IRQ status ... | ||
| 509 | */ | 567 | */ |
| 568 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | ||
| 569 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
| 510 | if (is_hpet_enabled()) | 570 | if (is_hpet_enabled()) |
| 511 | irqstat = (unsigned long)irq & 0xF0; | 571 | irqstat = (unsigned long)irq & 0xF0; |
| 512 | else { | 572 | irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
| 513 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | ||
| 514 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
| 515 | irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
| 516 | } | ||
| 517 | 573 | ||
| 518 | /* All Linux RTC alarms should be treated as if they were oneshot. | 574 | /* All Linux RTC alarms should be treated as if they were oneshot. |
| 519 | * Similar code may be needed in system wakeup paths, in case the | 575 | * Similar code may be needed in system wakeup paths, in case the |
| 520 | * alarm woke the system. | 576 | * alarm woke the system. |
| 521 | */ | 577 | */ |
| 522 | if (irqstat & RTC_AIE) { | 578 | if (irqstat & RTC_AIE) { |
| 523 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
| 524 | rtc_control &= ~RTC_AIE; | 579 | rtc_control &= ~RTC_AIE; |
| 525 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 580 | CMOS_WRITE(rtc_control, RTC_CONTROL); |
| 581 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
| 582 | |||
| 526 | CMOS_READ(RTC_INTR_FLAGS); | 583 | CMOS_READ(RTC_INTR_FLAGS); |
| 527 | } | 584 | } |
| 528 | spin_unlock(&rtc_lock); | 585 | spin_unlock(&rtc_lock); |
| @@ -629,18 +686,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 629 | * do something about other clock frequencies. | 686 | * do something about other clock frequencies. |
| 630 | */ | 687 | */ |
| 631 | cmos_rtc.rtc->irq_freq = 1024; | 688 | cmos_rtc.rtc->irq_freq = 1024; |
| 632 | if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq)) | 689 | hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); |
| 633 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | 690 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); |
| 691 | |||
| 692 | /* disable irqs */ | ||
| 693 | cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE); | ||
| 634 | 694 | ||
| 635 | /* disable irqs. | ||
| 636 | * | ||
| 637 | * NOTE after changing RTC_xIE bits we always read INTR_FLAGS; | ||
| 638 | * allegedly some older rtcs need that to handle irqs properly | ||
| 639 | */ | ||
| 640 | rtc_control = CMOS_READ(RTC_CONTROL); | 695 | rtc_control = CMOS_READ(RTC_CONTROL); |
| 641 | rtc_control &= ~(RTC_PIE | RTC_AIE | RTC_UIE); | ||
| 642 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
| 643 | CMOS_READ(RTC_INTR_FLAGS); | ||
| 644 | 696 | ||
| 645 | spin_unlock_irq(&rtc_lock); | 697 | spin_unlock_irq(&rtc_lock); |
| 646 | 698 | ||
| @@ -687,7 +739,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 687 | goto cleanup2; | 739 | goto cleanup2; |
| 688 | } | 740 | } |
| 689 | 741 | ||
| 690 | pr_info("%s: alarms up to one %s%s\n", | 742 | pr_info("%s: alarms up to one %s%s%s\n", |
| 691 | cmos_rtc.rtc->dev.bus_id, | 743 | cmos_rtc.rtc->dev.bus_id, |
| 692 | is_valid_irq(rtc_irq) | 744 | is_valid_irq(rtc_irq) |
| 693 | ? (cmos_rtc.mon_alrm | 745 | ? (cmos_rtc.mon_alrm |
| @@ -695,8 +747,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 695 | : (cmos_rtc.day_alrm | 747 | : (cmos_rtc.day_alrm |
| 696 | ? "month" : "day")) | 748 | ? "month" : "day")) |
| 697 | : "no", | 749 | : "no", |
| 698 | cmos_rtc.century ? ", y3k" : "" | 750 | cmos_rtc.century ? ", y3k" : "", |
| 699 | ); | 751 | is_hpet_enabled() ? ", hpet irqs" : ""); |
| 700 | 752 | ||
| 701 | return 0; | 753 | return 0; |
| 702 | 754 | ||
| @@ -713,13 +765,8 @@ cleanup0: | |||
| 713 | 765 | ||
| 714 | static void cmos_do_shutdown(void) | 766 | static void cmos_do_shutdown(void) |
| 715 | { | 767 | { |
| 716 | unsigned char rtc_control; | ||
| 717 | |||
| 718 | spin_lock_irq(&rtc_lock); | 768 | spin_lock_irq(&rtc_lock); |
| 719 | rtc_control = CMOS_READ(RTC_CONTROL); | 769 | cmos_irq_disable(&cmos_rtc, RTC_IRQMASK); |
| 720 | rtc_control &= ~(RTC_PIE|RTC_AIE|RTC_UIE); | ||
| 721 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
| 722 | CMOS_READ(RTC_INTR_FLAGS); | ||
| 723 | spin_unlock_irq(&rtc_lock); | 770 | spin_unlock_irq(&rtc_lock); |
| 724 | } | 771 | } |
| 725 | 772 | ||
| @@ -760,17 +807,17 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
| 760 | spin_lock_irq(&rtc_lock); | 807 | spin_lock_irq(&rtc_lock); |
| 761 | cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL); | 808 | cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL); |
| 762 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { | 809 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { |
| 763 | unsigned char irqstat; | 810 | unsigned char mask; |
| 764 | 811 | ||
| 765 | if (do_wake) | 812 | if (do_wake) |
| 766 | tmp &= ~(RTC_PIE|RTC_UIE); | 813 | mask = RTC_IRQMASK & ~RTC_AIE; |
| 767 | else | 814 | else |
| 768 | tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE); | 815 | mask = RTC_IRQMASK; |
| 816 | tmp &= ~mask; | ||
| 769 | CMOS_WRITE(tmp, RTC_CONTROL); | 817 | CMOS_WRITE(tmp, RTC_CONTROL); |
| 770 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | 818 | hpet_mask_rtc_irq_bit(mask); |
| 771 | irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF; | 819 | |
| 772 | if (is_intr(irqstat)) | 820 | cmos_checkintr(cmos, tmp); |
| 773 | rtc_update_irq(cmos->rtc, 1, irqstat); | ||
| 774 | } | 821 | } |
| 775 | spin_unlock_irq(&rtc_lock); | 822 | spin_unlock_irq(&rtc_lock); |
| 776 | 823 | ||
| @@ -796,7 +843,8 @@ static int cmos_resume(struct device *dev) | |||
| 796 | unsigned char tmp = cmos->suspend_ctrl; | 843 | unsigned char tmp = cmos->suspend_ctrl; |
| 797 | 844 | ||
| 798 | /* re-enable any irqs previously active */ | 845 | /* re-enable any irqs previously active */ |
| 799 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { | 846 | if (tmp & RTC_IRQMASK) { |
| 847 | unsigned char mask; | ||
| 800 | 848 | ||
| 801 | if (cmos->enabled_wake) { | 849 | if (cmos->enabled_wake) { |
| 802 | if (cmos->wake_off) | 850 | if (cmos->wake_off) |
| @@ -807,18 +855,28 @@ static int cmos_resume(struct device *dev) | |||
| 807 | } | 855 | } |
| 808 | 856 | ||
| 809 | spin_lock_irq(&rtc_lock); | 857 | spin_lock_irq(&rtc_lock); |
| 810 | CMOS_WRITE(tmp, RTC_CONTROL); | 858 | do { |
| 811 | tmp = CMOS_READ(RTC_INTR_FLAGS); | 859 | CMOS_WRITE(tmp, RTC_CONTROL); |
| 812 | tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF; | 860 | hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK); |
| 813 | if (is_intr(tmp)) | 861 | |
| 814 | rtc_update_irq(cmos->rtc, 1, tmp); | 862 | mask = CMOS_READ(RTC_INTR_FLAGS); |
| 863 | mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; | ||
| 864 | if (!is_hpet_enabled() || !is_intr(mask)) | ||
| 865 | break; | ||
| 866 | |||
| 867 | /* force one-shot behavior if HPET blocked | ||
| 868 | * the wake alarm's irq | ||
| 869 | */ | ||
| 870 | rtc_update_irq(cmos->rtc, 1, mask); | ||
| 871 | tmp &= ~RTC_AIE; | ||
| 872 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
| 873 | } while (mask & RTC_AIE); | ||
| 815 | spin_unlock_irq(&rtc_lock); | 874 | spin_unlock_irq(&rtc_lock); |
| 816 | } | 875 | } |
| 817 | 876 | ||
| 818 | pr_debug("%s: resume, ctrl %02x\n", | 877 | pr_debug("%s: resume, ctrl %02x\n", |
| 819 | cmos_rtc.rtc->dev.bus_id, | 878 | cmos_rtc.rtc->dev.bus_id, |
| 820 | cmos->suspend_ctrl); | 879 | tmp); |
| 821 | |||
| 822 | 880 | ||
| 823 | return 0; | 881 | return 0; |
| 824 | } | 882 | } |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 0114a78b7cbb..35dcc06eb3e2 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
| 16 | #include <linux/smp_lock.h> | ||
| 17 | #include "rtc-core.h" | 16 | #include "rtc-core.h" |
| 18 | 17 | ||
| 19 | static dev_t rtc_devt; | 18 | static dev_t rtc_devt; |
| @@ -27,11 +26,8 @@ static int rtc_dev_open(struct inode *inode, struct file *file) | |||
| 27 | struct rtc_device, char_dev); | 26 | struct rtc_device, char_dev); |
| 28 | const struct rtc_class_ops *ops = rtc->ops; | 27 | const struct rtc_class_ops *ops = rtc->ops; |
| 29 | 28 | ||
| 30 | lock_kernel(); | 29 | if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) |
| 31 | if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) { | 30 | return -EBUSY; |
| 32 | err = -EBUSY; | ||
| 33 | goto out; | ||
| 34 | } | ||
| 35 | 31 | ||
| 36 | file->private_data = rtc; | 32 | file->private_data = rtc; |
| 37 | 33 | ||
| @@ -41,13 +37,11 @@ static int rtc_dev_open(struct inode *inode, struct file *file) | |||
| 41 | rtc->irq_data = 0; | 37 | rtc->irq_data = 0; |
| 42 | spin_unlock_irq(&rtc->irq_lock); | 38 | spin_unlock_irq(&rtc->irq_lock); |
| 43 | 39 | ||
| 44 | goto out; | 40 | return 0; |
| 45 | } | 41 | } |
| 46 | 42 | ||
| 47 | /* something has gone wrong */ | 43 | /* something has gone wrong */ |
| 48 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); | 44 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); |
| 49 | out: | ||
| 50 | unlock_kernel(); | ||
| 51 | return err; | 45 | return err; |
| 52 | } | 46 | } |
| 53 | 47 | ||
| @@ -209,7 +203,7 @@ static unsigned int rtc_dev_poll(struct file *file, poll_table *wait) | |||
| 209 | return (data != 0) ? (POLLIN | POLLRDNORM) : 0; | 203 | return (data != 0) ? (POLLIN | POLLRDNORM) : 0; |
| 210 | } | 204 | } |
| 211 | 205 | ||
| 212 | static int rtc_dev_ioctl(struct inode *inode, struct file *file, | 206 | static long rtc_dev_ioctl(struct file *file, |
| 213 | unsigned int cmd, unsigned long arg) | 207 | unsigned int cmd, unsigned long arg) |
| 214 | { | 208 | { |
| 215 | int err = 0; | 209 | int err = 0; |
| @@ -219,6 +213,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 219 | struct rtc_wkalrm alarm; | 213 | struct rtc_wkalrm alarm; |
| 220 | void __user *uarg = (void __user *) arg; | 214 | void __user *uarg = (void __user *) arg; |
| 221 | 215 | ||
| 216 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
| 217 | if (err) | ||
| 218 | return err; | ||
| 219 | |||
| 222 | /* check that the calling task has appropriate permissions | 220 | /* check that the calling task has appropriate permissions |
| 223 | * for certain ioctls. doing this check here is useful | 221 | * for certain ioctls. doing this check here is useful |
| 224 | * to avoid duplicate code in each driver. | 222 | * to avoid duplicate code in each driver. |
| @@ -227,26 +225,31 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 227 | case RTC_EPOCH_SET: | 225 | case RTC_EPOCH_SET: |
| 228 | case RTC_SET_TIME: | 226 | case RTC_SET_TIME: |
| 229 | if (!capable(CAP_SYS_TIME)) | 227 | if (!capable(CAP_SYS_TIME)) |
| 230 | return -EACCES; | 228 | err = -EACCES; |
| 231 | break; | 229 | break; |
| 232 | 230 | ||
| 233 | case RTC_IRQP_SET: | 231 | case RTC_IRQP_SET: |
| 234 | if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE)) | 232 | if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE)) |
| 235 | return -EACCES; | 233 | err = -EACCES; |
| 236 | break; | 234 | break; |
| 237 | 235 | ||
| 238 | case RTC_PIE_ON: | 236 | case RTC_PIE_ON: |
| 239 | if (rtc->irq_freq > rtc->max_user_freq && | 237 | if (rtc->irq_freq > rtc->max_user_freq && |
| 240 | !capable(CAP_SYS_RESOURCE)) | 238 | !capable(CAP_SYS_RESOURCE)) |
| 241 | return -EACCES; | 239 | err = -EACCES; |
| 242 | break; | 240 | break; |
| 243 | } | 241 | } |
| 244 | 242 | ||
| 243 | if (err) | ||
| 244 | goto done; | ||
| 245 | |||
| 245 | /* try the driver's ioctl interface */ | 246 | /* try the driver's ioctl interface */ |
| 246 | if (ops->ioctl) { | 247 | if (ops->ioctl) { |
| 247 | err = ops->ioctl(rtc->dev.parent, cmd, arg); | 248 | err = ops->ioctl(rtc->dev.parent, cmd, arg); |
| 248 | if (err != -ENOIOCTLCMD) | 249 | if (err != -ENOIOCTLCMD) { |
| 250 | mutex_unlock(&rtc->ops_lock); | ||
| 249 | return err; | 251 | return err; |
| 252 | } | ||
| 250 | } | 253 | } |
| 251 | 254 | ||
| 252 | /* if the driver does not provide the ioctl interface | 255 | /* if the driver does not provide the ioctl interface |
| @@ -265,15 +268,19 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 265 | 268 | ||
| 266 | switch (cmd) { | 269 | switch (cmd) { |
| 267 | case RTC_ALM_READ: | 270 | case RTC_ALM_READ: |
| 271 | mutex_unlock(&rtc->ops_lock); | ||
| 272 | |||
| 268 | err = rtc_read_alarm(rtc, &alarm); | 273 | err = rtc_read_alarm(rtc, &alarm); |
| 269 | if (err < 0) | 274 | if (err < 0) |
| 270 | return err; | 275 | return err; |
| 271 | 276 | ||
| 272 | if (copy_to_user(uarg, &alarm.time, sizeof(tm))) | 277 | if (copy_to_user(uarg, &alarm.time, sizeof(tm))) |
| 273 | return -EFAULT; | 278 | err = -EFAULT; |
| 274 | break; | 279 | return err; |
| 275 | 280 | ||
| 276 | case RTC_ALM_SET: | 281 | case RTC_ALM_SET: |
| 282 | mutex_unlock(&rtc->ops_lock); | ||
| 283 | |||
| 277 | if (copy_from_user(&alarm.time, uarg, sizeof(tm))) | 284 | if (copy_from_user(&alarm.time, uarg, sizeof(tm))) |
| 278 | return -EFAULT; | 285 | return -EFAULT; |
| 279 | 286 | ||
| @@ -321,24 +328,26 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 321 | } | 328 | } |
| 322 | } | 329 | } |
| 323 | 330 | ||
| 324 | err = rtc_set_alarm(rtc, &alarm); | 331 | return rtc_set_alarm(rtc, &alarm); |
| 325 | break; | ||
| 326 | 332 | ||
| 327 | case RTC_RD_TIME: | 333 | case RTC_RD_TIME: |
| 334 | mutex_unlock(&rtc->ops_lock); | ||
| 335 | |||
| 328 | err = rtc_read_time(rtc, &tm); | 336 | err = rtc_read_time(rtc, &tm); |
| 329 | if (err < 0) | 337 | if (err < 0) |
| 330 | return err; | 338 | return err; |
| 331 | 339 | ||
| 332 | if (copy_to_user(uarg, &tm, sizeof(tm))) | 340 | if (copy_to_user(uarg, &tm, sizeof(tm))) |
| 333 | return -EFAULT; | 341 | err = -EFAULT; |
| 334 | break; | 342 | return err; |
| 335 | 343 | ||
| 336 | case RTC_SET_TIME: | 344 | case RTC_SET_TIME: |
| 345 | mutex_unlock(&rtc->ops_lock); | ||
| 346 | |||
| 337 | if (copy_from_user(&tm, uarg, sizeof(tm))) | 347 | if (copy_from_user(&tm, uarg, sizeof(tm))) |
| 338 | return -EFAULT; | 348 | return -EFAULT; |
| 339 | 349 | ||
| 340 | err = rtc_set_time(rtc, &tm); | 350 | return rtc_set_time(rtc, &tm); |
| 341 | break; | ||
| 342 | 351 | ||
| 343 | case RTC_PIE_ON: | 352 | case RTC_PIE_ON: |
| 344 | err = rtc_irq_set_state(rtc, NULL, 1); | 353 | err = rtc_irq_set_state(rtc, NULL, 1); |
| @@ -376,34 +385,37 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 376 | break; | 385 | break; |
| 377 | #endif | 386 | #endif |
| 378 | case RTC_WKALM_SET: | 387 | case RTC_WKALM_SET: |
| 388 | mutex_unlock(&rtc->ops_lock); | ||
| 379 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) | 389 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) |
| 380 | return -EFAULT; | 390 | return -EFAULT; |
| 381 | 391 | ||
| 382 | err = rtc_set_alarm(rtc, &alarm); | 392 | return rtc_set_alarm(rtc, &alarm); |
| 383 | break; | ||
| 384 | 393 | ||
| 385 | case RTC_WKALM_RD: | 394 | case RTC_WKALM_RD: |
| 395 | mutex_unlock(&rtc->ops_lock); | ||
| 386 | err = rtc_read_alarm(rtc, &alarm); | 396 | err = rtc_read_alarm(rtc, &alarm); |
| 387 | if (err < 0) | 397 | if (err < 0) |
| 388 | return err; | 398 | return err; |
| 389 | 399 | ||
| 390 | if (copy_to_user(uarg, &alarm, sizeof(alarm))) | 400 | if (copy_to_user(uarg, &alarm, sizeof(alarm))) |
| 391 | return -EFAULT; | 401 | err = -EFAULT; |
| 392 | break; | 402 | return err; |
| 393 | 403 | ||
| 394 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 404 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL |
| 395 | case RTC_UIE_OFF: | 405 | case RTC_UIE_OFF: |
| 396 | clear_uie(rtc); | 406 | clear_uie(rtc); |
| 397 | return 0; | 407 | break; |
| 398 | 408 | ||
| 399 | case RTC_UIE_ON: | 409 | case RTC_UIE_ON: |
| 400 | return set_uie(rtc); | 410 | err = set_uie(rtc); |
| 401 | #endif | 411 | #endif |
| 402 | default: | 412 | default: |
| 403 | err = -ENOTTY; | 413 | err = -ENOTTY; |
| 404 | break; | 414 | break; |
| 405 | } | 415 | } |
| 406 | 416 | ||
| 417 | done: | ||
| 418 | mutex_unlock(&rtc->ops_lock); | ||
| 407 | return err; | 419 | return err; |
| 408 | } | 420 | } |
| 409 | 421 | ||
| @@ -414,6 +426,8 @@ static int rtc_dev_release(struct inode *inode, struct file *file) | |||
| 414 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 426 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL |
| 415 | clear_uie(rtc); | 427 | clear_uie(rtc); |
| 416 | #endif | 428 | #endif |
| 429 | rtc_irq_set_state(rtc, NULL, 0); | ||
| 430 | |||
| 417 | if (rtc->ops->release) | 431 | if (rtc->ops->release) |
| 418 | rtc->ops->release(rtc->dev.parent); | 432 | rtc->ops->release(rtc->dev.parent); |
| 419 | 433 | ||
| @@ -432,7 +446,7 @@ static const struct file_operations rtc_dev_fops = { | |||
| 432 | .llseek = no_llseek, | 446 | .llseek = no_llseek, |
| 433 | .read = rtc_dev_read, | 447 | .read = rtc_dev_read, |
| 434 | .poll = rtc_dev_poll, | 448 | .poll = rtc_dev_poll, |
| 435 | .ioctl = rtc_dev_ioctl, | 449 | .unlocked_ioctl = rtc_dev_ioctl, |
| 436 | .open = rtc_dev_open, | 450 | .open = rtc_dev_open, |
| 437 | .release = rtc_dev_release, | 451 | .release = rtc_dev_release, |
| 438 | .fasync = rtc_dev_fasync, | 452 | .fasync = rtc_dev_fasync, |
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c new file mode 100644 index 000000000000..b91d02a3ace9 --- /dev/null +++ b/drivers/rtc/rtc-ds1305.c | |||
| @@ -0,0 +1,847 @@ | |||
| 1 | /* | ||
| 2 | * rtc-ds1305.c -- driver for DS1305 and DS1306 SPI RTC chips | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 David Brownell | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/bcd.h> | ||
| 14 | #include <linux/rtc.h> | ||
| 15 | #include <linux/workqueue.h> | ||
| 16 | |||
| 17 | #include <linux/spi/spi.h> | ||
| 18 | #include <linux/spi/ds1305.h> | ||
| 19 | |||
| 20 | |||
| 21 | /* | ||
| 22 | * Registers ... mask DS1305_WRITE into register address to write, | ||
| 23 | * otherwise you're reading it. All non-bitmask values are BCD. | ||
| 24 | */ | ||
| 25 | #define DS1305_WRITE 0x80 | ||
| 26 | |||
| 27 | |||
| 28 | /* RTC date/time ... the main special cases are that we: | ||
| 29 | * - Need fancy "hours" encoding in 12hour mode | ||
| 30 | * - Don't rely on the "day-of-week" field (or tm_wday) | ||
| 31 | * - Are a 21st-century clock (2000 <= year < 2100) | ||
| 32 | */ | ||
| 33 | #define DS1305_RTC_LEN 7 /* bytes for RTC regs */ | ||
| 34 | |||
| 35 | #define DS1305_SEC 0x00 /* register addresses */ | ||
| 36 | #define DS1305_MIN 0x01 | ||
| 37 | #define DS1305_HOUR 0x02 | ||
| 38 | # define DS1305_HR_12 0x40 /* set == 12 hr mode */ | ||
| 39 | # define DS1305_HR_PM 0x20 /* set == PM (12hr mode) */ | ||
| 40 | #define DS1305_WDAY 0x03 | ||
| 41 | #define DS1305_MDAY 0x04 | ||
| 42 | #define DS1305_MON 0x05 | ||
| 43 | #define DS1305_YEAR 0x06 | ||
| 44 | |||
| 45 | |||
| 46 | /* The two alarms have only sec/min/hour/wday fields (ALM_LEN). | ||
| 47 | * DS1305_ALM_DISABLE disables a match field (some combos are bad). | ||
| 48 | * | ||
| 49 | * NOTE that since we don't use WDAY, we limit ourselves to alarms | ||
| 50 | * only one day into the future (vs potentially up to a week). | ||
| 51 | * | ||
| 52 | * NOTE ALSO that while we could generate once-a-second IRQs (UIE), we | ||
| 53 | * don't currently support them. We'd either need to do it only when | ||
| 54 | * no alarm is pending (not the standard model), or to use the second | ||
| 55 | * alarm (implying that this is a DS1305 not DS1306, *and* that either | ||
| 56 | * it's wired up a second IRQ we know, or that INTCN is set) | ||
| 57 | */ | ||
| 58 | #define DS1305_ALM_LEN 4 /* bytes for ALM regs */ | ||
| 59 | #define DS1305_ALM_DISABLE 0x80 | ||
| 60 | |||
| 61 | #define DS1305_ALM0(r) (0x07 + (r)) /* register addresses */ | ||
| 62 | #define DS1305_ALM1(r) (0x0b + (r)) | ||
| 63 | |||
| 64 | |||
| 65 | /* three control registers */ | ||
| 66 | #define DS1305_CONTROL_LEN 3 /* bytes of control regs */ | ||
| 67 | |||
| 68 | #define DS1305_CONTROL 0x0f /* register addresses */ | ||
| 69 | # define DS1305_nEOSC 0x80 /* low enables oscillator */ | ||
| 70 | # define DS1305_WP 0x40 /* write protect */ | ||
| 71 | # define DS1305_INTCN 0x04 /* clear == only int0 used */ | ||
| 72 | # define DS1306_1HZ 0x04 /* enable 1Hz output */ | ||
| 73 | # define DS1305_AEI1 0x02 /* enable ALM1 IRQ */ | ||
| 74 | # define DS1305_AEI0 0x01 /* enable ALM0 IRQ */ | ||
| 75 | #define DS1305_STATUS 0x10 | ||
| 76 | /* status has just AEIx bits, mirrored as IRQFx */ | ||
| 77 | #define DS1305_TRICKLE 0x11 | ||
| 78 | /* trickle bits are defined in <linux/spi/ds1305.h> */ | ||
| 79 | |||
| 80 | /* a bunch of NVRAM */ | ||
| 81 | #define DS1305_NVRAM_LEN 96 /* bytes of NVRAM */ | ||
| 82 | |||
| 83 | #define DS1305_NVRAM 0x20 /* register addresses */ | ||
| 84 | |||
| 85 | |||
| 86 | struct ds1305 { | ||
| 87 | struct spi_device *spi; | ||
| 88 | struct rtc_device *rtc; | ||
| 89 | |||
| 90 | struct work_struct work; | ||
| 91 | |||
| 92 | unsigned long flags; | ||
| 93 | #define FLAG_EXITING 0 | ||
| 94 | |||
| 95 | bool hr12; | ||
| 96 | u8 ctrl[DS1305_CONTROL_LEN]; | ||
| 97 | }; | ||
| 98 | |||
| 99 | |||
| 100 | /*----------------------------------------------------------------------*/ | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Utilities ... tolerate 12-hour AM/PM notation in case of non-Linux | ||
| 104 | * software (like a bootloader) which may require it. | ||
| 105 | */ | ||
| 106 | |||
| 107 | static unsigned bcd2hour(u8 bcd) | ||
| 108 | { | ||
| 109 | if (bcd & DS1305_HR_12) { | ||
| 110 | unsigned hour = 0; | ||
| 111 | |||
| 112 | bcd &= ~DS1305_HR_12; | ||
| 113 | if (bcd & DS1305_HR_PM) { | ||
| 114 | hour = 12; | ||
| 115 | bcd &= ~DS1305_HR_PM; | ||
| 116 | } | ||
| 117 | hour += BCD2BIN(bcd); | ||
| 118 | return hour - 1; | ||
| 119 | } | ||
| 120 | return BCD2BIN(bcd); | ||
| 121 | } | ||
| 122 | |||
| 123 | static u8 hour2bcd(bool hr12, int hour) | ||
| 124 | { | ||
| 125 | if (hr12) { | ||
| 126 | hour++; | ||
| 127 | if (hour <= 12) | ||
| 128 | return DS1305_HR_12 | BIN2BCD(hour); | ||
| 129 | hour -= 12; | ||
| 130 | return DS1305_HR_12 | DS1305_HR_PM | BIN2BCD(hour); | ||
| 131 | } | ||
| 132 | return BIN2BCD(hour); | ||
| 133 | } | ||
| 134 | |||
| 135 | /*----------------------------------------------------------------------*/ | ||
| 136 | |||
| 137 | /* | ||
| 138 | * Interface to RTC framework | ||
| 139 | */ | ||
| 140 | |||
| 141 | #ifdef CONFIG_RTC_INTF_DEV | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) | ||
| 145 | */ | ||
| 146 | static int ds1305_ioctl(struct device *dev, unsigned cmd, unsigned long arg) | ||
| 147 | { | ||
| 148 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
| 149 | u8 buf[2]; | ||
| 150 | int status = -ENOIOCTLCMD; | ||
| 151 | |||
| 152 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
| 153 | buf[1] = ds1305->ctrl[0]; | ||
| 154 | |||
| 155 | switch (cmd) { | ||
| 156 | case RTC_AIE_OFF: | ||
| 157 | status = 0; | ||
| 158 | if (!(buf[1] & DS1305_AEI0)) | ||
| 159 | goto done; | ||
| 160 | buf[1] &= ~DS1305_AEI0; | ||
| 161 | break; | ||
| 162 | |||
| 163 | case RTC_AIE_ON: | ||
| 164 | status = 0; | ||
| 165 | if (ds1305->ctrl[0] & DS1305_AEI0) | ||
| 166 | goto done; | ||
| 167 | buf[1] |= DS1305_AEI0; | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | if (status == 0) { | ||
| 171 | status = spi_write_then_read(ds1305->spi, buf, sizeof buf, | ||
| 172 | NULL, 0); | ||
| 173 | if (status >= 0) | ||
| 174 | ds1305->ctrl[0] = buf[1]; | ||
| 175 | } | ||
| 176 | |||
| 177 | done: | ||
| 178 | return status; | ||
| 179 | } | ||
| 180 | |||
| 181 | #else | ||
| 182 | #define ds1305_ioctl NULL | ||
| 183 | #endif | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Get/set of date and time is pretty normal. | ||
| 187 | */ | ||
| 188 | |||
| 189 | static int ds1305_get_time(struct device *dev, struct rtc_time *time) | ||
| 190 | { | ||
| 191 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
| 192 | u8 addr = DS1305_SEC; | ||
| 193 | u8 buf[DS1305_RTC_LEN]; | ||
| 194 | int status; | ||
| 195 | |||
| 196 | /* Use write-then-read to get all the date/time registers | ||
| 197 | * since dma from stack is nonportable | ||
| 198 | */ | ||
| 199 | status = spi_write_then_read(ds1305->spi, &addr, sizeof addr, | ||
| 200 | buf, sizeof buf); | ||
| 201 | if (status < 0) | ||
| 202 | return status; | ||
| 203 | |||
| 204 | dev_vdbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n", | ||
| 205 | "read", buf[0], buf[1], buf[2], buf[3], | ||
| 206 | buf[4], buf[5], buf[6]); | ||
| 207 | |||
| 208 | /* Decode the registers */ | ||
| 209 | time->tm_sec = BCD2BIN(buf[DS1305_SEC]); | ||
| 210 | time->tm_min = BCD2BIN(buf[DS1305_MIN]); | ||
| 211 | time->tm_hour = bcd2hour(buf[DS1305_HOUR]); | ||
| 212 | time->tm_wday = buf[DS1305_WDAY] - 1; | ||
| 213 | time->tm_mday = BCD2BIN(buf[DS1305_MDAY]); | ||
| 214 | time->tm_mon = BCD2BIN(buf[DS1305_MON]) - 1; | ||
| 215 | time->tm_year = BCD2BIN(buf[DS1305_YEAR]) + 100; | ||
| 216 | |||
| 217 | dev_vdbg(dev, "%s secs=%d, mins=%d, " | ||
| 218 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 219 | "read", time->tm_sec, time->tm_min, | ||
| 220 | time->tm_hour, time->tm_mday, | ||
| 221 | time->tm_mon, time->tm_year, time->tm_wday); | ||
| 222 | |||
| 223 | /* Time may not be set */ | ||
| 224 | return rtc_valid_tm(time); | ||
| 225 | } | ||
| 226 | |||
| 227 | static int ds1305_set_time(struct device *dev, struct rtc_time *time) | ||
| 228 | { | ||
| 229 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
| 230 | u8 buf[1 + DS1305_RTC_LEN]; | ||
| 231 | u8 *bp = buf; | ||
| 232 | |||
| 233 | dev_vdbg(dev, "%s secs=%d, mins=%d, " | ||
| 234 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 235 | "write", time->tm_sec, time->tm_min, | ||
| 236 | time->tm_hour, time->tm_mday, | ||
| 237 | time->tm_mon, time->tm_year, time->tm_wday); | ||
| 238 | |||
| 239 | /* Write registers starting at the first time/date address. */ | ||
| 240 | *bp++ = DS1305_WRITE | DS1305_SEC; | ||
| 241 | |||
| 242 | *bp++ = BIN2BCD(time->tm_sec); | ||
| 243 | *bp++ = BIN2BCD(time->tm_min); | ||
| 244 | *bp++ = hour2bcd(ds1305->hr12, time->tm_hour); | ||
| 245 | *bp++ = (time->tm_wday < 7) ? (time->tm_wday + 1) : 1; | ||
| 246 | *bp++ = BIN2BCD(time->tm_mday); | ||
| 247 | *bp++ = BIN2BCD(time->tm_mon + 1); | ||
| 248 | *bp++ = BIN2BCD(time->tm_year - 100); | ||
| 249 | |||
| 250 | dev_dbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n", | ||
| 251 | "write", buf[1], buf[2], buf[3], | ||
| 252 | buf[4], buf[5], buf[6], buf[7]); | ||
| 253 | |||
| 254 | /* use write-then-read since dma from stack is nonportable */ | ||
| 255 | return spi_write_then_read(ds1305->spi, buf, sizeof buf, | ||
| 256 | NULL, 0); | ||
| 257 | } | ||
| 258 | |||
| 259 | /* | ||
| 260 | * Get/set of alarm is a bit funky: | ||
| 261 | * | ||
| 262 | * - First there's the inherent raciness of getting the (partitioned) | ||
| 263 | * status of an alarm that could trigger while we're reading parts | ||
| 264 | * of that status. | ||
| 265 | * | ||
| 266 | * - Second there's its limited range (we could increase it a bit by | ||
| 267 | * relying on WDAY), which means it will easily roll over. | ||
| 268 | * | ||
| 269 | * - Third there's the choice of two alarms and alarm signals. | ||
| 270 | * Here we use ALM0 and expect that nINT0 (open drain) is used; | ||
| 271 | * that's the only real option for DS1306 runtime alarms, and is | ||
| 272 | * natural on DS1305. | ||
| 273 | * | ||
| 274 | * - Fourth, there's also ALM1, and a second interrupt signal: | ||
| 275 | * + On DS1305 ALM1 uses nINT1 (when INTCN=1) else nINT0; | ||
| 276 | * + On DS1306 ALM1 only uses INT1 (an active high pulse) | ||
| 277 | * and it won't work when VCC1 is active. | ||
| 278 | * | ||
| 279 | * So to be most general, we should probably set both alarms to the | ||
| 280 | * same value, letting ALM1 be the wakeup event source on DS1306 | ||
| 281 | * and handling several wiring options on DS1305. | ||
| 282 | * | ||
| 283 | * - Fifth, we support the polled mode (as well as possible; why not?) | ||
| 284 | * even when no interrupt line is wired to an IRQ. | ||
| 285 | */ | ||
| 286 | |||
| 287 | /* | ||
| 288 | * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) | ||
| 289 | */ | ||
| 290 | static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
| 291 | { | ||
| 292 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
| 293 | struct spi_device *spi = ds1305->spi; | ||
| 294 | u8 addr; | ||
| 295 | int status; | ||
| 296 | u8 buf[DS1305_ALM_LEN]; | ||
| 297 | |||
| 298 | /* Refresh control register cache BEFORE reading ALM0 registers, | ||
| 299 | * since reading alarm registers acks any pending IRQ. That | ||
| 300 | * makes returning "pending" status a bit of a lie, but that bit | ||
| 301 | * of EFI status is at best fragile anyway (given IRQ handlers). | ||
| 302 | */ | ||
| 303 | addr = DS1305_CONTROL; | ||
| 304 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
| 305 | ds1305->ctrl, sizeof ds1305->ctrl); | ||
| 306 | if (status < 0) | ||
| 307 | return status; | ||
| 308 | |||
| 309 | alm->enabled = !!(ds1305->ctrl[0] & DS1305_AEI0); | ||
| 310 | alm->pending = !!(ds1305->ctrl[1] & DS1305_AEI0); | ||
| 311 | |||
| 312 | /* get and check ALM0 registers */ | ||
| 313 | addr = DS1305_ALM0(DS1305_SEC); | ||
| 314 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
| 315 | buf, sizeof buf); | ||
| 316 | if (status < 0) | ||
| 317 | return status; | ||
| 318 | |||
| 319 | dev_vdbg(dev, "%s: %02x %02x %02x %02x\n", | ||
| 320 | "alm0 read", buf[DS1305_SEC], buf[DS1305_MIN], | ||
| 321 | buf[DS1305_HOUR], buf[DS1305_WDAY]); | ||
| 322 | |||
| 323 | if ((DS1305_ALM_DISABLE & buf[DS1305_SEC]) | ||
| 324 | || (DS1305_ALM_DISABLE & buf[DS1305_MIN]) | ||
| 325 | || (DS1305_ALM_DISABLE & buf[DS1305_HOUR])) | ||
| 326 | return -EIO; | ||
| 327 | |||
| 328 | /* Stuff these values into alm->time and let RTC framework code | ||
| 329 | * fill in the rest ... and also handle rollover to tomorrow when | ||
| 330 | * that's needed. | ||
| 331 | */ | ||
| 332 | alm->time.tm_sec = BCD2BIN(buf[DS1305_SEC]); | ||
| 333 | alm->time.tm_min = BCD2BIN(buf[DS1305_MIN]); | ||
| 334 | alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]); | ||
| 335 | alm->time.tm_mday = -1; | ||
| 336 | alm->time.tm_mon = -1; | ||
| 337 | alm->time.tm_year = -1; | ||
| 338 | /* next three fields are unused by Linux */ | ||
| 339 | alm->time.tm_wday = -1; | ||
| 340 | alm->time.tm_mday = -1; | ||
| 341 | alm->time.tm_isdst = -1; | ||
| 342 | |||
| 343 | return 0; | ||
| 344 | } | ||
| 345 | |||
| 346 | /* | ||
| 347 | * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) | ||
| 348 | */ | ||
| 349 | static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
| 350 | { | ||
| 351 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
| 352 | struct spi_device *spi = ds1305->spi; | ||
| 353 | unsigned long now, later; | ||
| 354 | struct rtc_time tm; | ||
| 355 | int status; | ||
| 356 | u8 buf[1 + DS1305_ALM_LEN]; | ||
| 357 | |||
| 358 | /* convert desired alarm to time_t */ | ||
| 359 | status = rtc_tm_to_time(&alm->time, &later); | ||
| 360 | if (status < 0) | ||
| 361 | return status; | ||
| 362 | |||
| 363 | /* Read current time as time_t */ | ||
| 364 | status = ds1305_get_time(dev, &tm); | ||
| 365 | if (status < 0) | ||
| 366 | return status; | ||
| 367 | status = rtc_tm_to_time(&tm, &now); | ||
| 368 | if (status < 0) | ||
| 369 | return status; | ||
| 370 | |||
| 371 | /* make sure alarm fires within the next 24 hours */ | ||
| 372 | if (later <= now) | ||
| 373 | return -EINVAL; | ||
| 374 | if ((later - now) > 24 * 60 * 60) | ||
| 375 | return -EDOM; | ||
| 376 | |||
| 377 | /* disable alarm if needed */ | ||
| 378 | if (ds1305->ctrl[0] & DS1305_AEI0) { | ||
| 379 | ds1305->ctrl[0] &= ~DS1305_AEI0; | ||
| 380 | |||
| 381 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
| 382 | buf[1] = ds1305->ctrl[0]; | ||
| 383 | status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0); | ||
| 384 | if (status < 0) | ||
| 385 | return status; | ||
| 386 | } | ||
| 387 | |||
| 388 | /* write alarm */ | ||
| 389 | buf[0] = DS1305_WRITE | DS1305_ALM0(DS1305_SEC); | ||
| 390 | buf[1 + DS1305_SEC] = BIN2BCD(alm->time.tm_sec); | ||
| 391 | buf[1 + DS1305_MIN] = BIN2BCD(alm->time.tm_min); | ||
| 392 | buf[1 + DS1305_HOUR] = hour2bcd(ds1305->hr12, alm->time.tm_hour); | ||
| 393 | buf[1 + DS1305_WDAY] = DS1305_ALM_DISABLE; | ||
| 394 | |||
| 395 | dev_dbg(dev, "%s: %02x %02x %02x %02x\n", | ||
| 396 | "alm0 write", buf[1 + DS1305_SEC], buf[1 + DS1305_MIN], | ||
| 397 | buf[1 + DS1305_HOUR], buf[1 + DS1305_WDAY]); | ||
| 398 | |||
| 399 | status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0); | ||
| 400 | if (status < 0) | ||
| 401 | return status; | ||
| 402 | |||
| 403 | /* enable alarm if requested */ | ||
| 404 | if (alm->enabled) { | ||
| 405 | ds1305->ctrl[0] |= DS1305_AEI0; | ||
| 406 | |||
| 407 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
| 408 | buf[1] = ds1305->ctrl[0]; | ||
| 409 | status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0); | ||
| 410 | } | ||
| 411 | |||
| 412 | return status; | ||
| 413 | } | ||
| 414 | |||
| 415 | #ifdef CONFIG_PROC_FS | ||
| 416 | |||
| 417 | static int ds1305_proc(struct device *dev, struct seq_file *seq) | ||
| 418 | { | ||
| 419 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
| 420 | char *diodes = "no"; | ||
| 421 | char *resistors = ""; | ||
| 422 | |||
| 423 | /* ctrl[2] is treated as read-only; no locking needed */ | ||
| 424 | if ((ds1305->ctrl[2] & 0xf0) == DS1305_TRICKLE_MAGIC) { | ||
| 425 | switch (ds1305->ctrl[2] & 0x0c) { | ||
| 426 | case DS1305_TRICKLE_DS2: | ||
| 427 | diodes = "2 diodes, "; | ||
| 428 | break; | ||
| 429 | case DS1305_TRICKLE_DS1: | ||
| 430 | diodes = "1 diode, "; | ||
| 431 | break; | ||
| 432 | default: | ||
| 433 | goto done; | ||
| 434 | } | ||
| 435 | switch (ds1305->ctrl[2] & 0x03) { | ||
| 436 | case DS1305_TRICKLE_2K: | ||
| 437 | resistors = "2k Ohm"; | ||
| 438 | break; | ||
| 439 | case DS1305_TRICKLE_4K: | ||
| 440 | resistors = "4k Ohm"; | ||
| 441 | break; | ||
| 442 | case DS1305_TRICKLE_8K: | ||
| 443 | resistors = "8k Ohm"; | ||
| 444 | break; | ||
| 445 | default: | ||
| 446 | diodes = "no"; | ||
| 447 | break; | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | done: | ||
| 452 | return seq_printf(seq, | ||
| 453 | "trickle_charge\t: %s%s\n", | ||
| 454 | diodes, resistors); | ||
| 455 | } | ||
| 456 | |||
| 457 | #else | ||
| 458 | #define ds1305_proc NULL | ||
| 459 | #endif | ||
| 460 | |||
| 461 | static const struct rtc_class_ops ds1305_ops = { | ||
| 462 | .ioctl = ds1305_ioctl, | ||
| 463 | .read_time = ds1305_get_time, | ||
| 464 | .set_time = ds1305_set_time, | ||
| 465 | .read_alarm = ds1305_get_alarm, | ||
| 466 | .set_alarm = ds1305_set_alarm, | ||
| 467 | .proc = ds1305_proc, | ||
| 468 | }; | ||
| 469 | |||
| 470 | static void ds1305_work(struct work_struct *work) | ||
| 471 | { | ||
| 472 | struct ds1305 *ds1305 = container_of(work, struct ds1305, work); | ||
| 473 | struct mutex *lock = &ds1305->rtc->ops_lock; | ||
| 474 | struct spi_device *spi = ds1305->spi; | ||
| 475 | u8 buf[3]; | ||
| 476 | int status; | ||
| 477 | |||
| 478 | /* lock to protect ds1305->ctrl */ | ||
| 479 | mutex_lock(lock); | ||
| 480 | |||
| 481 | /* Disable the IRQ, and clear its status ... for now, we "know" | ||
| 482 | * that if more than one alarm is active, they're in sync. | ||
| 483 | * Note that reading ALM data registers also clears IRQ status. | ||
| 484 | */ | ||
| 485 | ds1305->ctrl[0] &= ~(DS1305_AEI1 | DS1305_AEI0); | ||
| 486 | ds1305->ctrl[1] = 0; | ||
| 487 | |||
| 488 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
| 489 | buf[1] = ds1305->ctrl[0]; | ||
| 490 | buf[2] = 0; | ||
| 491 | |||
| 492 | status = spi_write_then_read(spi, buf, sizeof buf, | ||
| 493 | NULL, 0); | ||
| 494 | if (status < 0) | ||
| 495 | dev_dbg(&spi->dev, "clear irq --> %d\n", status); | ||
| 496 | |||
| 497 | mutex_unlock(lock); | ||
| 498 | |||
| 499 | if (!test_bit(FLAG_EXITING, &ds1305->flags)) | ||
| 500 | enable_irq(spi->irq); | ||
| 501 | |||
| 502 | /* rtc_update_irq() requires an IRQ-disabled context */ | ||
| 503 | local_irq_disable(); | ||
| 504 | rtc_update_irq(ds1305->rtc, 1, RTC_AF | RTC_IRQF); | ||
| 505 | local_irq_enable(); | ||
| 506 | } | ||
| 507 | |||
| 508 | /* | ||
| 509 | * This "real" IRQ handler hands off to a workqueue mostly to allow | ||
| 510 | * mutex locking for ds1305->ctrl ... unlike I2C, we could issue async | ||
| 511 | * I/O requests in IRQ context (to clear the IRQ status). | ||
| 512 | */ | ||
| 513 | static irqreturn_t ds1305_irq(int irq, void *p) | ||
| 514 | { | ||
| 515 | struct ds1305 *ds1305 = p; | ||
| 516 | |||
| 517 | disable_irq(irq); | ||
| 518 | schedule_work(&ds1305->work); | ||
| 519 | return IRQ_HANDLED; | ||
| 520 | } | ||
| 521 | |||
| 522 | /*----------------------------------------------------------------------*/ | ||
| 523 | |||
| 524 | /* | ||
| 525 | * Interface for NVRAM | ||
| 526 | */ | ||
| 527 | |||
| 528 | static void msg_init(struct spi_message *m, struct spi_transfer *x, | ||
| 529 | u8 *addr, size_t count, char *tx, char *rx) | ||
| 530 | { | ||
| 531 | spi_message_init(m); | ||
| 532 | memset(x, 0, 2 * sizeof(*x)); | ||
| 533 | |||
| 534 | x->tx_buf = addr; | ||
| 535 | x->len = 1; | ||
| 536 | spi_message_add_tail(x, m); | ||
| 537 | |||
| 538 | x++; | ||
| 539 | |||
| 540 | x->tx_buf = tx; | ||
| 541 | x->rx_buf = rx; | ||
| 542 | x->len = count; | ||
| 543 | spi_message_add_tail(x, m); | ||
| 544 | } | ||
| 545 | |||
| 546 | static ssize_t | ||
| 547 | ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | ||
| 548 | char *buf, loff_t off, size_t count) | ||
| 549 | { | ||
| 550 | struct spi_device *spi; | ||
| 551 | u8 addr; | ||
| 552 | struct spi_message m; | ||
| 553 | struct spi_transfer x[2]; | ||
| 554 | int status; | ||
| 555 | |||
| 556 | spi = container_of(kobj, struct spi_device, dev.kobj); | ||
| 557 | |||
| 558 | if (unlikely(off >= DS1305_NVRAM_LEN)) | ||
| 559 | return 0; | ||
| 560 | if (count >= DS1305_NVRAM_LEN) | ||
| 561 | count = DS1305_NVRAM_LEN; | ||
| 562 | if ((off + count) > DS1305_NVRAM_LEN) | ||
| 563 | count = DS1305_NVRAM_LEN - off; | ||
| 564 | if (unlikely(!count)) | ||
| 565 | return count; | ||
| 566 | |||
| 567 | addr = DS1305_NVRAM + off; | ||
| 568 | msg_init(&m, x, &addr, count, NULL, buf); | ||
| 569 | |||
| 570 | status = spi_sync(spi, &m); | ||
| 571 | if (status < 0) | ||
| 572 | dev_err(&spi->dev, "nvram %s error %d\n", "read", status); | ||
| 573 | return (status < 0) ? status : count; | ||
| 574 | } | ||
| 575 | |||
| 576 | static ssize_t | ||
| 577 | ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | ||
| 578 | char *buf, loff_t off, size_t count) | ||
| 579 | { | ||
| 580 | struct spi_device *spi; | ||
| 581 | u8 addr; | ||
| 582 | struct spi_message m; | ||
| 583 | struct spi_transfer x[2]; | ||
| 584 | int status; | ||
| 585 | |||
| 586 | spi = container_of(kobj, struct spi_device, dev.kobj); | ||
| 587 | |||
| 588 | if (unlikely(off >= DS1305_NVRAM_LEN)) | ||
| 589 | return -EFBIG; | ||
| 590 | if (count >= DS1305_NVRAM_LEN) | ||
| 591 | count = DS1305_NVRAM_LEN; | ||
| 592 | if ((off + count) > DS1305_NVRAM_LEN) | ||
| 593 | count = DS1305_NVRAM_LEN - off; | ||
| 594 | if (unlikely(!count)) | ||
| 595 | return count; | ||
| 596 | |||
| 597 | addr = (DS1305_WRITE | DS1305_NVRAM) + off; | ||
| 598 | msg_init(&m, x, &addr, count, buf, NULL); | ||
| 599 | |||
| 600 | status = spi_sync(spi, &m); | ||
| 601 | if (status < 0) | ||
| 602 | dev_err(&spi->dev, "nvram %s error %d\n", "write", status); | ||
| 603 | return (status < 0) ? status : count; | ||
| 604 | } | ||
| 605 | |||
| 606 | static struct bin_attribute nvram = { | ||
| 607 | .attr.name = "nvram", | ||
| 608 | .attr.mode = S_IRUGO | S_IWUSR, | ||
| 609 | .attr.owner = THIS_MODULE, | ||
| 610 | .read = ds1305_nvram_read, | ||
| 611 | .write = ds1305_nvram_write, | ||
| 612 | .size = DS1305_NVRAM_LEN, | ||
| 613 | }; | ||
| 614 | |||
| 615 | /*----------------------------------------------------------------------*/ | ||
| 616 | |||
| 617 | /* | ||
| 618 | * Interface to SPI stack | ||
| 619 | */ | ||
| 620 | |||
| 621 | static int __devinit ds1305_probe(struct spi_device *spi) | ||
| 622 | { | ||
| 623 | struct ds1305 *ds1305; | ||
| 624 | struct rtc_device *rtc; | ||
| 625 | int status; | ||
| 626 | u8 addr, value; | ||
| 627 | struct ds1305_platform_data *pdata = spi->dev.platform_data; | ||
| 628 | bool write_ctrl = false; | ||
| 629 | |||
| 630 | /* Sanity check board setup data. This may be hooked up | ||
| 631 | * in 3wire mode, but we don't care. Note that unless | ||
| 632 | * there's an inverter in place, this needs SPI_CS_HIGH! | ||
| 633 | */ | ||
| 634 | if ((spi->bits_per_word && spi->bits_per_word != 8) | ||
| 635 | || (spi->max_speed_hz > 2000000) | ||
| 636 | || !(spi->mode & SPI_CPHA)) | ||
| 637 | return -EINVAL; | ||
| 638 | |||
| 639 | /* set up driver data */ | ||
| 640 | ds1305 = kzalloc(sizeof *ds1305, GFP_KERNEL); | ||
| 641 | if (!ds1305) | ||
| 642 | return -ENOMEM; | ||
| 643 | ds1305->spi = spi; | ||
| 644 | spi_set_drvdata(spi, ds1305); | ||
| 645 | |||
| 646 | /* read and cache control registers */ | ||
| 647 | addr = DS1305_CONTROL; | ||
| 648 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
| 649 | ds1305->ctrl, sizeof ds1305->ctrl); | ||
| 650 | if (status < 0) { | ||
| 651 | dev_dbg(&spi->dev, "can't %s, %d\n", | ||
| 652 | "read", status); | ||
| 653 | goto fail0; | ||
| 654 | } | ||
| 655 | |||
| 656 | dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", | ||
| 657 | "read", ds1305->ctrl[0], | ||
| 658 | ds1305->ctrl[1], ds1305->ctrl[2]); | ||
| 659 | |||
| 660 | /* Sanity check register values ... partially compensating for the | ||
| 661 | * fact that SPI has no device handshake. A pullup on MISO would | ||
| 662 | * make these tests fail; but not all systems will have one. If | ||
| 663 | * some register is neither 0x00 nor 0xff, a chip is likely there. | ||
| 664 | */ | ||
| 665 | if ((ds1305->ctrl[0] & 0x38) != 0 || (ds1305->ctrl[1] & 0xfc) != 0) { | ||
| 666 | dev_dbg(&spi->dev, "RTC chip is not present\n"); | ||
| 667 | status = -ENODEV; | ||
| 668 | goto fail0; | ||
| 669 | } | ||
| 670 | if (ds1305->ctrl[2] == 0) | ||
| 671 | dev_dbg(&spi->dev, "chip may not be present\n"); | ||
| 672 | |||
| 673 | /* enable writes if needed ... if we were paranoid it would | ||
| 674 | * make sense to enable them only when absolutely necessary. | ||
| 675 | */ | ||
| 676 | if (ds1305->ctrl[0] & DS1305_WP) { | ||
| 677 | u8 buf[2]; | ||
| 678 | |||
| 679 | ds1305->ctrl[0] &= ~DS1305_WP; | ||
| 680 | |||
| 681 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
| 682 | buf[1] = ds1305->ctrl[0]; | ||
| 683 | status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0); | ||
| 684 | |||
| 685 | dev_dbg(&spi->dev, "clear WP --> %d\n", status); | ||
| 686 | if (status < 0) | ||
| 687 | goto fail0; | ||
| 688 | } | ||
| 689 | |||
| 690 | /* on DS1305, maybe start oscillator; like most low power | ||
| 691 | * oscillators, it may take a second to stabilize | ||
| 692 | */ | ||
| 693 | if (ds1305->ctrl[0] & DS1305_nEOSC) { | ||
| 694 | ds1305->ctrl[0] &= ~DS1305_nEOSC; | ||
| 695 | write_ctrl = true; | ||
| 696 | dev_warn(&spi->dev, "SET TIME!\n"); | ||
| 697 | } | ||
| 698 | |||
| 699 | /* ack any pending IRQs */ | ||
| 700 | if (ds1305->ctrl[1]) { | ||
| 701 | ds1305->ctrl[1] = 0; | ||
| 702 | write_ctrl = true; | ||
| 703 | } | ||
| 704 | |||
| 705 | /* this may need one-time (re)init */ | ||
| 706 | if (pdata) { | ||
| 707 | /* maybe enable trickle charge */ | ||
| 708 | if (((ds1305->ctrl[2] & 0xf0) != DS1305_TRICKLE_MAGIC)) { | ||
| 709 | ds1305->ctrl[2] = DS1305_TRICKLE_MAGIC | ||
| 710 | | pdata->trickle; | ||
| 711 | write_ctrl = true; | ||
| 712 | } | ||
| 713 | |||
| 714 | /* on DS1306, configure 1 Hz signal */ | ||
| 715 | if (pdata->is_ds1306) { | ||
| 716 | if (pdata->en_1hz) { | ||
| 717 | if (!(ds1305->ctrl[0] & DS1306_1HZ)) { | ||
| 718 | ds1305->ctrl[0] |= DS1306_1HZ; | ||
| 719 | write_ctrl = true; | ||
| 720 | } | ||
| 721 | } else { | ||
| 722 | if (ds1305->ctrl[0] & DS1306_1HZ) { | ||
| 723 | ds1305->ctrl[0] &= ~DS1306_1HZ; | ||
| 724 | write_ctrl = true; | ||
| 725 | } | ||
| 726 | } | ||
| 727 | } | ||
| 728 | } | ||
| 729 | |||
| 730 | if (write_ctrl) { | ||
| 731 | u8 buf[4]; | ||
| 732 | |||
| 733 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
| 734 | buf[1] = ds1305->ctrl[0]; | ||
| 735 | buf[2] = ds1305->ctrl[1]; | ||
| 736 | buf[3] = ds1305->ctrl[2]; | ||
| 737 | status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0); | ||
| 738 | if (status < 0) { | ||
| 739 | dev_dbg(&spi->dev, "can't %s, %d\n", | ||
| 740 | "write", status); | ||
| 741 | goto fail0; | ||
| 742 | } | ||
| 743 | |||
| 744 | dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", | ||
| 745 | "write", ds1305->ctrl[0], | ||
| 746 | ds1305->ctrl[1], ds1305->ctrl[2]); | ||
| 747 | } | ||
| 748 | |||
| 749 | /* see if non-Linux software set up AM/PM mode */ | ||
| 750 | addr = DS1305_HOUR; | ||
| 751 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
| 752 | &value, sizeof value); | ||
| 753 | if (status < 0) { | ||
| 754 | dev_dbg(&spi->dev, "read HOUR --> %d\n", status); | ||
| 755 | goto fail0; | ||
| 756 | } | ||
| 757 | |||
| 758 | ds1305->hr12 = (DS1305_HR_12 & value) != 0; | ||
| 759 | if (ds1305->hr12) | ||
| 760 | dev_dbg(&spi->dev, "AM/PM\n"); | ||
| 761 | |||
| 762 | /* register RTC ... from here on, ds1305->ctrl needs locking */ | ||
| 763 | rtc = rtc_device_register("ds1305", &spi->dev, | ||
| 764 | &ds1305_ops, THIS_MODULE); | ||
| 765 | if (IS_ERR(rtc)) { | ||
| 766 | status = PTR_ERR(rtc); | ||
| 767 | dev_dbg(&spi->dev, "register rtc --> %d\n", status); | ||
| 768 | goto fail0; | ||
| 769 | } | ||
| 770 | ds1305->rtc = rtc; | ||
| 771 | |||
| 772 | /* Maybe set up alarm IRQ; be ready to handle it triggering right | ||
| 773 | * away. NOTE that we don't share this. The signal is active low, | ||
| 774 | * and we can't ack it before a SPI message delay. We temporarily | ||
| 775 | * disable the IRQ until it's acked, which lets us work with more | ||
| 776 | * IRQ trigger modes (not all IRQ controllers can do falling edge). | ||
| 777 | */ | ||
| 778 | if (spi->irq) { | ||
| 779 | INIT_WORK(&ds1305->work, ds1305_work); | ||
| 780 | status = request_irq(spi->irq, ds1305_irq, | ||
| 781 | 0, dev_name(&rtc->dev), ds1305); | ||
| 782 | if (status < 0) { | ||
| 783 | dev_dbg(&spi->dev, "request_irq %d --> %d\n", | ||
| 784 | spi->irq, status); | ||
| 785 | goto fail1; | ||
| 786 | } | ||
| 787 | } | ||
| 788 | |||
| 789 | /* export NVRAM */ | ||
| 790 | status = sysfs_create_bin_file(&spi->dev.kobj, &nvram); | ||
| 791 | if (status < 0) { | ||
| 792 | dev_dbg(&spi->dev, "register nvram --> %d\n", status); | ||
| 793 | goto fail2; | ||
| 794 | } | ||
| 795 | |||
| 796 | return 0; | ||
| 797 | |||
| 798 | fail2: | ||
| 799 | free_irq(spi->irq, ds1305); | ||
| 800 | fail1: | ||
| 801 | rtc_device_unregister(rtc); | ||
| 802 | fail0: | ||
| 803 | kfree(ds1305); | ||
| 804 | return status; | ||
| 805 | } | ||
| 806 | |||
| 807 | static int __devexit ds1305_remove(struct spi_device *spi) | ||
| 808 | { | ||
| 809 | struct ds1305 *ds1305 = spi_get_drvdata(spi); | ||
| 810 | |||
| 811 | sysfs_remove_bin_file(&spi->dev.kobj, &nvram); | ||
| 812 | |||
| 813 | /* carefully shut down irq and workqueue, if present */ | ||
| 814 | if (spi->irq) { | ||
| 815 | set_bit(FLAG_EXITING, &ds1305->flags); | ||
| 816 | free_irq(spi->irq, ds1305); | ||
| 817 | flush_scheduled_work(); | ||
| 818 | } | ||
| 819 | |||
| 820 | rtc_device_unregister(ds1305->rtc); | ||
| 821 | spi_set_drvdata(spi, NULL); | ||
| 822 | kfree(ds1305); | ||
| 823 | return 0; | ||
| 824 | } | ||
| 825 | |||
| 826 | static struct spi_driver ds1305_driver = { | ||
| 827 | .driver.name = "rtc-ds1305", | ||
| 828 | .driver.owner = THIS_MODULE, | ||
| 829 | .probe = ds1305_probe, | ||
| 830 | .remove = __devexit_p(ds1305_remove), | ||
| 831 | /* REVISIT add suspend/resume */ | ||
| 832 | }; | ||
| 833 | |||
| 834 | static int __init ds1305_init(void) | ||
| 835 | { | ||
| 836 | return spi_register_driver(&ds1305_driver); | ||
| 837 | } | ||
| 838 | module_init(ds1305_init); | ||
| 839 | |||
| 840 | static void __exit ds1305_exit(void) | ||
| 841 | { | ||
| 842 | spi_unregister_driver(&ds1305_driver); | ||
| 843 | } | ||
| 844 | module_exit(ds1305_exit); | ||
| 845 | |||
| 846 | MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips"); | ||
| 847 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 1e99325270df..36e4ac0bd69c 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <asm/hardware.h> | 15 | #include <mach/hardware.h> |
| 16 | 16 | ||
| 17 | #define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) | 17 | #define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) |
| 18 | #define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) | 18 | #define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) |
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index fbb90b1e4098..a81adab6e515 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c | |||
| @@ -482,7 +482,7 @@ isl1208_sysfs_register(struct device *dev) | |||
| 482 | static int | 482 | static int |
| 483 | isl1208_sysfs_unregister(struct device *dev) | 483 | isl1208_sysfs_unregister(struct device *dev) |
| 484 | { | 484 | { |
| 485 | device_remove_file(dev, &dev_attr_atrim); | 485 | device_remove_file(dev, &dev_attr_dtrim); |
| 486 | device_remove_file(dev, &dev_attr_atrim); | 486 | device_remove_file(dev, &dev_attr_atrim); |
| 487 | device_remove_file(dev, &dev_attr_usr); | 487 | device_remove_file(dev, &dev_attr_usr); |
| 488 | 488 | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 0a19c06019be..24bc1689fc74 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
| @@ -13,21 +13,21 @@ | |||
| 13 | * | 13 | * |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/module.h> | 16 | #include <linux/bcd.h> |
| 17 | #include <linux/i2c.h> | ||
| 17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 18 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/rtc.h> | ||
| 19 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 20 | #include <linux/smp_lock.h> | 23 | #include <linux/smp_lock.h> |
| 21 | #include <linux/string.h> | 24 | #include <linux/string.h> |
| 22 | #include <linux/i2c.h> | ||
| 23 | #include <linux/rtc.h> | ||
| 24 | #include <linux/bcd.h> | ||
| 25 | #ifdef CONFIG_RTC_DRV_M41T80_WDT | 25 | #ifdef CONFIG_RTC_DRV_M41T80_WDT |
| 26 | #include <linux/miscdevice.h> | ||
| 27 | #include <linux/watchdog.h> | ||
| 28 | #include <linux/reboot.h> | ||
| 29 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
| 30 | #include <linux/ioctl.h> | 27 | #include <linux/ioctl.h> |
| 28 | #include <linux/miscdevice.h> | ||
| 29 | #include <linux/reboot.h> | ||
| 30 | #include <linux/watchdog.h> | ||
| 31 | #endif | 31 | #endif |
| 32 | 32 | ||
| 33 | #define M41T80_REG_SSEC 0 | 33 | #define M41T80_REG_SSEC 0 |
| @@ -631,14 +631,12 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 631 | return -EFAULT; | 631 | return -EFAULT; |
| 632 | 632 | ||
| 633 | if (rv & WDIOS_DISABLECARD) { | 633 | if (rv & WDIOS_DISABLECARD) { |
| 634 | printk(KERN_INFO | 634 | pr_info("rtc-m41t80: disable watchdog\n"); |
| 635 | "rtc-m41t80: disable watchdog\n"); | ||
| 636 | wdt_disable(); | 635 | wdt_disable(); |
| 637 | } | 636 | } |
| 638 | 637 | ||
| 639 | if (rv & WDIOS_ENABLECARD) { | 638 | if (rv & WDIOS_ENABLECARD) { |
| 640 | printk(KERN_INFO | 639 | pr_info("rtc-m41t80: enable watchdog\n"); |
| 641 | "rtc-m41t80: enable watchdog\n"); | ||
| 642 | wdt_ping(); | 640 | wdt_ping(); |
| 643 | } | 641 | } |
| 644 | 642 | ||
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c new file mode 100644 index 000000000000..9b19499c829e --- /dev/null +++ b/drivers/rtc/rtc-m41t94.c | |||
| @@ -0,0 +1,173 @@ | |||
| 1 | /* | ||
| 2 | * Driver for ST M41T94 SPI RTC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Kim B. Heino | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/rtc.h> | ||
| 15 | #include <linux/spi/spi.h> | ||
| 16 | #include <linux/bcd.h> | ||
| 17 | |||
| 18 | #define M41T94_REG_SECONDS 0x01 | ||
| 19 | #define M41T94_REG_MINUTES 0x02 | ||
| 20 | #define M41T94_REG_HOURS 0x03 | ||
| 21 | #define M41T94_REG_WDAY 0x04 | ||
| 22 | #define M41T94_REG_DAY 0x05 | ||
| 23 | #define M41T94_REG_MONTH 0x06 | ||
| 24 | #define M41T94_REG_YEAR 0x07 | ||
| 25 | #define M41T94_REG_HT 0x0c | ||
| 26 | |||
| 27 | #define M41T94_BIT_HALT 0x40 | ||
| 28 | #define M41T94_BIT_STOP 0x80 | ||
| 29 | #define M41T94_BIT_CB 0x40 | ||
| 30 | #define M41T94_BIT_CEB 0x80 | ||
| 31 | |||
| 32 | static int m41t94_set_time(struct device *dev, struct rtc_time *tm) | ||
| 33 | { | ||
| 34 | struct spi_device *spi = to_spi_device(dev); | ||
| 35 | u8 buf[8]; /* write cmd + 7 registers */ | ||
| 36 | |||
| 37 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
| 38 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 39 | "write", tm->tm_sec, tm->tm_min, | ||
| 40 | tm->tm_hour, tm->tm_mday, | ||
| 41 | tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 42 | |||
| 43 | buf[0] = 0x80 | M41T94_REG_SECONDS; /* write time + date */ | ||
| 44 | buf[M41T94_REG_SECONDS] = BIN2BCD(tm->tm_sec); | ||
| 45 | buf[M41T94_REG_MINUTES] = BIN2BCD(tm->tm_min); | ||
| 46 | buf[M41T94_REG_HOURS] = BIN2BCD(tm->tm_hour); | ||
| 47 | buf[M41T94_REG_WDAY] = BIN2BCD(tm->tm_wday + 1); | ||
| 48 | buf[M41T94_REG_DAY] = BIN2BCD(tm->tm_mday); | ||
| 49 | buf[M41T94_REG_MONTH] = BIN2BCD(tm->tm_mon + 1); | ||
| 50 | |||
| 51 | buf[M41T94_REG_HOURS] |= M41T94_BIT_CEB; | ||
| 52 | if (tm->tm_year >= 100) | ||
| 53 | buf[M41T94_REG_HOURS] |= M41T94_BIT_CB; | ||
| 54 | buf[M41T94_REG_YEAR] = BIN2BCD(tm->tm_year % 100); | ||
| 55 | |||
| 56 | return spi_write(spi, buf, 8); | ||
| 57 | } | ||
| 58 | |||
| 59 | static int m41t94_read_time(struct device *dev, struct rtc_time *tm) | ||
| 60 | { | ||
| 61 | struct spi_device *spi = to_spi_device(dev); | ||
| 62 | u8 buf[2]; | ||
| 63 | int ret, hour; | ||
| 64 | |||
| 65 | /* clear halt update bit */ | ||
| 66 | ret = spi_w8r8(spi, M41T94_REG_HT); | ||
| 67 | if (ret < 0) | ||
| 68 | return ret; | ||
| 69 | if (ret & M41T94_BIT_HALT) { | ||
| 70 | buf[0] = 0x80 | M41T94_REG_HT; | ||
| 71 | buf[1] = ret & ~M41T94_BIT_HALT; | ||
| 72 | spi_write(spi, buf, 2); | ||
| 73 | } | ||
| 74 | |||
| 75 | /* clear stop bit */ | ||
| 76 | ret = spi_w8r8(spi, M41T94_REG_SECONDS); | ||
| 77 | if (ret < 0) | ||
| 78 | return ret; | ||
| 79 | if (ret & M41T94_BIT_STOP) { | ||
| 80 | buf[0] = 0x80 | M41T94_REG_SECONDS; | ||
| 81 | buf[1] = ret & ~M41T94_BIT_STOP; | ||
| 82 | spi_write(spi, buf, 2); | ||
| 83 | } | ||
| 84 | |||
| 85 | tm->tm_sec = BCD2BIN(spi_w8r8(spi, M41T94_REG_SECONDS)); | ||
| 86 | tm->tm_min = BCD2BIN(spi_w8r8(spi, M41T94_REG_MINUTES)); | ||
| 87 | hour = spi_w8r8(spi, M41T94_REG_HOURS); | ||
| 88 | tm->tm_hour = BCD2BIN(hour & 0x3f); | ||
| 89 | tm->tm_wday = BCD2BIN(spi_w8r8(spi, M41T94_REG_WDAY)) - 1; | ||
| 90 | tm->tm_mday = BCD2BIN(spi_w8r8(spi, M41T94_REG_DAY)); | ||
| 91 | tm->tm_mon = BCD2BIN(spi_w8r8(spi, M41T94_REG_MONTH)) - 1; | ||
| 92 | tm->tm_year = BCD2BIN(spi_w8r8(spi, M41T94_REG_YEAR)); | ||
| 93 | if ((hour & M41T94_BIT_CB) || !(hour & M41T94_BIT_CEB)) | ||
| 94 | tm->tm_year += 100; | ||
| 95 | |||
| 96 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
| 97 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 98 | "read", tm->tm_sec, tm->tm_min, | ||
| 99 | tm->tm_hour, tm->tm_mday, | ||
| 100 | tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 101 | |||
| 102 | /* initial clock setting can be undefined */ | ||
| 103 | return rtc_valid_tm(tm); | ||
| 104 | } | ||
| 105 | |||
| 106 | static const struct rtc_class_ops m41t94_rtc_ops = { | ||
| 107 | .read_time = m41t94_read_time, | ||
| 108 | .set_time = m41t94_set_time, | ||
| 109 | }; | ||
| 110 | |||
| 111 | static struct spi_driver m41t94_driver; | ||
| 112 | |||
| 113 | static int __devinit m41t94_probe(struct spi_device *spi) | ||
| 114 | { | ||
| 115 | struct rtc_device *rtc; | ||
| 116 | int res; | ||
| 117 | |||
| 118 | spi->bits_per_word = 8; | ||
| 119 | spi_setup(spi); | ||
| 120 | |||
| 121 | res = spi_w8r8(spi, M41T94_REG_SECONDS); | ||
| 122 | if (res < 0) { | ||
| 123 | dev_err(&spi->dev, "not found.\n"); | ||
| 124 | return res; | ||
| 125 | } | ||
| 126 | |||
| 127 | rtc = rtc_device_register(m41t94_driver.driver.name, | ||
| 128 | &spi->dev, &m41t94_rtc_ops, THIS_MODULE); | ||
| 129 | if (IS_ERR(rtc)) | ||
| 130 | return PTR_ERR(rtc); | ||
| 131 | |||
| 132 | dev_set_drvdata(&spi->dev, rtc); | ||
| 133 | |||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | static int __devexit m41t94_remove(struct spi_device *spi) | ||
| 138 | { | ||
| 139 | struct rtc_device *rtc = platform_get_drvdata(spi); | ||
| 140 | |||
| 141 | if (rtc) | ||
| 142 | rtc_device_unregister(rtc); | ||
| 143 | |||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | |||
| 147 | static struct spi_driver m41t94_driver = { | ||
| 148 | .driver = { | ||
| 149 | .name = "rtc-m41t94", | ||
| 150 | .bus = &spi_bus_type, | ||
| 151 | .owner = THIS_MODULE, | ||
| 152 | }, | ||
| 153 | .probe = m41t94_probe, | ||
| 154 | .remove = __devexit_p(m41t94_remove), | ||
| 155 | }; | ||
| 156 | |||
| 157 | static __init int m41t94_init(void) | ||
| 158 | { | ||
| 159 | return spi_register_driver(&m41t94_driver); | ||
| 160 | } | ||
| 161 | |||
| 162 | module_init(m41t94_init); | ||
| 163 | |||
| 164 | static __exit void m41t94_exit(void) | ||
| 165 | { | ||
| 166 | spi_unregister_driver(&m41t94_driver); | ||
| 167 | } | ||
| 168 | |||
| 169 | module_exit(m41t94_exit); | ||
| 170 | |||
| 171 | MODULE_AUTHOR("Kim B. Heino <Kim.Heino@bluegiga.com>"); | ||
| 172 | MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC"); | ||
| 173 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index eb23d8423f42..8876605d4d4b 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
| @@ -92,18 +92,6 @@ | |||
| 92 | #define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr)) | 92 | #define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr)) |
| 93 | 93 | ||
| 94 | 94 | ||
| 95 | /* platform_bus isn't hotpluggable, so for static linkage it'd be safe | ||
| 96 | * to get rid of probe() and remove() code ... too bad the driver struct | ||
| 97 | * remembers probe(), that's about 25% of the runtime footprint!! | ||
| 98 | */ | ||
| 99 | #ifndef MODULE | ||
| 100 | #undef __devexit | ||
| 101 | #undef __devexit_p | ||
| 102 | #define __devexit __exit | ||
| 103 | #define __devexit_p __exit_p | ||
| 104 | #endif | ||
| 105 | |||
| 106 | |||
| 107 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), | 95 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), |
| 108 | * so the only other requirement is that register accesses which | 96 | * so the only other requirement is that register accesses which |
| 109 | * require BUSY to be clear are made with IRQs locally disabled | 97 | * require BUSY to be clear are made with IRQs locally disabled |
| @@ -324,7 +312,7 @@ static struct rtc_class_ops omap_rtc_ops = { | |||
| 324 | static int omap_rtc_alarm; | 312 | static int omap_rtc_alarm; |
| 325 | static int omap_rtc_timer; | 313 | static int omap_rtc_timer; |
| 326 | 314 | ||
| 327 | static int __devinit omap_rtc_probe(struct platform_device *pdev) | 315 | static int __init omap_rtc_probe(struct platform_device *pdev) |
| 328 | { | 316 | { |
| 329 | struct resource *res, *mem; | 317 | struct resource *res, *mem; |
| 330 | struct rtc_device *rtc; | 318 | struct rtc_device *rtc; |
| @@ -440,7 +428,7 @@ fail: | |||
| 440 | return -EIO; | 428 | return -EIO; |
| 441 | } | 429 | } |
| 442 | 430 | ||
| 443 | static int __devexit omap_rtc_remove(struct platform_device *pdev) | 431 | static int __exit omap_rtc_remove(struct platform_device *pdev) |
| 444 | { | 432 | { |
| 445 | struct rtc_device *rtc = platform_get_drvdata(pdev);; | 433 | struct rtc_device *rtc = platform_get_drvdata(pdev);; |
| 446 | 434 | ||
| @@ -498,8 +486,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev) | |||
| 498 | 486 | ||
| 499 | MODULE_ALIAS("platform:omap_rtc"); | 487 | MODULE_ALIAS("platform:omap_rtc"); |
| 500 | static struct platform_driver omap_rtc_driver = { | 488 | static struct platform_driver omap_rtc_driver = { |
| 501 | .probe = omap_rtc_probe, | 489 | .remove = __exit_p(omap_rtc_remove), |
| 502 | .remove = __devexit_p(omap_rtc_remove), | ||
| 503 | .suspend = omap_rtc_suspend, | 490 | .suspend = omap_rtc_suspend, |
| 504 | .resume = omap_rtc_resume, | 491 | .resume = omap_rtc_resume, |
| 505 | .shutdown = omap_rtc_shutdown, | 492 | .shutdown = omap_rtc_shutdown, |
| @@ -511,7 +498,7 @@ static struct platform_driver omap_rtc_driver = { | |||
| 511 | 498 | ||
| 512 | static int __init rtc_init(void) | 499 | static int __init rtc_init(void) |
| 513 | { | 500 | { |
| 514 | return platform_driver_register(&omap_rtc_driver); | 501 | return platform_driver_probe(&omap_rtc_driver, omap_rtc_probe); |
| 515 | } | 502 | } |
| 516 | module_init(rtc_init); | 503 | module_init(rtc_init); |
| 517 | 504 | ||
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 3d09d8f0b1f0..d388c662bf4b 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * drivers/rtc/rtc-pcf8583.c | 2 | * drivers/rtc/rtc-pcf8583.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2000 Russell King | 4 | * Copyright (C) 2000 Russell King |
| 5 | * Copyright (C) 2008 Wolfram Sang & Juergen Beisert, Pengutronix | ||
| 5 | * | 6 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
| @@ -14,7 +15,6 @@ | |||
| 14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 15 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
| 16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 17 | #include <linux/string.h> | ||
| 18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
| @@ -27,7 +27,6 @@ struct rtc_mem { | |||
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | struct pcf8583 { | 29 | struct pcf8583 { |
| 30 | struct i2c_client client; | ||
| 31 | struct rtc_device *rtc; | 30 | struct rtc_device *rtc; |
| 32 | unsigned char ctrl; | 31 | unsigned char ctrl; |
| 33 | }; | 32 | }; |
| @@ -40,10 +39,6 @@ struct pcf8583 { | |||
| 40 | #define CTRL_ALARM 0x02 | 39 | #define CTRL_ALARM 0x02 |
| 41 | #define CTRL_TIMER 0x01 | 40 | #define CTRL_TIMER 0x01 |
| 42 | 41 | ||
| 43 | static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; | ||
| 44 | |||
| 45 | /* Module parameters */ | ||
| 46 | I2C_CLIENT_INSMOD; | ||
| 47 | 42 | ||
| 48 | static struct i2c_driver pcf8583_driver; | 43 | static struct i2c_driver pcf8583_driver; |
| 49 | 44 | ||
| @@ -269,106 +264,60 @@ static const struct rtc_class_ops pcf8583_rtc_ops = { | |||
| 269 | .set_time = pcf8583_rtc_set_time, | 264 | .set_time = pcf8583_rtc_set_time, |
| 270 | }; | 265 | }; |
| 271 | 266 | ||
| 272 | static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind); | 267 | static int pcf8583_probe(struct i2c_client *client, |
| 273 | 268 | const struct i2c_device_id *id) | |
| 274 | static int pcf8583_attach(struct i2c_adapter *adap) | ||
| 275 | { | ||
| 276 | return i2c_probe(adap, &addr_data, pcf8583_probe); | ||
| 277 | } | ||
| 278 | |||
| 279 | static int pcf8583_detach(struct i2c_client *client) | ||
| 280 | { | ||
| 281 | int err; | ||
| 282 | struct pcf8583 *pcf = i2c_get_clientdata(client); | ||
| 283 | struct rtc_device *rtc = pcf->rtc; | ||
| 284 | |||
| 285 | if (rtc) | ||
| 286 | rtc_device_unregister(rtc); | ||
| 287 | |||
| 288 | if ((err = i2c_detach_client(client))) | ||
| 289 | return err; | ||
| 290 | |||
| 291 | kfree(pcf); | ||
| 292 | return 0; | ||
| 293 | } | ||
| 294 | |||
| 295 | static struct i2c_driver pcf8583_driver = { | ||
| 296 | .driver = { | ||
| 297 | .name = "pcf8583", | ||
| 298 | }, | ||
| 299 | .id = I2C_DRIVERID_PCF8583, | ||
| 300 | .attach_adapter = pcf8583_attach, | ||
| 301 | .detach_client = pcf8583_detach, | ||
| 302 | }; | ||
| 303 | |||
| 304 | static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind) | ||
| 305 | { | 269 | { |
| 306 | struct pcf8583 *pcf; | 270 | struct pcf8583 *pcf8583; |
| 307 | struct i2c_client *client; | ||
| 308 | struct rtc_device *rtc; | ||
| 309 | unsigned char buf[1], ad[1] = { 0 }; | ||
| 310 | int err; | 271 | int err; |
| 311 | struct i2c_msg msgs[2] = { | ||
| 312 | { | ||
| 313 | .addr = addr, | ||
| 314 | .flags = 0, | ||
| 315 | .len = 1, | ||
| 316 | .buf = ad, | ||
| 317 | }, { | ||
| 318 | .addr = addr, | ||
| 319 | .flags = I2C_M_RD, | ||
| 320 | .len = 1, | ||
| 321 | .buf = buf, | ||
| 322 | } | ||
| 323 | }; | ||
| 324 | 272 | ||
| 325 | if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) | 273 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
| 326 | return 0; | 274 | return -ENODEV; |
| 327 | 275 | ||
| 328 | pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); | 276 | pcf8583 = kzalloc(sizeof(struct pcf8583), GFP_KERNEL); |
| 329 | if (!pcf) | 277 | if (!pcf8583) |
| 330 | return -ENOMEM; | 278 | return -ENOMEM; |
| 331 | 279 | ||
| 332 | client = &pcf->client; | 280 | pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name, |
| 281 | &client->dev, &pcf8583_rtc_ops, THIS_MODULE); | ||
| 333 | 282 | ||
| 334 | client->addr = addr; | 283 | if (IS_ERR(pcf8583->rtc)) { |
| 335 | client->adapter = adap; | 284 | err = PTR_ERR(pcf8583->rtc); |
| 336 | client->driver = &pcf8583_driver; | ||
| 337 | |||
| 338 | strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE); | ||
| 339 | |||
| 340 | if (i2c_transfer(client->adapter, msgs, 2) != 2) { | ||
| 341 | err = -EIO; | ||
| 342 | goto exit_kfree; | 285 | goto exit_kfree; |
| 343 | } | 286 | } |
| 344 | 287 | ||
| 345 | err = i2c_attach_client(client); | 288 | i2c_set_clientdata(client, pcf8583); |
| 346 | 289 | return 0; | |
| 347 | if (err) | ||
| 348 | goto exit_kfree; | ||
| 349 | |||
| 350 | rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev, | ||
| 351 | &pcf8583_rtc_ops, THIS_MODULE); | ||
| 352 | 290 | ||
| 353 | if (IS_ERR(rtc)) { | 291 | exit_kfree: |
| 354 | err = PTR_ERR(rtc); | 292 | kfree(pcf8583); |
| 355 | goto exit_detach; | 293 | return err; |
| 356 | } | 294 | } |
| 357 | 295 | ||
| 358 | pcf->rtc = rtc; | 296 | static int __devexit pcf8583_remove(struct i2c_client *client) |
| 359 | i2c_set_clientdata(client, pcf); | 297 | { |
| 360 | set_ctrl(client, buf[0]); | 298 | struct pcf8583 *pcf8583 = i2c_get_clientdata(client); |
| 361 | 299 | ||
| 300 | if (pcf8583->rtc) | ||
| 301 | rtc_device_unregister(pcf8583->rtc); | ||
| 302 | kfree(pcf8583); | ||
| 362 | return 0; | 303 | return 0; |
| 304 | } | ||
| 363 | 305 | ||
| 364 | exit_detach: | 306 | static const struct i2c_device_id pcf8583_id[] = { |
| 365 | i2c_detach_client(client); | 307 | { "pcf8583", 0 }, |
| 366 | 308 | { } | |
| 367 | exit_kfree: | 309 | }; |
| 368 | kfree(pcf); | 310 | MODULE_DEVICE_TABLE(i2c, pcf8583_id); |
| 369 | 311 | ||
| 370 | return err; | 312 | static struct i2c_driver pcf8583_driver = { |
| 371 | } | 313 | .driver = { |
| 314 | .name = "pcf8583", | ||
| 315 | .owner = THIS_MODULE, | ||
| 316 | }, | ||
| 317 | .probe = pcf8583_probe, | ||
| 318 | .remove = __devexit_p(pcf8583_remove), | ||
| 319 | .id_table = pcf8583_id, | ||
| 320 | }; | ||
| 372 | 321 | ||
| 373 | static __init int pcf8583_init(void) | 322 | static __init int pcf8583_init(void) |
| 374 | { | 323 | { |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index fed86e507fdf..e7d19b6c265a 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
| 23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
| 24 | 24 | ||
| 25 | #include <asm/hardware.h> | 25 | #include <mach/hardware.h> |
| 26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
| 27 | #include <asm/io.h> | 27 | #include <asm/io.h> |
| 28 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
| @@ -36,10 +36,8 @@ static struct resource *s3c_rtc_mem; | |||
| 36 | static void __iomem *s3c_rtc_base; | 36 | static void __iomem *s3c_rtc_base; |
| 37 | static int s3c_rtc_alarmno = NO_IRQ; | 37 | static int s3c_rtc_alarmno = NO_IRQ; |
| 38 | static int s3c_rtc_tickno = NO_IRQ; | 38 | static int s3c_rtc_tickno = NO_IRQ; |
| 39 | static int s3c_rtc_freq = 1; | ||
| 40 | 39 | ||
| 41 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | 40 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); |
| 42 | static unsigned int tick_count; | ||
| 43 | 41 | ||
| 44 | /* IRQ Handlers */ | 42 | /* IRQ Handlers */ |
| 45 | 43 | ||
| @@ -55,7 +53,7 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
| 55 | { | 53 | { |
| 56 | struct rtc_device *rdev = id; | 54 | struct rtc_device *rdev = id; |
| 57 | 55 | ||
| 58 | rtc_update_irq(rdev, tick_count++, RTC_PF | RTC_IRQF); | 56 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
| 59 | return IRQ_HANDLED; | 57 | return IRQ_HANDLED; |
| 60 | } | 58 | } |
| 61 | 59 | ||
| @@ -74,35 +72,37 @@ static void s3c_rtc_setaie(int to) | |||
| 74 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); | 72 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); |
| 75 | } | 73 | } |
| 76 | 74 | ||
| 77 | static void s3c_rtc_setpie(int to) | 75 | static int s3c_rtc_setpie(struct device *dev, int enabled) |
| 78 | { | 76 | { |
| 79 | unsigned int tmp; | 77 | unsigned int tmp; |
| 80 | 78 | ||
| 81 | pr_debug("%s: pie=%d\n", __func__, to); | 79 | pr_debug("%s: pie=%d\n", __func__, enabled); |
| 82 | 80 | ||
| 83 | spin_lock_irq(&s3c_rtc_pie_lock); | 81 | spin_lock_irq(&s3c_rtc_pie_lock); |
| 84 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; | 82 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; |
| 85 | 83 | ||
| 86 | if (to) | 84 | if (enabled) |
| 87 | tmp |= S3C2410_TICNT_ENABLE; | 85 | tmp |= S3C2410_TICNT_ENABLE; |
| 88 | 86 | ||
| 89 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 87 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); |
| 90 | spin_unlock_irq(&s3c_rtc_pie_lock); | 88 | spin_unlock_irq(&s3c_rtc_pie_lock); |
| 89 | |||
| 90 | return 0; | ||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | static void s3c_rtc_setfreq(int freq) | 93 | static int s3c_rtc_setfreq(struct device *dev, int freq) |
| 94 | { | 94 | { |
| 95 | unsigned int tmp; | 95 | unsigned int tmp; |
| 96 | 96 | ||
| 97 | spin_lock_irq(&s3c_rtc_pie_lock); | 97 | spin_lock_irq(&s3c_rtc_pie_lock); |
| 98 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | ||
| 99 | |||
| 100 | s3c_rtc_freq = freq; | ||
| 101 | 98 | ||
| 99 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | ||
| 102 | tmp |= (128 / freq)-1; | 100 | tmp |= (128 / freq)-1; |
| 103 | 101 | ||
| 104 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 102 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); |
| 105 | spin_unlock_irq(&s3c_rtc_pie_lock); | 103 | spin_unlock_irq(&s3c_rtc_pie_lock); |
| 104 | |||
| 105 | return 0; | ||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /* Time read/write */ | 108 | /* Time read/write */ |
| @@ -267,12 +267,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 267 | 267 | ||
| 268 | writeb(alrm_en, base + S3C2410_RTCALM); | 268 | writeb(alrm_en, base + S3C2410_RTCALM); |
| 269 | 269 | ||
| 270 | if (0) { | 270 | s3c_rtc_setaie(alrm->enabled); |
| 271 | alrm_en = readb(base + S3C2410_RTCALM); | ||
| 272 | alrm_en &= ~S3C2410_RTCALM_ALMEN; | ||
| 273 | writeb(alrm_en, base + S3C2410_RTCALM); | ||
| 274 | disable_irq_wake(s3c_rtc_alarmno); | ||
| 275 | } | ||
| 276 | 271 | ||
| 277 | if (alrm->enabled) | 272 | if (alrm->enabled) |
| 278 | enable_irq_wake(s3c_rtc_alarmno); | 273 | enable_irq_wake(s3c_rtc_alarmno); |
| @@ -282,59 +277,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 282 | return 0; | 277 | return 0; |
| 283 | } | 278 | } |
| 284 | 279 | ||
| 285 | static int s3c_rtc_ioctl(struct device *dev, | ||
| 286 | unsigned int cmd, unsigned long arg) | ||
| 287 | { | ||
| 288 | unsigned int ret = -ENOIOCTLCMD; | ||
| 289 | |||
| 290 | switch (cmd) { | ||
| 291 | case RTC_AIE_OFF: | ||
| 292 | case RTC_AIE_ON: | ||
| 293 | s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0); | ||
| 294 | ret = 0; | ||
| 295 | break; | ||
| 296 | |||
| 297 | case RTC_PIE_OFF: | ||
| 298 | case RTC_PIE_ON: | ||
| 299 | tick_count = 0; | ||
| 300 | s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0); | ||
| 301 | ret = 0; | ||
| 302 | break; | ||
| 303 | |||
| 304 | case RTC_IRQP_READ: | ||
| 305 | ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg); | ||
| 306 | break; | ||
| 307 | |||
| 308 | case RTC_IRQP_SET: | ||
| 309 | if (!is_power_of_2(arg)) { | ||
| 310 | ret = -EINVAL; | ||
| 311 | goto exit; | ||
| 312 | } | ||
| 313 | |||
| 314 | pr_debug("s3c2410_rtc: setting frequency %ld\n", arg); | ||
| 315 | |||
| 316 | s3c_rtc_setfreq(arg); | ||
| 317 | ret = 0; | ||
| 318 | break; | ||
| 319 | |||
| 320 | case RTC_UIE_ON: | ||
| 321 | case RTC_UIE_OFF: | ||
| 322 | ret = -EINVAL; | ||
| 323 | } | ||
| 324 | |||
| 325 | exit: | ||
| 326 | return ret; | ||
| 327 | } | ||
| 328 | |||
| 329 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | 280 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) |
| 330 | { | 281 | { |
| 331 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 282 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); |
| 332 | 283 | ||
| 333 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 284 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
| 334 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); | 285 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); |
| 335 | |||
| 336 | seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq); | ||
| 337 | |||
| 338 | return 0; | 286 | return 0; |
| 339 | } | 287 | } |
| 340 | 288 | ||
| @@ -374,7 +322,7 @@ static void s3c_rtc_release(struct device *dev) | |||
| 374 | 322 | ||
| 375 | /* do not clear AIE here, it may be needed for wake */ | 323 | /* do not clear AIE here, it may be needed for wake */ |
| 376 | 324 | ||
| 377 | s3c_rtc_setpie(0); | 325 | s3c_rtc_setpie(dev, 0); |
| 378 | free_irq(s3c_rtc_alarmno, rtc_dev); | 326 | free_irq(s3c_rtc_alarmno, rtc_dev); |
| 379 | free_irq(s3c_rtc_tickno, rtc_dev); | 327 | free_irq(s3c_rtc_tickno, rtc_dev); |
| 380 | } | 328 | } |
| @@ -382,11 +330,12 @@ static void s3c_rtc_release(struct device *dev) | |||
| 382 | static const struct rtc_class_ops s3c_rtcops = { | 330 | static const struct rtc_class_ops s3c_rtcops = { |
| 383 | .open = s3c_rtc_open, | 331 | .open = s3c_rtc_open, |
| 384 | .release = s3c_rtc_release, | 332 | .release = s3c_rtc_release, |
| 385 | .ioctl = s3c_rtc_ioctl, | ||
| 386 | .read_time = s3c_rtc_gettime, | 333 | .read_time = s3c_rtc_gettime, |
| 387 | .set_time = s3c_rtc_settime, | 334 | .set_time = s3c_rtc_settime, |
| 388 | .read_alarm = s3c_rtc_getalarm, | 335 | .read_alarm = s3c_rtc_getalarm, |
| 389 | .set_alarm = s3c_rtc_setalarm, | 336 | .set_alarm = s3c_rtc_setalarm, |
| 337 | .irq_set_freq = s3c_rtc_setfreq, | ||
| 338 | .irq_set_state = s3c_rtc_setpie, | ||
| 390 | .proc = s3c_rtc_proc, | 339 | .proc = s3c_rtc_proc, |
| 391 | }; | 340 | }; |
| 392 | 341 | ||
| @@ -430,14 +379,14 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
| 430 | } | 379 | } |
| 431 | } | 380 | } |
| 432 | 381 | ||
| 433 | static int s3c_rtc_remove(struct platform_device *dev) | 382 | static int __devexit s3c_rtc_remove(struct platform_device *dev) |
| 434 | { | 383 | { |
| 435 | struct rtc_device *rtc = platform_get_drvdata(dev); | 384 | struct rtc_device *rtc = platform_get_drvdata(dev); |
| 436 | 385 | ||
| 437 | platform_set_drvdata(dev, NULL); | 386 | platform_set_drvdata(dev, NULL); |
| 438 | rtc_device_unregister(rtc); | 387 | rtc_device_unregister(rtc); |
| 439 | 388 | ||
| 440 | s3c_rtc_setpie(0); | 389 | s3c_rtc_setpie(&dev->dev, 0); |
| 441 | s3c_rtc_setaie(0); | 390 | s3c_rtc_setaie(0); |
| 442 | 391 | ||
| 443 | iounmap(s3c_rtc_base); | 392 | iounmap(s3c_rtc_base); |
| @@ -447,7 +396,7 @@ static int s3c_rtc_remove(struct platform_device *dev) | |||
| 447 | return 0; | 396 | return 0; |
| 448 | } | 397 | } |
| 449 | 398 | ||
| 450 | static int s3c_rtc_probe(struct platform_device *pdev) | 399 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) |
| 451 | { | 400 | { |
| 452 | struct rtc_device *rtc; | 401 | struct rtc_device *rtc; |
| 453 | struct resource *res; | 402 | struct resource *res; |
| @@ -504,7 +453,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) | |||
| 504 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 453 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
| 505 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 454 | readb(s3c_rtc_base + S3C2410_RTCCON)); |
| 506 | 455 | ||
| 507 | s3c_rtc_setfreq(s3c_rtc_freq); | 456 | s3c_rtc_setfreq(&pdev->dev, 1); |
| 508 | 457 | ||
| 509 | /* register RTC and exit */ | 458 | /* register RTC and exit */ |
| 510 | 459 | ||
| @@ -560,7 +509,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
| 560 | 509 | ||
| 561 | static struct platform_driver s3c2410_rtcdrv = { | 510 | static struct platform_driver s3c2410_rtcdrv = { |
| 562 | .probe = s3c_rtc_probe, | 511 | .probe = s3c_rtc_probe, |
| 563 | .remove = s3c_rtc_remove, | 512 | .remove = __devexit_p(s3c_rtc_remove), |
| 564 | .suspend = s3c_rtc_suspend, | 513 | .suspend = s3c_rtc_suspend, |
| 565 | .resume = s3c_rtc_resume, | 514 | .resume = s3c_rtc_resume, |
| 566 | .driver = { | 515 | .driver = { |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index f47294c60148..66a9bb85bbe8 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
| @@ -31,11 +31,11 @@ | |||
| 31 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
| 32 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
| 33 | 33 | ||
| 34 | #include <asm/hardware.h> | 34 | #include <mach/hardware.h> |
| 35 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
| 36 | 36 | ||
| 37 | #ifdef CONFIG_ARCH_PXA | 37 | #ifdef CONFIG_ARCH_PXA |
| 38 | #include <asm/arch/pxa-regs.h> | 38 | #include <mach/pxa-regs.h> |
| 39 | #endif | 39 | #endif |
| 40 | 40 | ||
| 41 | #define TIMER_FREQ CLOCK_TICK_RATE | 41 | #define TIMER_FREQ CLOCK_TICK_RATE |
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index be9c70d0b193..884b635f028b 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Driver for NEC VR4100 series Real Time Clock unit. | 2 | * Driver for NEC VR4100 series Real Time Clock unit. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| @@ -34,7 +34,7 @@ | |||
| 34 | 34 | ||
| 35 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 35 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); |
| 36 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); | 36 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); |
| 37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL v2"); |
| 38 | 38 | ||
| 39 | /* RTC 1 registers */ | 39 | /* RTC 1 registers */ |
| 40 | #define ETIMELREG 0x00 | 40 | #define ETIMELREG 0x00 |
| @@ -82,7 +82,6 @@ static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */ | |||
| 82 | 82 | ||
| 83 | static DEFINE_SPINLOCK(rtc_lock); | 83 | static DEFINE_SPINLOCK(rtc_lock); |
| 84 | static char rtc_name[] = "RTC"; | 84 | static char rtc_name[] = "RTC"; |
| 85 | static unsigned long periodic_frequency; | ||
| 86 | static unsigned long periodic_count; | 85 | static unsigned long periodic_count; |
| 87 | static unsigned int alarm_enabled; | 86 | static unsigned int alarm_enabled; |
| 88 | static int aie_irq = -1; | 87 | static int aie_irq = -1; |
| @@ -207,10 +206,37 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
| 207 | return 0; | 206 | return 0; |
| 208 | } | 207 | } |
| 209 | 208 | ||
| 210 | static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 209 | static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq) |
| 211 | { | 210 | { |
| 212 | unsigned long count; | 211 | unsigned long count; |
| 213 | 212 | ||
| 213 | count = RTC_FREQUENCY; | ||
| 214 | do_div(count, freq); | ||
| 215 | |||
| 216 | periodic_count = count; | ||
| 217 | |||
| 218 | spin_lock_irq(&rtc_lock); | ||
| 219 | |||
| 220 | rtc1_write(RTCL1LREG, count); | ||
| 221 | rtc1_write(RTCL1HREG, count >> 16); | ||
| 222 | |||
| 223 | spin_unlock_irq(&rtc_lock); | ||
| 224 | |||
| 225 | return 0; | ||
| 226 | } | ||
| 227 | |||
| 228 | static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled) | ||
| 229 | { | ||
| 230 | if (enabled) | ||
| 231 | enable_irq(pie_irq); | ||
| 232 | else | ||
| 233 | disable_irq(pie_irq); | ||
| 234 | |||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
| 239 | { | ||
| 214 | switch (cmd) { | 240 | switch (cmd) { |
| 215 | case RTC_AIE_ON: | 241 | case RTC_AIE_ON: |
| 216 | spin_lock_irq(&rtc_lock); | 242 | spin_lock_irq(&rtc_lock); |
| @@ -232,33 +258,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long | |||
| 232 | 258 | ||
| 233 | spin_unlock_irq(&rtc_lock); | 259 | spin_unlock_irq(&rtc_lock); |
| 234 | break; | 260 | break; |
| 235 | case RTC_PIE_ON: | ||
| 236 | enable_irq(pie_irq); | ||
| 237 | break; | ||
| 238 | case RTC_PIE_OFF: | ||
| 239 | disable_irq(pie_irq); | ||
| 240 | break; | ||
| 241 | case RTC_IRQP_READ: | ||
| 242 | return put_user(periodic_frequency, (unsigned long __user *)arg); | ||
| 243 | break; | ||
| 244 | case RTC_IRQP_SET: | ||
| 245 | if (arg > MAX_PERIODIC_RATE) | ||
| 246 | return -EINVAL; | ||
| 247 | |||
| 248 | periodic_frequency = arg; | ||
| 249 | |||
| 250 | count = RTC_FREQUENCY; | ||
| 251 | do_div(count, arg); | ||
| 252 | |||
| 253 | periodic_count = count; | ||
| 254 | |||
| 255 | spin_lock_irq(&rtc_lock); | ||
| 256 | |||
| 257 | rtc1_write(RTCL1LREG, count); | ||
| 258 | rtc1_write(RTCL1HREG, count >> 16); | ||
| 259 | |||
| 260 | spin_unlock_irq(&rtc_lock); | ||
| 261 | break; | ||
| 262 | case RTC_EPOCH_READ: | 261 | case RTC_EPOCH_READ: |
| 263 | return put_user(epoch, (unsigned long __user *)arg); | 262 | return put_user(epoch, (unsigned long __user *)arg); |
| 264 | case RTC_EPOCH_SET: | 263 | case RTC_EPOCH_SET: |
| @@ -309,6 +308,8 @@ static const struct rtc_class_ops vr41xx_rtc_ops = { | |||
| 309 | .set_time = vr41xx_rtc_set_time, | 308 | .set_time = vr41xx_rtc_set_time, |
| 310 | .read_alarm = vr41xx_rtc_read_alarm, | 309 | .read_alarm = vr41xx_rtc_read_alarm, |
| 311 | .set_alarm = vr41xx_rtc_set_alarm, | 310 | .set_alarm = vr41xx_rtc_set_alarm, |
| 311 | .irq_set_freq = vr41xx_rtc_irq_set_freq, | ||
| 312 | .irq_set_state = vr41xx_rtc_irq_set_state, | ||
| 312 | }; | 313 | }; |
| 313 | 314 | ||
| 314 | static int __devinit rtc_probe(struct platform_device *pdev) | 315 | static int __devinit rtc_probe(struct platform_device *pdev) |
| @@ -346,6 +347,8 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
| 346 | goto err_iounmap_all; | 347 | goto err_iounmap_all; |
| 347 | } | 348 | } |
| 348 | 349 | ||
| 350 | rtc->max_user_freq = MAX_PERIODIC_RATE; | ||
| 351 | |||
| 349 | spin_lock_irq(&rtc_lock); | 352 | spin_lock_irq(&rtc_lock); |
| 350 | 353 | ||
| 351 | rtc1_write(ECMPLREG, 0); | 354 | rtc1_write(ECMPLREG, 0); |
