diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 126 | ||||
| -rw-r--r-- | drivers/rtc/Makefile | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-at91sam9.c | 520 | ||||
| -rw-r--r-- | drivers/rtc/rtc-bfin.c | 351 | ||||
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 221 | ||||
| -rw-r--r-- | drivers/rtc/rtc-dev.c | 9 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1302.c | 262 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1307.c | 27 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1511.c | 656 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf8583.c | 24 | ||||
| -rw-r--r-- | drivers/rtc/rtc-r9701.c | 178 | ||||
| -rw-r--r-- | drivers/rtc/rtc-s3c.c | 5 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sa1100.c | 16 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sysfs.c | 19 |
14 files changed, 2157 insertions, 261 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 45e4b9648176..6402d699072b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -20,6 +20,10 @@ menuconfig RTC_CLASS | |||
| 20 | 20 | ||
| 21 | if RTC_CLASS | 21 | if RTC_CLASS |
| 22 | 22 | ||
| 23 | if GEN_RTC || RTC | ||
| 24 | comment "Conflicting RTC option has been selected, check GEN_RTC and RTC" | ||
| 25 | endif | ||
| 26 | |||
| 23 | config RTC_HCTOSYS | 27 | config RTC_HCTOSYS |
| 24 | bool "Set system time from RTC on startup and resume" | 28 | bool "Set system time from RTC on startup and resume" |
| 25 | depends on RTC_CLASS = y | 29 | depends on RTC_CLASS = y |
| @@ -49,7 +53,7 @@ config RTC_HCTOSYS_DEVICE | |||
| 49 | 53 | ||
| 50 | If the clock you specify here is not battery backed, it may still | 54 | If the clock you specify here is not battery backed, it may still |
| 51 | be useful to reinitialize system time when resuming from system | 55 | be useful to reinitialize system time when resuming from system |
| 52 | sleep states. Do not specify an RTC here unless it stays powered | 56 | sleep states. Do not specify an RTC here unless it stays powered |
| 53 | during all this system's supported sleep states. | 57 | during all this system's supported sleep states. |
| 54 | 58 | ||
| 55 | config RTC_DEBUG | 59 | config RTC_DEBUG |
| @@ -142,7 +146,7 @@ config RTC_DRV_DS1307 | |||
| 142 | will be called rtc-ds1307. | 146 | will be called rtc-ds1307. |
| 143 | 147 | ||
| 144 | config RTC_DRV_DS1374 | 148 | config RTC_DRV_DS1374 |
| 145 | tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock" | 149 | tristate "Dallas/Maxim DS1374" |
| 146 | depends on RTC_CLASS && I2C | 150 | depends on RTC_CLASS && I2C |
| 147 | help | 151 | help |
| 148 | If you say yes here you get support for Dallas Semiconductor | 152 | If you say yes here you get support for Dallas Semiconductor |
| @@ -162,7 +166,7 @@ config RTC_DRV_DS1672 | |||
| 162 | will be called rtc-ds1672. | 166 | will be called rtc-ds1672. |
| 163 | 167 | ||
| 164 | config RTC_DRV_MAX6900 | 168 | config RTC_DRV_MAX6900 |
| 165 | tristate "Maxim 6900" | 169 | tristate "Maxim MAX6900" |
| 166 | help | 170 | help |
| 167 | If you say yes here you will get support for the | 171 | If you say yes here you will get support for the |
| 168 | Maxim MAX6900 I2C RTC chip. | 172 | Maxim MAX6900 I2C RTC chip. |
| @@ -180,10 +184,10 @@ config RTC_DRV_RS5C372 | |||
| 180 | will be called rtc-rs5c372. | 184 | will be called rtc-rs5c372. |
| 181 | 185 | ||
| 182 | config RTC_DRV_ISL1208 | 186 | config RTC_DRV_ISL1208 |
| 183 | tristate "Intersil 1208" | 187 | tristate "Intersil ISL1208" |
| 184 | help | 188 | help |
| 185 | If you say yes here you get support for the | 189 | If you say yes here you get support for the |
| 186 | Intersil 1208 RTC chip. | 190 | Intersil ISL1208 RTC chip. |
| 187 | 191 | ||
| 188 | This driver can also be built as a module. If so, the module | 192 | This driver can also be built as a module. If so, the module |
| 189 | will be called rtc-isl1208. | 193 | will be called rtc-isl1208. |
| @@ -220,7 +224,7 @@ config RTC_DRV_PCF8583 | |||
| 220 | will be called rtc-pcf8583. | 224 | will be called rtc-pcf8583. |
| 221 | 225 | ||
| 222 | config RTC_DRV_M41T80 | 226 | config RTC_DRV_M41T80 |
| 223 | tristate "ST M41T80 series RTC" | 227 | tristate "ST M41T80/81/82/83/84/85/87" |
| 224 | help | 228 | help |
| 225 | If you say Y here you will get support for the | 229 | If you say Y here you will get support for the |
| 226 | ST M41T80 RTC chips series. Currently following chips are | 230 | ST M41T80 RTC chips series. Currently following chips are |
| @@ -252,23 +256,32 @@ comment "SPI RTC drivers" | |||
| 252 | 256 | ||
| 253 | if SPI_MASTER | 257 | if SPI_MASTER |
| 254 | 258 | ||
| 255 | config RTC_DRV_RS5C348 | 259 | config RTC_DRV_MAX6902 |
| 256 | tristate "Ricoh RS5C348A/B" | 260 | tristate "Maxim MAX6902" |
| 257 | help | 261 | help |
| 258 | If you say yes here you get support for the | 262 | If you say yes here you will get support for the |
| 259 | Ricoh RS5C348A and RS5C348B RTC chips. | 263 | Maxim MAX6902 SPI RTC chip. |
| 260 | 264 | ||
| 261 | This driver can also be built as a module. If so, the module | 265 | This driver can also be built as a module. If so, the module |
| 262 | will be called rtc-rs5c348. | 266 | will be called rtc-max6902. |
| 263 | 267 | ||
| 264 | config RTC_DRV_MAX6902 | 268 | config RTC_DRV_R9701 |
| 265 | tristate "Maxim 6902" | 269 | tristate "Epson RTC-9701JE" |
| 266 | help | 270 | help |
| 267 | If you say yes here you will get support for the | 271 | If you say yes here you will get support for the |
| 268 | Maxim MAX6902 SPI RTC chip. | 272 | Epson RTC-9701JE SPI RTC chip. |
| 269 | 273 | ||
| 270 | This driver can also be built as a module. If so, the module | 274 | This driver can also be built as a module. If so, the module |
| 271 | will be called rtc-max6902. | 275 | will be called rtc-r9701. |
| 276 | |||
| 277 | config RTC_DRV_RS5C348 | ||
| 278 | tristate "Ricoh RS5C348A/B" | ||
| 279 | help | ||
| 280 | If you say yes here you get support for the | ||
| 281 | Ricoh RS5C348A and RS5C348B RTC chips. | ||
| 282 | |||
| 283 | This driver can also be built as a module. If so, the module | ||
| 284 | will be called rtc-rs5c348. | ||
| 272 | 285 | ||
| 273 | endif # SPI_MASTER | 286 | endif # SPI_MASTER |
| 274 | 287 | ||
| @@ -302,34 +315,50 @@ config RTC_DRV_DS1216 | |||
| 302 | help | 315 | help |
| 303 | If you say yes here you get support for the Dallas DS1216 RTC chips. | 316 | If you say yes here you get support for the Dallas DS1216 RTC chips. |
| 304 | 317 | ||
| 305 | config RTC_DRV_DS1553 | 318 | config RTC_DRV_DS1302 |
| 306 | tristate "Dallas DS1553" | 319 | tristate "Dallas DS1302" |
| 320 | depends on SH_SECUREEDGE5410 | ||
| 321 | help | ||
| 322 | If you say yes here you get support for the Dallas DS1302 RTC chips. | ||
| 323 | |||
| 324 | config RTC_DRV_DS1511 | ||
| 325 | tristate "Dallas DS1511" | ||
| 326 | depends on RTC_CLASS | ||
| 307 | help | 327 | help |
| 308 | If you say yes here you get support for the | 328 | If you say yes here you get support for the |
| 309 | Dallas DS1553 timekeeping chip. | 329 | Dallas DS1511 timekeeping/watchdog chip. |
| 310 | 330 | ||
| 311 | This driver can also be built as a module. If so, the module | 331 | This driver can also be built as a module. If so, the module |
| 312 | will be called rtc-ds1553. | 332 | will be called rtc-ds1511. |
| 313 | 333 | ||
| 314 | config RTC_DRV_STK17TA8 | 334 | config RTC_DRV_DS1553 |
| 315 | tristate "Simtek STK17TA8" | 335 | tristate "Maxim/Dallas DS1553" |
| 316 | depends on RTC_CLASS | ||
| 317 | help | 336 | help |
| 318 | If you say yes here you get support for the | 337 | If you say yes here you get support for the |
| 319 | Simtek STK17TA8 timekeeping chip. | 338 | Maxim/Dallas DS1553 timekeeping chip. |
| 320 | 339 | ||
| 321 | This driver can also be built as a module. If so, the module | 340 | This driver can also be built as a module. If so, the module |
| 322 | will be called rtc-stk17ta8. | 341 | will be called rtc-ds1553. |
| 323 | 342 | ||
| 324 | config RTC_DRV_DS1742 | 343 | config RTC_DRV_DS1742 |
| 325 | tristate "Dallas DS1742/1743" | 344 | tristate "Maxim/Dallas DS1742/1743" |
| 326 | help | 345 | help |
| 327 | If you say yes here you get support for the | 346 | If you say yes here you get support for the |
| 328 | Dallas DS1742/1743 timekeeping chip. | 347 | Maxim/Dallas DS1742/1743 timekeeping chip. |
| 329 | 348 | ||
| 330 | This driver can also be built as a module. If so, the module | 349 | This driver can also be built as a module. If so, the module |
| 331 | will be called rtc-ds1742. | 350 | will be called rtc-ds1742. |
| 332 | 351 | ||
| 352 | config RTC_DRV_STK17TA8 | ||
| 353 | tristate "Simtek STK17TA8" | ||
| 354 | depends on RTC_CLASS | ||
| 355 | help | ||
| 356 | If you say yes here you get support for the | ||
| 357 | Simtek STK17TA8 timekeeping chip. | ||
| 358 | |||
| 359 | This driver can also be built as a module. If so, the module | ||
| 360 | will be called rtc-stk17ta8. | ||
| 361 | |||
| 333 | config RTC_DRV_M48T86 | 362 | config RTC_DRV_M48T86 |
| 334 | tristate "ST M48T86/Dallas DS12887" | 363 | tristate "ST M48T86/Dallas DS12887" |
| 335 | help | 364 | help |
| @@ -440,10 +469,47 @@ config RTC_DRV_AT32AP700X | |||
| 440 | AT32AP700x family processors. | 469 | AT32AP700x family processors. |
| 441 | 470 | ||
| 442 | config RTC_DRV_AT91RM9200 | 471 | config RTC_DRV_AT91RM9200 |
| 443 | tristate "AT91RM9200" | 472 | tristate "AT91RM9200 or AT91SAM9RL" |
| 444 | depends on ARCH_AT91RM9200 | 473 | depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL |
| 445 | help | 474 | help |
| 446 | Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock). | 475 | Driver for the internal RTC (Realtime Clock) module found on |
| 476 | Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips | ||
| 477 | this is powered by the backup power supply. | ||
| 478 | |||
| 479 | config RTC_DRV_AT91SAM9 | ||
| 480 | tristate "AT91SAM9x" | ||
| 481 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) | ||
| 482 | help | ||
| 483 | RTC driver for the Atmel AT91SAM9x internal RTT (Real Time Timer). | ||
| 484 | These timers are powered by the backup power supply (such as a | ||
| 485 | small coin cell battery), but do not need to be used as RTCs. | ||
| 486 | |||
| 487 | (On AT91SAM9rl chips you probably want to use the dedicated RTC | ||
| 488 | module and leave the RTT available for other uses.) | ||
| 489 | |||
| 490 | config RTC_DRV_AT91SAM9_RTT | ||
| 491 | int | ||
| 492 | range 0 1 | ||
| 493 | default 0 | ||
| 494 | prompt "RTT module Number" if ARCH_AT91SAM9263 | ||
| 495 | depends on RTC_DRV_AT91SAM9 | ||
| 496 | help | ||
| 497 | More than one RTT module is available. You can choose which | ||
| 498 | one will be used as an RTC. The default of zero is normally | ||
| 499 | OK to use, though some systems use that for non-RTC purposes. | ||
| 500 | |||
| 501 | config RTC_DRV_AT91SAM9_GPBR | ||
| 502 | int | ||
| 503 | range 0 3 if !ARCH_AT91SAM9263 | ||
| 504 | range 0 15 if ARCH_AT91SAM9263 | ||
| 505 | default 0 | ||
| 506 | prompt "Backup Register Number" | ||
| 507 | depends on RTC_DRV_AT91SAM9 | ||
| 508 | help | ||
| 509 | The RTC driver needs to use one of the General Purpose Backup | ||
| 510 | Registers (GPBRs) as well as the RTT. You can choose which one | ||
| 511 | will be used. The default of zero is normally OK to use, but | ||
| 512 | on some systems other software needs to use that register. | ||
| 447 | 513 | ||
| 448 | config RTC_DRV_BFIN | 514 | config RTC_DRV_BFIN |
| 449 | tristate "Blackfin On-Chip RTC" | 515 | tristate "Blackfin On-Chip RTC" |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 465db4dd50b2..ec703f34ab86 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -19,11 +19,14 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | |||
| 19 | 19 | ||
| 20 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o | 20 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o |
| 21 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | 21 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
| 22 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | ||
| 22 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | 23 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o |
| 23 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 24 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
| 24 | 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 | ||
| 25 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 27 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
| 26 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o | 28 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o |
| 29 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | ||
| 27 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 30 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
| 28 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 31 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
| 29 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 32 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
| @@ -38,6 +41,7 @@ obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | |||
| 38 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 41 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
| 39 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o | 42 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
| 40 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 43 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
| 44 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o | ||
| 41 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 45 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
| 42 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 46 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
| 43 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 47 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c new file mode 100644 index 000000000000..bbf10ecf416c --- /dev/null +++ b/drivers/rtc/rtc-at91sam9.c | |||
| @@ -0,0 +1,520 @@ | |||
| 1 | /* | ||
| 2 | * "RTT as Real Time Clock" driver for AT91SAM9 SoC family | ||
| 3 | * | ||
| 4 | * (C) 2007 Michel Benoit | ||
| 5 | * | ||
| 6 | * Based on rtc-at91rm9200.c by Rick Bronson | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License | ||
| 10 | * as published by the Free Software Foundation; either version | ||
| 11 | * 2 of the License, or (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/time.h> | ||
| 18 | #include <linux/rtc.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/ioctl.h> | ||
| 21 | |||
| 22 | #include <asm/mach/time.h> | ||
| 23 | #include <asm/arch/board.h> | ||
| 24 | #include <asm/arch/at91_rtt.h> | ||
| 25 | |||
| 26 | |||
| 27 | /* | ||
| 28 | * This driver uses two configurable hardware resources that live in the | ||
| 29 | * AT91SAM9 backup power domain (intended to be powered at all times) | ||
| 30 | * to implement the Real Time Clock interfaces | ||
| 31 | * | ||
| 32 | * - A "Real-time Timer" (RTT) counts up in seconds from a base time. | ||
| 33 | * We can't assign the counter value (CRTV) ... but we can reset it. | ||
| 34 | * | ||
| 35 | * - One of the "General Purpose Backup Registers" (GPBRs) holds the | ||
| 36 | * base time, normally an offset from the beginning of the POSIX | ||
| 37 | * epoch (1970-Jan-1 00:00:00 UTC). Some systems also include the | ||
| 38 | * local timezone's offset. | ||
| 39 | * | ||
| 40 | * The RTC's value is the RTT counter plus that offset. The RTC's alarm | ||
| 41 | * is likewise a base (ALMV) plus that offset. | ||
| 42 | * | ||
| 43 | * Not all RTTs will be used as RTCs; some systems have multiple RTTs to | ||
| 44 | * choose from, or a "real" RTC module. All systems have multiple GPBR | ||
| 45 | * registers available, likewise usable for more than "RTC" support. | ||
| 46 | */ | ||
| 47 | |||
| 48 | /* | ||
| 49 | * We store ALARM_DISABLED in ALMV to record that no alarm is set. | ||
| 50 | * It's also the reset value for that field. | ||
| 51 | */ | ||
| 52 | #define ALARM_DISABLED ((u32)~0) | ||
| 53 | |||
| 54 | |||
| 55 | struct sam9_rtc { | ||
| 56 | void __iomem *rtt; | ||
| 57 | struct rtc_device *rtcdev; | ||
| 58 | u32 imr; | ||
| 59 | }; | ||
| 60 | |||
| 61 | #define rtt_readl(rtc, field) \ | ||
| 62 | __raw_readl((rtc)->rtt + AT91_RTT_ ## field) | ||
| 63 | #define rtt_writel(rtc, field, val) \ | ||
| 64 | __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field) | ||
| 65 | |||
| 66 | #define gpbr_readl(rtc) \ | ||
| 67 | at91_sys_read(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR) | ||
| 68 | #define gpbr_writel(rtc, val) \ | ||
| 69 | at91_sys_write(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR, (val)) | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Read current time and date in RTC | ||
| 73 | */ | ||
| 74 | static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm) | ||
| 75 | { | ||
| 76 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
| 77 | u32 secs, secs2; | ||
| 78 | u32 offset; | ||
| 79 | |||
| 80 | /* read current time offset */ | ||
| 81 | offset = gpbr_readl(rtc); | ||
| 82 | if (offset == 0) | ||
| 83 | return -EILSEQ; | ||
| 84 | |||
| 85 | /* reread the counter to help sync the two clock domains */ | ||
| 86 | secs = rtt_readl(rtc, VR); | ||
| 87 | secs2 = rtt_readl(rtc, VR); | ||
| 88 | if (secs != secs2) | ||
| 89 | secs = rtt_readl(rtc, VR); | ||
| 90 | |||
| 91 | rtc_time_to_tm(offset + secs, tm); | ||
| 92 | |||
| 93 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readtime", | ||
| 94 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | ||
| 95 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
| 96 | |||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Set current time and date in RTC | ||
| 102 | */ | ||
| 103 | static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | ||
| 104 | { | ||
| 105 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
| 106 | int err; | ||
| 107 | u32 offset, alarm, mr; | ||
| 108 | unsigned long secs; | ||
| 109 | |||
| 110 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "settime", | ||
| 111 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | ||
| 112 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
| 113 | |||
| 114 | err = rtc_tm_to_time(tm, &secs); | ||
| 115 | if (err != 0) | ||
| 116 | return err; | ||
| 117 | |||
| 118 | mr = rtt_readl(rtc, MR); | ||
| 119 | |||
| 120 | /* disable interrupts */ | ||
| 121 | rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); | ||
| 122 | |||
| 123 | /* read current time offset */ | ||
| 124 | offset = gpbr_readl(rtc); | ||
| 125 | |||
| 126 | /* store the new base time in a battery backup register */ | ||
| 127 | secs += 1; | ||
| 128 | gpbr_writel(rtc, secs); | ||
| 129 | |||
| 130 | /* adjust the alarm time for the new base */ | ||
| 131 | alarm = rtt_readl(rtc, AR); | ||
| 132 | if (alarm != ALARM_DISABLED) { | ||
| 133 | if (offset > secs) { | ||
| 134 | /* time jumped backwards, increase time until alarm */ | ||
| 135 | alarm += (offset - secs); | ||
| 136 | } else if ((alarm + offset) > secs) { | ||
| 137 | /* time jumped forwards, decrease time until alarm */ | ||
| 138 | alarm -= (secs - offset); | ||
| 139 | } else { | ||
| 140 | /* time jumped past the alarm, disable alarm */ | ||
| 141 | alarm = ALARM_DISABLED; | ||
| 142 | mr &= ~AT91_RTT_ALMIEN; | ||
| 143 | } | ||
| 144 | rtt_writel(rtc, AR, alarm); | ||
| 145 | } | ||
| 146 | |||
| 147 | /* reset the timer, and re-enable interrupts */ | ||
| 148 | rtt_writel(rtc, MR, mr | AT91_RTT_RTTRST); | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 154 | { | ||
| 155 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
| 156 | struct rtc_time *tm = &alrm->time; | ||
| 157 | u32 alarm = rtt_readl(rtc, AR); | ||
| 158 | u32 offset; | ||
| 159 | |||
| 160 | offset = gpbr_readl(rtc); | ||
| 161 | if (offset == 0) | ||
| 162 | return -EILSEQ; | ||
| 163 | |||
| 164 | memset(alrm, 0, sizeof(alrm)); | ||
| 165 | if (alarm != ALARM_DISABLED && offset != 0) { | ||
| 166 | rtc_time_to_tm(offset + alarm, tm); | ||
| 167 | |||
| 168 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readalarm", | ||
| 169 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | ||
| 170 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
| 171 | |||
| 172 | if (rtt_readl(rtc, MR) & AT91_RTT_ALMIEN) | ||
| 173 | alrm->enabled = 1; | ||
| 174 | } | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 180 | { | ||
| 181 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
| 182 | struct rtc_time *tm = &alrm->time; | ||
| 183 | unsigned long secs; | ||
| 184 | u32 offset; | ||
| 185 | u32 mr; | ||
| 186 | int err; | ||
| 187 | |||
| 188 | err = rtc_tm_to_time(tm, &secs); | ||
| 189 | if (err != 0) | ||
| 190 | return err; | ||
| 191 | |||
| 192 | offset = gpbr_readl(rtc); | ||
| 193 | if (offset == 0) { | ||
| 194 | /* time is not set */ | ||
| 195 | return -EILSEQ; | ||
| 196 | } | ||
| 197 | mr = rtt_readl(rtc, MR); | ||
| 198 | rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); | ||
| 199 | |||
| 200 | /* alarm in the past? finish and leave disabled */ | ||
| 201 | if (secs <= offset) { | ||
| 202 | rtt_writel(rtc, AR, ALARM_DISABLED); | ||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | |||
| 206 | /* else set alarm and maybe enable it */ | ||
| 207 | rtt_writel(rtc, AR, secs - offset); | ||
| 208 | if (alrm->enabled) | ||
| 209 | rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); | ||
| 210 | |||
| 211 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "setalarm", | ||
| 212 | tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, | ||
| 213 | tm->tm_min, tm->tm_sec); | ||
| 214 | |||
| 215 | return 0; | ||
| 216 | } | ||
| 217 | |||
| 218 | /* | ||
| 219 | * Handle commands from user-space | ||
| 220 | */ | ||
| 221 | static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
| 222 | unsigned long arg) | ||
| 223 | { | ||
| 224 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
| 225 | int ret = 0; | ||
| 226 | u32 mr = rtt_readl(rtc, MR); | ||
| 227 | |||
| 228 | dev_dbg(dev, "ioctl: cmd=%08x, arg=%08lx, mr %08x\n", cmd, arg, mr); | ||
| 229 | |||
| 230 | switch (cmd) { | ||
| 231 | case RTC_AIE_OFF: /* alarm off */ | ||
| 232 | rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); | ||
| 233 | break; | ||
| 234 | case RTC_AIE_ON: /* alarm on */ | ||
| 235 | rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); | ||
| 236 | break; | ||
| 237 | case RTC_UIE_OFF: /* update off */ | ||
| 238 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); | ||
| 239 | break; | ||
| 240 | case RTC_UIE_ON: /* update on */ | ||
| 241 | rtt_writel(rtc, MR, mr | AT91_RTT_RTTINCIEN); | ||
| 242 | break; | ||
| 243 | default: | ||
| 244 | ret = -ENOIOCTLCMD; | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | |||
| 248 | return ret; | ||
| 249 | } | ||
| 250 | |||
| 251 | /* | ||
| 252 | * Provide additional RTC information in /proc/driver/rtc | ||
| 253 | */ | ||
| 254 | static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | ||
| 255 | { | ||
| 256 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
| 257 | u32 mr = mr = rtt_readl(rtc, MR); | ||
| 258 | |||
| 259 | seq_printf(seq, "update_IRQ\t: %s\n", | ||
| 260 | (mr & AT91_RTT_RTTINCIEN) ? "yes" : "no"); | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* | ||
| 265 | * IRQ handler for the RTC | ||
| 266 | */ | ||
| 267 | static irqreturn_t at91_rtc_interrupt(int irq, void *_rtc) | ||
| 268 | { | ||
| 269 | struct sam9_rtc *rtc = _rtc; | ||
| 270 | u32 sr, mr; | ||
| 271 | unsigned long events = 0; | ||
| 272 | |||
| 273 | /* Shared interrupt may be for another device. Note: reading | ||
| 274 | * SR clears it, so we must only read it in this irq handler! | ||
| 275 | */ | ||
| 276 | mr = rtt_readl(rtc, MR) & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
| 277 | sr = rtt_readl(rtc, SR) & mr; | ||
| 278 | if (!sr) | ||
| 279 | return IRQ_NONE; | ||
| 280 | |||
| 281 | /* alarm status */ | ||
| 282 | if (sr & AT91_RTT_ALMS) | ||
| 283 | events |= (RTC_AF | RTC_IRQF); | ||
| 284 | |||
| 285 | /* timer update/increment */ | ||
| 286 | if (sr & AT91_RTT_RTTINC) | ||
| 287 | events |= (RTC_UF | RTC_IRQF); | ||
| 288 | |||
| 289 | rtc_update_irq(rtc->rtcdev, 1, events); | ||
| 290 | |||
| 291 | pr_debug("%s: num=%ld, events=0x%02lx\n", __FUNCTION__, | ||
| 292 | events >> 8, events & 0x000000FF); | ||
| 293 | |||
| 294 | return IRQ_HANDLED; | ||
| 295 | } | ||
| 296 | |||
| 297 | static const struct rtc_class_ops at91_rtc_ops = { | ||
| 298 | .ioctl = at91_rtc_ioctl, | ||
| 299 | .read_time = at91_rtc_readtime, | ||
| 300 | .set_time = at91_rtc_settime, | ||
| 301 | .read_alarm = at91_rtc_readalarm, | ||
| 302 | .set_alarm = at91_rtc_setalarm, | ||
| 303 | .proc = at91_rtc_proc, | ||
| 304 | }; | ||
| 305 | |||
| 306 | /* | ||
| 307 | * Initialize and install RTC driver | ||
| 308 | */ | ||
| 309 | static int __init at91_rtc_probe(struct platform_device *pdev) | ||
| 310 | { | ||
| 311 | struct resource *r; | ||
| 312 | struct sam9_rtc *rtc; | ||
| 313 | int ret; | ||
| 314 | u32 mr; | ||
| 315 | |||
| 316 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 317 | if (!r) | ||
| 318 | return -ENODEV; | ||
| 319 | |||
| 320 | rtc = kzalloc(sizeof *rtc, GFP_KERNEL); | ||
| 321 | if (!rtc) | ||
| 322 | return -ENOMEM; | ||
| 323 | |||
| 324 | platform_set_drvdata(pdev, rtc); | ||
| 325 | rtc->rtt = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS); | ||
| 326 | rtc->rtt += r->start; | ||
| 327 | |||
| 328 | mr = rtt_readl(rtc, MR); | ||
| 329 | |||
| 330 | /* unless RTT is counting at 1 Hz, re-initialize it */ | ||
| 331 | if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) { | ||
| 332 | mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES); | ||
| 333 | gpbr_writel(rtc, 0); | ||
| 334 | } | ||
| 335 | |||
| 336 | /* disable all interrupts (same as on shutdown path) */ | ||
| 337 | mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
| 338 | rtt_writel(rtc, MR, mr); | ||
| 339 | |||
| 340 | rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | ||
| 341 | &at91_rtc_ops, THIS_MODULE); | ||
| 342 | if (IS_ERR(rtc->rtcdev)) { | ||
| 343 | ret = PTR_ERR(rtc->rtcdev); | ||
| 344 | goto fail; | ||
| 345 | } | ||
| 346 | |||
| 347 | /* register irq handler after we know what name we'll use */ | ||
| 348 | ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, | ||
| 349 | IRQF_DISABLED | IRQF_SHARED, | ||
| 350 | rtc->rtcdev->dev.bus_id, rtc); | ||
| 351 | if (ret) { | ||
| 352 | dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); | ||
| 353 | rtc_device_unregister(rtc->rtcdev); | ||
| 354 | goto fail; | ||
| 355 | } | ||
| 356 | |||
| 357 | /* NOTE: sam9260 rev A silicon has a ROM bug which resets the | ||
| 358 | * RTT on at least some reboots. If you have that chip, you must | ||
| 359 | * initialize the time from some external source like a GPS, wall | ||
| 360 | * clock, discrete RTC, etc | ||
| 361 | */ | ||
| 362 | |||
| 363 | if (gpbr_readl(rtc) == 0) | ||
| 364 | dev_warn(&pdev->dev, "%s: SET TIME!\n", | ||
| 365 | rtc->rtcdev->dev.bus_id); | ||
| 366 | |||
| 367 | return 0; | ||
| 368 | |||
| 369 | fail: | ||
| 370 | platform_set_drvdata(pdev, NULL); | ||
| 371 | kfree(rtc); | ||
| 372 | return ret; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* | ||
| 376 | * Disable and remove the RTC driver | ||
| 377 | */ | ||
| 378 | static int __exit at91_rtc_remove(struct platform_device *pdev) | ||
| 379 | { | ||
| 380 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
| 381 | u32 mr = rtt_readl(rtc, MR); | ||
| 382 | |||
| 383 | /* disable all interrupts */ | ||
| 384 | rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); | ||
| 385 | free_irq(AT91_ID_SYS, rtc); | ||
| 386 | |||
| 387 | rtc_device_unregister(rtc->rtcdev); | ||
| 388 | |||
| 389 | platform_set_drvdata(pdev, NULL); | ||
| 390 | kfree(rtc); | ||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | static void at91_rtc_shutdown(struct platform_device *pdev) | ||
| 395 | { | ||
| 396 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
| 397 | u32 mr = rtt_readl(rtc, MR); | ||
| 398 | |||
| 399 | rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
| 400 | rtt_writel(rtc, MR, mr & ~rtc->imr); | ||
| 401 | } | ||
| 402 | |||
| 403 | #ifdef CONFIG_PM | ||
| 404 | |||
| 405 | /* AT91SAM9 RTC Power management control */ | ||
| 406 | |||
| 407 | static int at91_rtc_suspend(struct platform_device *pdev, | ||
| 408 | pm_message_t state) | ||
| 409 | { | ||
| 410 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
| 411 | u32 mr = rtt_readl(rtc, MR); | ||
| 412 | |||
| 413 | /* | ||
| 414 | * This IRQ is shared with DBGU and other hardware which isn't | ||
| 415 | * necessarily a wakeup event source. | ||
| 416 | */ | ||
| 417 | rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
| 418 | if (rtc->imr) { | ||
| 419 | if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) { | ||
| 420 | enable_irq_wake(AT91_ID_SYS); | ||
| 421 | /* don't let RTTINC cause wakeups */ | ||
| 422 | if (mr & AT91_RTT_RTTINCIEN) | ||
| 423 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); | ||
| 424 | } else | ||
| 425 | rtt_writel(rtc, MR, mr & ~rtc->imr); | ||
| 426 | } | ||
| 427 | |||
| 428 | return 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | static int at91_rtc_resume(struct platform_device *pdev) | ||
| 432 | { | ||
| 433 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
| 434 | u32 mr; | ||
| 435 | |||
| 436 | if (rtc->imr) { | ||
| 437 | if (device_may_wakeup(&pdev->dev)) | ||
| 438 | disable_irq_wake(AT91_ID_SYS); | ||
| 439 | mr = rtt_readl(rtc, MR); | ||
| 440 | rtt_writel(rtc, MR, mr | rtc->imr); | ||
| 441 | } | ||
| 442 | |||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | #else | ||
| 446 | #define at91_rtc_suspend NULL | ||
| 447 | #define at91_rtc_resume NULL | ||
| 448 | #endif | ||
| 449 | |||
| 450 | static struct platform_driver at91_rtc_driver = { | ||
| 451 | .driver.name = "rtc-at91sam9", | ||
| 452 | .driver.owner = THIS_MODULE, | ||
| 453 | .remove = __exit_p(at91_rtc_remove), | ||
| 454 | .shutdown = at91_rtc_shutdown, | ||
| 455 | .suspend = at91_rtc_suspend, | ||
| 456 | .resume = at91_rtc_resume, | ||
| 457 | }; | ||
| 458 | |||
| 459 | /* Chips can have more than one RTT module, and they can be used for more | ||
| 460 | * than just RTCs. So we can't just register as "the" RTT driver. | ||
| 461 | * | ||
| 462 | * A normal approach in such cases is to create a library to allocate and | ||
| 463 | * free the modules. Here we just use bus_find_device() as like such a | ||
| 464 | * library, binding directly ... no runtime "library" footprint is needed. | ||
| 465 | */ | ||
| 466 | static int __init at91_rtc_match(struct device *dev, void *v) | ||
| 467 | { | ||
| 468 | struct platform_device *pdev = to_platform_device(dev); | ||
| 469 | int ret; | ||
| 470 | |||
| 471 | /* continue searching if this isn't the RTT we need */ | ||
| 472 | if (strcmp("at91_rtt", pdev->name) != 0 | ||
| 473 | || pdev->id != CONFIG_RTC_DRV_AT91SAM9_RTT) | ||
| 474 | goto fail; | ||
| 475 | |||
| 476 | /* else we found it ... but fail unless we can bind to the RTC driver */ | ||
| 477 | if (dev->driver) { | ||
| 478 | dev_dbg(dev, "busy, can't use as RTC!\n"); | ||
| 479 | goto fail; | ||
| 480 | } | ||
| 481 | dev->driver = &at91_rtc_driver.driver; | ||
| 482 | if (device_attach(dev) == 0) { | ||
| 483 | dev_dbg(dev, "can't attach RTC!\n"); | ||
| 484 | goto fail; | ||
| 485 | } | ||
| 486 | ret = at91_rtc_probe(pdev); | ||
| 487 | if (ret == 0) | ||
| 488 | return true; | ||
| 489 | |||
| 490 | dev_dbg(dev, "RTC probe err %d!\n", ret); | ||
| 491 | fail: | ||
| 492 | return false; | ||
| 493 | } | ||
| 494 | |||
| 495 | static int __init at91_rtc_init(void) | ||
| 496 | { | ||
| 497 | int status; | ||
| 498 | struct device *rtc; | ||
| 499 | |||
| 500 | status = platform_driver_register(&at91_rtc_driver); | ||
| 501 | if (status) | ||
| 502 | return status; | ||
| 503 | rtc = bus_find_device(&platform_bus_type, NULL, | ||
| 504 | NULL, at91_rtc_match); | ||
| 505 | if (!rtc) | ||
| 506 | platform_driver_unregister(&at91_rtc_driver); | ||
| 507 | return rtc ? 0 : -ENODEV; | ||
| 508 | } | ||
| 509 | module_init(at91_rtc_init); | ||
| 510 | |||
| 511 | static void __exit at91_rtc_exit(void) | ||
| 512 | { | ||
| 513 | platform_driver_unregister(&at91_rtc_driver); | ||
| 514 | } | ||
| 515 | module_exit(at91_rtc_exit); | ||
| 516 | |||
| 517 | |||
| 518 | MODULE_AUTHOR("Michel Benoit"); | ||
| 519 | MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x"); | ||
| 520 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 1aa709dda0d6..d90ba860d216 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
| 3 | * Supports BF53[123]/BF53[467]/BF54[2489] | 3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] |
| 4 | * | 4 | * |
| 5 | * Copyright 2004-2007 Analog Devices Inc. | 5 | * Copyright 2004-2007 Analog Devices Inc. |
| 6 | * | 6 | * |
| @@ -32,26 +32,25 @@ | |||
| 32 | * writes to clear status registers complete immediately. | 32 | * writes to clear status registers complete immediately. |
| 33 | */ | 33 | */ |
| 34 | 34 | ||
| 35 | #include <linux/module.h> | ||
| 36 | #include <linux/kernel.h> | ||
| 37 | #include <linux/bcd.h> | 35 | #include <linux/bcd.h> |
| 38 | #include <linux/rtc.h> | 36 | #include <linux/completion.h> |
| 37 | #include <linux/delay.h> | ||
| 39 | #include <linux/init.h> | 38 | #include <linux/init.h> |
| 39 | #include <linux/interrupt.h> | ||
| 40 | #include <linux/kernel.h> | ||
| 41 | #include <linux/module.h> | ||
| 40 | #include <linux/platform_device.h> | 42 | #include <linux/platform_device.h> |
| 43 | #include <linux/rtc.h> | ||
| 41 | #include <linux/seq_file.h> | 44 | #include <linux/seq_file.h> |
| 42 | #include <linux/interrupt.h> | ||
| 43 | #include <linux/spinlock.h> | ||
| 44 | #include <linux/delay.h> | ||
| 45 | 45 | ||
| 46 | #include <asm/blackfin.h> | 46 | #include <asm/blackfin.h> |
| 47 | 47 | ||
| 48 | #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __FUNCTION__, __LINE__, ## args) | 48 | #define dev_dbg_stamp(dev) dev_dbg(dev, "%s:%i: here i am\n", __func__, __LINE__) |
| 49 | #define stampit() stamp("here i am") | ||
| 50 | 49 | ||
| 51 | struct bfin_rtc { | 50 | struct bfin_rtc { |
| 52 | struct rtc_device *rtc_dev; | 51 | struct rtc_device *rtc_dev; |
| 53 | struct rtc_time rtc_alarm; | 52 | struct rtc_time rtc_alarm; |
| 54 | spinlock_t lock; | 53 | u16 rtc_wrote_regs; |
| 55 | }; | 54 | }; |
| 56 | 55 | ||
| 57 | /* Bit values for the ISTAT / ICTL registers */ | 56 | /* Bit values for the ISTAT / ICTL registers */ |
| @@ -72,7 +71,7 @@ struct bfin_rtc { | |||
| 72 | #define SEC_BITS_OFF 0 | 71 | #define SEC_BITS_OFF 0 |
| 73 | 72 | ||
| 74 | /* Some helper functions to convert between the common RTC notion of time | 73 | /* Some helper functions to convert between the common RTC notion of time |
| 75 | * and the internal Blackfin notion that is stored in 32bits. | 74 | * and the internal Blackfin notion that is encoded in 32bits. |
| 76 | */ | 75 | */ |
| 77 | static inline u32 rtc_time_to_bfin(unsigned long now) | 76 | static inline u32 rtc_time_to_bfin(unsigned long now) |
| 78 | { | 77 | { |
| @@ -97,7 +96,10 @@ static inline void rtc_bfin_to_tm(u32 rtc_bfin, struct rtc_time *tm) | |||
| 97 | rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm); | 96 | rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm); |
| 98 | } | 97 | } |
| 99 | 98 | ||
| 100 | /* Wait for the previous write to a RTC register to complete. | 99 | /** |
| 100 | * bfin_rtc_sync_pending - make sure pending writes have complete | ||
| 101 | * | ||
| 102 | * Wait for the previous write to a RTC register to complete. | ||
| 101 | * Unfortunately, we can't sleep here as that introduces a race condition when | 103 | * Unfortunately, we can't sleep here as that introduces a race condition when |
| 102 | * turning on interrupt events. Consider this: | 104 | * turning on interrupt events. Consider this: |
| 103 | * - process sets alarm | 105 | * - process sets alarm |
| @@ -112,188 +114,202 @@ static inline void rtc_bfin_to_tm(u32 rtc_bfin, struct rtc_time *tm) | |||
| 112 | * If anyone can point out the obvious solution here, i'm listening :). This | 114 | * If anyone can point out the obvious solution here, i'm listening :). This |
| 113 | * shouldn't be an issue on an SMP or preempt system as this function should | 115 | * shouldn't be an issue on an SMP or preempt system as this function should |
| 114 | * only be called with the rtc lock held. | 116 | * only be called with the rtc lock held. |
| 117 | * | ||
| 118 | * Other options: | ||
| 119 | * - disable PREN so the sync happens at 32.768kHZ ... but this changes the | ||
| 120 | * inc rate for all RTC registers from 1HZ to 32.768kHZ ... | ||
| 121 | * - use the write complete IRQ | ||
| 115 | */ | 122 | */ |
| 116 | static void rtc_bfin_sync_pending(void) | 123 | /* |
| 124 | static void bfin_rtc_sync_pending_polled(void) | ||
| 117 | { | 125 | { |
| 118 | stampit(); | 126 | while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) |
| 119 | while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) { | ||
| 120 | if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)) | 127 | if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)) |
| 121 | break; | 128 | break; |
| 122 | } | ||
| 123 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); | 129 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); |
| 124 | } | 130 | } |
| 131 | */ | ||
| 132 | static DECLARE_COMPLETION(bfin_write_complete); | ||
| 133 | static void bfin_rtc_sync_pending(struct device *dev) | ||
| 134 | { | ||
| 135 | dev_dbg_stamp(dev); | ||
| 136 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) | ||
| 137 | wait_for_completion_timeout(&bfin_write_complete, HZ * 5); | ||
| 138 | dev_dbg_stamp(dev); | ||
| 139 | } | ||
| 125 | 140 | ||
| 126 | static void rtc_bfin_reset(struct bfin_rtc *rtc) | 141 | /** |
| 142 | * bfin_rtc_reset - set RTC to sane/known state | ||
| 143 | * | ||
| 144 | * Initialize the RTC. Enable pre-scaler to scale RTC clock | ||
| 145 | * to 1Hz and clear interrupt/status registers. | ||
| 146 | */ | ||
| 147 | static void bfin_rtc_reset(struct device *dev) | ||
| 127 | { | 148 | { |
| 128 | /* Initialize the RTC. Enable pre-scaler to scale RTC clock | 149 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
| 129 | * to 1Hz and clear interrupt/status registers. */ | 150 | dev_dbg_stamp(dev); |
| 130 | spin_lock_irq(&rtc->lock); | 151 | bfin_rtc_sync_pending(dev); |
| 131 | rtc_bfin_sync_pending(); | ||
| 132 | bfin_write_RTC_PREN(0x1); | 152 | bfin_write_RTC_PREN(0x1); |
| 133 | bfin_write_RTC_ICTL(0); | 153 | bfin_write_RTC_ICTL(RTC_ISTAT_WRITE_COMPLETE); |
| 134 | bfin_write_RTC_SWCNT(0); | 154 | bfin_write_RTC_SWCNT(0); |
| 135 | bfin_write_RTC_ALARM(0); | 155 | bfin_write_RTC_ALARM(0); |
| 136 | bfin_write_RTC_ISTAT(0xFFFF); | 156 | bfin_write_RTC_ISTAT(0xFFFF); |
| 137 | spin_unlock_irq(&rtc->lock); | 157 | rtc->rtc_wrote_regs = 0; |
| 138 | } | 158 | } |
| 139 | 159 | ||
| 160 | /** | ||
| 161 | * bfin_rtc_interrupt - handle interrupt from RTC | ||
| 162 | * | ||
| 163 | * Since we handle all RTC events here, we have to make sure the requested | ||
| 164 | * interrupt is enabled (in RTC_ICTL) as the event status register (RTC_ISTAT) | ||
| 165 | * always gets updated regardless of the interrupt being enabled. So when one | ||
| 166 | * even we care about (e.g. stopwatch) goes off, we don't want to turn around | ||
| 167 | * and say that other events have happened as well (e.g. second). We do not | ||
| 168 | * have to worry about pending writes to the RTC_ICTL register as interrupts | ||
| 169 | * only fire if they are enabled in the RTC_ICTL register. | ||
| 170 | */ | ||
| 140 | static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | 171 | static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) |
| 141 | { | 172 | { |
| 142 | struct platform_device *pdev = to_platform_device(dev_id); | 173 | struct device *dev = dev_id; |
| 143 | struct bfin_rtc *rtc = platform_get_drvdata(pdev); | 174 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
| 144 | unsigned long events = 0; | 175 | unsigned long events = 0; |
| 145 | u16 rtc_istat; | 176 | bool write_complete = false; |
| 146 | 177 | u16 rtc_istat, rtc_ictl; | |
| 147 | stampit(); | ||
| 148 | 178 | ||
| 149 | spin_lock_irq(&rtc->lock); | 179 | dev_dbg_stamp(dev); |
| 150 | 180 | ||
| 151 | rtc_istat = bfin_read_RTC_ISTAT(); | 181 | rtc_istat = bfin_read_RTC_ISTAT(); |
| 182 | rtc_ictl = bfin_read_RTC_ICTL(); | ||
| 152 | 183 | ||
| 153 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 184 | if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) { |
| 154 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); | 185 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); |
| 155 | events |= RTC_AF | RTC_IRQF; | 186 | write_complete = true; |
| 187 | complete(&bfin_write_complete); | ||
| 156 | } | 188 | } |
| 157 | 189 | ||
| 158 | if (rtc_istat & RTC_ISTAT_STOPWATCH) { | 190 | if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { |
| 159 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); | 191 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { |
| 160 | events |= RTC_PF | RTC_IRQF; | 192 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); |
| 161 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | 193 | events |= RTC_AF | RTC_IRQF; |
| 194 | } | ||
| 162 | } | 195 | } |
| 163 | 196 | ||
| 164 | if (rtc_istat & RTC_ISTAT_SEC) { | 197 | if (rtc_ictl & RTC_ISTAT_STOPWATCH) { |
| 165 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 198 | if (rtc_istat & RTC_ISTAT_STOPWATCH) { |
| 166 | events |= RTC_UF | RTC_IRQF; | 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 | } | ||
| 167 | } | 203 | } |
| 168 | 204 | ||
| 169 | rtc_update_irq(rtc->rtc_dev, 1, events); | 205 | if (rtc_ictl & RTC_ISTAT_SEC) { |
| 206 | if (rtc_istat & RTC_ISTAT_SEC) { | ||
| 207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | ||
| 208 | events |= RTC_UF | RTC_IRQF; | ||
| 209 | } | ||
| 210 | } | ||
| 170 | 211 | ||
| 171 | spin_unlock_irq(&rtc->lock); | 212 | if (events) |
| 213 | rtc_update_irq(rtc->rtc_dev, 1, events); | ||
| 172 | 214 | ||
| 173 | return IRQ_HANDLED; | 215 | if (write_complete || events) |
| 216 | return IRQ_HANDLED; | ||
| 217 | else | ||
| 218 | return IRQ_NONE; | ||
| 174 | } | 219 | } |
| 175 | 220 | ||
| 176 | static int bfin_rtc_open(struct device *dev) | 221 | static int bfin_rtc_open(struct device *dev) |
| 177 | { | 222 | { |
| 178 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | ||
| 179 | int ret; | 223 | int ret; |
| 180 | 224 | ||
| 181 | stampit(); | 225 | dev_dbg_stamp(dev); |
| 182 | 226 | ||
| 183 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_DISABLED, "rtc-bfin", dev); | 227 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); |
| 184 | if (unlikely(ret)) { | 228 | if (!ret) |
| 185 | dev_err(dev, "request RTC IRQ failed with %d\n", ret); | 229 | bfin_rtc_reset(dev); |
| 186 | return ret; | ||
| 187 | } | ||
| 188 | |||
| 189 | rtc_bfin_reset(rtc); | ||
| 190 | 230 | ||
| 191 | return ret; | 231 | return ret; |
| 192 | } | 232 | } |
| 193 | 233 | ||
| 194 | static void bfin_rtc_release(struct device *dev) | 234 | static void bfin_rtc_release(struct device *dev) |
| 195 | { | 235 | { |
| 196 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 236 | dev_dbg_stamp(dev); |
| 197 | stampit(); | 237 | bfin_rtc_reset(dev); |
| 198 | rtc_bfin_reset(rtc); | ||
| 199 | free_irq(IRQ_RTC, dev); | 238 | free_irq(IRQ_RTC, dev); |
| 200 | } | 239 | } |
| 201 | 240 | ||
| 241 | static void bfin_rtc_int_set(struct bfin_rtc *rtc, u16 rtc_int) | ||
| 242 | { | ||
| 243 | bfin_write_RTC_ISTAT(rtc_int); | ||
| 244 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); | ||
| 245 | } | ||
| 246 | static void bfin_rtc_int_clear(struct bfin_rtc *rtc, u16 rtc_int) | ||
| 247 | { | ||
| 248 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); | ||
| 249 | } | ||
| 250 | static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc) | ||
| 251 | { | ||
| 252 | /* Blackfin has different bits for whether the alarm is | ||
| 253 | * more than 24 hours away. | ||
| 254 | */ | ||
| 255 | bfin_rtc_int_set(rtc, (rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY)); | ||
| 256 | } | ||
| 202 | 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) |
| 203 | { | 258 | { |
| 204 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 259 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
| 260 | int ret = 0; | ||
| 261 | |||
| 262 | dev_dbg_stamp(dev); | ||
| 205 | 263 | ||
| 206 | stampit(); | 264 | bfin_rtc_sync_pending(dev); |
| 207 | 265 | ||
| 208 | switch (cmd) { | 266 | switch (cmd) { |
| 209 | case RTC_PIE_ON: | 267 | case RTC_PIE_ON: |
| 210 | stampit(); | 268 | dev_dbg_stamp(dev); |
| 211 | spin_lock_irq(&rtc->lock); | 269 | bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH); |
| 212 | rtc_bfin_sync_pending(); | ||
| 213 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); | ||
| 214 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | 270 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); |
| 215 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_STOPWATCH); | 271 | break; |
| 216 | spin_unlock_irq(&rtc->lock); | ||
| 217 | return 0; | ||
| 218 | case RTC_PIE_OFF: | 272 | case RTC_PIE_OFF: |
| 219 | stampit(); | 273 | dev_dbg_stamp(dev); |
| 220 | spin_lock_irq(&rtc->lock); | 274 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_STOPWATCH); |
| 221 | rtc_bfin_sync_pending(); | 275 | break; |
| 222 | bfin_write_RTC_SWCNT(0); | ||
| 223 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_STOPWATCH); | ||
| 224 | spin_unlock_irq(&rtc->lock); | ||
| 225 | return 0; | ||
| 226 | 276 | ||
| 227 | case RTC_UIE_ON: | 277 | case RTC_UIE_ON: |
| 228 | stampit(); | 278 | dev_dbg_stamp(dev); |
| 229 | spin_lock_irq(&rtc->lock); | 279 | bfin_rtc_int_set(rtc, RTC_ISTAT_SEC); |
| 230 | rtc_bfin_sync_pending(); | 280 | break; |
| 231 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | ||
| 232 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_SEC); | ||
| 233 | spin_unlock_irq(&rtc->lock); | ||
| 234 | return 0; | ||
| 235 | case RTC_UIE_OFF: | 281 | case RTC_UIE_OFF: |
| 236 | stampit(); | 282 | dev_dbg_stamp(dev); |
| 237 | spin_lock_irq(&rtc->lock); | 283 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_SEC); |
| 238 | rtc_bfin_sync_pending(); | 284 | break; |
| 239 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_SEC); | 285 | |
| 240 | spin_unlock_irq(&rtc->lock); | 286 | case RTC_AIE_ON: |
| 241 | return 0; | 287 | dev_dbg_stamp(dev); |
| 242 | 288 | bfin_rtc_int_set_alarm(rtc); | |
| 243 | case RTC_AIE_ON: { | 289 | break; |
| 244 | unsigned long rtc_alarm; | ||
| 245 | u16 which_alarm; | ||
| 246 | int ret = 0; | ||
| 247 | |||
| 248 | stampit(); | ||
| 249 | |||
| 250 | spin_lock_irq(&rtc->lock); | ||
| 251 | |||
| 252 | rtc_bfin_sync_pending(); | ||
| 253 | if (rtc->rtc_alarm.tm_yday == -1) { | ||
| 254 | struct rtc_time now; | ||
| 255 | rtc_bfin_to_tm(bfin_read_RTC_STAT(), &now); | ||
| 256 | now.tm_sec = rtc->rtc_alarm.tm_sec; | ||
| 257 | now.tm_min = rtc->rtc_alarm.tm_min; | ||
| 258 | now.tm_hour = rtc->rtc_alarm.tm_hour; | ||
| 259 | ret = rtc_tm_to_time(&now, &rtc_alarm); | ||
| 260 | which_alarm = RTC_ISTAT_ALARM; | ||
| 261 | } else { | ||
| 262 | ret = rtc_tm_to_time(&rtc->rtc_alarm, &rtc_alarm); | ||
| 263 | which_alarm = RTC_ISTAT_ALARM_DAY; | ||
| 264 | } | ||
| 265 | if (ret == 0) { | ||
| 266 | bfin_write_RTC_ISTAT(which_alarm); | ||
| 267 | bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm)); | ||
| 268 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | which_alarm); | ||
| 269 | } | ||
| 270 | |||
| 271 | spin_unlock_irq(&rtc->lock); | ||
| 272 | |||
| 273 | return ret; | ||
| 274 | } | ||
| 275 | case RTC_AIE_OFF: | 290 | case RTC_AIE_OFF: |
| 276 | stampit(); | 291 | dev_dbg_stamp(dev); |
| 277 | spin_lock_irq(&rtc->lock); | 292 | bfin_rtc_int_clear(rtc, ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); |
| 278 | rtc_bfin_sync_pending(); | 293 | break; |
| 279 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 294 | |
| 280 | spin_unlock_irq(&rtc->lock); | 295 | default: |
| 281 | return 0; | 296 | dev_dbg_stamp(dev); |
| 297 | ret = -ENOIOCTLCMD; | ||
| 282 | } | 298 | } |
| 283 | 299 | ||
| 284 | return -ENOIOCTLCMD; | 300 | return ret; |
| 285 | } | 301 | } |
| 286 | 302 | ||
| 287 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) | 303 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 288 | { | 304 | { |
| 289 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 305 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
| 290 | 306 | ||
| 291 | stampit(); | 307 | dev_dbg_stamp(dev); |
| 308 | |||
| 309 | if (rtc->rtc_wrote_regs & 0x1) | ||
| 310 | bfin_rtc_sync_pending(dev); | ||
| 292 | 311 | ||
| 293 | spin_lock_irq(&rtc->lock); | ||
| 294 | rtc_bfin_sync_pending(); | ||
| 295 | rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm); | 312 | rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm); |
| 296 | spin_unlock_irq(&rtc->lock); | ||
| 297 | 313 | ||
| 298 | return 0; | 314 | return 0; |
| 299 | } | 315 | } |
| @@ -304,64 +320,79 @@ static int bfin_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 304 | int ret; | 320 | int ret; |
| 305 | unsigned long now; | 321 | unsigned long now; |
| 306 | 322 | ||
| 307 | stampit(); | 323 | dev_dbg_stamp(dev); |
| 308 | |||
| 309 | spin_lock_irq(&rtc->lock); | ||
| 310 | 324 | ||
| 311 | ret = rtc_tm_to_time(tm, &now); | 325 | ret = rtc_tm_to_time(tm, &now); |
| 312 | if (ret == 0) { | 326 | if (ret == 0) { |
| 313 | rtc_bfin_sync_pending(); | 327 | if (rtc->rtc_wrote_regs & 0x1) |
| 328 | bfin_rtc_sync_pending(dev); | ||
| 314 | bfin_write_RTC_STAT(rtc_time_to_bfin(now)); | 329 | bfin_write_RTC_STAT(rtc_time_to_bfin(now)); |
| 330 | rtc->rtc_wrote_regs = 0x1; | ||
| 315 | } | 331 | } |
| 316 | 332 | ||
| 317 | spin_unlock_irq(&rtc->lock); | ||
| 318 | |||
| 319 | return ret; | 333 | return ret; |
| 320 | } | 334 | } |
| 321 | 335 | ||
| 322 | static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 336 | static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| 323 | { | 337 | { |
| 324 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 338 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
| 325 | stampit(); | 339 | dev_dbg_stamp(dev); |
| 326 | memcpy(&alrm->time, &rtc->rtc_alarm, sizeof(struct rtc_time)); | 340 | alrm->time = rtc->rtc_alarm; |
| 327 | alrm->pending = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 341 | bfin_rtc_sync_pending(dev); |
| 342 | alrm->enabled = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | ||
| 328 | return 0; | 343 | return 0; |
| 329 | } | 344 | } |
| 330 | 345 | ||
| 331 | static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 346 | static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| 332 | { | 347 | { |
| 333 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 348 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
| 334 | stampit(); | 349 | unsigned long rtc_alarm; |
| 335 | memcpy(&rtc->rtc_alarm, &alrm->time, sizeof(struct rtc_time)); | 350 | |
| 351 | dev_dbg_stamp(dev); | ||
| 352 | |||
| 353 | if (rtc_tm_to_time(&alrm->time, &rtc_alarm)) | ||
| 354 | return -EINVAL; | ||
| 355 | |||
| 356 | rtc->rtc_alarm = alrm->time; | ||
| 357 | |||
| 358 | bfin_rtc_sync_pending(dev); | ||
| 359 | bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm)); | ||
| 360 | if (alrm->enabled) | ||
| 361 | bfin_rtc_int_set_alarm(rtc); | ||
| 362 | |||
| 336 | return 0; | 363 | return 0; |
| 337 | } | 364 | } |
| 338 | 365 | ||
| 339 | static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) | 366 | static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) |
| 340 | { | 367 | { |
| 341 | #define yesno(x) (x ? "yes" : "no") | 368 | #define yesno(x) ((x) ? "yes" : "no") |
| 342 | u16 ictl = bfin_read_RTC_ICTL(); | 369 | u16 ictl = bfin_read_RTC_ICTL(); |
| 343 | stampit(); | 370 | dev_dbg_stamp(dev); |
| 344 | seq_printf(seq, "alarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM)); | 371 | seq_printf(seq, |
| 345 | seq_printf(seq, "wkalarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM_DAY)); | 372 | "alarm_IRQ\t: %s\n" |
| 346 | seq_printf(seq, "seconds_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_SEC)); | 373 | "wkalarm_IRQ\t: %s\n" |
| 347 | seq_printf(seq, "periodic_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_STOPWATCH)); | 374 | "seconds_IRQ\t: %s\n" |
| 348 | #ifdef DEBUG | 375 | "periodic_IRQ\t: %s\n", |
| 349 | seq_printf(seq, "RTC_STAT\t: 0x%08X\n", bfin_read_RTC_STAT()); | 376 | yesno(ictl & RTC_ISTAT_ALARM), |
| 350 | seq_printf(seq, "RTC_ICTL\t: 0x%04X\n", bfin_read_RTC_ICTL()); | 377 | yesno(ictl & RTC_ISTAT_ALARM_DAY), |
| 351 | seq_printf(seq, "RTC_ISTAT\t: 0x%04X\n", bfin_read_RTC_ISTAT()); | 378 | yesno(ictl & RTC_ISTAT_SEC), |
| 352 | seq_printf(seq, "RTC_SWCNT\t: 0x%04X\n", bfin_read_RTC_SWCNT()); | 379 | yesno(ictl & RTC_ISTAT_STOPWATCH)); |
| 353 | seq_printf(seq, "RTC_ALARM\t: 0x%08X\n", bfin_read_RTC_ALARM()); | ||
| 354 | seq_printf(seq, "RTC_PREN\t: 0x%04X\n", bfin_read_RTC_PREN()); | ||
| 355 | #endif | ||
| 356 | return 0; | 380 | return 0; |
| 381 | #undef yesno | ||
| 357 | } | 382 | } |
| 358 | 383 | ||
| 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 | */ | ||
| 359 | static int bfin_irq_set_freq(struct device *dev, int freq) | 392 | static int bfin_irq_set_freq(struct device *dev, int freq) |
| 360 | { | 393 | { |
| 361 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 394 | dev_dbg_stamp(dev); |
| 362 | stampit(); | 395 | return -ENOTTY; |
| 363 | rtc->rtc_dev->irq_freq = freq; | ||
| 364 | return 0; | ||
| 365 | } | 396 | } |
| 366 | 397 | ||
| 367 | static struct rtc_class_ops bfin_rtc_ops = { | 398 | static struct rtc_class_ops bfin_rtc_ops = { |
| @@ -381,27 +412,24 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
| 381 | struct bfin_rtc *rtc; | 412 | struct bfin_rtc *rtc; |
| 382 | int ret = 0; | 413 | int ret = 0; |
| 383 | 414 | ||
| 384 | stampit(); | 415 | dev_dbg_stamp(&pdev->dev); |
| 385 | 416 | ||
| 386 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 417 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
| 387 | if (unlikely(!rtc)) | 418 | if (unlikely(!rtc)) |
| 388 | return -ENOMEM; | 419 | return -ENOMEM; |
| 389 | 420 | ||
| 390 | spin_lock_init(&rtc->lock); | ||
| 391 | |||
| 392 | rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE); | 421 | rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE); |
| 393 | if (unlikely(IS_ERR(rtc))) { | 422 | if (unlikely(IS_ERR(rtc))) { |
| 394 | ret = PTR_ERR(rtc->rtc_dev); | 423 | ret = PTR_ERR(rtc->rtc_dev); |
| 395 | goto err; | 424 | goto err; |
| 396 | } | 425 | } |
| 397 | rtc->rtc_dev->irq_freq = 0; | 426 | rtc->rtc_dev->irq_freq = 1; |
| 398 | rtc->rtc_dev->max_user_freq = (2 << 16); /* stopwatch is an unsigned 16 bit reg */ | ||
| 399 | 427 | ||
| 400 | platform_set_drvdata(pdev, rtc); | 428 | platform_set_drvdata(pdev, rtc); |
| 401 | 429 | ||
| 402 | return 0; | 430 | return 0; |
| 403 | 431 | ||
| 404 | err: | 432 | err: |
| 405 | kfree(rtc); | 433 | kfree(rtc); |
| 406 | return ret; | 434 | return ret; |
| 407 | } | 435 | } |
| @@ -428,7 +456,6 @@ static struct platform_driver bfin_rtc_driver = { | |||
| 428 | 456 | ||
| 429 | static int __init bfin_rtc_init(void) | 457 | static int __init bfin_rtc_init(void) |
| 430 | { | 458 | { |
| 431 | stampit(); | ||
| 432 | return platform_driver_register(&bfin_rtc_driver); | 459 | return platform_driver_register(&bfin_rtc_driver); |
| 433 | } | 460 | } |
| 434 | 461 | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 29cf1457ca10..e059f94c79eb 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
| @@ -36,9 +36,24 @@ | |||
| 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 | |||
| 39 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
| 40 | #include <asm-generic/rtc.h> | 44 | #include <asm-generic/rtc.h> |
| 41 | 45 | ||
| 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 | ||
| 42 | 57 | ||
| 43 | struct cmos_rtc { | 58 | struct cmos_rtc { |
| 44 | struct rtc_device *rtc; | 59 | struct rtc_device *rtc; |
| @@ -199,6 +214,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 199 | sec = t->time.tm_sec; | 214 | sec = t->time.tm_sec; |
| 200 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; | 215 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; |
| 201 | 216 | ||
| 217 | hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); | ||
| 202 | spin_lock_irq(&rtc_lock); | 218 | spin_lock_irq(&rtc_lock); |
| 203 | 219 | ||
| 204 | /* next rtc irq must not be from previous alarm setting */ | 220 | /* next rtc irq must not be from previous alarm setting */ |
| @@ -252,7 +268,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
| 252 | f = 16 - f; | 268 | f = 16 - f; |
| 253 | 269 | ||
| 254 | spin_lock_irqsave(&rtc_lock, flags); | 270 | spin_lock_irqsave(&rtc_lock, flags); |
| 255 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | 271 | if (!hpet_set_periodic_freq(freq)) |
| 272 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | ||
| 256 | spin_unlock_irqrestore(&rtc_lock, flags); | 273 | spin_unlock_irqrestore(&rtc_lock, flags); |
| 257 | 274 | ||
| 258 | return 0; | 275 | return 0; |
| @@ -314,28 +331,37 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
| 314 | switch (cmd) { | 331 | switch (cmd) { |
| 315 | case RTC_AIE_OFF: /* alarm off */ | 332 | case RTC_AIE_OFF: /* alarm off */ |
| 316 | rtc_control &= ~RTC_AIE; | 333 | rtc_control &= ~RTC_AIE; |
| 334 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
| 317 | break; | 335 | break; |
| 318 | case RTC_AIE_ON: /* alarm on */ | 336 | case RTC_AIE_ON: /* alarm on */ |
| 319 | rtc_control |= RTC_AIE; | 337 | rtc_control |= RTC_AIE; |
| 338 | hpet_set_rtc_irq_bit(RTC_AIE); | ||
| 320 | break; | 339 | break; |
| 321 | case RTC_UIE_OFF: /* update off */ | 340 | case RTC_UIE_OFF: /* update off */ |
| 322 | rtc_control &= ~RTC_UIE; | 341 | rtc_control &= ~RTC_UIE; |
| 342 | hpet_mask_rtc_irq_bit(RTC_UIE); | ||
| 323 | break; | 343 | break; |
| 324 | case RTC_UIE_ON: /* update on */ | 344 | case RTC_UIE_ON: /* update on */ |
| 325 | rtc_control |= RTC_UIE; | 345 | rtc_control |= RTC_UIE; |
| 346 | hpet_set_rtc_irq_bit(RTC_UIE); | ||
| 326 | break; | 347 | break; |
| 327 | case RTC_PIE_OFF: /* periodic off */ | 348 | case RTC_PIE_OFF: /* periodic off */ |
| 328 | rtc_control &= ~RTC_PIE; | 349 | rtc_control &= ~RTC_PIE; |
| 350 | hpet_mask_rtc_irq_bit(RTC_PIE); | ||
| 329 | break; | 351 | break; |
| 330 | case RTC_PIE_ON: /* periodic on */ | 352 | case RTC_PIE_ON: /* periodic on */ |
| 331 | rtc_control |= RTC_PIE; | 353 | rtc_control |= RTC_PIE; |
| 354 | hpet_set_rtc_irq_bit(RTC_PIE); | ||
| 332 | break; | 355 | break; |
| 333 | } | 356 | } |
| 334 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 357 | if (!is_hpet_enabled()) |
| 358 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
| 359 | |||
| 335 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 360 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
| 336 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 361 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
| 337 | if (is_intr(rtc_intr)) | 362 | if (is_intr(rtc_intr)) |
| 338 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | 363 | rtc_update_irq(cmos->rtc, 1, rtc_intr); |
| 364 | |||
| 339 | spin_unlock_irqrestore(&rtc_lock, flags); | 365 | spin_unlock_irqrestore(&rtc_lock, flags); |
| 340 | return 0; | 366 | return 0; |
| 341 | } | 367 | } |
| @@ -393,15 +419,111 @@ static const struct rtc_class_ops cmos_rtc_ops = { | |||
| 393 | 419 | ||
| 394 | /*----------------------------------------------------------------*/ | 420 | /*----------------------------------------------------------------*/ |
| 395 | 421 | ||
| 422 | /* | ||
| 423 | * All these chips have at least 64 bytes of address space, shared by | ||
| 424 | * RTC registers and NVRAM. Most of those bytes of NVRAM are used | ||
| 425 | * by boot firmware. Modern chips have 128 or 256 bytes. | ||
| 426 | */ | ||
| 427 | |||
| 428 | #define NVRAM_OFFSET (RTC_REG_D + 1) | ||
| 429 | |||
| 430 | static ssize_t | ||
| 431 | cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | ||
| 432 | char *buf, loff_t off, size_t count) | ||
| 433 | { | ||
| 434 | int retval; | ||
| 435 | |||
| 436 | if (unlikely(off >= attr->size)) | ||
| 437 | return 0; | ||
| 438 | if ((off + count) > attr->size) | ||
| 439 | count = attr->size - off; | ||
| 440 | |||
| 441 | spin_lock_irq(&rtc_lock); | ||
| 442 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) | ||
| 443 | *buf++ = CMOS_READ(off); | ||
| 444 | spin_unlock_irq(&rtc_lock); | ||
| 445 | |||
| 446 | return retval; | ||
| 447 | } | ||
| 448 | |||
| 449 | static ssize_t | ||
| 450 | cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | ||
| 451 | char *buf, loff_t off, size_t count) | ||
| 452 | { | ||
| 453 | struct cmos_rtc *cmos; | ||
| 454 | int retval; | ||
| 455 | |||
| 456 | cmos = dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
| 457 | if (unlikely(off >= attr->size)) | ||
| 458 | return -EFBIG; | ||
| 459 | if ((off + count) > attr->size) | ||
| 460 | count = attr->size - off; | ||
| 461 | |||
| 462 | /* NOTE: on at least PCs and Ataris, the boot firmware uses a | ||
| 463 | * checksum on part of the NVRAM data. That's currently ignored | ||
| 464 | * here. If userspace is smart enough to know what fields of | ||
| 465 | * NVRAM to update, updating checksums is also part of its job. | ||
| 466 | */ | ||
| 467 | spin_lock_irq(&rtc_lock); | ||
| 468 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) { | ||
| 469 | /* don't trash RTC registers */ | ||
| 470 | if (off == cmos->day_alrm | ||
| 471 | || off == cmos->mon_alrm | ||
| 472 | || off == cmos->century) | ||
| 473 | buf++; | ||
| 474 | else | ||
| 475 | CMOS_WRITE(*buf++, off); | ||
| 476 | } | ||
| 477 | spin_unlock_irq(&rtc_lock); | ||
| 478 | |||
| 479 | return retval; | ||
| 480 | } | ||
| 481 | |||
| 482 | static struct bin_attribute nvram = { | ||
| 483 | .attr = { | ||
| 484 | .name = "nvram", | ||
| 485 | .mode = S_IRUGO | S_IWUSR, | ||
| 486 | .owner = THIS_MODULE, | ||
| 487 | }, | ||
| 488 | |||
| 489 | .read = cmos_nvram_read, | ||
| 490 | .write = cmos_nvram_write, | ||
| 491 | /* size gets set up later */ | ||
| 492 | }; | ||
| 493 | |||
| 494 | /*----------------------------------------------------------------*/ | ||
| 495 | |||
| 396 | static struct cmos_rtc cmos_rtc; | 496 | static struct cmos_rtc cmos_rtc; |
| 397 | 497 | ||
| 398 | static irqreturn_t cmos_interrupt(int irq, void *p) | 498 | static irqreturn_t cmos_interrupt(int irq, void *p) |
| 399 | { | 499 | { |
| 400 | u8 irqstat; | 500 | u8 irqstat; |
| 501 | u8 rtc_control; | ||
| 401 | 502 | ||
| 402 | spin_lock(&rtc_lock); | 503 | spin_lock(&rtc_lock); |
| 403 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | 504 | /* |
| 404 | irqstat &= (CMOS_READ(RTC_CONTROL) & RTC_IRQMASK) | RTC_IRQF; | 505 | * In this case it is HPET RTC interrupt handler |
| 506 | * calling us, with the interrupt information | ||
| 507 | * passed as arg1, instead of irq. | ||
| 508 | */ | ||
| 509 | if (is_hpet_enabled()) | ||
| 510 | irqstat = (unsigned long)irq & 0xF0; | ||
| 511 | else { | ||
| 512 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | ||
| 513 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
| 514 | irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
| 515 | } | ||
| 516 | |||
| 517 | /* All Linux RTC alarms should be treated as if they were oneshot. | ||
| 518 | * Similar code may be needed in system wakeup paths, in case the | ||
| 519 | * alarm woke the system. | ||
| 520 | */ | ||
| 521 | if (irqstat & RTC_AIE) { | ||
| 522 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
| 523 | rtc_control &= ~RTC_AIE; | ||
| 524 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
| 525 | CMOS_READ(RTC_INTR_FLAGS); | ||
| 526 | } | ||
| 405 | spin_unlock(&rtc_lock); | 527 | spin_unlock(&rtc_lock); |
| 406 | 528 | ||
| 407 | if (is_intr(irqstat)) { | 529 | if (is_intr(irqstat)) { |
| @@ -412,11 +534,9 @@ static irqreturn_t cmos_interrupt(int irq, void *p) | |||
| 412 | } | 534 | } |
| 413 | 535 | ||
| 414 | #ifdef CONFIG_PNP | 536 | #ifdef CONFIG_PNP |
| 415 | #define is_pnp() 1 | ||
| 416 | #define INITSECTION | 537 | #define INITSECTION |
| 417 | 538 | ||
| 418 | #else | 539 | #else |
| 419 | #define is_pnp() 0 | ||
| 420 | #define INITSECTION __init | 540 | #define INITSECTION __init |
| 421 | #endif | 541 | #endif |
| 422 | 542 | ||
| @@ -426,6 +546,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 426 | struct cmos_rtc_board_info *info = dev->platform_data; | 546 | struct cmos_rtc_board_info *info = dev->platform_data; |
| 427 | int retval = 0; | 547 | int retval = 0; |
| 428 | unsigned char rtc_control; | 548 | unsigned char rtc_control; |
| 549 | unsigned address_space; | ||
| 429 | 550 | ||
| 430 | /* there can be only one ... */ | 551 | /* there can be only one ... */ |
| 431 | if (cmos_rtc.dev) | 552 | if (cmos_rtc.dev) |
| @@ -450,15 +571,36 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 450 | cmos_rtc.irq = rtc_irq; | 571 | cmos_rtc.irq = rtc_irq; |
| 451 | cmos_rtc.iomem = ports; | 572 | cmos_rtc.iomem = ports; |
| 452 | 573 | ||
| 574 | /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM | ||
| 575 | * driver did, but don't reject unknown configs. Old hardware | ||
| 576 | * won't address 128 bytes, and for now we ignore the way newer | ||
| 577 | * chips can address 256 bytes (using two more i/o ports). | ||
| 578 | */ | ||
| 579 | #if defined(CONFIG_ATARI) | ||
| 580 | address_space = 64; | ||
| 581 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) | ||
| 582 | address_space = 128; | ||
| 583 | #else | ||
| 584 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | ||
| 585 | address_space = 128; | ||
| 586 | #endif | ||
| 587 | |||
| 453 | /* For ACPI systems extension info comes from the FADT. On others, | 588 | /* For ACPI systems extension info comes from the FADT. On others, |
| 454 | * board specific setup provides it as appropriate. Systems where | 589 | * board specific setup provides it as appropriate. Systems where |
| 455 | * the alarm IRQ isn't automatically a wakeup IRQ (like ACPI, and | 590 | * the alarm IRQ isn't automatically a wakeup IRQ (like ACPI, and |
| 456 | * some almost-clones) can provide hooks to make that behave. | 591 | * some almost-clones) can provide hooks to make that behave. |
| 592 | * | ||
| 593 | * Note that ACPI doesn't preclude putting these registers into | ||
| 594 | * "extended" areas of the chip, including some that we won't yet | ||
| 595 | * expect CMOS_READ and friends to handle. | ||
| 457 | */ | 596 | */ |
| 458 | if (info) { | 597 | if (info) { |
| 459 | cmos_rtc.day_alrm = info->rtc_day_alarm; | 598 | if (info->rtc_day_alarm && info->rtc_day_alarm < 128) |
| 460 | cmos_rtc.mon_alrm = info->rtc_mon_alarm; | 599 | cmos_rtc.day_alrm = info->rtc_day_alarm; |
| 461 | cmos_rtc.century = info->rtc_century; | 600 | if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128) |
| 601 | cmos_rtc.mon_alrm = info->rtc_mon_alarm; | ||
| 602 | if (info->rtc_century && info->rtc_century < 128) | ||
| 603 | cmos_rtc.century = info->rtc_century; | ||
| 462 | 604 | ||
| 463 | if (info->wake_on && info->wake_off) { | 605 | if (info->wake_on && info->wake_off) { |
| 464 | cmos_rtc.wake_on = info->wake_on; | 606 | cmos_rtc.wake_on = info->wake_on; |
| @@ -485,8 +627,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 485 | * doesn't use 32KHz here ... for portability we might need to | 627 | * doesn't use 32KHz here ... for portability we might need to |
| 486 | * do something about other clock frequencies. | 628 | * do something about other clock frequencies. |
| 487 | */ | 629 | */ |
| 488 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | ||
| 489 | cmos_rtc.rtc->irq_freq = 1024; | 630 | cmos_rtc.rtc->irq_freq = 1024; |
| 631 | if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq)) | ||
| 632 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | ||
| 490 | 633 | ||
| 491 | /* disable irqs. | 634 | /* disable irqs. |
| 492 | * | 635 | * |
| @@ -509,19 +652,39 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 509 | goto cleanup1; | 652 | goto cleanup1; |
| 510 | } | 653 | } |
| 511 | 654 | ||
| 512 | if (is_valid_irq(rtc_irq)) | 655 | if (is_valid_irq(rtc_irq)) { |
| 513 | retval = request_irq(rtc_irq, cmos_interrupt, IRQF_DISABLED, | 656 | irq_handler_t rtc_cmos_int_handler; |
| 514 | cmos_rtc.rtc->dev.bus_id, | 657 | |
| 658 | if (is_hpet_enabled()) { | ||
| 659 | int err; | ||
| 660 | |||
| 661 | rtc_cmos_int_handler = hpet_rtc_interrupt; | ||
| 662 | err = hpet_register_irq_handler(cmos_interrupt); | ||
| 663 | if (err != 0) { | ||
| 664 | printk(KERN_WARNING "hpet_register_irq_handler " | ||
| 665 | " failed in rtc_init()."); | ||
| 666 | goto cleanup1; | ||
| 667 | } | ||
| 668 | } else | ||
| 669 | rtc_cmos_int_handler = cmos_interrupt; | ||
| 670 | |||
| 671 | retval = request_irq(rtc_irq, rtc_cmos_int_handler, | ||
| 672 | IRQF_DISABLED, cmos_rtc.rtc->dev.bus_id, | ||
| 515 | cmos_rtc.rtc); | 673 | cmos_rtc.rtc); |
| 516 | if (retval < 0) { | 674 | if (retval < 0) { |
| 517 | dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); | 675 | dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); |
| 518 | goto cleanup1; | 676 | goto cleanup1; |
| 677 | } | ||
| 519 | } | 678 | } |
| 679 | hpet_rtc_timer_init(); | ||
| 520 | 680 | ||
| 521 | /* REVISIT optionally make 50 or 114 bytes NVRAM available, | 681 | /* export at least the first block of NVRAM */ |
| 522 | * like rtc-ds1553, rtc-ds1742 ... this will often include | 682 | nvram.size = address_space - NVRAM_OFFSET; |
| 523 | * registers for century, and day/month alarm. | 683 | retval = sysfs_create_bin_file(&dev->kobj, &nvram); |
| 524 | */ | 684 | if (retval < 0) { |
| 685 | dev_dbg(dev, "can't create nvram file? %d\n", retval); | ||
| 686 | goto cleanup2; | ||
| 687 | } | ||
| 525 | 688 | ||
| 526 | pr_info("%s: alarms up to one %s%s\n", | 689 | pr_info("%s: alarms up to one %s%s\n", |
| 527 | cmos_rtc.rtc->dev.bus_id, | 690 | cmos_rtc.rtc->dev.bus_id, |
| @@ -536,6 +699,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 536 | 699 | ||
| 537 | return 0; | 700 | return 0; |
| 538 | 701 | ||
| 702 | cleanup2: | ||
| 703 | if (is_valid_irq(rtc_irq)) | ||
| 704 | free_irq(rtc_irq, cmos_rtc.rtc); | ||
| 539 | cleanup1: | 705 | cleanup1: |
| 540 | cmos_rtc.dev = NULL; | 706 | cmos_rtc.dev = NULL; |
| 541 | rtc_device_unregister(cmos_rtc.rtc); | 707 | rtc_device_unregister(cmos_rtc.rtc); |
| @@ -563,8 +729,12 @@ static void __exit cmos_do_remove(struct device *dev) | |||
| 563 | 729 | ||
| 564 | cmos_do_shutdown(); | 730 | cmos_do_shutdown(); |
| 565 | 731 | ||
| 566 | if (is_valid_irq(cmos->irq)) | 732 | sysfs_remove_bin_file(&dev->kobj, &nvram); |
| 733 | |||
| 734 | if (is_valid_irq(cmos->irq)) { | ||
| 567 | free_irq(cmos->irq, cmos->rtc); | 735 | free_irq(cmos->irq, cmos->rtc); |
| 736 | hpet_unregister_irq_handler(cmos_interrupt); | ||
| 737 | } | ||
| 568 | 738 | ||
| 569 | rtc_device_unregister(cmos->rtc); | 739 | rtc_device_unregister(cmos->rtc); |
| 570 | cmos->rtc = NULL; | 740 | cmos->rtc = NULL; |
| @@ -659,9 +829,12 @@ static int cmos_resume(struct device *dev) | |||
| 659 | 829 | ||
| 660 | /*----------------------------------------------------------------*/ | 830 | /*----------------------------------------------------------------*/ |
| 661 | 831 | ||
| 662 | /* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems, | 832 | /* On non-x86 systems, a "CMOS" RTC lives most naturally on platform_bus. |
| 663 | * the device node will always be created as a PNPACPI device. Plus | 833 | * ACPI systems always list these as PNPACPI devices, and pre-ACPI PCs |
| 664 | * pre-ACPI PCs probably list it in the PNPBIOS tables. | 834 | * probably list them in similar PNPBIOS tables; so PNP is more common. |
| 835 | * | ||
| 836 | * We don't use legacy "poke at the hardware" probing. Ancient PCs that | ||
| 837 | * predate even PNPBIOS should set up platform_bus devices. | ||
| 665 | */ | 838 | */ |
| 666 | 839 | ||
| 667 | #ifdef CONFIG_PNP | 840 | #ifdef CONFIG_PNP |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 025c60a17a4a..90dfa0df747a 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
| @@ -246,6 +246,15 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 246 | /* if the driver does not provide the ioctl interface | 246 | /* if the driver does not provide the ioctl interface |
| 247 | * or if that particular ioctl was not implemented | 247 | * or if that particular ioctl was not implemented |
| 248 | * (-ENOIOCTLCMD), we will try to emulate here. | 248 | * (-ENOIOCTLCMD), we will try to emulate here. |
| 249 | * | ||
| 250 | * Drivers *SHOULD NOT* provide ioctl implementations | ||
| 251 | * for these requests. Instead, provide methods to | ||
| 252 | * support the following code, so that the RTC's main | ||
| 253 | * features are accessible without using ioctls. | ||
| 254 | * | ||
| 255 | * RTC and alarm times will be in UTC, by preference, | ||
| 256 | * but dual-booting with MS-Windows implies RTCs must | ||
| 257 | * use the local wall clock time. | ||
| 249 | */ | 258 | */ |
| 250 | 259 | ||
| 251 | switch (cmd) { | 260 | switch (cmd) { |
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c new file mode 100644 index 000000000000..7b002ceeaa7d --- /dev/null +++ b/drivers/rtc/rtc-ds1302.c | |||
| @@ -0,0 +1,262 @@ | |||
| 1 | /* | ||
| 2 | * Dallas DS1302 RTC Support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002 David McCullough | ||
| 5 | * Copyright (C) 2003 - 2007 Paul Mundt | ||
| 6 | * | ||
| 7 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 8 | * License version 2. See the file "COPYING" in the main directory of | ||
| 9 | * this archive for more details. | ||
| 10 | */ | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/time.h> | ||
| 16 | #include <linux/rtc.h> | ||
| 17 | #include <linux/spinlock.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/bcd.h> | ||
| 20 | #include <asm/rtc.h> | ||
| 21 | |||
| 22 | #define DRV_NAME "rtc-ds1302" | ||
| 23 | #define DRV_VERSION "0.1.0" | ||
| 24 | |||
| 25 | #define RTC_CMD_READ 0x81 /* Read command */ | ||
| 26 | #define RTC_CMD_WRITE 0x80 /* Write command */ | ||
| 27 | |||
| 28 | #define RTC_ADDR_RAM0 0x20 /* Address of RAM0 */ | ||
| 29 | #define RTC_ADDR_TCR 0x08 /* Address of trickle charge register */ | ||
| 30 | #define RTC_ADDR_YEAR 0x06 /* Address of year register */ | ||
| 31 | #define RTC_ADDR_DAY 0x05 /* Address of day of week register */ | ||
| 32 | #define RTC_ADDR_MON 0x04 /* Address of month register */ | ||
| 33 | #define RTC_ADDR_DATE 0x03 /* Address of day of month register */ | ||
| 34 | #define RTC_ADDR_HOUR 0x02 /* Address of hour register */ | ||
| 35 | #define RTC_ADDR_MIN 0x01 /* Address of minute register */ | ||
| 36 | #define RTC_ADDR_SEC 0x00 /* Address of second register */ | ||
| 37 | |||
| 38 | #define RTC_RESET 0x1000 | ||
| 39 | #define RTC_IODATA 0x0800 | ||
| 40 | #define RTC_SCLK 0x0400 | ||
| 41 | |||
| 42 | #ifdef CONFIG_SH_SECUREEDGE5410 | ||
| 43 | #include <asm/snapgear.h> | ||
| 44 | #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) | ||
| 45 | #define get_dp() SECUREEDGE_READ_IOPORT() | ||
| 46 | #else | ||
| 47 | #error "Add support for your platform" | ||
| 48 | #endif | ||
| 49 | |||
| 50 | struct ds1302_rtc { | ||
| 51 | struct rtc_device *rtc_dev; | ||
| 52 | spinlock_t lock; | ||
| 53 | }; | ||
| 54 | |||
| 55 | static void ds1302_sendbits(unsigned int val) | ||
| 56 | { | ||
| 57 | int i; | ||
| 58 | |||
| 59 | for (i = 8; (i); i--, val >>= 1) { | ||
| 60 | set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? | ||
| 61 | RTC_IODATA : 0)); | ||
| 62 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
| 63 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | static unsigned int ds1302_recvbits(void) | ||
| 68 | { | ||
| 69 | unsigned int val; | ||
| 70 | int i; | ||
| 71 | |||
| 72 | for (i = 0, val = 0; (i < 8); i++) { | ||
| 73 | val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i); | ||
| 74 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
| 75 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
| 76 | } | ||
| 77 | |||
| 78 | return val; | ||
| 79 | } | ||
| 80 | |||
| 81 | static unsigned int ds1302_readbyte(unsigned int addr) | ||
| 82 | { | ||
| 83 | unsigned int val; | ||
| 84 | |||
| 85 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
| 86 | |||
| 87 | set_dp(get_dp() | RTC_RESET); | ||
| 88 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); | ||
| 89 | val = ds1302_recvbits(); | ||
| 90 | set_dp(get_dp() & ~RTC_RESET); | ||
| 91 | |||
| 92 | return val; | ||
| 93 | } | ||
| 94 | |||
| 95 | static void ds1302_writebyte(unsigned int addr, unsigned int val) | ||
| 96 | { | ||
| 97 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
| 98 | set_dp(get_dp() | RTC_RESET); | ||
| 99 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); | ||
| 100 | ds1302_sendbits(val); | ||
| 101 | set_dp(get_dp() & ~RTC_RESET); | ||
| 102 | } | ||
| 103 | |||
| 104 | static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 105 | { | ||
| 106 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
| 107 | |||
| 108 | spin_lock_irq(&rtc->lock); | ||
| 109 | |||
| 110 | tm->tm_sec = BCD2BIN(ds1302_readbyte(RTC_ADDR_SEC)); | ||
| 111 | tm->tm_min = BCD2BIN(ds1302_readbyte(RTC_ADDR_MIN)); | ||
| 112 | tm->tm_hour = BCD2BIN(ds1302_readbyte(RTC_ADDR_HOUR)); | ||
| 113 | tm->tm_wday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DAY)); | ||
| 114 | tm->tm_mday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DATE)); | ||
| 115 | tm->tm_mon = BCD2BIN(ds1302_readbyte(RTC_ADDR_MON)) - 1; | ||
| 116 | tm->tm_year = BCD2BIN(ds1302_readbyte(RTC_ADDR_YEAR)); | ||
| 117 | |||
| 118 | if (tm->tm_year < 70) | ||
| 119 | tm->tm_year += 100; | ||
| 120 | |||
| 121 | spin_unlock_irq(&rtc->lock); | ||
| 122 | |||
| 123 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
| 124 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 125 | __FUNCTION__, | ||
| 126 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
| 127 | tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); | ||
| 128 | |||
| 129 | if (rtc_valid_tm(tm) < 0) | ||
| 130 | dev_err(dev, "invalid date\n"); | ||
| 131 | |||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 136 | { | ||
| 137 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
| 138 | |||
| 139 | spin_lock_irq(&rtc->lock); | ||
| 140 | |||
| 141 | /* Stop RTC */ | ||
| 142 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); | ||
| 143 | |||
| 144 | ds1302_writebyte(RTC_ADDR_SEC, BIN2BCD(tm->tm_sec)); | ||
| 145 | ds1302_writebyte(RTC_ADDR_MIN, BIN2BCD(tm->tm_min)); | ||
| 146 | ds1302_writebyte(RTC_ADDR_HOUR, BIN2BCD(tm->tm_hour)); | ||
| 147 | ds1302_writebyte(RTC_ADDR_DAY, BIN2BCD(tm->tm_wday)); | ||
| 148 | ds1302_writebyte(RTC_ADDR_DATE, BIN2BCD(tm->tm_mday)); | ||
| 149 | ds1302_writebyte(RTC_ADDR_MON, BIN2BCD(tm->tm_mon + 1)); | ||
| 150 | ds1302_writebyte(RTC_ADDR_YEAR, BIN2BCD(tm->tm_year % 100)); | ||
| 151 | |||
| 152 | /* Start RTC */ | ||
| 153 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); | ||
| 154 | |||
| 155 | spin_unlock_irq(&rtc->lock); | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
| 161 | unsigned long arg) | ||
| 162 | { | ||
| 163 | switch (cmd) { | ||
| 164 | #ifdef RTC_SET_CHARGE | ||
| 165 | case RTC_SET_CHARGE: | ||
| 166 | { | ||
| 167 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
| 168 | int tcs_val; | ||
| 169 | |||
| 170 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) | ||
| 171 | return -EFAULT; | ||
| 172 | |||
| 173 | spin_lock_irq(&rtc->lock); | ||
| 174 | ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf)); | ||
| 175 | spin_unlock_irq(&rtc->lock); | ||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | #endif | ||
| 179 | } | ||
| 180 | |||
| 181 | return -ENOIOCTLCMD; | ||
| 182 | } | ||
| 183 | |||
| 184 | static struct rtc_class_ops ds1302_rtc_ops = { | ||
| 185 | .read_time = ds1302_rtc_read_time, | ||
| 186 | .set_time = ds1302_rtc_set_time, | ||
| 187 | .ioctl = ds1302_rtc_ioctl, | ||
| 188 | }; | ||
| 189 | |||
| 190 | static int __devinit ds1302_rtc_probe(struct platform_device *pdev) | ||
| 191 | { | ||
| 192 | struct ds1302_rtc *rtc; | ||
| 193 | int ret; | ||
| 194 | |||
| 195 | /* Reset */ | ||
| 196 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
| 197 | |||
| 198 | /* Write a magic value to the DS1302 RAM, and see if it sticks. */ | ||
| 199 | ds1302_writebyte(RTC_ADDR_RAM0, 0x42); | ||
| 200 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) | ||
| 201 | return -ENODEV; | ||
| 202 | |||
| 203 | rtc = kzalloc(sizeof(struct ds1302_rtc), GFP_KERNEL); | ||
| 204 | if (unlikely(!rtc)) | ||
| 205 | return -ENOMEM; | ||
| 206 | |||
| 207 | spin_lock_init(&rtc->lock); | ||
| 208 | rtc->rtc_dev = rtc_device_register("ds1302", &pdev->dev, | ||
| 209 | &ds1302_rtc_ops, THIS_MODULE); | ||
| 210 | if (IS_ERR(rtc->rtc_dev)) { | ||
| 211 | ret = PTR_ERR(rtc->rtc_dev); | ||
| 212 | goto out; | ||
| 213 | } | ||
| 214 | |||
| 215 | platform_set_drvdata(pdev, rtc); | ||
| 216 | |||
| 217 | return 0; | ||
| 218 | out: | ||
| 219 | kfree(rtc); | ||
| 220 | return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int __devexit ds1302_rtc_remove(struct platform_device *pdev) | ||
| 224 | { | ||
| 225 | struct ds1302_rtc *rtc = platform_get_drvdata(pdev); | ||
| 226 | |||
| 227 | if (likely(rtc->rtc_dev)) | ||
| 228 | rtc_device_unregister(rtc->rtc_dev); | ||
| 229 | |||
| 230 | platform_set_drvdata(pdev, NULL); | ||
| 231 | |||
| 232 | kfree(rtc); | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | static struct platform_driver ds1302_platform_driver = { | ||
| 238 | .driver = { | ||
| 239 | .name = DRV_NAME, | ||
| 240 | .owner = THIS_MODULE, | ||
| 241 | }, | ||
| 242 | .probe = ds1302_rtc_probe, | ||
| 243 | .remove = __devexit_p(ds1302_rtc_remove), | ||
| 244 | }; | ||
| 245 | |||
| 246 | static int __init ds1302_rtc_init(void) | ||
| 247 | { | ||
| 248 | return platform_driver_register(&ds1302_platform_driver); | ||
| 249 | } | ||
| 250 | |||
| 251 | static void __exit ds1302_rtc_exit(void) | ||
| 252 | { | ||
| 253 | platform_driver_unregister(&ds1302_platform_driver); | ||
| 254 | } | ||
| 255 | |||
| 256 | module_init(ds1302_rtc_init); | ||
| 257 | module_exit(ds1302_rtc_exit); | ||
| 258 | |||
| 259 | MODULE_DESCRIPTION("Dallas DS1302 RTC driver"); | ||
| 260 | MODULE_VERSION(DRV_VERSION); | ||
| 261 | MODULE_AUTHOR("Paul Mundt, David McCullough"); | ||
| 262 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index bc1c7fe94ad3..f389a28720d2 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
| @@ -256,7 +256,7 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
| 256 | struct i2c_msg msg[2]; | 256 | struct i2c_msg msg[2]; |
| 257 | int result; | 257 | int result; |
| 258 | 258 | ||
| 259 | client = to_i2c_client(container_of(kobj, struct device, kobj)); | 259 | client = kobj_to_i2c_client(kobj); |
| 260 | ds1307 = i2c_get_clientdata(client); | 260 | ds1307 = i2c_get_clientdata(client); |
| 261 | 261 | ||
| 262 | if (unlikely(off >= NVRAM_SIZE)) | 262 | if (unlikely(off >= NVRAM_SIZE)) |
| @@ -294,7 +294,7 @@ ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
| 294 | u8 buffer[NVRAM_SIZE + 1]; | 294 | u8 buffer[NVRAM_SIZE + 1]; |
| 295 | int ret; | 295 | int ret; |
| 296 | 296 | ||
| 297 | client = to_i2c_client(container_of(kobj, struct device, kobj)); | 297 | client = kobj_to_i2c_client(kobj); |
| 298 | 298 | ||
| 299 | if (unlikely(off >= NVRAM_SIZE)) | 299 | if (unlikely(off >= NVRAM_SIZE)) |
| 300 | return -EFBIG; | 300 | return -EFBIG; |
| @@ -412,11 +412,6 @@ read_rtc: | |||
| 412 | */ | 412 | */ |
| 413 | tmp = ds1307->regs[DS1307_REG_SECS]; | 413 | tmp = ds1307->regs[DS1307_REG_SECS]; |
| 414 | switch (ds1307->type) { | 414 | switch (ds1307->type) { |
| 415 | case ds_1340: | ||
| 416 | /* FIXME read register with DS1340_BIT_OSF, use that to | ||
| 417 | * trigger the "set time" warning (*after* restarting the | ||
| 418 | * oscillator!) instead of this weaker ds1307/m41t00 test. | ||
| 419 | */ | ||
| 420 | case ds_1307: | 415 | case ds_1307: |
| 421 | case m41t00: | 416 | case m41t00: |
| 422 | /* clock halted? turn it on, so clock can tick. */ | 417 | /* clock halted? turn it on, so clock can tick. */ |
| @@ -440,6 +435,24 @@ read_rtc: | |||
| 440 | goto read_rtc; | 435 | goto read_rtc; |
| 441 | } | 436 | } |
| 442 | break; | 437 | break; |
| 438 | case ds_1340: | ||
| 439 | /* clock halted? turn it on, so clock can tick. */ | ||
| 440 | if (tmp & DS1340_BIT_nEOSC) | ||
| 441 | i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0); | ||
| 442 | |||
| 443 | tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG); | ||
| 444 | if (tmp < 0) { | ||
| 445 | pr_debug("read error %d\n", tmp); | ||
| 446 | err = -EIO; | ||
| 447 | goto exit_free; | ||
| 448 | } | ||
| 449 | |||
| 450 | /* oscillator fault? clear flag, and warn */ | ||
| 451 | if (tmp & DS1340_BIT_OSF) { | ||
| 452 | i2c_smbus_write_byte_data(client, DS1340_REG_FLAG, 0); | ||
| 453 | dev_warn(&client->dev, "SET TIME!\n"); | ||
| 454 | } | ||
| 455 | break; | ||
| 443 | case ds_1337: | 456 | case ds_1337: |
| 444 | case ds_1339: | 457 | case ds_1339: |
| 445 | break; | 458 | break; |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c new file mode 100644 index 000000000000..d74b8086fa31 --- /dev/null +++ b/drivers/rtc/rtc-ds1511.c | |||
| @@ -0,0 +1,656 @@ | |||
| 1 | /* | ||
| 2 | * An rtc driver for the Dallas DS1511 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> | ||
| 5 | * Copyright (C) 2007 Andrew Sharp <andy.sharp@onstor.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * Real time clock driver for the Dallas 1511 chip, which also | ||
| 12 | * contains a watchdog timer. There is a tiny amount of code that | ||
| 13 | * platform code could use to mess with the watchdog device a little | ||
| 14 | * bit, but not a full watchdog driver. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/bcd.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/rtc.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/io.h> | ||
| 25 | |||
| 26 | #define DRV_VERSION "0.6" | ||
| 27 | |||
| 28 | enum ds1511reg { | ||
| 29 | DS1511_SEC = 0x0, | ||
| 30 | DS1511_MIN = 0x1, | ||
| 31 | DS1511_HOUR = 0x2, | ||
| 32 | DS1511_DOW = 0x3, | ||
| 33 | DS1511_DOM = 0x4, | ||
| 34 | DS1511_MONTH = 0x5, | ||
| 35 | DS1511_YEAR = 0x6, | ||
| 36 | DS1511_CENTURY = 0x7, | ||
| 37 | DS1511_AM1_SEC = 0x8, | ||
| 38 | DS1511_AM2_MIN = 0x9, | ||
| 39 | DS1511_AM3_HOUR = 0xa, | ||
| 40 | DS1511_AM4_DATE = 0xb, | ||
| 41 | DS1511_WD_MSEC = 0xc, | ||
| 42 | DS1511_WD_SEC = 0xd, | ||
| 43 | DS1511_CONTROL_A = 0xe, | ||
| 44 | DS1511_CONTROL_B = 0xf, | ||
| 45 | DS1511_RAMADDR_LSB = 0x10, | ||
| 46 | DS1511_RAMDATA = 0x13 | ||
| 47 | }; | ||
| 48 | |||
| 49 | #define DS1511_BLF1 0x80 | ||
| 50 | #define DS1511_BLF2 0x40 | ||
| 51 | #define DS1511_PRS 0x20 | ||
| 52 | #define DS1511_PAB 0x10 | ||
| 53 | #define DS1511_TDF 0x08 | ||
| 54 | #define DS1511_KSF 0x04 | ||
| 55 | #define DS1511_WDF 0x02 | ||
| 56 | #define DS1511_IRQF 0x01 | ||
| 57 | #define DS1511_TE 0x80 | ||
| 58 | #define DS1511_CS 0x40 | ||
| 59 | #define DS1511_BME 0x20 | ||
| 60 | #define DS1511_TPE 0x10 | ||
| 61 | #define DS1511_TIE 0x08 | ||
| 62 | #define DS1511_KIE 0x04 | ||
| 63 | #define DS1511_WDE 0x02 | ||
| 64 | #define DS1511_WDS 0x01 | ||
| 65 | #define DS1511_RAM_MAX 0xff | ||
| 66 | |||
| 67 | #define RTC_CMD DS1511_CONTROL_B | ||
| 68 | #define RTC_CMD1 DS1511_CONTROL_A | ||
| 69 | |||
| 70 | #define RTC_ALARM_SEC DS1511_AM1_SEC | ||
| 71 | #define RTC_ALARM_MIN DS1511_AM2_MIN | ||
| 72 | #define RTC_ALARM_HOUR DS1511_AM3_HOUR | ||
| 73 | #define RTC_ALARM_DATE DS1511_AM4_DATE | ||
| 74 | |||
| 75 | #define RTC_SEC DS1511_SEC | ||
| 76 | #define RTC_MIN DS1511_MIN | ||
| 77 | #define RTC_HOUR DS1511_HOUR | ||
| 78 | #define RTC_DOW DS1511_DOW | ||
| 79 | #define RTC_DOM DS1511_DOM | ||
| 80 | #define RTC_MON DS1511_MONTH | ||
| 81 | #define RTC_YEAR DS1511_YEAR | ||
| 82 | #define RTC_CENTURY DS1511_CENTURY | ||
| 83 | |||
| 84 | #define RTC_TIE DS1511_TIE | ||
| 85 | #define RTC_TE DS1511_TE | ||
| 86 | |||
| 87 | struct rtc_plat_data { | ||
| 88 | struct rtc_device *rtc; | ||
| 89 | void __iomem *ioaddr; /* virtual base address */ | ||
| 90 | unsigned long baseaddr; /* physical base address */ | ||
| 91 | int size; /* amount of memory mapped */ | ||
| 92 | int irq; | ||
| 93 | unsigned int irqen; | ||
| 94 | int alrm_sec; | ||
| 95 | int alrm_min; | ||
| 96 | int alrm_hour; | ||
| 97 | int alrm_mday; | ||
| 98 | }; | ||
| 99 | |||
| 100 | static DEFINE_SPINLOCK(ds1511_lock); | ||
| 101 | |||
| 102 | static __iomem char *ds1511_base; | ||
| 103 | static u32 reg_spacing = 1; | ||
| 104 | |||
| 105 | static noinline void | ||
| 106 | rtc_write(uint8_t val, uint32_t reg) | ||
| 107 | { | ||
| 108 | writeb(val, ds1511_base + (reg * reg_spacing)); | ||
| 109 | } | ||
| 110 | |||
| 111 | static inline void | ||
| 112 | rtc_write_alarm(uint8_t val, enum ds1511reg reg) | ||
| 113 | { | ||
| 114 | rtc_write((val | 0x80), reg); | ||
| 115 | } | ||
| 116 | |||
| 117 | static noinline uint8_t | ||
| 118 | rtc_read(enum ds1511reg reg) | ||
| 119 | { | ||
| 120 | return readb(ds1511_base + (reg * reg_spacing)); | ||
| 121 | } | ||
| 122 | |||
| 123 | static inline void | ||
| 124 | rtc_disable_update(void) | ||
| 125 | { | ||
| 126 | rtc_write((rtc_read(RTC_CMD) & ~RTC_TE), RTC_CMD); | ||
| 127 | } | ||
| 128 | |||
| 129 | static void | ||
| 130 | rtc_enable_update(void) | ||
| 131 | { | ||
| 132 | rtc_write((rtc_read(RTC_CMD) | RTC_TE), RTC_CMD); | ||
| 133 | } | ||
| 134 | |||
| 135 | /* | ||
| 136 | * #define DS1511_WDOG_RESET_SUPPORT | ||
| 137 | * | ||
| 138 | * Uncomment this if you want to use these routines in | ||
| 139 | * some platform code. | ||
| 140 | */ | ||
| 141 | #ifdef DS1511_WDOG_RESET_SUPPORT | ||
| 142 | /* | ||
| 143 | * just enough code to set the watchdog timer so that it | ||
| 144 | * will reboot the system | ||
| 145 | */ | ||
| 146 | void | ||
| 147 | ds1511_wdog_set(unsigned long deciseconds) | ||
| 148 | { | ||
| 149 | /* | ||
| 150 | * the wdog timer can take 99.99 seconds | ||
| 151 | */ | ||
| 152 | deciseconds %= 10000; | ||
| 153 | /* | ||
| 154 | * set the wdog values in the wdog registers | ||
| 155 | */ | ||
| 156 | rtc_write(BIN2BCD(deciseconds % 100), DS1511_WD_MSEC); | ||
| 157 | rtc_write(BIN2BCD(deciseconds / 100), DS1511_WD_SEC); | ||
| 158 | /* | ||
| 159 | * set wdog enable and wdog 'steering' bit to issue a reset | ||
| 160 | */ | ||
| 161 | rtc_write(DS1511_WDE | DS1511_WDS, RTC_CMD); | ||
| 162 | } | ||
| 163 | |||
| 164 | void | ||
| 165 | ds1511_wdog_disable(void) | ||
| 166 | { | ||
| 167 | /* | ||
| 168 | * clear wdog enable and wdog 'steering' bits | ||
| 169 | */ | ||
| 170 | rtc_write(rtc_read(RTC_CMD) & ~(DS1511_WDE | DS1511_WDS), RTC_CMD); | ||
| 171 | /* | ||
| 172 | * clear the wdog counter | ||
| 173 | */ | ||
| 174 | rtc_write(0, DS1511_WD_MSEC); | ||
| 175 | rtc_write(0, DS1511_WD_SEC); | ||
| 176 | } | ||
| 177 | #endif | ||
| 178 | |||
| 179 | /* | ||
| 180 | * set the rtc chip's idea of the time. | ||
| 181 | * stupidly, some callers call with year unmolested; | ||
| 182 | * and some call with year = year - 1900. thanks. | ||
| 183 | */ | ||
| 184 | int | ||
| 185 | ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm) | ||
| 186 | { | ||
| 187 | u8 mon, day, dow, hrs, min, sec, yrs, cen; | ||
| 188 | unsigned int flags; | ||
| 189 | |||
| 190 | /* | ||
| 191 | * won't have to change this for a while | ||
| 192 | */ | ||
| 193 | if (rtc_tm->tm_year < 1900) { | ||
| 194 | rtc_tm->tm_year += 1900; | ||
| 195 | } | ||
| 196 | |||
| 197 | if (rtc_tm->tm_year < 1970) { | ||
| 198 | return -EINVAL; | ||
| 199 | } | ||
| 200 | yrs = rtc_tm->tm_year % 100; | ||
| 201 | cen = rtc_tm->tm_year / 100; | ||
| 202 | mon = rtc_tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
| 203 | day = rtc_tm->tm_mday; | ||
| 204 | dow = rtc_tm->tm_wday & 0x7; /* automatic BCD */ | ||
| 205 | hrs = rtc_tm->tm_hour; | ||
| 206 | min = rtc_tm->tm_min; | ||
| 207 | sec = rtc_tm->tm_sec; | ||
| 208 | |||
| 209 | if ((mon > 12) || (day == 0)) { | ||
| 210 | return -EINVAL; | ||
| 211 | } | ||
| 212 | |||
| 213 | if (day > rtc_month_days(rtc_tm->tm_mon, rtc_tm->tm_year)) { | ||
| 214 | return -EINVAL; | ||
| 215 | } | ||
| 216 | |||
| 217 | if ((hrs >= 24) || (min >= 60) || (sec >= 60)) { | ||
| 218 | return -EINVAL; | ||
| 219 | } | ||
| 220 | |||
| 221 | /* | ||
| 222 | * each register is a different number of valid bits | ||
| 223 | */ | ||
| 224 | sec = BIN2BCD(sec) & 0x7f; | ||
| 225 | min = BIN2BCD(min) & 0x7f; | ||
| 226 | hrs = BIN2BCD(hrs) & 0x3f; | ||
| 227 | day = BIN2BCD(day) & 0x3f; | ||
| 228 | mon = BIN2BCD(mon) & 0x1f; | ||
| 229 | yrs = BIN2BCD(yrs) & 0xff; | ||
| 230 | cen = BIN2BCD(cen) & 0xff; | ||
| 231 | |||
| 232 | spin_lock_irqsave(&ds1511_lock, flags); | ||
| 233 | rtc_disable_update(); | ||
| 234 | rtc_write(cen, RTC_CENTURY); | ||
| 235 | rtc_write(yrs, RTC_YEAR); | ||
| 236 | rtc_write((rtc_read(RTC_MON) & 0xe0) | mon, RTC_MON); | ||
| 237 | rtc_write(day, RTC_DOM); | ||
| 238 | rtc_write(hrs, RTC_HOUR); | ||
| 239 | rtc_write(min, RTC_MIN); | ||
| 240 | rtc_write(sec, RTC_SEC); | ||
| 241 | rtc_write(dow, RTC_DOW); | ||
| 242 | rtc_enable_update(); | ||
| 243 | spin_unlock_irqrestore(&ds1511_lock, flags); | ||
| 244 | |||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 248 | int | ||
| 249 | ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | ||
| 250 | { | ||
| 251 | unsigned int century; | ||
| 252 | unsigned int flags; | ||
| 253 | |||
| 254 | spin_lock_irqsave(&ds1511_lock, flags); | ||
| 255 | rtc_disable_update(); | ||
| 256 | |||
| 257 | rtc_tm->tm_sec = rtc_read(RTC_SEC) & 0x7f; | ||
| 258 | rtc_tm->tm_min = rtc_read(RTC_MIN) & 0x7f; | ||
| 259 | rtc_tm->tm_hour = rtc_read(RTC_HOUR) & 0x3f; | ||
| 260 | rtc_tm->tm_mday = rtc_read(RTC_DOM) & 0x3f; | ||
| 261 | rtc_tm->tm_wday = rtc_read(RTC_DOW) & 0x7; | ||
| 262 | rtc_tm->tm_mon = rtc_read(RTC_MON) & 0x1f; | ||
| 263 | rtc_tm->tm_year = rtc_read(RTC_YEAR) & 0x7f; | ||
| 264 | century = rtc_read(RTC_CENTURY); | ||
| 265 | |||
| 266 | rtc_enable_update(); | ||
| 267 | spin_unlock_irqrestore(&ds1511_lock, flags); | ||
| 268 | |||
| 269 | rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec); | ||
| 270 | rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min); | ||
| 271 | rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour); | ||
| 272 | rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday); | ||
| 273 | rtc_tm->tm_wday = BCD2BIN(rtc_tm->tm_wday); | ||
| 274 | rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon); | ||
| 275 | rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year); | ||
| 276 | century = BCD2BIN(century) * 100; | ||
| 277 | |||
| 278 | /* | ||
| 279 | * Account for differences between how the RTC uses the values | ||
| 280 | * and how they are defined in a struct rtc_time; | ||
| 281 | */ | ||
| 282 | century += rtc_tm->tm_year; | ||
| 283 | rtc_tm->tm_year = century - 1900; | ||
| 284 | |||
| 285 | rtc_tm->tm_mon--; | ||
| 286 | |||
| 287 | if (rtc_valid_tm(rtc_tm) < 0) { | ||
| 288 | dev_err(dev, "retrieved date/time is not valid.\n"); | ||
| 289 | rtc_time_to_tm(0, rtc_tm); | ||
| 290 | } | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 295 | * write the alarm register settings | ||
| 296 | * | ||
| 297 | * we only have the use to interrupt every second, otherwise | ||
| 298 | * known as the update interrupt, or the interrupt if the whole | ||
| 299 | * date/hours/mins/secs matches. the ds1511 has many more | ||
| 300 | * permutations, but the kernel doesn't. | ||
| 301 | */ | ||
| 302 | static void | ||
| 303 | ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | ||
| 304 | { | ||
| 305 | unsigned long flags; | ||
| 306 | |||
| 307 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | ||
| 308 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | ||
| 309 | 0x80 : BIN2BCD(pdata->alrm_mday) & 0x3f, | ||
| 310 | RTC_ALARM_DATE); | ||
| 311 | rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? | ||
| 312 | 0x80 : BIN2BCD(pdata->alrm_hour) & 0x3f, | ||
| 313 | RTC_ALARM_HOUR); | ||
| 314 | rtc_write(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? | ||
| 315 | 0x80 : BIN2BCD(pdata->alrm_min) & 0x7f, | ||
| 316 | RTC_ALARM_MIN); | ||
| 317 | rtc_write(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? | ||
| 318 | 0x80 : BIN2BCD(pdata->alrm_sec) & 0x7f, | ||
| 319 | RTC_ALARM_SEC); | ||
| 320 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); | ||
| 321 | rtc_read(RTC_CMD1); /* clear interrupts */ | ||
| 322 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); | ||
| 323 | } | ||
| 324 | |||
| 325 | static int | ||
| 326 | ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 327 | { | ||
| 328 | struct platform_device *pdev = to_platform_device(dev); | ||
| 329 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 330 | |||
| 331 | if (pdata->irq < 0) { | ||
| 332 | return -EINVAL; | ||
| 333 | } | ||
| 334 | pdata->alrm_mday = alrm->time.tm_mday; | ||
| 335 | pdata->alrm_hour = alrm->time.tm_hour; | ||
| 336 | pdata->alrm_min = alrm->time.tm_min; | ||
| 337 | pdata->alrm_sec = alrm->time.tm_sec; | ||
| 338 | if (alrm->enabled) { | ||
| 339 | pdata->irqen |= RTC_AF; | ||
| 340 | } | ||
| 341 | ds1511_rtc_update_alarm(pdata); | ||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | |||
| 345 | static int | ||
| 346 | ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 347 | { | ||
| 348 | struct platform_device *pdev = to_platform_device(dev); | ||
| 349 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 350 | |||
| 351 | if (pdata->irq < 0) { | ||
| 352 | return -EINVAL; | ||
| 353 | } | ||
| 354 | alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday; | ||
| 355 | alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour; | ||
| 356 | alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min; | ||
| 357 | alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec; | ||
| 358 | alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0; | ||
| 359 | return 0; | ||
| 360 | } | ||
| 361 | |||
| 362 | static irqreturn_t | ||
| 363 | ds1511_interrupt(int irq, void *dev_id) | ||
| 364 | { | ||
| 365 | struct platform_device *pdev = dev_id; | ||
| 366 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 367 | unsigned long events = RTC_IRQF; | ||
| 368 | |||
| 369 | /* | ||
| 370 | * read and clear interrupt | ||
| 371 | */ | ||
| 372 | if (!(rtc_read(RTC_CMD1) & DS1511_IRQF)) { | ||
| 373 | return IRQ_NONE; | ||
| 374 | } | ||
| 375 | if (rtc_read(RTC_ALARM_SEC) & 0x80) { | ||
| 376 | events |= RTC_UF; | ||
| 377 | } else { | ||
| 378 | events |= RTC_AF; | ||
| 379 | } | ||
| 380 | rtc_update_irq(pdata->rtc, 1, events); | ||
| 381 | return IRQ_HANDLED; | ||
| 382 | } | ||
| 383 | |||
| 384 | static void | ||
| 385 | ds1511_rtc_release(struct device *dev) | ||
| 386 | { | ||
| 387 | struct platform_device *pdev = to_platform_device(dev); | ||
| 388 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 389 | |||
| 390 | if (pdata->irq >= 0) { | ||
| 391 | pdata->irqen = 0; | ||
| 392 | ds1511_rtc_update_alarm(pdata); | ||
| 393 | } | ||
| 394 | } | ||
| 395 | |||
| 396 | static int | ||
| 397 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
| 398 | { | ||
| 399 | struct platform_device *pdev = to_platform_device(dev); | ||
| 400 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 401 | |||
| 402 | if (pdata->irq < 0) { | ||
| 403 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | ||
| 404 | } | ||
| 405 | switch (cmd) { | ||
| 406 | case RTC_AIE_OFF: | ||
| 407 | pdata->irqen &= ~RTC_AF; | ||
| 408 | ds1511_rtc_update_alarm(pdata); | ||
| 409 | break; | ||
| 410 | case RTC_AIE_ON: | ||
| 411 | pdata->irqen |= RTC_AF; | ||
| 412 | ds1511_rtc_update_alarm(pdata); | ||
| 413 | break; | ||
| 414 | case RTC_UIE_OFF: | ||
| 415 | pdata->irqen &= ~RTC_UF; | ||
| 416 | ds1511_rtc_update_alarm(pdata); | ||
| 417 | break; | ||
| 418 | case RTC_UIE_ON: | ||
| 419 | pdata->irqen |= RTC_UF; | ||
| 420 | ds1511_rtc_update_alarm(pdata); | ||
| 421 | break; | ||
| 422 | default: | ||
| 423 | return -ENOIOCTLCMD; | ||
| 424 | } | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | static const struct rtc_class_ops ds1511_rtc_ops = { | ||
| 429 | .read_time = ds1511_rtc_read_time, | ||
| 430 | .set_time = ds1511_rtc_set_time, | ||
| 431 | .read_alarm = ds1511_rtc_read_alarm, | ||
| 432 | .set_alarm = ds1511_rtc_set_alarm, | ||
| 433 | .release = ds1511_rtc_release, | ||
| 434 | .ioctl = ds1511_rtc_ioctl, | ||
| 435 | }; | ||
| 436 | |||
| 437 | static ssize_t | ||
| 438 | ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, | ||
| 439 | char *buf, loff_t pos, size_t size) | ||
| 440 | { | ||
| 441 | ssize_t count; | ||
| 442 | |||
| 443 | /* | ||
| 444 | * if count is more than one, turn on "burst" mode | ||
| 445 | * turn it off when you're done | ||
| 446 | */ | ||
| 447 | if (size > 1) { | ||
| 448 | rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD); | ||
| 449 | } | ||
| 450 | if (pos > DS1511_RAM_MAX) { | ||
| 451 | pos = DS1511_RAM_MAX; | ||
| 452 | } | ||
| 453 | if (size + pos > DS1511_RAM_MAX + 1) { | ||
| 454 | size = DS1511_RAM_MAX - pos + 1; | ||
| 455 | } | ||
| 456 | rtc_write(pos, DS1511_RAMADDR_LSB); | ||
| 457 | for (count = 0; size > 0; count++, size--) { | ||
| 458 | *buf++ = rtc_read(DS1511_RAMDATA); | ||
| 459 | } | ||
| 460 | if (count > 1) { | ||
| 461 | rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD); | ||
| 462 | } | ||
| 463 | return count; | ||
| 464 | } | ||
| 465 | |||
| 466 | static ssize_t | ||
| 467 | ds1511_nvram_write(struct kobject *kobj, struct bin_attribute *bin_attr, | ||
| 468 | char *buf, loff_t pos, size_t size) | ||
| 469 | { | ||
| 470 | ssize_t count; | ||
| 471 | |||
| 472 | /* | ||
| 473 | * if count is more than one, turn on "burst" mode | ||
| 474 | * turn it off when you're done | ||
| 475 | */ | ||
| 476 | if (size > 1) { | ||
| 477 | rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD); | ||
| 478 | } | ||
| 479 | if (pos > DS1511_RAM_MAX) { | ||
| 480 | pos = DS1511_RAM_MAX; | ||
| 481 | } | ||
| 482 | if (size + pos > DS1511_RAM_MAX + 1) { | ||
| 483 | size = DS1511_RAM_MAX - pos + 1; | ||
| 484 | } | ||
| 485 | rtc_write(pos, DS1511_RAMADDR_LSB); | ||
| 486 | for (count = 0; size > 0; count++, size--) { | ||
| 487 | rtc_write(*buf++, DS1511_RAMDATA); | ||
| 488 | } | ||
| 489 | if (count > 1) { | ||
| 490 | rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD); | ||
| 491 | } | ||
| 492 | return count; | ||
| 493 | } | ||
| 494 | |||
| 495 | static struct bin_attribute ds1511_nvram_attr = { | ||
| 496 | .attr = { | ||
| 497 | .name = "nvram", | ||
| 498 | .mode = S_IRUGO | S_IWUGO, | ||
| 499 | .owner = THIS_MODULE, | ||
| 500 | }, | ||
| 501 | .size = DS1511_RAM_MAX, | ||
| 502 | .read = ds1511_nvram_read, | ||
| 503 | .write = ds1511_nvram_write, | ||
| 504 | }; | ||
| 505 | |||
| 506 | static int __devinit | ||
| 507 | ds1511_rtc_probe(struct platform_device *pdev) | ||
| 508 | { | ||
| 509 | struct rtc_device *rtc; | ||
| 510 | struct resource *res; | ||
| 511 | struct rtc_plat_data *pdata = NULL; | ||
| 512 | int ret = 0; | ||
| 513 | |||
| 514 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 515 | if (!res) { | ||
| 516 | return -ENODEV; | ||
| 517 | } | ||
| 518 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
| 519 | if (!pdata) { | ||
| 520 | return -ENOMEM; | ||
| 521 | } | ||
| 522 | pdata->irq = -1; | ||
| 523 | pdata->size = res->end - res->start + 1; | ||
| 524 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | ||
| 525 | ret = -EBUSY; | ||
| 526 | goto out; | ||
| 527 | } | ||
| 528 | pdata->baseaddr = res->start; | ||
| 529 | pdata->size = pdata->size; | ||
| 530 | ds1511_base = ioremap(pdata->baseaddr, pdata->size); | ||
| 531 | if (!ds1511_base) { | ||
| 532 | ret = -ENOMEM; | ||
| 533 | goto out; | ||
| 534 | } | ||
| 535 | pdata->ioaddr = ds1511_base; | ||
| 536 | pdata->irq = platform_get_irq(pdev, 0); | ||
| 537 | |||
| 538 | /* | ||
| 539 | * turn on the clock and the crystal, etc. | ||
| 540 | */ | ||
| 541 | rtc_write(0, RTC_CMD); | ||
| 542 | rtc_write(0, RTC_CMD1); | ||
| 543 | /* | ||
| 544 | * clear the wdog counter | ||
| 545 | */ | ||
| 546 | rtc_write(0, DS1511_WD_MSEC); | ||
| 547 | rtc_write(0, DS1511_WD_SEC); | ||
| 548 | /* | ||
| 549 | * start the clock | ||
| 550 | */ | ||
| 551 | rtc_enable_update(); | ||
| 552 | |||
| 553 | /* | ||
| 554 | * check for a dying bat-tree | ||
| 555 | */ | ||
| 556 | if (rtc_read(RTC_CMD1) & DS1511_BLF1) { | ||
| 557 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | ||
| 558 | } | ||
| 559 | |||
| 560 | /* | ||
| 561 | * if the platform has an interrupt in mind for this device, | ||
| 562 | * then by all means, set it | ||
| 563 | */ | ||
| 564 | if (pdata->irq >= 0) { | ||
| 565 | rtc_read(RTC_CMD1); | ||
| 566 | if (request_irq(pdata->irq, ds1511_interrupt, | ||
| 567 | IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { | ||
| 568 | |||
| 569 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
| 570 | pdata->irq = -1; | ||
| 571 | } | ||
| 572 | } | ||
| 573 | |||
| 574 | rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, | ||
| 575 | THIS_MODULE); | ||
| 576 | if (IS_ERR(rtc)) { | ||
| 577 | ret = PTR_ERR(rtc); | ||
| 578 | goto out; | ||
| 579 | } | ||
| 580 | pdata->rtc = rtc; | ||
| 581 | platform_set_drvdata(pdev, pdata); | ||
| 582 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | ||
| 583 | if (ret) { | ||
| 584 | goto out; | ||
| 585 | } | ||
| 586 | return 0; | ||
| 587 | out: | ||
| 588 | if (pdata->rtc) { | ||
| 589 | rtc_device_unregister(pdata->rtc); | ||
| 590 | } | ||
| 591 | if (pdata->irq >= 0) { | ||
| 592 | free_irq(pdata->irq, pdev); | ||
| 593 | } | ||
| 594 | if (ds1511_base) { | ||
| 595 | iounmap(ds1511_base); | ||
| 596 | ds1511_base = NULL; | ||
| 597 | } | ||
| 598 | if (pdata->baseaddr) { | ||
| 599 | release_mem_region(pdata->baseaddr, pdata->size); | ||
| 600 | } | ||
| 601 | |||
| 602 | kfree(pdata); | ||
| 603 | return ret; | ||
| 604 | } | ||
| 605 | |||
| 606 | static int __devexit | ||
| 607 | ds1511_rtc_remove(struct platform_device *pdev) | ||
| 608 | { | ||
| 609 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 610 | |||
| 611 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | ||
| 612 | rtc_device_unregister(pdata->rtc); | ||
| 613 | pdata->rtc = NULL; | ||
| 614 | if (pdata->irq >= 0) { | ||
| 615 | /* | ||
| 616 | * disable the alarm interrupt | ||
| 617 | */ | ||
| 618 | rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); | ||
| 619 | rtc_read(RTC_CMD1); | ||
| 620 | free_irq(pdata->irq, pdev); | ||
| 621 | } | ||
| 622 | iounmap(pdata->ioaddr); | ||
| 623 | ds1511_base = NULL; | ||
| 624 | release_mem_region(pdata->baseaddr, pdata->size); | ||
| 625 | kfree(pdata); | ||
| 626 | return 0; | ||
| 627 | } | ||
| 628 | |||
| 629 | static struct platform_driver ds1511_rtc_driver = { | ||
| 630 | .probe = ds1511_rtc_probe, | ||
| 631 | .remove = __devexit_p(ds1511_rtc_remove), | ||
| 632 | .driver = { | ||
| 633 | .name = "ds1511", | ||
| 634 | .owner = THIS_MODULE, | ||
| 635 | }, | ||
| 636 | }; | ||
| 637 | |||
| 638 | static int __init | ||
| 639 | ds1511_rtc_init(void) | ||
| 640 | { | ||
| 641 | return platform_driver_register(&ds1511_rtc_driver); | ||
| 642 | } | ||
| 643 | |||
| 644 | static void __exit | ||
| 645 | ds1511_rtc_exit(void) | ||
| 646 | { | ||
| 647 | return platform_driver_unregister(&ds1511_rtc_driver); | ||
| 648 | } | ||
| 649 | |||
| 650 | module_init(ds1511_rtc_init); | ||
| 651 | module_exit(ds1511_rtc_exit); | ||
| 652 | |||
| 653 | MODULE_AUTHOR("Andrew Sharp <andy.sharp@onstor.com>"); | ||
| 654 | MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); | ||
| 655 | MODULE_LICENSE("GPL"); | ||
| 656 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index c973ba94c422..8b3997007506 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
| @@ -163,27 +163,17 @@ static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem) | |||
| 163 | 163 | ||
| 164 | static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem) | 164 | static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem) |
| 165 | { | 165 | { |
| 166 | unsigned char addr[1]; | 166 | unsigned char buf[9]; |
| 167 | struct i2c_msg msgs[2] = { | 167 | int ret; |
| 168 | { | ||
| 169 | .addr = client->addr, | ||
| 170 | .flags = 0, | ||
| 171 | .len = 1, | ||
| 172 | .buf = addr, | ||
| 173 | }, { | ||
| 174 | .addr = client->addr, | ||
| 175 | .flags = I2C_M_NOSTART, | ||
| 176 | .len = mem->nr, | ||
| 177 | .buf = mem->data, | ||
| 178 | } | ||
| 179 | }; | ||
| 180 | 168 | ||
| 181 | if (mem->loc < 8) | 169 | if (mem->loc < 8 || mem->nr > 8) |
| 182 | return -EINVAL; | 170 | return -EINVAL; |
| 183 | 171 | ||
| 184 | addr[0] = mem->loc; | 172 | buf[0] = mem->loc; |
| 173 | memcpy(buf + 1, mem->data, mem->nr); | ||
| 185 | 174 | ||
| 186 | return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; | 175 | ret = i2c_master_send(client, buf, mem->nr + 1); |
| 176 | return ret == mem->nr + 1 ? 0 : -EIO; | ||
| 187 | } | 177 | } |
| 188 | 178 | ||
| 189 | static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) | 179 | static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) |
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c new file mode 100644 index 000000000000..a64626a82d0b --- /dev/null +++ b/drivers/rtc/rtc-r9701.c | |||
| @@ -0,0 +1,178 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Epson RTC-9701JE | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Magnus Damm | ||
| 5 | * | ||
| 6 | * Based on rtc-max6902.c | ||
| 7 | * | ||
| 8 | * Copyright (C) 2006 8D Technologies inc. | ||
| 9 | * Copyright (C) 2004 Compulab Ltd. | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/version.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/device.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/rtc.h> | ||
| 23 | #include <linux/spi/spi.h> | ||
| 24 | #include <linux/bcd.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/bitops.h> | ||
| 27 | |||
| 28 | #define RSECCNT 0x00 /* Second Counter */ | ||
| 29 | #define RMINCNT 0x01 /* Minute Counter */ | ||
| 30 | #define RHRCNT 0x02 /* Hour Counter */ | ||
| 31 | #define RWKCNT 0x03 /* Week Counter */ | ||
| 32 | #define RDAYCNT 0x04 /* Day Counter */ | ||
| 33 | #define RMONCNT 0x05 /* Month Counter */ | ||
| 34 | #define RYRCNT 0x06 /* Year Counter */ | ||
| 35 | #define R100CNT 0x07 /* Y100 Counter */ | ||
| 36 | #define RMINAR 0x08 /* Minute Alarm */ | ||
| 37 | #define RHRAR 0x09 /* Hour Alarm */ | ||
| 38 | #define RWKAR 0x0a /* Week/Day Alarm */ | ||
| 39 | #define RTIMCNT 0x0c /* Interval Timer */ | ||
| 40 | #define REXT 0x0d /* Extension Register */ | ||
| 41 | #define RFLAG 0x0e /* RTC Flag Register */ | ||
| 42 | #define RCR 0x0f /* RTC Control Register */ | ||
| 43 | |||
| 44 | static int write_reg(struct device *dev, int address, unsigned char data) | ||
| 45 | { | ||
| 46 | struct spi_device *spi = to_spi_device(dev); | ||
| 47 | unsigned char buf[2]; | ||
| 48 | |||
| 49 | buf[0] = address & 0x7f; | ||
| 50 | buf[1] = data; | ||
| 51 | |||
| 52 | return spi_write(spi, buf, ARRAY_SIZE(buf)); | ||
| 53 | } | ||
| 54 | |||
| 55 | static int read_regs(struct device *dev, unsigned char *regs, int no_regs) | ||
| 56 | { | ||
| 57 | struct spi_device *spi = to_spi_device(dev); | ||
| 58 | u8 txbuf[1], rxbuf[1]; | ||
| 59 | int k, ret; | ||
| 60 | |||
| 61 | ret = 0; | ||
| 62 | |||
| 63 | for (k = 0; ret == 0 && k < no_regs; k++) { | ||
| 64 | txbuf[0] = 0x80 | regs[k]; | ||
| 65 | ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1); | ||
| 66 | regs[k] = rxbuf[0]; | ||
| 67 | } | ||
| 68 | |||
| 69 | return ret; | ||
| 70 | } | ||
| 71 | |||
| 72 | static int r9701_get_datetime(struct device *dev, struct rtc_time *dt) | ||
| 73 | { | ||
| 74 | unsigned long time; | ||
| 75 | int ret; | ||
| 76 | unsigned char buf[] = { RSECCNT, RMINCNT, RHRCNT, | ||
| 77 | RDAYCNT, RMONCNT, RYRCNT }; | ||
| 78 | |||
| 79 | ret = read_regs(dev, buf, ARRAY_SIZE(buf)); | ||
| 80 | if (ret) | ||
| 81 | return ret; | ||
| 82 | |||
| 83 | memset(dt, 0, sizeof(*dt)); | ||
| 84 | |||
| 85 | dt->tm_sec = BCD2BIN(buf[0]); /* RSECCNT */ | ||
| 86 | dt->tm_min = BCD2BIN(buf[1]); /* RMINCNT */ | ||
| 87 | dt->tm_hour = BCD2BIN(buf[2]); /* RHRCNT */ | ||
| 88 | |||
| 89 | dt->tm_mday = BCD2BIN(buf[3]); /* RDAYCNT */ | ||
| 90 | dt->tm_mon = BCD2BIN(buf[4]) - 1; /* RMONCNT */ | ||
| 91 | dt->tm_year = BCD2BIN(buf[5]) + 100; /* RYRCNT */ | ||
| 92 | |||
| 93 | /* the rtc device may contain illegal values on power up | ||
| 94 | * according to the data sheet. make sure they are valid. | ||
| 95 | */ | ||
| 96 | |||
| 97 | return rtc_valid_tm(dt); | ||
| 98 | } | ||
| 99 | |||
| 100 | static int r9701_set_datetime(struct device *dev, struct rtc_time *dt) | ||
| 101 | { | ||
| 102 | int ret, year; | ||
| 103 | |||
| 104 | year = dt->tm_year + 1900; | ||
| 105 | if (year >= 2100 || year < 2000) | ||
| 106 | return -EINVAL; | ||
| 107 | |||
| 108 | ret = write_reg(dev, RHRCNT, BIN2BCD(dt->tm_hour)); | ||
| 109 | ret = ret ? ret : write_reg(dev, RMINCNT, BIN2BCD(dt->tm_min)); | ||
| 110 | ret = ret ? ret : write_reg(dev, RSECCNT, BIN2BCD(dt->tm_sec)); | ||
| 111 | ret = ret ? ret : write_reg(dev, RDAYCNT, BIN2BCD(dt->tm_mday)); | ||
| 112 | ret = ret ? ret : write_reg(dev, RMONCNT, BIN2BCD(dt->tm_mon + 1)); | ||
| 113 | ret = ret ? ret : write_reg(dev, RYRCNT, BIN2BCD(dt->tm_year - 100)); | ||
| 114 | ret = ret ? ret : write_reg(dev, RWKCNT, 1 << dt->tm_wday); | ||
| 115 | |||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | static const struct rtc_class_ops r9701_rtc_ops = { | ||
| 120 | .read_time = r9701_get_datetime, | ||
| 121 | .set_time = r9701_set_datetime, | ||
| 122 | }; | ||
| 123 | |||
| 124 | static int __devinit r9701_probe(struct spi_device *spi) | ||
| 125 | { | ||
| 126 | struct rtc_device *rtc; | ||
| 127 | unsigned char tmp; | ||
| 128 | int res; | ||
| 129 | |||
| 130 | rtc = rtc_device_register("r9701", | ||
| 131 | &spi->dev, &r9701_rtc_ops, THIS_MODULE); | ||
| 132 | if (IS_ERR(rtc)) | ||
| 133 | return PTR_ERR(rtc); | ||
| 134 | |||
| 135 | dev_set_drvdata(&spi->dev, rtc); | ||
| 136 | |||
| 137 | tmp = R100CNT; | ||
| 138 | res = read_regs(&spi->dev, &tmp, 1); | ||
| 139 | if (res || tmp != 0x20) { | ||
| 140 | rtc_device_unregister(rtc); | ||
| 141 | return res; | ||
| 142 | } | ||
| 143 | |||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | |||
| 147 | static int __devexit r9701_remove(struct spi_device *spi) | ||
| 148 | { | ||
| 149 | struct rtc_device *rtc = dev_get_drvdata(&spi->dev); | ||
| 150 | |||
| 151 | rtc_device_unregister(rtc); | ||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | static struct spi_driver r9701_driver = { | ||
| 156 | .driver = { | ||
| 157 | .name = "rtc-r9701", | ||
| 158 | .owner = THIS_MODULE, | ||
| 159 | }, | ||
| 160 | .probe = r9701_probe, | ||
| 161 | .remove = __devexit_p(r9701_remove), | ||
| 162 | }; | ||
| 163 | |||
| 164 | static __init int r9701_init(void) | ||
| 165 | { | ||
| 166 | return spi_register_driver(&r9701_driver); | ||
| 167 | } | ||
| 168 | module_init(r9701_init); | ||
| 169 | |||
| 170 | static __exit void r9701_exit(void) | ||
| 171 | { | ||
| 172 | spi_unregister_driver(&r9701_driver); | ||
| 173 | } | ||
| 174 | module_exit(r9701_exit); | ||
| 175 | |||
| 176 | MODULE_DESCRIPTION("r9701 spi RTC driver"); | ||
| 177 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | ||
| 178 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index e2041b4d0c85..86766f1f2496 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/rtc.h> | 20 | #include <linux/rtc.h> |
| 21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
| 22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
| 23 | #include <linux/log2.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/hardware.h> | 25 | #include <asm/hardware.h> |
| 25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
| @@ -309,9 +310,7 @@ static int s3c_rtc_ioctl(struct device *dev, | |||
| 309 | break; | 310 | break; |
| 310 | 311 | ||
| 311 | case RTC_IRQP_SET: | 312 | case RTC_IRQP_SET: |
| 312 | /* check for power of 2 */ | 313 | if (!is_power_of_2(arg)) { |
| 313 | |||
| 314 | if ((arg & (arg-1)) != 0 || arg < 1) { | ||
| 315 | ret = -EINVAL; | 314 | ret = -EINVAL; |
| 316 | goto exit; | 315 | goto exit; |
| 317 | } | 316 | } |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 2eb38520f0c8..ee253cc45de1 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
| @@ -357,23 +357,15 @@ static int sa1100_rtc_remove(struct platform_device *pdev) | |||
| 357 | #ifdef CONFIG_PM | 357 | #ifdef CONFIG_PM |
| 358 | static int sa1100_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 358 | static int sa1100_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
| 359 | { | 359 | { |
| 360 | if (pdev->dev.power.power_state.event != state.event) { | 360 | if (device_may_wakeup(&pdev->dev)) |
| 361 | if (state.event == PM_EVENT_SUSPEND && | 361 | enable_irq_wake(IRQ_RTCAlrm); |
| 362 | device_may_wakeup(&pdev->dev)) | ||
| 363 | enable_irq_wake(IRQ_RTCAlrm); | ||
| 364 | |||
| 365 | pdev->dev.power.power_state = state; | ||
| 366 | } | ||
| 367 | return 0; | 362 | return 0; |
| 368 | } | 363 | } |
| 369 | 364 | ||
| 370 | static int sa1100_rtc_resume(struct platform_device *pdev) | 365 | static int sa1100_rtc_resume(struct platform_device *pdev) |
| 371 | { | 366 | { |
| 372 | if (pdev->dev.power.power_state.event != PM_EVENT_ON) { | 367 | if (device_may_wakeup(&pdev->dev)) |
| 373 | if (device_may_wakeup(&pdev->dev)) | 368 | disable_irq_wake(IRQ_RTCAlrm); |
| 374 | disable_irq_wake(IRQ_RTCAlrm); | ||
| 375 | pdev->dev.power.power_state = PMSG_ON; | ||
| 376 | } | ||
| 377 | return 0; | 369 | return 0; |
| 378 | } | 370 | } |
| 379 | #else | 371 | #else |
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 2ae0e8304d3a..4d27ccc4fc06 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
| @@ -17,6 +17,13 @@ | |||
| 17 | 17 | ||
| 18 | /* device attributes */ | 18 | /* device attributes */ |
| 19 | 19 | ||
| 20 | /* | ||
| 21 | * NOTE: RTC times displayed in sysfs use the RTC's timezone. That's | ||
| 22 | * ideally UTC. However, PCs that also boot to MS-Windows normally use | ||
| 23 | * the local time and change to match daylight savings time. That affects | ||
| 24 | * attributes including date, time, since_epoch, and wakealarm. | ||
| 25 | */ | ||
| 26 | |||
| 20 | static ssize_t | 27 | static ssize_t |
| 21 | rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, | 28 | rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, |
| 22 | char *buf) | 29 | char *buf) |
| @@ -113,13 +120,13 @@ rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, | |||
| 113 | unsigned long alarm; | 120 | unsigned long alarm; |
| 114 | struct rtc_wkalrm alm; | 121 | struct rtc_wkalrm alm; |
| 115 | 122 | ||
| 116 | /* Don't show disabled alarms; but the RTC could leave the | 123 | /* Don't show disabled alarms. For uniformity, RTC alarms are |
| 117 | * alarm enabled after it's already triggered. Alarms are | 124 | * conceptually one-shot, even though some common RTCs (on PCs) |
| 118 | * conceptually one-shot, even though some common hardware | 125 | * don't actually work that way. |
| 119 | * (PCs) doesn't actually work that way. | ||
| 120 | * | 126 | * |
| 121 | * REVISIT maybe we should require RTC implementations to | 127 | * NOTE: RTC implementations where the alarm doesn't match an |
| 122 | * disable the RTC alarm after it triggers, for uniformity. | 128 | * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC |
| 129 | * alarms after they trigger, to ensure one-shot semantics. | ||
| 123 | */ | 130 | */ |
| 124 | retval = rtc_read_alarm(to_rtc_device(dev), &alm); | 131 | retval = rtc_read_alarm(to_rtc_device(dev), &alm); |
| 125 | if (retval == 0 && alm.enabled) { | 132 | if (retval == 0 && alm.enabled) { |
