diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 276 | ||||
| -rw-r--r-- | drivers/rtc/Makefile | 8 | ||||
| -rw-r--r-- | drivers/rtc/class.c | 118 | ||||
| -rw-r--r-- | drivers/rtc/hctosys.c | 14 | ||||
| -rw-r--r-- | drivers/rtc/interface.c | 86 | ||||
| -rw-r--r-- | drivers/rtc/rtc-at91rm9200.c | 32 | ||||
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 79 | ||||
| -rw-r--r-- | drivers/rtc/rtc-core.h | 70 | ||||
| -rw-r--r-- | drivers/rtc/rtc-dev.c | 184 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1553.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-lib.c | 81 | ||||
| -rw-r--r-- | drivers/rtc/rtc-max6900.c | 311 | ||||
| -rw-r--r-- | drivers/rtc/rtc-omap.c | 57 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pl031.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-proc.c | 68 | ||||
| -rw-r--r-- | drivers/rtc/rtc-rs5c313.c | 405 | ||||
| -rw-r--r-- | drivers/rtc/rtc-s3c.c | 26 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sa1100.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sh.c | 6 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sysfs.c | 129 | ||||
| -rw-r--r-- | drivers/rtc/rtc-test.c | 6 | ||||
| -rw-r--r-- | drivers/rtc/rtc-vr41xx.c | 32 |
22 files changed, 1333 insertions, 663 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ef1eae98ba44..5e439836db2d 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -21,21 +21,31 @@ config RTC_CLASS | |||
| 21 | will be called rtc-class. | 21 | will be called rtc-class. |
| 22 | 22 | ||
| 23 | config RTC_HCTOSYS | 23 | config RTC_HCTOSYS |
| 24 | bool "Set system time from RTC on startup" | 24 | bool "Set system time from RTC on startup and resume" |
| 25 | depends on RTC_CLASS = y | 25 | depends on RTC_CLASS = y |
| 26 | default y | 26 | default y |
| 27 | help | 27 | help |
| 28 | If you say yes here, the system time will be set using | 28 | If you say yes here, the system time (wall clock) will be set using |
| 29 | the value read from the specified RTC device. This is useful | 29 | the value read from a specified RTC device. This is useful to avoid |
| 30 | in order to avoid unnecessary fsck runs. | 30 | unnecessary fsck runs at boot time, and to network better. |
| 31 | 31 | ||
| 32 | config RTC_HCTOSYS_DEVICE | 32 | config RTC_HCTOSYS_DEVICE |
| 33 | string "The RTC to read the time from" | 33 | string "RTC used to set the system time" |
| 34 | depends on RTC_HCTOSYS = y | 34 | depends on RTC_HCTOSYS = y |
| 35 | default "rtc0" | 35 | default "rtc0" |
| 36 | help | 36 | help |
| 37 | The RTC device that will be used as the source for | 37 | The RTC device that will be used to (re)initialize the system |
| 38 | the system time, usually rtc0. | 38 | clock, usually rtc0. Initialization is done when the system |
| 39 | starts up, and when it resumes from a low power state. | ||
| 40 | |||
| 41 | This clock should be battery-backed, so that it reads the correct | ||
| 42 | time when the system boots from a power-off state. Otherwise, your | ||
| 43 | system will need an external clock source (like an NTP server). | ||
| 44 | |||
| 45 | If the clock you specify here is not battery backed, it may still | ||
| 46 | be useful to reinitialize system time when resuming from system | ||
| 47 | sleep states. Do not specify an RTC here unless it stays powered | ||
| 48 | during all this system's supported sleep states. | ||
| 39 | 49 | ||
| 40 | config RTC_DEBUG | 50 | config RTC_DEBUG |
| 41 | bool "RTC debug support" | 51 | bool "RTC debug support" |
| @@ -48,7 +58,7 @@ comment "RTC interfaces" | |||
| 48 | depends on RTC_CLASS | 58 | depends on RTC_CLASS |
| 49 | 59 | ||
| 50 | config RTC_INTF_SYSFS | 60 | config RTC_INTF_SYSFS |
| 51 | tristate "sysfs" | 61 | boolean "sysfs" |
| 52 | depends on RTC_CLASS && SYSFS | 62 | depends on RTC_CLASS && SYSFS |
| 53 | default RTC_CLASS | 63 | default RTC_CLASS |
| 54 | help | 64 | help |
| @@ -59,7 +69,7 @@ config RTC_INTF_SYSFS | |||
| 59 | will be called rtc-sysfs. | 69 | will be called rtc-sysfs. |
| 60 | 70 | ||
| 61 | config RTC_INTF_PROC | 71 | config RTC_INTF_PROC |
| 62 | tristate "proc" | 72 | boolean "proc" |
| 63 | depends on RTC_CLASS && PROC_FS | 73 | depends on RTC_CLASS && PROC_FS |
| 64 | default RTC_CLASS | 74 | default RTC_CLASS |
| 65 | help | 75 | help |
| @@ -71,7 +81,7 @@ config RTC_INTF_PROC | |||
| 71 | will be called rtc-proc. | 81 | will be called rtc-proc. |
| 72 | 82 | ||
| 73 | config RTC_INTF_DEV | 83 | config RTC_INTF_DEV |
| 74 | tristate "dev" | 84 | boolean "dev" |
| 75 | depends on RTC_CLASS | 85 | depends on RTC_CLASS |
| 76 | default RTC_CLASS | 86 | default RTC_CLASS |
| 77 | help | 87 | help |
| @@ -92,44 +102,26 @@ config RTC_INTF_DEV_UIE_EMUL | |||
| 92 | driver does not expose RTC_UIE ioctls. Those requests generate | 102 | driver does not expose RTC_UIE ioctls. Those requests generate |
| 93 | once-per-second update interrupts, used for synchronization. | 103 | once-per-second update interrupts, used for synchronization. |
| 94 | 104 | ||
| 95 | comment "RTC drivers" | 105 | config RTC_DRV_TEST |
| 106 | tristate "Test driver/device" | ||
| 96 | depends on RTC_CLASS | 107 | depends on RTC_CLASS |
| 97 | |||
| 98 | # this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h> | ||
| 99 | # requires <asm/mc146818rtc.h> defining CMOS_READ/CMOS_WRITE, and a | ||
| 100 | # global rtc_lock ... it's not yet just another platform_device. | ||
| 101 | |||
| 102 | config RTC_DRV_CMOS | ||
| 103 | tristate "PC-style 'CMOS' real time clock" | ||
| 104 | depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \ | ||
| 105 | || M32R || ATARI || POWERPC) | ||
| 106 | help | ||
| 107 | Say "yes" here to get direct support for the real time clock | ||
| 108 | found in every PC or ACPI-based system, and some other boards. | ||
| 109 | Specifically the original MC146818, compatibles like those in | ||
| 110 | PC south bridges, the DS12887 or M48T86, some multifunction | ||
| 111 | or LPC bus chips, and so on. | ||
| 112 | |||
| 113 | Your system will need to define the platform device used by | ||
| 114 | this driver, otherwise it won't be accessible. This means | ||
| 115 | you can safely enable this driver if you don't know whether | ||
| 116 | or not your board has this kind of hardware. | ||
| 117 | |||
| 118 | This driver can also be built as a module. If so, the module | ||
| 119 | will be called rtc-cmos. | ||
| 120 | |||
| 121 | config RTC_DRV_X1205 | ||
| 122 | tristate "Xicor/Intersil X1205" | ||
| 123 | depends on RTC_CLASS && I2C | ||
| 124 | help | 108 | help |
| 125 | If you say yes here you get support for the | 109 | If you say yes here you get support for the |
| 126 | Xicor/Intersil X1205 RTC chip. | 110 | RTC test driver. It's a software RTC which can be |
| 111 | used to test the RTC subsystem APIs. It gets | ||
| 112 | the time from the system clock. | ||
| 113 | You want this driver only if you are doing development | ||
| 114 | on the RTC subsystem. Please read the source code | ||
| 115 | for further details. | ||
| 127 | 116 | ||
| 128 | This driver can also be built as a module. If so, the module | 117 | This driver can also be built as a module. If so, the module |
| 129 | will be called rtc-x1205. | 118 | will be called rtc-test. |
| 119 | |||
| 120 | comment "I2C RTC drivers" | ||
| 121 | depends on RTC_CLASS | ||
| 130 | 122 | ||
| 131 | config RTC_DRV_DS1307 | 123 | config RTC_DRV_DS1307 |
| 132 | tristate "Dallas/Maxim DS1307 and similar I2C RTC chips" | 124 | tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00" |
| 133 | depends on RTC_CLASS && I2C | 125 | depends on RTC_CLASS && I2C |
| 134 | help | 126 | help |
| 135 | If you say yes here you get support for various compatible RTC | 127 | If you say yes here you get support for various compatible RTC |
| @@ -146,53 +138,55 @@ config RTC_DRV_DS1307 | |||
| 146 | This driver can also be built as a module. If so, the module | 138 | This driver can also be built as a module. If so, the module |
| 147 | will be called rtc-ds1307. | 139 | will be called rtc-ds1307. |
| 148 | 140 | ||
| 149 | config RTC_DRV_DS1553 | 141 | config RTC_DRV_DS1672 |
| 150 | tristate "Dallas DS1553" | 142 | tristate "Dallas/Maxim DS1672" |
| 151 | depends on RTC_CLASS | 143 | depends on RTC_CLASS && I2C |
| 152 | help | 144 | help |
| 153 | If you say yes here you get support for the | 145 | If you say yes here you get support for the |
| 154 | Dallas DS1553 timekeeping chip. | 146 | Dallas/Maxim DS1672 timekeeping chip. |
| 155 | 147 | ||
| 156 | This driver can also be built as a module. If so, the module | 148 | This driver can also be built as a module. If so, the module |
| 157 | will be called rtc-ds1553. | 149 | will be called rtc-ds1672. |
| 158 | 150 | ||
| 159 | config RTC_DRV_ISL1208 | 151 | config RTC_DRV_MAX6900 |
| 160 | tristate "Intersil 1208" | 152 | tristate "Maxim 6900" |
| 161 | depends on RTC_CLASS && I2C | 153 | depends on RTC_CLASS && I2C |
| 162 | help | 154 | help |
| 163 | If you say yes here you get support for the | 155 | If you say yes here you will get support for the |
| 164 | Intersil 1208 RTC chip. | 156 | Maxim MAX6900 I2C RTC chip. |
| 165 | 157 | ||
| 166 | This driver can also be built as a module. If so, the module | 158 | This driver can also be built as a module. If so, the module |
| 167 | will be called rtc-isl1208. | 159 | will be called rtc-max6900. |
| 168 | 160 | ||
| 169 | config RTC_DRV_DS1672 | 161 | config RTC_DRV_RS5C372 |
| 170 | tristate "Dallas/Maxim DS1672" | 162 | tristate "Ricoh RS5C372A/B" |
| 171 | depends on RTC_CLASS && I2C | 163 | depends on RTC_CLASS && I2C |
| 172 | help | 164 | help |
| 173 | If you say yes here you get support for the | 165 | If you say yes here you get support for the |
| 174 | Dallas/Maxim DS1672 timekeeping chip. | 166 | Ricoh RS5C372A and RS5C372B RTC chips. |
| 175 | 167 | ||
| 176 | This driver can also be built as a module. If so, the module | 168 | This driver can also be built as a module. If so, the module |
| 177 | will be called rtc-ds1672. | 169 | will be called rtc-rs5c372. |
| 178 | 170 | ||
| 179 | config RTC_DRV_DS1742 | 171 | config RTC_DRV_ISL1208 |
| 180 | tristate "Dallas DS1742/1743" | 172 | tristate "Intersil 1208" |
| 181 | depends on RTC_CLASS | 173 | depends on RTC_CLASS && I2C |
| 182 | help | 174 | help |
| 183 | If you say yes here you get support for the | 175 | If you say yes here you get support for the |
| 184 | Dallas DS1742/1743 timekeeping chip. | 176 | Intersil 1208 RTC chip. |
| 185 | 177 | ||
| 186 | This driver can also be built as a module. If so, the module | 178 | This driver can also be built as a module. If so, the module |
| 187 | will be called rtc-ds1742. | 179 | will be called rtc-isl1208. |
| 188 | 180 | ||
| 189 | config RTC_DRV_OMAP | 181 | config RTC_DRV_X1205 |
| 190 | tristate "TI OMAP1" | 182 | tristate "Xicor/Intersil X1205" |
| 191 | depends on RTC_CLASS && ( \ | 183 | depends on RTC_CLASS && I2C |
| 192 | ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 ) | ||
| 193 | help | 184 | help |
| 194 | Say "yes" here to support the real time clock on TI OMAP1 chips. | 185 | If you say yes here you get support for the |
| 195 | This driver can also be built as a module called rtc-omap. | 186 | Xicor/Intersil X1205 RTC chip. |
| 187 | |||
| 188 | This driver can also be built as a module. If so, the module | ||
| 189 | will be called rtc-x1205. | ||
| 196 | 190 | ||
| 197 | config RTC_DRV_PCF8563 | 191 | config RTC_DRV_PCF8563 |
| 198 | tristate "Philips PCF8563/Epson RTC8564" | 192 | tristate "Philips PCF8563/Epson RTC8564" |
| @@ -207,16 +201,20 @@ config RTC_DRV_PCF8563 | |||
| 207 | 201 | ||
| 208 | config RTC_DRV_PCF8583 | 202 | config RTC_DRV_PCF8583 |
| 209 | tristate "Philips PCF8583" | 203 | tristate "Philips PCF8583" |
| 210 | depends on RTC_CLASS && I2C && ARCH_RPC | 204 | depends on RTC_CLASS && I2C |
| 211 | help | 205 | help |
| 212 | If you say yes here you get support for the Philips PCF8583 | 206 | If you say yes here you get support for the Philips PCF8583 |
| 213 | RTC chip found on Acorn RiscPCs. This driver supports the | 207 | RTC chip found on Acorn RiscPCs. This driver supports the |
| 214 | platform specific method of retrieving the current year from | 208 | platform specific method of retrieving the current year from |
| 215 | the RTC's SRAM. | 209 | the RTC's SRAM. It will work on other platforms with the same |
| 210 | chip, but the year will probably have to be tweaked. | ||
| 216 | 211 | ||
| 217 | This driver can also be built as a module. If so, the module | 212 | This driver can also be built as a module. If so, the module |
| 218 | will be called rtc-pcf8583. | 213 | will be called rtc-pcf8583. |
| 219 | 214 | ||
| 215 | comment "SPI RTC drivers" | ||
| 216 | depends on RTC_CLASS | ||
| 217 | |||
| 220 | config RTC_DRV_RS5C348 | 218 | config RTC_DRV_RS5C348 |
| 221 | tristate "Ricoh RS5C348A/B" | 219 | tristate "Ricoh RS5C348A/B" |
| 222 | depends on RTC_CLASS && SPI | 220 | depends on RTC_CLASS && SPI |
| @@ -227,15 +225,92 @@ config RTC_DRV_RS5C348 | |||
| 227 | This driver can also be built as a module. If so, the module | 225 | This driver can also be built as a module. If so, the module |
| 228 | will be called rtc-rs5c348. | 226 | will be called rtc-rs5c348. |
| 229 | 227 | ||
| 230 | config RTC_DRV_RS5C372 | 228 | config RTC_DRV_MAX6902 |
| 231 | tristate "Ricoh RS5C372A/B" | 229 | tristate "Maxim 6902" |
| 232 | depends on RTC_CLASS && I2C | 230 | depends on RTC_CLASS && SPI |
| 231 | help | ||
| 232 | If you say yes here you will get support for the | ||
| 233 | Maxim MAX6902 SPI RTC chip. | ||
| 234 | |||
| 235 | This driver can also be built as a module. If so, the module | ||
| 236 | will be called rtc-max6902. | ||
| 237 | |||
| 238 | comment "Platform RTC drivers" | ||
| 239 | depends on RTC_CLASS | ||
| 240 | |||
| 241 | # this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h> | ||
| 242 | # requires <asm/mc146818rtc.h> defining CMOS_READ/CMOS_WRITE, and a | ||
| 243 | # global rtc_lock ... it's not yet just another platform_device. | ||
| 244 | |||
| 245 | config RTC_DRV_CMOS | ||
| 246 | tristate "PC-style 'CMOS'" | ||
| 247 | depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \ | ||
| 248 | || M32R || ATARI || POWERPC) | ||
| 249 | help | ||
| 250 | Say "yes" here to get direct support for the real time clock | ||
| 251 | found in every PC or ACPI-based system, and some other boards. | ||
| 252 | Specifically the original MC146818, compatibles like those in | ||
| 253 | PC south bridges, the DS12887 or M48T86, some multifunction | ||
| 254 | or LPC bus chips, and so on. | ||
| 255 | |||
| 256 | Your system will need to define the platform device used by | ||
| 257 | this driver, otherwise it won't be accessible. This means | ||
| 258 | you can safely enable this driver if you don't know whether | ||
| 259 | or not your board has this kind of hardware. | ||
| 260 | |||
| 261 | This driver can also be built as a module. If so, the module | ||
| 262 | will be called rtc-cmos. | ||
| 263 | |||
| 264 | config RTC_DRV_DS1553 | ||
| 265 | tristate "Dallas DS1553" | ||
| 266 | depends on RTC_CLASS | ||
| 233 | help | 267 | help |
| 234 | If you say yes here you get support for the | 268 | If you say yes here you get support for the |
| 235 | Ricoh RS5C372A and RS5C372B RTC chips. | 269 | Dallas DS1553 timekeeping chip. |
| 236 | 270 | ||
| 237 | This driver can also be built as a module. If so, the module | 271 | This driver can also be built as a module. If so, the module |
| 238 | will be called rtc-rs5c372. | 272 | will be called rtc-ds1553. |
| 273 | |||
| 274 | config RTC_DRV_DS1742 | ||
| 275 | tristate "Dallas DS1742/1743" | ||
| 276 | depends on RTC_CLASS | ||
| 277 | help | ||
| 278 | If you say yes here you get support for the | ||
| 279 | Dallas DS1742/1743 timekeeping chip. | ||
| 280 | |||
| 281 | This driver can also be built as a module. If so, the module | ||
| 282 | will be called rtc-ds1742. | ||
| 283 | |||
| 284 | config RTC_DRV_M48T86 | ||
| 285 | tristate "ST M48T86/Dallas DS12887" | ||
| 286 | depends on RTC_CLASS | ||
| 287 | help | ||
| 288 | If you say Y here you will get support for the | ||
| 289 | ST M48T86 and Dallas DS12887 RTC chips. | ||
| 290 | |||
| 291 | This driver can also be built as a module. If so, the module | ||
| 292 | will be called rtc-m48t86. | ||
| 293 | |||
| 294 | config RTC_DRV_V3020 | ||
| 295 | tristate "EM Microelectronic V3020" | ||
| 296 | depends on RTC_CLASS | ||
| 297 | help | ||
| 298 | If you say yes here you will get support for the | ||
| 299 | EM Microelectronic v3020 RTC chip. | ||
| 300 | |||
| 301 | This driver can also be built as a module. If so, the module | ||
| 302 | will be called rtc-v3020. | ||
| 303 | |||
| 304 | comment "on-CPU RTC drivers" | ||
| 305 | depends on RTC_CLASS | ||
| 306 | |||
| 307 | config RTC_DRV_OMAP | ||
| 308 | tristate "TI OMAP1" | ||
| 309 | depends on RTC_CLASS && ( \ | ||
| 310 | ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 ) | ||
| 311 | help | ||
| 312 | Say "yes" here to support the real time clock on TI OMAP1 chips. | ||
| 313 | This driver can also be built as a module called rtc-omap. | ||
| 239 | 314 | ||
| 240 | config RTC_DRV_S3C | 315 | config RTC_DRV_S3C |
| 241 | tristate "Samsung S3C series SoC RTC" | 316 | tristate "Samsung S3C series SoC RTC" |
| @@ -253,16 +328,6 @@ config RTC_DRV_S3C | |||
| 253 | This driver can also be build as a module. If so, the module | 328 | This driver can also be build as a module. If so, the module |
| 254 | will be called rtc-s3c. | 329 | will be called rtc-s3c. |
| 255 | 330 | ||
| 256 | config RTC_DRV_M48T86 | ||
| 257 | tristate "ST M48T86/Dallas DS12887" | ||
| 258 | depends on RTC_CLASS | ||
| 259 | help | ||
| 260 | If you say Y here you will get support for the | ||
| 261 | ST M48T86 and Dallas DS12887 RTC chips. | ||
| 262 | |||
| 263 | This driver can also be built as a module. If so, the module | ||
| 264 | will be called rtc-m48t86. | ||
| 265 | |||
| 266 | config RTC_DRV_EP93XX | 331 | config RTC_DRV_EP93XX |
| 267 | tristate "Cirrus Logic EP93XX" | 332 | tristate "Cirrus Logic EP93XX" |
| 268 | depends on RTC_CLASS && ARCH_EP93XX | 333 | depends on RTC_CLASS && ARCH_EP93XX |
| @@ -308,7 +373,7 @@ config RTC_DRV_PL031 | |||
| 308 | depends on RTC_CLASS && ARM_AMBA | 373 | depends on RTC_CLASS && ARM_AMBA |
| 309 | help | 374 | help |
| 310 | If you say Y here you will get access to ARM AMBA | 375 | If you say Y here you will get access to ARM AMBA |
| 311 | PrimeCell PL031 UART found on certain ARM SOCs. | 376 | PrimeCell PL031 RTC found on certain ARM SOCs. |
| 312 | 377 | ||
| 313 | To compile this driver as a module, choose M here: the | 378 | To compile this driver as a module, choose M here: the |
| 314 | module will be called rtc-pl031. | 379 | module will be called rtc-pl031. |
| @@ -319,41 +384,6 @@ config RTC_DRV_AT91RM9200 | |||
| 319 | help | 384 | help |
| 320 | Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock). | 385 | Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock). |
| 321 | 386 | ||
| 322 | config RTC_DRV_TEST | ||
| 323 | tristate "Test driver/device" | ||
| 324 | depends on RTC_CLASS | ||
| 325 | help | ||
| 326 | If you say yes here you get support for the | ||
| 327 | RTC test driver. It's a software RTC which can be | ||
| 328 | used to test the RTC subsystem APIs. It gets | ||
| 329 | the time from the system clock. | ||
| 330 | You want this driver only if you are doing development | ||
| 331 | on the RTC subsystem. Please read the source code | ||
| 332 | for further details. | ||
| 333 | |||
| 334 | This driver can also be built as a module. If so, the module | ||
| 335 | will be called rtc-test. | ||
| 336 | |||
| 337 | config RTC_DRV_MAX6902 | ||
| 338 | tristate "Maxim 6902" | ||
| 339 | depends on RTC_CLASS && SPI | ||
| 340 | help | ||
| 341 | If you say yes here you will get support for the | ||
| 342 | Maxim MAX6902 spi RTC chip. | ||
| 343 | |||
| 344 | This driver can also be built as a module. If so, the module | ||
| 345 | will be called rtc-max6902. | ||
| 346 | |||
| 347 | config RTC_DRV_V3020 | ||
| 348 | tristate "EM Microelectronic V3020" | ||
| 349 | depends on RTC_CLASS | ||
| 350 | help | ||
| 351 | If you say yes here you will get support for the | ||
| 352 | EM Microelectronic v3020 RTC chip. | ||
| 353 | |||
| 354 | This driver can also be built as a module. If so, the module | ||
| 355 | will be called rtc-v3020. | ||
| 356 | |||
| 357 | config RTC_DRV_BFIN | 387 | config RTC_DRV_BFIN |
| 358 | tristate "Blackfin On-Chip RTC" | 388 | tristate "Blackfin On-Chip RTC" |
| 359 | depends on RTC_CLASS && BFIN | 389 | depends on RTC_CLASS && BFIN |
| @@ -364,4 +394,10 @@ config RTC_DRV_BFIN | |||
| 364 | This driver can also be built as a module. If so, the module | 394 | This driver can also be built as a module. If so, the module |
| 365 | will be called rtc-bfin. | 395 | will be called rtc-bfin. |
| 366 | 396 | ||
| 397 | config RTC_DRV_RS5C313 | ||
| 398 | tristate "Ricoh RS5C313" | ||
| 399 | depends on RTC_CLASS && BROKEN | ||
| 400 | help | ||
| 401 | If you say yes here you get support for the Ricoh RS5C313 RTC chips. | ||
| 402 | |||
| 367 | endmenu | 403 | endmenu |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 9218cf28d6ed..a1afbc236073 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -11,9 +11,9 @@ obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o | |||
| 11 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o | 11 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o |
| 12 | rtc-core-y := class.o interface.o | 12 | rtc-core-y := class.o interface.o |
| 13 | 13 | ||
| 14 | obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | 14 | rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o |
| 15 | obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o | 15 | rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o |
| 16 | obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o | 16 | rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o |
| 17 | 17 | ||
| 18 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 18 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
| 19 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 19 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
| @@ -30,10 +30,12 @@ obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o | |||
| 30 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 30 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
| 31 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 31 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
| 32 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 32 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
| 33 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | ||
| 33 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 34 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
| 34 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o | 35 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o |
| 35 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 36 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
| 36 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 37 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
| 38 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | ||
| 37 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 39 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
| 38 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 40 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
| 39 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | 41 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 04aaa6347234..8b3cd31d6a61 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -16,19 +16,94 @@ | |||
| 16 | #include <linux/kdev_t.h> | 16 | #include <linux/kdev_t.h> |
| 17 | #include <linux/idr.h> | 17 | #include <linux/idr.h> |
| 18 | 18 | ||
| 19 | #include "rtc-core.h" | ||
| 20 | |||
| 21 | |||
| 19 | static DEFINE_IDR(rtc_idr); | 22 | static DEFINE_IDR(rtc_idr); |
| 20 | static DEFINE_MUTEX(idr_lock); | 23 | static DEFINE_MUTEX(idr_lock); |
| 21 | struct class *rtc_class; | 24 | struct class *rtc_class; |
| 22 | 25 | ||
| 23 | static void rtc_device_release(struct class_device *class_dev) | 26 | static void rtc_device_release(struct device *dev) |
| 24 | { | 27 | { |
| 25 | struct rtc_device *rtc = to_rtc_device(class_dev); | 28 | struct rtc_device *rtc = to_rtc_device(dev); |
| 26 | mutex_lock(&idr_lock); | 29 | mutex_lock(&idr_lock); |
| 27 | idr_remove(&rtc_idr, rtc->id); | 30 | idr_remove(&rtc_idr, rtc->id); |
| 28 | mutex_unlock(&idr_lock); | 31 | mutex_unlock(&idr_lock); |
| 29 | kfree(rtc); | 32 | kfree(rtc); |
| 30 | } | 33 | } |
| 31 | 34 | ||
| 35 | #if defined(CONFIG_PM) && defined(CONFIG_RTC_HCTOSYS_DEVICE) | ||
| 36 | |||
| 37 | /* | ||
| 38 | * On suspend(), measure the delta between one RTC and the | ||
| 39 | * system's wall clock; restore it on resume(). | ||
| 40 | */ | ||
| 41 | |||
| 42 | static struct timespec delta; | ||
| 43 | static time_t oldtime; | ||
| 44 | |||
| 45 | static int rtc_suspend(struct device *dev, pm_message_t mesg) | ||
| 46 | { | ||
| 47 | struct rtc_device *rtc = to_rtc_device(dev); | ||
| 48 | struct rtc_time tm; | ||
| 49 | |||
| 50 | if (strncmp(rtc->dev.bus_id, | ||
| 51 | CONFIG_RTC_HCTOSYS_DEVICE, | ||
| 52 | BUS_ID_SIZE) != 0) | ||
| 53 | return 0; | ||
| 54 | |||
| 55 | rtc_read_time(rtc, &tm); | ||
| 56 | rtc_tm_to_time(&tm, &oldtime); | ||
| 57 | |||
| 58 | /* RTC precision is 1 second; adjust delta for avg 1/2 sec err */ | ||
| 59 | set_normalized_timespec(&delta, | ||
| 60 | xtime.tv_sec - oldtime, | ||
| 61 | xtime.tv_nsec - (NSEC_PER_SEC >> 1)); | ||
| 62 | |||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int rtc_resume(struct device *dev) | ||
| 67 | { | ||
| 68 | struct rtc_device *rtc = to_rtc_device(dev); | ||
| 69 | struct rtc_time tm; | ||
| 70 | time_t newtime; | ||
| 71 | struct timespec time; | ||
| 72 | |||
| 73 | if (strncmp(rtc->dev.bus_id, | ||
| 74 | CONFIG_RTC_HCTOSYS_DEVICE, | ||
| 75 | BUS_ID_SIZE) != 0) | ||
| 76 | return 0; | ||
| 77 | |||
| 78 | rtc_read_time(rtc, &tm); | ||
| 79 | if (rtc_valid_tm(&tm) != 0) { | ||
| 80 | pr_debug("%s: bogus resume time\n", rtc->dev.bus_id); | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | rtc_tm_to_time(&tm, &newtime); | ||
| 84 | if (newtime <= oldtime) { | ||
| 85 | if (newtime < oldtime) | ||
| 86 | pr_debug("%s: time travel!\n", rtc->dev.bus_id); | ||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* restore wall clock using delta against this RTC; | ||
| 91 | * adjust again for avg 1/2 second RTC sampling error | ||
| 92 | */ | ||
| 93 | set_normalized_timespec(&time, | ||
| 94 | newtime + delta.tv_sec, | ||
| 95 | (NSEC_PER_SEC >> 1) + delta.tv_nsec); | ||
| 96 | do_settimeofday(&time); | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | #else | ||
| 102 | #define rtc_suspend NULL | ||
| 103 | #define rtc_resume NULL | ||
| 104 | #endif | ||
| 105 | |||
| 106 | |||
| 32 | /** | 107 | /** |
| 33 | * rtc_device_register - register w/ RTC class | 108 | * rtc_device_register - register w/ RTC class |
| 34 | * @dev: the device to register | 109 | * @dev: the device to register |
| @@ -70,23 +145,29 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
| 70 | rtc->ops = ops; | 145 | rtc->ops = ops; |
| 71 | rtc->owner = owner; | 146 | rtc->owner = owner; |
| 72 | rtc->max_user_freq = 64; | 147 | rtc->max_user_freq = 64; |
| 73 | rtc->class_dev.dev = dev; | 148 | rtc->dev.parent = dev; |
| 74 | rtc->class_dev.class = rtc_class; | 149 | rtc->dev.class = rtc_class; |
| 75 | rtc->class_dev.release = rtc_device_release; | 150 | rtc->dev.release = rtc_device_release; |
| 76 | 151 | ||
| 77 | mutex_init(&rtc->ops_lock); | 152 | mutex_init(&rtc->ops_lock); |
| 78 | spin_lock_init(&rtc->irq_lock); | 153 | spin_lock_init(&rtc->irq_lock); |
| 79 | spin_lock_init(&rtc->irq_task_lock); | 154 | spin_lock_init(&rtc->irq_task_lock); |
| 80 | 155 | ||
| 81 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); | 156 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); |
| 82 | snprintf(rtc->class_dev.class_id, BUS_ID_SIZE, "rtc%d", id); | 157 | snprintf(rtc->dev.bus_id, BUS_ID_SIZE, "rtc%d", id); |
| 83 | 158 | ||
| 84 | err = class_device_register(&rtc->class_dev); | 159 | rtc_dev_prepare(rtc); |
| 160 | |||
| 161 | err = device_register(&rtc->dev); | ||
| 85 | if (err) | 162 | if (err) |
| 86 | goto exit_kfree; | 163 | goto exit_kfree; |
| 87 | 164 | ||
| 165 | rtc_dev_add_device(rtc); | ||
| 166 | rtc_sysfs_add_device(rtc); | ||
| 167 | rtc_proc_add_device(rtc); | ||
| 168 | |||
| 88 | dev_info(dev, "rtc core: registered %s as %s\n", | 169 | dev_info(dev, "rtc core: registered %s as %s\n", |
| 89 | rtc->name, rtc->class_dev.class_id); | 170 | rtc->name, rtc->dev.bus_id); |
| 90 | 171 | ||
| 91 | return rtc; | 172 | return rtc; |
| 92 | 173 | ||
| @@ -113,26 +194,22 @@ EXPORT_SYMBOL_GPL(rtc_device_register); | |||
| 113 | */ | 194 | */ |
| 114 | void rtc_device_unregister(struct rtc_device *rtc) | 195 | void rtc_device_unregister(struct rtc_device *rtc) |
| 115 | { | 196 | { |
| 116 | if (class_device_get(&rtc->class_dev) != NULL) { | 197 | if (get_device(&rtc->dev) != NULL) { |
| 117 | mutex_lock(&rtc->ops_lock); | 198 | mutex_lock(&rtc->ops_lock); |
| 118 | /* remove innards of this RTC, then disable it, before | 199 | /* remove innards of this RTC, then disable it, before |
| 119 | * letting any rtc_class_open() users access it again | 200 | * letting any rtc_class_open() users access it again |
| 120 | */ | 201 | */ |
| 121 | class_device_unregister(&rtc->class_dev); | 202 | rtc_sysfs_del_device(rtc); |
| 203 | rtc_dev_del_device(rtc); | ||
| 204 | rtc_proc_del_device(rtc); | ||
| 205 | device_unregister(&rtc->dev); | ||
| 122 | rtc->ops = NULL; | 206 | rtc->ops = NULL; |
| 123 | mutex_unlock(&rtc->ops_lock); | 207 | mutex_unlock(&rtc->ops_lock); |
| 124 | class_device_put(&rtc->class_dev); | 208 | put_device(&rtc->dev); |
| 125 | } | 209 | } |
| 126 | } | 210 | } |
| 127 | EXPORT_SYMBOL_GPL(rtc_device_unregister); | 211 | EXPORT_SYMBOL_GPL(rtc_device_unregister); |
| 128 | 212 | ||
| 129 | int rtc_interface_register(struct class_interface *intf) | ||
| 130 | { | ||
| 131 | intf->class = rtc_class; | ||
| 132 | return class_interface_register(intf); | ||
| 133 | } | ||
| 134 | EXPORT_SYMBOL_GPL(rtc_interface_register); | ||
| 135 | |||
| 136 | static int __init rtc_init(void) | 213 | static int __init rtc_init(void) |
| 137 | { | 214 | { |
| 138 | rtc_class = class_create(THIS_MODULE, "rtc"); | 215 | rtc_class = class_create(THIS_MODULE, "rtc"); |
| @@ -140,11 +217,16 @@ static int __init rtc_init(void) | |||
| 140 | printk(KERN_ERR "%s: couldn't create class\n", __FILE__); | 217 | printk(KERN_ERR "%s: couldn't create class\n", __FILE__); |
| 141 | return PTR_ERR(rtc_class); | 218 | return PTR_ERR(rtc_class); |
| 142 | } | 219 | } |
| 220 | rtc_class->suspend = rtc_suspend; | ||
| 221 | rtc_class->resume = rtc_resume; | ||
| 222 | rtc_dev_init(); | ||
| 223 | rtc_sysfs_init(rtc_class); | ||
| 143 | return 0; | 224 | return 0; |
| 144 | } | 225 | } |
| 145 | 226 | ||
| 146 | static void __exit rtc_exit(void) | 227 | static void __exit rtc_exit(void) |
| 147 | { | 228 | { |
| 229 | rtc_dev_exit(); | ||
| 148 | class_destroy(rtc_class); | 230 | class_destroy(rtc_class); |
| 149 | } | 231 | } |
| 150 | 232 | ||
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index d02fe9a0001f..178527252c6a 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c | |||
| @@ -26,15 +26,15 @@ static int __init rtc_hctosys(void) | |||
| 26 | { | 26 | { |
| 27 | int err; | 27 | int err; |
| 28 | struct rtc_time tm; | 28 | struct rtc_time tm; |
| 29 | struct class_device *class_dev = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); | 29 | struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); |
| 30 | 30 | ||
| 31 | if (class_dev == NULL) { | 31 | if (rtc == NULL) { |
| 32 | printk("%s: unable to open rtc device (%s)\n", | 32 | printk("%s: unable to open rtc device (%s)\n", |
| 33 | __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); | 33 | __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); |
| 34 | return -ENODEV; | 34 | return -ENODEV; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | err = rtc_read_time(class_dev, &tm); | 37 | err = rtc_read_time(rtc, &tm); |
| 38 | if (err == 0) { | 38 | if (err == 0) { |
| 39 | err = rtc_valid_tm(&tm); | 39 | err = rtc_valid_tm(&tm); |
| 40 | if (err == 0) { | 40 | if (err == 0) { |
| @@ -46,7 +46,7 @@ static int __init rtc_hctosys(void) | |||
| 46 | 46 | ||
| 47 | do_settimeofday(&tv); | 47 | do_settimeofday(&tv); |
| 48 | 48 | ||
| 49 | dev_info(class_dev->dev, | 49 | dev_info(rtc->dev.parent, |
| 50 | "setting the system clock to " | 50 | "setting the system clock to " |
| 51 | "%d-%02d-%02d %02d:%02d:%02d (%u)\n", | 51 | "%d-%02d-%02d %02d:%02d:%02d (%u)\n", |
| 52 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | 52 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, |
| @@ -54,14 +54,14 @@ static int __init rtc_hctosys(void) | |||
| 54 | (unsigned int) tv.tv_sec); | 54 | (unsigned int) tv.tv_sec); |
| 55 | } | 55 | } |
| 56 | else | 56 | else |
| 57 | dev_err(class_dev->dev, | 57 | dev_err(rtc->dev.parent, |
| 58 | "hctosys: invalid date/time\n"); | 58 | "hctosys: invalid date/time\n"); |
| 59 | } | 59 | } |
| 60 | else | 60 | else |
| 61 | dev_err(class_dev->dev, | 61 | dev_err(rtc->dev.parent, |
| 62 | "hctosys: unable to read the hardware clock\n"); | 62 | "hctosys: unable to read the hardware clock\n"); |
| 63 | 63 | ||
| 64 | rtc_class_close(class_dev); | 64 | rtc_class_close(rtc); |
| 65 | 65 | ||
| 66 | return 0; | 66 | return 0; |
| 67 | } | 67 | } |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index ef40df0f169d..ad66c6ecf365 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
| @@ -13,10 +13,9 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
| 15 | 15 | ||
| 16 | int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm) | 16 | int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) |
| 17 | { | 17 | { |
| 18 | int err; | 18 | int err; |
| 19 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 20 | 19 | ||
| 21 | err = mutex_lock_interruptible(&rtc->ops_lock); | 20 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 22 | if (err) | 21 | if (err) |
| @@ -28,7 +27,7 @@ int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm) | |||
| 28 | err = -EINVAL; | 27 | err = -EINVAL; |
| 29 | else { | 28 | else { |
| 30 | memset(tm, 0, sizeof(struct rtc_time)); | 29 | memset(tm, 0, sizeof(struct rtc_time)); |
| 31 | err = rtc->ops->read_time(class_dev->dev, tm); | 30 | err = rtc->ops->read_time(rtc->dev.parent, tm); |
| 32 | } | 31 | } |
| 33 | 32 | ||
| 34 | mutex_unlock(&rtc->ops_lock); | 33 | mutex_unlock(&rtc->ops_lock); |
| @@ -36,10 +35,9 @@ int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm) | |||
| 36 | } | 35 | } |
| 37 | EXPORT_SYMBOL_GPL(rtc_read_time); | 36 | EXPORT_SYMBOL_GPL(rtc_read_time); |
| 38 | 37 | ||
| 39 | int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm) | 38 | int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) |
| 40 | { | 39 | { |
| 41 | int err; | 40 | int err; |
| 42 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 43 | 41 | ||
| 44 | err = rtc_valid_tm(tm); | 42 | err = rtc_valid_tm(tm); |
| 45 | if (err != 0) | 43 | if (err != 0) |
| @@ -54,17 +52,16 @@ int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm) | |||
| 54 | else if (!rtc->ops->set_time) | 52 | else if (!rtc->ops->set_time) |
| 55 | err = -EINVAL; | 53 | err = -EINVAL; |
| 56 | else | 54 | else |
| 57 | err = rtc->ops->set_time(class_dev->dev, tm); | 55 | err = rtc->ops->set_time(rtc->dev.parent, tm); |
| 58 | 56 | ||
| 59 | mutex_unlock(&rtc->ops_lock); | 57 | mutex_unlock(&rtc->ops_lock); |
| 60 | return err; | 58 | return err; |
| 61 | } | 59 | } |
| 62 | EXPORT_SYMBOL_GPL(rtc_set_time); | 60 | EXPORT_SYMBOL_GPL(rtc_set_time); |
| 63 | 61 | ||
| 64 | int rtc_set_mmss(struct class_device *class_dev, unsigned long secs) | 62 | int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) |
| 65 | { | 63 | { |
| 66 | int err; | 64 | int err; |
| 67 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 68 | 65 | ||
| 69 | err = mutex_lock_interruptible(&rtc->ops_lock); | 66 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 70 | if (err) | 67 | if (err) |
| @@ -73,11 +70,11 @@ int rtc_set_mmss(struct class_device *class_dev, unsigned long secs) | |||
| 73 | if (!rtc->ops) | 70 | if (!rtc->ops) |
| 74 | err = -ENODEV; | 71 | err = -ENODEV; |
| 75 | else if (rtc->ops->set_mmss) | 72 | else if (rtc->ops->set_mmss) |
| 76 | err = rtc->ops->set_mmss(class_dev->dev, secs); | 73 | err = rtc->ops->set_mmss(rtc->dev.parent, secs); |
| 77 | else if (rtc->ops->read_time && rtc->ops->set_time) { | 74 | else if (rtc->ops->read_time && rtc->ops->set_time) { |
| 78 | struct rtc_time new, old; | 75 | struct rtc_time new, old; |
| 79 | 76 | ||
| 80 | err = rtc->ops->read_time(class_dev->dev, &old); | 77 | err = rtc->ops->read_time(rtc->dev.parent, &old); |
| 81 | if (err == 0) { | 78 | if (err == 0) { |
| 82 | rtc_time_to_tm(secs, &new); | 79 | rtc_time_to_tm(secs, &new); |
| 83 | 80 | ||
| @@ -89,7 +86,8 @@ int rtc_set_mmss(struct class_device *class_dev, unsigned long secs) | |||
| 89 | */ | 86 | */ |
| 90 | if (!((old.tm_hour == 23 && old.tm_min == 59) || | 87 | if (!((old.tm_hour == 23 && old.tm_min == 59) || |
| 91 | (new.tm_hour == 23 && new.tm_min == 59))) | 88 | (new.tm_hour == 23 && new.tm_min == 59))) |
| 92 | err = rtc->ops->set_time(class_dev->dev, &new); | 89 | err = rtc->ops->set_time(rtc->dev.parent, |
| 90 | &new); | ||
| 93 | } | 91 | } |
| 94 | } | 92 | } |
| 95 | else | 93 | else |
| @@ -101,10 +99,9 @@ int rtc_set_mmss(struct class_device *class_dev, unsigned long secs) | |||
| 101 | } | 99 | } |
| 102 | EXPORT_SYMBOL_GPL(rtc_set_mmss); | 100 | EXPORT_SYMBOL_GPL(rtc_set_mmss); |
| 103 | 101 | ||
| 104 | int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) | 102 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
| 105 | { | 103 | { |
| 106 | int err; | 104 | int err; |
| 107 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 108 | 105 | ||
| 109 | err = mutex_lock_interruptible(&rtc->ops_lock); | 106 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 110 | if (err) | 107 | if (err) |
| @@ -116,7 +113,7 @@ int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) | |||
| 116 | err = -EINVAL; | 113 | err = -EINVAL; |
| 117 | else { | 114 | else { |
| 118 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); | 115 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); |
| 119 | err = rtc->ops->read_alarm(class_dev->dev, alarm); | 116 | err = rtc->ops->read_alarm(rtc->dev.parent, alarm); |
| 120 | } | 117 | } |
| 121 | 118 | ||
| 122 | mutex_unlock(&rtc->ops_lock); | 119 | mutex_unlock(&rtc->ops_lock); |
| @@ -124,10 +121,13 @@ int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) | |||
| 124 | } | 121 | } |
| 125 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | 122 | EXPORT_SYMBOL_GPL(rtc_read_alarm); |
| 126 | 123 | ||
| 127 | int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) | 124 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
| 128 | { | 125 | { |
| 129 | int err; | 126 | int err; |
| 130 | struct rtc_device *rtc = to_rtc_device(class_dev); | 127 | |
| 128 | err = rtc_valid_tm(&alarm->time); | ||
| 129 | if (err != 0) | ||
| 130 | return err; | ||
| 131 | 131 | ||
| 132 | err = mutex_lock_interruptible(&rtc->ops_lock); | 132 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 133 | if (err) | 133 | if (err) |
| @@ -138,7 +138,7 @@ int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) | |||
| 138 | else if (!rtc->ops->set_alarm) | 138 | else if (!rtc->ops->set_alarm) |
| 139 | err = -EINVAL; | 139 | err = -EINVAL; |
| 140 | else | 140 | else |
| 141 | err = rtc->ops->set_alarm(class_dev->dev, alarm); | 141 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); |
| 142 | 142 | ||
| 143 | mutex_unlock(&rtc->ops_lock); | 143 | mutex_unlock(&rtc->ops_lock); |
| 144 | return err; | 144 | return err; |
| @@ -147,16 +147,14 @@ EXPORT_SYMBOL_GPL(rtc_set_alarm); | |||
| 147 | 147 | ||
| 148 | /** | 148 | /** |
| 149 | * rtc_update_irq - report RTC periodic, alarm, and/or update irqs | 149 | * rtc_update_irq - report RTC periodic, alarm, and/or update irqs |
| 150 | * @class_dev: the rtc's class device | 150 | * @rtc: the rtc device |
| 151 | * @num: how many irqs are being reported (usually one) | 151 | * @num: how many irqs are being reported (usually one) |
| 152 | * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF | 152 | * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF |
| 153 | * Context: in_interrupt(), irqs blocked | 153 | * Context: in_interrupt(), irqs blocked |
| 154 | */ | 154 | */ |
| 155 | void rtc_update_irq(struct class_device *class_dev, | 155 | void rtc_update_irq(struct rtc_device *rtc, |
| 156 | unsigned long num, unsigned long events) | 156 | unsigned long num, unsigned long events) |
| 157 | { | 157 | { |
| 158 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 159 | |||
| 160 | spin_lock(&rtc->irq_lock); | 158 | spin_lock(&rtc->irq_lock); |
| 161 | rtc->irq_data = (rtc->irq_data + (num << 8)) | events; | 159 | rtc->irq_data = (rtc->irq_data + (num << 8)) | events; |
| 162 | spin_unlock(&rtc->irq_lock); | 160 | spin_unlock(&rtc->irq_lock); |
| @@ -171,40 +169,43 @@ void rtc_update_irq(struct class_device *class_dev, | |||
| 171 | } | 169 | } |
| 172 | EXPORT_SYMBOL_GPL(rtc_update_irq); | 170 | EXPORT_SYMBOL_GPL(rtc_update_irq); |
| 173 | 171 | ||
| 174 | struct class_device *rtc_class_open(char *name) | 172 | struct rtc_device *rtc_class_open(char *name) |
| 175 | { | 173 | { |
| 176 | struct class_device *class_dev = NULL, | 174 | struct device *dev; |
| 177 | *class_dev_tmp; | 175 | struct rtc_device *rtc = NULL; |
| 178 | 176 | ||
| 179 | down(&rtc_class->sem); | 177 | down(&rtc_class->sem); |
| 180 | list_for_each_entry(class_dev_tmp, &rtc_class->children, node) { | 178 | list_for_each_entry(dev, &rtc_class->devices, node) { |
| 181 | if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) { | 179 | if (strncmp(dev->bus_id, name, BUS_ID_SIZE) == 0) { |
| 182 | class_dev = class_device_get(class_dev_tmp); | 180 | dev = get_device(dev); |
| 181 | if (dev) | ||
| 182 | rtc = to_rtc_device(dev); | ||
| 183 | break; | 183 | break; |
| 184 | } | 184 | } |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | if (class_dev) { | 187 | if (rtc) { |
| 188 | if (!try_module_get(to_rtc_device(class_dev)->owner)) | 188 | if (!try_module_get(rtc->owner)) { |
| 189 | class_dev = NULL; | 189 | put_device(dev); |
| 190 | rtc = NULL; | ||
| 191 | } | ||
| 190 | } | 192 | } |
| 191 | up(&rtc_class->sem); | 193 | up(&rtc_class->sem); |
| 192 | 194 | ||
| 193 | return class_dev; | 195 | return rtc; |
| 194 | } | 196 | } |
| 195 | EXPORT_SYMBOL_GPL(rtc_class_open); | 197 | EXPORT_SYMBOL_GPL(rtc_class_open); |
| 196 | 198 | ||
| 197 | void rtc_class_close(struct class_device *class_dev) | 199 | void rtc_class_close(struct rtc_device *rtc) |
| 198 | { | 200 | { |
| 199 | module_put(to_rtc_device(class_dev)->owner); | 201 | module_put(rtc->owner); |
| 200 | class_device_put(class_dev); | 202 | put_device(&rtc->dev); |
| 201 | } | 203 | } |
| 202 | EXPORT_SYMBOL_GPL(rtc_class_close); | 204 | EXPORT_SYMBOL_GPL(rtc_class_close); |
| 203 | 205 | ||
| 204 | int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task) | 206 | int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) |
| 205 | { | 207 | { |
| 206 | int retval = -EBUSY; | 208 | int retval = -EBUSY; |
| 207 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 208 | 209 | ||
| 209 | if (task == NULL || task->func == NULL) | 210 | if (task == NULL || task->func == NULL) |
| 210 | return -EINVAL; | 211 | return -EINVAL; |
| @@ -220,9 +221,8 @@ int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task) | |||
| 220 | } | 221 | } |
| 221 | EXPORT_SYMBOL_GPL(rtc_irq_register); | 222 | EXPORT_SYMBOL_GPL(rtc_irq_register); |
| 222 | 223 | ||
| 223 | void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task) | 224 | void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) |
| 224 | { | 225 | { |
| 225 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 226 | 226 | ||
| 227 | spin_lock_irq(&rtc->irq_task_lock); | 227 | spin_lock_irq(&rtc->irq_task_lock); |
| 228 | if (rtc->irq_task == task) | 228 | if (rtc->irq_task == task) |
| @@ -231,11 +231,10 @@ void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task) | |||
| 231 | } | 231 | } |
| 232 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); | 232 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); |
| 233 | 233 | ||
| 234 | int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int enabled) | 234 | int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) |
| 235 | { | 235 | { |
| 236 | int err = 0; | 236 | int err = 0; |
| 237 | unsigned long flags; | 237 | unsigned long flags; |
| 238 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 239 | 238 | ||
| 240 | if (rtc->ops->irq_set_state == NULL) | 239 | if (rtc->ops->irq_set_state == NULL) |
| 241 | return -ENXIO; | 240 | return -ENXIO; |
| @@ -246,17 +245,16 @@ int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int | |||
| 246 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | 245 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
| 247 | 246 | ||
| 248 | if (err == 0) | 247 | if (err == 0) |
| 249 | err = rtc->ops->irq_set_state(class_dev->dev, enabled); | 248 | err = rtc->ops->irq_set_state(rtc->dev.parent, enabled); |
| 250 | 249 | ||
| 251 | return err; | 250 | return err; |
| 252 | } | 251 | } |
| 253 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); | 252 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); |
| 254 | 253 | ||
| 255 | int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq) | 254 | int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) |
| 256 | { | 255 | { |
| 257 | int err = 0; | 256 | int err = 0; |
| 258 | unsigned long flags; | 257 | unsigned long flags; |
| 259 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 260 | 258 | ||
| 261 | if (rtc->ops->irq_set_freq == NULL) | 259 | if (rtc->ops->irq_set_freq == NULL) |
| 262 | return -ENXIO; | 260 | return -ENXIO; |
| @@ -267,7 +265,7 @@ int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int | |||
| 267 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | 265 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
| 268 | 266 | ||
| 269 | if (err == 0) { | 267 | if (err == 0) { |
| 270 | err = rtc->ops->irq_set_freq(class_dev->dev, freq); | 268 | err = rtc->ops->irq_set_freq(rtc->dev.parent, freq); |
| 271 | if (err == 0) | 269 | if (err == 0) |
| 272 | rtc->irq_freq = freq; | 270 | rtc->irq_freq = freq; |
| 273 | } | 271 | } |
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index ac0e68e2f025..33795e5a5595 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
| @@ -263,7 +263,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id) | |||
| 263 | 263 | ||
| 264 | at91_sys_write(AT91_RTC_SCCR, rtsr); /* clear status reg */ | 264 | at91_sys_write(AT91_RTC_SCCR, rtsr); /* clear status reg */ |
| 265 | 265 | ||
| 266 | rtc_update_irq(&rtc->class_dev, 1, events); | 266 | rtc_update_irq(rtc, 1, events); |
| 267 | 267 | ||
| 268 | pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__, | 268 | pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__, |
| 269 | events >> 8, events & 0x000000FF); | 269 | events >> 8, events & 0x000000FF); |
| @@ -348,21 +348,10 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) | |||
| 348 | 348 | ||
| 349 | /* AT91RM9200 RTC Power management control */ | 349 | /* AT91RM9200 RTC Power management control */ |
| 350 | 350 | ||
| 351 | static struct timespec at91_rtc_delta; | ||
| 352 | static u32 at91_rtc_imr; | 351 | static u32 at91_rtc_imr; |
| 353 | 352 | ||
| 354 | static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 353 | static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
| 355 | { | 354 | { |
| 356 | struct rtc_time tm; | ||
| 357 | struct timespec time; | ||
| 358 | |||
| 359 | time.tv_nsec = 0; | ||
| 360 | |||
| 361 | /* calculate time delta for suspend */ | ||
| 362 | at91_rtc_readtime(&pdev->dev, &tm); | ||
| 363 | rtc_tm_to_time(&tm, &time.tv_sec); | ||
| 364 | save_time_delta(&at91_rtc_delta, &time); | ||
| 365 | |||
| 366 | /* this IRQ is shared with DBGU and other hardware which isn't | 355 | /* this IRQ is shared with DBGU and other hardware which isn't |
| 367 | * necessarily doing PM like we are... | 356 | * necessarily doing PM like we are... |
| 368 | */ | 357 | */ |
| @@ -374,36 +363,17 @@ static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 374 | else | 363 | else |
| 375 | at91_sys_write(AT91_RTC_IDR, at91_rtc_imr); | 364 | at91_sys_write(AT91_RTC_IDR, at91_rtc_imr); |
| 376 | } | 365 | } |
| 377 | |||
| 378 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, | ||
| 379 | 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday, | ||
| 380 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
| 381 | |||
| 382 | return 0; | 366 | return 0; |
| 383 | } | 367 | } |
| 384 | 368 | ||
| 385 | static int at91_rtc_resume(struct platform_device *pdev) | 369 | static int at91_rtc_resume(struct platform_device *pdev) |
| 386 | { | 370 | { |
| 387 | struct rtc_time tm; | ||
| 388 | struct timespec time; | ||
| 389 | |||
| 390 | time.tv_nsec = 0; | ||
| 391 | |||
| 392 | at91_rtc_readtime(&pdev->dev, &tm); | ||
| 393 | rtc_tm_to_time(&tm, &time.tv_sec); | ||
| 394 | restore_time_delta(&at91_rtc_delta, &time); | ||
| 395 | |||
| 396 | if (at91_rtc_imr) { | 371 | if (at91_rtc_imr) { |
| 397 | if (device_may_wakeup(&pdev->dev)) | 372 | if (device_may_wakeup(&pdev->dev)) |
| 398 | disable_irq_wake(AT91_ID_SYS); | 373 | disable_irq_wake(AT91_ID_SYS); |
| 399 | else | 374 | else |
| 400 | at91_sys_write(AT91_RTC_IER, at91_rtc_imr); | 375 | at91_sys_write(AT91_RTC_IER, at91_rtc_imr); |
| 401 | } | 376 | } |
| 402 | |||
| 403 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, | ||
| 404 | 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday, | ||
| 405 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
| 406 | |||
| 407 | return 0; | 377 | return 0; |
| 408 | } | 378 | } |
| 409 | #else | 379 | #else |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 7c0d60910077..6085261aa2c1 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
| @@ -46,6 +46,10 @@ struct cmos_rtc { | |||
| 46 | int irq; | 46 | int irq; |
| 47 | struct resource *iomem; | 47 | struct resource *iomem; |
| 48 | 48 | ||
| 49 | void (*wake_on)(struct device *); | ||
| 50 | void (*wake_off)(struct device *); | ||
| 51 | |||
| 52 | u8 enabled_wake; | ||
| 49 | u8 suspend_ctrl; | 53 | u8 suspend_ctrl; |
| 50 | 54 | ||
| 51 | /* newer hardware extends the original register set */ | 55 | /* newer hardware extends the original register set */ |
| @@ -203,7 +207,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 203 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 207 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
| 204 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 208 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
| 205 | if (is_intr(rtc_intr)) | 209 | if (is_intr(rtc_intr)) |
| 206 | rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr); | 210 | rtc_update_irq(cmos->rtc, 1, rtc_intr); |
| 207 | 211 | ||
| 208 | /* update alarm */ | 212 | /* update alarm */ |
| 209 | CMOS_WRITE(hrs, RTC_HOURS_ALARM); | 213 | CMOS_WRITE(hrs, RTC_HOURS_ALARM); |
| @@ -223,7 +227,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 223 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 227 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
| 224 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 228 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
| 225 | if (is_intr(rtc_intr)) | 229 | if (is_intr(rtc_intr)) |
| 226 | rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr); | 230 | rtc_update_irq(cmos->rtc, 1, rtc_intr); |
| 227 | } | 231 | } |
| 228 | 232 | ||
| 229 | spin_unlock_irq(&rtc_lock); | 233 | spin_unlock_irq(&rtc_lock); |
| @@ -304,7 +308,7 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
| 304 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 308 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
| 305 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 309 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
| 306 | if (is_intr(rtc_intr)) | 310 | if (is_intr(rtc_intr)) |
| 307 | rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr); | 311 | rtc_update_irq(cmos->rtc, 1, rtc_intr); |
| 308 | spin_unlock_irqrestore(&rtc_lock, flags); | 312 | spin_unlock_irqrestore(&rtc_lock, flags); |
| 309 | return 0; | 313 | return 0; |
| 310 | } | 314 | } |
| @@ -379,12 +383,12 @@ static irqreturn_t cmos_interrupt(int irq, void *p) | |||
| 379 | return IRQ_NONE; | 383 | return IRQ_NONE; |
| 380 | } | 384 | } |
| 381 | 385 | ||
| 382 | #ifdef CONFIG_PNPACPI | 386 | #ifdef CONFIG_PNP |
| 383 | #define is_pnpacpi() 1 | 387 | #define is_pnp() 1 |
| 384 | #define INITSECTION | 388 | #define INITSECTION |
| 385 | 389 | ||
| 386 | #else | 390 | #else |
| 387 | #define is_pnpacpi() 0 | 391 | #define is_pnp() 0 |
| 388 | #define INITSECTION __init | 392 | #define INITSECTION __init |
| 389 | #endif | 393 | #endif |
| 390 | 394 | ||
| @@ -405,13 +409,20 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 405 | cmos_rtc.irq = rtc_irq; | 409 | cmos_rtc.irq = rtc_irq; |
| 406 | cmos_rtc.iomem = ports; | 410 | cmos_rtc.iomem = ports; |
| 407 | 411 | ||
| 408 | /* For ACPI systems the info comes from the FADT. On others, | 412 | /* For ACPI systems extension info comes from the FADT. On others, |
| 409 | * board specific setup provides it as appropriate. | 413 | * board specific setup provides it as appropriate. Systems where |
| 414 | * the alarm IRQ isn't automatically a wakeup IRQ (like ACPI, and | ||
| 415 | * some almost-clones) can provide hooks to make that behave. | ||
| 410 | */ | 416 | */ |
| 411 | if (info) { | 417 | if (info) { |
| 412 | cmos_rtc.day_alrm = info->rtc_day_alarm; | 418 | cmos_rtc.day_alrm = info->rtc_day_alarm; |
| 413 | cmos_rtc.mon_alrm = info->rtc_mon_alarm; | 419 | cmos_rtc.mon_alrm = info->rtc_mon_alarm; |
| 414 | cmos_rtc.century = info->rtc_century; | 420 | cmos_rtc.century = info->rtc_century; |
| 421 | |||
| 422 | if (info->wake_on && info->wake_off) { | ||
| 423 | cmos_rtc.wake_on = info->wake_on; | ||
| 424 | cmos_rtc.wake_off = info->wake_off; | ||
| 425 | } | ||
| 415 | } | 426 | } |
| 416 | 427 | ||
| 417 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, | 428 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, |
| @@ -427,14 +438,14 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 427 | * REVISIT for non-x86 systems we may need to handle io memory | 438 | * REVISIT for non-x86 systems we may need to handle io memory |
| 428 | * resources: ioremap them, and request_mem_region(). | 439 | * resources: ioremap them, and request_mem_region(). |
| 429 | */ | 440 | */ |
| 430 | if (is_pnpacpi()) { | 441 | if (is_pnp()) { |
| 431 | retval = request_resource(&ioport_resource, ports); | 442 | retval = request_resource(&ioport_resource, ports); |
| 432 | if (retval < 0) { | 443 | if (retval < 0) { |
| 433 | dev_dbg(dev, "i/o registers already in use\n"); | 444 | dev_dbg(dev, "i/o registers already in use\n"); |
| 434 | goto cleanup0; | 445 | goto cleanup0; |
| 435 | } | 446 | } |
| 436 | } | 447 | } |
| 437 | rename_region(ports, cmos_rtc.rtc->class_dev.class_id); | 448 | rename_region(ports, cmos_rtc.rtc->dev.bus_id); |
| 438 | 449 | ||
| 439 | spin_lock_irq(&rtc_lock); | 450 | spin_lock_irq(&rtc_lock); |
| 440 | 451 | ||
| @@ -470,8 +481,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 470 | 481 | ||
| 471 | if (is_valid_irq(rtc_irq)) | 482 | if (is_valid_irq(rtc_irq)) |
| 472 | retval = request_irq(rtc_irq, cmos_interrupt, IRQF_DISABLED, | 483 | retval = request_irq(rtc_irq, cmos_interrupt, IRQF_DISABLED, |
| 473 | cmos_rtc.rtc->class_dev.class_id, | 484 | cmos_rtc.rtc->dev.bus_id, |
| 474 | &cmos_rtc.rtc->class_dev); | 485 | cmos_rtc.rtc); |
| 475 | if (retval < 0) { | 486 | if (retval < 0) { |
| 476 | dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); | 487 | dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); |
| 477 | goto cleanup1; | 488 | goto cleanup1; |
| @@ -483,7 +494,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 483 | */ | 494 | */ |
| 484 | 495 | ||
| 485 | pr_info("%s: alarms up to one %s%s\n", | 496 | pr_info("%s: alarms up to one %s%s\n", |
| 486 | cmos_rtc.rtc->class_dev.class_id, | 497 | cmos_rtc.rtc->dev.bus_id, |
| 487 | is_valid_irq(rtc_irq) | 498 | is_valid_irq(rtc_irq) |
| 488 | ? (cmos_rtc.mon_alrm | 499 | ? (cmos_rtc.mon_alrm |
| 489 | ? "year" | 500 | ? "year" |
| @@ -520,12 +531,12 @@ static void __exit cmos_do_remove(struct device *dev) | |||
| 520 | 531 | ||
| 521 | cmos_do_shutdown(); | 532 | cmos_do_shutdown(); |
| 522 | 533 | ||
| 523 | if (is_pnpacpi()) | 534 | if (is_pnp()) |
| 524 | release_resource(cmos->iomem); | 535 | release_resource(cmos->iomem); |
| 525 | rename_region(cmos->iomem, NULL); | 536 | rename_region(cmos->iomem, NULL); |
| 526 | 537 | ||
| 527 | if (is_valid_irq(cmos->irq)) | 538 | if (is_valid_irq(cmos->irq)) |
| 528 | free_irq(cmos->irq, &cmos_rtc.rtc->class_dev); | 539 | free_irq(cmos->irq, cmos_rtc.rtc); |
| 529 | 540 | ||
| 530 | rtc_device_unregister(cmos_rtc.rtc); | 541 | rtc_device_unregister(cmos_rtc.rtc); |
| 531 | 542 | ||
| @@ -555,16 +566,20 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
| 555 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | 566 | irqstat = CMOS_READ(RTC_INTR_FLAGS); |
| 556 | irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF; | 567 | irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF; |
| 557 | if (is_intr(irqstat)) | 568 | if (is_intr(irqstat)) |
| 558 | rtc_update_irq(&cmos->rtc->class_dev, 1, irqstat); | 569 | rtc_update_irq(cmos->rtc, 1, irqstat); |
| 559 | } | 570 | } |
| 560 | spin_unlock_irq(&rtc_lock); | 571 | spin_unlock_irq(&rtc_lock); |
| 561 | 572 | ||
| 562 | /* ACPI HOOK: enable ACPI_EVENT_RTC when (tmp & RTC_AIE) | 573 | if (tmp & RTC_AIE) { |
| 563 | * ... it'd be best if we could do that under rtc_lock. | 574 | cmos->enabled_wake = 1; |
| 564 | */ | 575 | if (cmos->wake_on) |
| 576 | cmos->wake_on(dev); | ||
| 577 | else | ||
| 578 | enable_irq_wake(cmos->irq); | ||
| 579 | } | ||
| 565 | 580 | ||
| 566 | pr_debug("%s: suspend%s, ctrl %02x\n", | 581 | pr_debug("%s: suspend%s, ctrl %02x\n", |
| 567 | cmos_rtc.rtc->class_dev.class_id, | 582 | cmos_rtc.rtc->dev.bus_id, |
| 568 | (tmp & RTC_AIE) ? ", alarm may wake" : "", | 583 | (tmp & RTC_AIE) ? ", alarm may wake" : "", |
| 569 | tmp); | 584 | tmp); |
| 570 | 585 | ||
| @@ -576,26 +591,28 @@ static int cmos_resume(struct device *dev) | |||
| 576 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 591 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
| 577 | unsigned char tmp = cmos->suspend_ctrl; | 592 | unsigned char tmp = cmos->suspend_ctrl; |
| 578 | 593 | ||
| 579 | /* REVISIT: a mechanism to resync the system clock (jiffies) | ||
| 580 | * on resume should be portable between platforms ... | ||
| 581 | */ | ||
| 582 | |||
| 583 | /* re-enable any irqs previously active */ | 594 | /* re-enable any irqs previously active */ |
| 584 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { | 595 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { |
| 585 | 596 | ||
| 586 | /* ACPI HOOK: disable ACPI_EVENT_RTC when (tmp & RTC_AIE) */ | 597 | if (cmos->enabled_wake) { |
| 598 | if (cmos->wake_off) | ||
| 599 | cmos->wake_off(dev); | ||
| 600 | else | ||
| 601 | disable_irq_wake(cmos->irq); | ||
| 602 | cmos->enabled_wake = 0; | ||
| 603 | } | ||
| 587 | 604 | ||
| 588 | spin_lock_irq(&rtc_lock); | 605 | spin_lock_irq(&rtc_lock); |
| 589 | CMOS_WRITE(tmp, RTC_CONTROL); | 606 | CMOS_WRITE(tmp, RTC_CONTROL); |
| 590 | tmp = CMOS_READ(RTC_INTR_FLAGS); | 607 | tmp = CMOS_READ(RTC_INTR_FLAGS); |
| 591 | tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF; | 608 | tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF; |
| 592 | if (is_intr(tmp)) | 609 | if (is_intr(tmp)) |
| 593 | rtc_update_irq(&cmos->rtc->class_dev, 1, tmp); | 610 | rtc_update_irq(cmos->rtc, 1, tmp); |
| 594 | spin_unlock_irq(&rtc_lock); | 611 | spin_unlock_irq(&rtc_lock); |
| 595 | } | 612 | } |
| 596 | 613 | ||
| 597 | pr_debug("%s: resume, ctrl %02x\n", | 614 | pr_debug("%s: resume, ctrl %02x\n", |
| 598 | cmos_rtc.rtc->class_dev.class_id, | 615 | cmos_rtc.rtc->dev.bus_id, |
| 599 | cmos->suspend_ctrl); | 616 | cmos->suspend_ctrl); |
| 600 | 617 | ||
| 601 | 618 | ||
| @@ -613,7 +630,7 @@ static int cmos_resume(struct device *dev) | |||
| 613 | * the device node will always be created as a PNPACPI device. | 630 | * the device node will always be created as a PNPACPI device. |
| 614 | */ | 631 | */ |
| 615 | 632 | ||
| 616 | #ifdef CONFIG_PNPACPI | 633 | #ifdef CONFIG_PNP |
| 617 | 634 | ||
| 618 | #include <linux/pnp.h> | 635 | #include <linux/pnp.h> |
| 619 | 636 | ||
| @@ -684,11 +701,11 @@ static void __exit cmos_exit(void) | |||
| 684 | } | 701 | } |
| 685 | module_exit(cmos_exit); | 702 | module_exit(cmos_exit); |
| 686 | 703 | ||
| 687 | #else /* no PNPACPI */ | 704 | #else /* no PNP */ |
| 688 | 705 | ||
| 689 | /*----------------------------------------------------------------*/ | 706 | /*----------------------------------------------------------------*/ |
| 690 | 707 | ||
| 691 | /* Platform setup should have set up an RTC device, when PNPACPI is | 708 | /* Platform setup should have set up an RTC device, when PNP is |
| 692 | * unavailable ... this could happen even on (older) PCs. | 709 | * unavailable ... this could happen even on (older) PCs. |
| 693 | */ | 710 | */ |
| 694 | 711 | ||
| @@ -734,7 +751,7 @@ static void __exit cmos_exit(void) | |||
| 734 | module_exit(cmos_exit); | 751 | module_exit(cmos_exit); |
| 735 | 752 | ||
| 736 | 753 | ||
| 737 | #endif /* !PNPACPI */ | 754 | #endif /* !PNP */ |
| 738 | 755 | ||
| 739 | MODULE_AUTHOR("David Brownell"); | 756 | MODULE_AUTHOR("David Brownell"); |
| 740 | MODULE_DESCRIPTION("Driver for PC-style 'CMOS' RTCs"); | 757 | MODULE_DESCRIPTION("Driver for PC-style 'CMOS' RTCs"); |
diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h new file mode 100644 index 000000000000..5f9df7430a22 --- /dev/null +++ b/drivers/rtc/rtc-core.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | #ifdef CONFIG_RTC_INTF_DEV | ||
| 2 | |||
| 3 | extern void __init rtc_dev_init(void); | ||
| 4 | extern void __exit rtc_dev_exit(void); | ||
| 5 | extern void rtc_dev_prepare(struct rtc_device *rtc); | ||
| 6 | extern void rtc_dev_add_device(struct rtc_device *rtc); | ||
| 7 | extern void rtc_dev_del_device(struct rtc_device *rtc); | ||
| 8 | |||
| 9 | #else | ||
| 10 | |||
| 11 | static inline void rtc_dev_init(void) | ||
| 12 | { | ||
| 13 | } | ||
| 14 | |||
| 15 | static inline void rtc_dev_exit(void) | ||
| 16 | { | ||
| 17 | } | ||
| 18 | |||
| 19 | static inline void rtc_dev_prepare(struct rtc_device *rtc) | ||
| 20 | { | ||
| 21 | } | ||
| 22 | |||
| 23 | static inline void rtc_dev_add_device(struct rtc_device *rtc) | ||
| 24 | { | ||
| 25 | } | ||
| 26 | |||
| 27 | static inline void rtc_dev_del_device(struct rtc_device *rtc) | ||
| 28 | { | ||
| 29 | } | ||
| 30 | |||
| 31 | #endif | ||
| 32 | |||
| 33 | #ifdef CONFIG_RTC_INTF_PROC | ||
| 34 | |||
| 35 | extern void rtc_proc_add_device(struct rtc_device *rtc); | ||
| 36 | extern void rtc_proc_del_device(struct rtc_device *rtc); | ||
| 37 | |||
| 38 | #else | ||
| 39 | |||
| 40 | static inline void rtc_proc_add_device(struct rtc_device *rtc) | ||
| 41 | { | ||
| 42 | } | ||
| 43 | |||
| 44 | static inline void rtc_proc_del_device(struct rtc_device *rtc) | ||
| 45 | { | ||
| 46 | } | ||
| 47 | |||
| 48 | #endif | ||
| 49 | |||
| 50 | #ifdef CONFIG_RTC_INTF_SYSFS | ||
| 51 | |||
| 52 | extern void __init rtc_sysfs_init(struct class *); | ||
| 53 | extern void rtc_sysfs_add_device(struct rtc_device *rtc); | ||
| 54 | extern void rtc_sysfs_del_device(struct rtc_device *rtc); | ||
| 55 | |||
| 56 | #else | ||
| 57 | |||
| 58 | static inline void rtc_sysfs_init(struct class *rtc) | ||
| 59 | { | ||
| 60 | } | ||
| 61 | |||
| 62 | static inline void rtc_sysfs_add_device(struct rtc_device *rtc) | ||
| 63 | { | ||
| 64 | } | ||
| 65 | |||
| 66 | static inline void rtc_sysfs_del_device(struct rtc_device *rtc) | ||
| 67 | { | ||
| 68 | } | ||
| 69 | |||
| 70 | #endif | ||
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 137330b8636b..f4e5f0040ff7 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
| 16 | #include "rtc-core.h" | ||
| 16 | 17 | ||
| 17 | static struct class *rtc_dev_class; | ||
| 18 | static dev_t rtc_devt; | 18 | static dev_t rtc_devt; |
| 19 | 19 | ||
| 20 | #define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */ | 20 | #define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */ |
| @@ -32,9 +32,9 @@ static int rtc_dev_open(struct inode *inode, struct file *file) | |||
| 32 | if (!(mutex_trylock(&rtc->char_lock))) | 32 | if (!(mutex_trylock(&rtc->char_lock))) |
| 33 | return -EBUSY; | 33 | return -EBUSY; |
| 34 | 34 | ||
| 35 | file->private_data = &rtc->class_dev; | 35 | file->private_data = rtc; |
| 36 | 36 | ||
| 37 | err = ops->open ? ops->open(rtc->class_dev.dev) : 0; | 37 | err = ops->open ? ops->open(rtc->dev.parent) : 0; |
| 38 | if (err == 0) { | 38 | if (err == 0) { |
| 39 | spin_lock_irq(&rtc->irq_lock); | 39 | spin_lock_irq(&rtc->irq_lock); |
| 40 | rtc->irq_data = 0; | 40 | rtc->irq_data = 0; |
| @@ -61,7 +61,7 @@ static void rtc_uie_task(struct work_struct *work) | |||
| 61 | int num = 0; | 61 | int num = 0; |
| 62 | int err; | 62 | int err; |
| 63 | 63 | ||
| 64 | err = rtc_read_time(&rtc->class_dev, &tm); | 64 | err = rtc_read_time(rtc, &tm); |
| 65 | 65 | ||
| 66 | local_irq_disable(); | 66 | local_irq_disable(); |
| 67 | spin_lock(&rtc->irq_lock); | 67 | spin_lock(&rtc->irq_lock); |
| @@ -79,7 +79,7 @@ static void rtc_uie_task(struct work_struct *work) | |||
| 79 | } | 79 | } |
| 80 | spin_unlock(&rtc->irq_lock); | 80 | spin_unlock(&rtc->irq_lock); |
| 81 | if (num) | 81 | if (num) |
| 82 | rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF); | 82 | rtc_update_irq(rtc, num, RTC_UF | RTC_IRQF); |
| 83 | local_irq_enable(); | 83 | local_irq_enable(); |
| 84 | } | 84 | } |
| 85 | static void rtc_uie_timer(unsigned long data) | 85 | static void rtc_uie_timer(unsigned long data) |
| @@ -121,7 +121,7 @@ static int set_uie(struct rtc_device *rtc) | |||
| 121 | struct rtc_time tm; | 121 | struct rtc_time tm; |
| 122 | int err; | 122 | int err; |
| 123 | 123 | ||
| 124 | err = rtc_read_time(&rtc->class_dev, &tm); | 124 | err = rtc_read_time(rtc, &tm); |
| 125 | if (err) | 125 | if (err) |
| 126 | return err; | 126 | return err; |
| 127 | spin_lock_irq(&rtc->irq_lock); | 127 | spin_lock_irq(&rtc->irq_lock); |
| @@ -180,7 +180,7 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 180 | if (ret == 0) { | 180 | if (ret == 0) { |
| 181 | /* Check for any data updates */ | 181 | /* Check for any data updates */ |
| 182 | if (rtc->ops->read_callback) | 182 | if (rtc->ops->read_callback) |
| 183 | data = rtc->ops->read_callback(rtc->class_dev.dev, | 183 | data = rtc->ops->read_callback(rtc->dev.parent, |
| 184 | data); | 184 | data); |
| 185 | 185 | ||
| 186 | if (sizeof(int) != sizeof(long) && | 186 | if (sizeof(int) != sizeof(long) && |
| @@ -210,8 +210,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 210 | unsigned int cmd, unsigned long arg) | 210 | unsigned int cmd, unsigned long arg) |
| 211 | { | 211 | { |
| 212 | int err = 0; | 212 | int err = 0; |
| 213 | struct class_device *class_dev = file->private_data; | 213 | struct rtc_device *rtc = file->private_data; |
| 214 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 215 | const struct rtc_class_ops *ops = rtc->ops; | 214 | const struct rtc_class_ops *ops = rtc->ops; |
| 216 | struct rtc_time tm; | 215 | struct rtc_time tm; |
| 217 | struct rtc_wkalrm alarm; | 216 | struct rtc_wkalrm alarm; |
| @@ -252,7 +251,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 252 | 251 | ||
| 253 | /* try the driver's ioctl interface */ | 252 | /* try the driver's ioctl interface */ |
| 254 | if (ops->ioctl) { | 253 | if (ops->ioctl) { |
| 255 | err = ops->ioctl(class_dev->dev, cmd, arg); | 254 | err = ops->ioctl(rtc->dev.parent, cmd, arg); |
| 256 | if (err != -ENOIOCTLCMD) | 255 | if (err != -ENOIOCTLCMD) |
| 257 | return err; | 256 | return err; |
| 258 | } | 257 | } |
| @@ -264,7 +263,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 264 | 263 | ||
| 265 | switch (cmd) { | 264 | switch (cmd) { |
| 266 | case RTC_ALM_READ: | 265 | case RTC_ALM_READ: |
| 267 | err = rtc_read_alarm(class_dev, &alarm); | 266 | err = rtc_read_alarm(rtc, &alarm); |
| 268 | if (err < 0) | 267 | if (err < 0) |
| 269 | return err; | 268 | return err; |
| 270 | 269 | ||
| @@ -278,17 +277,53 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 278 | 277 | ||
| 279 | alarm.enabled = 0; | 278 | alarm.enabled = 0; |
| 280 | alarm.pending = 0; | 279 | alarm.pending = 0; |
| 281 | alarm.time.tm_mday = -1; | ||
| 282 | alarm.time.tm_mon = -1; | ||
| 283 | alarm.time.tm_year = -1; | ||
| 284 | alarm.time.tm_wday = -1; | 280 | alarm.time.tm_wday = -1; |
| 285 | alarm.time.tm_yday = -1; | 281 | alarm.time.tm_yday = -1; |
| 286 | alarm.time.tm_isdst = -1; | 282 | alarm.time.tm_isdst = -1; |
| 287 | err = rtc_set_alarm(class_dev, &alarm); | 283 | |
| 284 | /* RTC_ALM_SET alarms may be up to 24 hours in the future. | ||
| 285 | * Rather than expecting every RTC to implement "don't care" | ||
| 286 | * for day/month/year fields, just force the alarm to have | ||
| 287 | * the right values for those fields. | ||
| 288 | * | ||
| 289 | * RTC_WKALM_SET should be used instead. Not only does it | ||
| 290 | * eliminate the need for a separate RTC_AIE_ON call, it | ||
| 291 | * doesn't have the "alarm 23:59:59 in the future" race. | ||
| 292 | * | ||
| 293 | * NOTE: some legacy code may have used invalid fields as | ||
| 294 | * wildcards, exposing hardware "periodic alarm" capabilities. | ||
| 295 | * Not supported here. | ||
| 296 | */ | ||
| 297 | { | ||
| 298 | unsigned long now, then; | ||
| 299 | |||
| 300 | err = rtc_read_time(rtc, &tm); | ||
| 301 | if (err < 0) | ||
| 302 | return err; | ||
| 303 | rtc_tm_to_time(&tm, &now); | ||
| 304 | |||
| 305 | alarm.time.tm_mday = tm.tm_mday; | ||
| 306 | alarm.time.tm_mon = tm.tm_mon; | ||
| 307 | alarm.time.tm_year = tm.tm_year; | ||
| 308 | err = rtc_valid_tm(&alarm.time); | ||
| 309 | if (err < 0) | ||
| 310 | return err; | ||
| 311 | rtc_tm_to_time(&alarm.time, &then); | ||
| 312 | |||
| 313 | /* alarm may need to wrap into tomorrow */ | ||
| 314 | if (then < now) { | ||
| 315 | rtc_time_to_tm(now + 24 * 60 * 60, &tm); | ||
| 316 | alarm.time.tm_mday = tm.tm_mday; | ||
| 317 | alarm.time.tm_mon = tm.tm_mon; | ||
| 318 | alarm.time.tm_year = tm.tm_year; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | err = rtc_set_alarm(rtc, &alarm); | ||
| 288 | break; | 323 | break; |
| 289 | 324 | ||
| 290 | case RTC_RD_TIME: | 325 | case RTC_RD_TIME: |
| 291 | err = rtc_read_time(class_dev, &tm); | 326 | err = rtc_read_time(rtc, &tm); |
| 292 | if (err < 0) | 327 | if (err < 0) |
| 293 | return err; | 328 | return err; |
| 294 | 329 | ||
| @@ -300,7 +335,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 300 | if (copy_from_user(&tm, uarg, sizeof(tm))) | 335 | if (copy_from_user(&tm, uarg, sizeof(tm))) |
| 301 | return -EFAULT; | 336 | return -EFAULT; |
| 302 | 337 | ||
| 303 | err = rtc_set_time(class_dev, &tm); | 338 | err = rtc_set_time(rtc, &tm); |
| 304 | break; | 339 | break; |
| 305 | 340 | ||
| 306 | case RTC_IRQP_READ: | 341 | case RTC_IRQP_READ: |
| @@ -310,7 +345,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 310 | 345 | ||
| 311 | case RTC_IRQP_SET: | 346 | case RTC_IRQP_SET: |
| 312 | if (ops->irq_set_freq) | 347 | if (ops->irq_set_freq) |
| 313 | err = rtc_irq_set_freq(class_dev, rtc->irq_task, arg); | 348 | err = rtc_irq_set_freq(rtc, rtc->irq_task, arg); |
| 314 | break; | 349 | break; |
| 315 | 350 | ||
| 316 | #if 0 | 351 | #if 0 |
| @@ -336,11 +371,11 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 336 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) | 371 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) |
| 337 | return -EFAULT; | 372 | return -EFAULT; |
| 338 | 373 | ||
| 339 | err = rtc_set_alarm(class_dev, &alarm); | 374 | err = rtc_set_alarm(rtc, &alarm); |
| 340 | break; | 375 | break; |
| 341 | 376 | ||
| 342 | case RTC_WKALM_RD: | 377 | case RTC_WKALM_RD: |
| 343 | err = rtc_read_alarm(class_dev, &alarm); | 378 | err = rtc_read_alarm(rtc, &alarm); |
| 344 | if (err < 0) | 379 | if (err < 0) |
| 345 | return err; | 380 | return err; |
| 346 | 381 | ||
| @@ -372,7 +407,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) | |||
| 372 | clear_uie(rtc); | 407 | clear_uie(rtc); |
| 373 | #endif | 408 | #endif |
| 374 | if (rtc->ops->release) | 409 | if (rtc->ops->release) |
| 375 | rtc->ops->release(rtc->class_dev.dev); | 410 | rtc->ops->release(rtc->dev.parent); |
| 376 | 411 | ||
| 377 | mutex_unlock(&rtc->char_lock); | 412 | mutex_unlock(&rtc->char_lock); |
| 378 | return 0; | 413 | return 0; |
| @@ -397,17 +432,18 @@ static const struct file_operations rtc_dev_fops = { | |||
| 397 | 432 | ||
| 398 | /* insertion/removal hooks */ | 433 | /* insertion/removal hooks */ |
| 399 | 434 | ||
| 400 | static int rtc_dev_add_device(struct class_device *class_dev, | 435 | void rtc_dev_prepare(struct rtc_device *rtc) |
| 401 | struct class_interface *class_intf) | ||
| 402 | { | 436 | { |
| 403 | int err = 0; | 437 | if (!rtc_devt) |
| 404 | struct rtc_device *rtc = to_rtc_device(class_dev); | 438 | return; |
| 405 | 439 | ||
| 406 | if (rtc->id >= RTC_DEV_MAX) { | 440 | if (rtc->id >= RTC_DEV_MAX) { |
| 407 | dev_err(class_dev->dev, "too many RTCs\n"); | 441 | pr_debug("%s: too many RTC devices\n", rtc->name); |
| 408 | return -EINVAL; | 442 | return; |
| 409 | } | 443 | } |
| 410 | 444 | ||
| 445 | rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); | ||
| 446 | |||
| 411 | mutex_init(&rtc->char_lock); | 447 | mutex_init(&rtc->char_lock); |
| 412 | spin_lock_init(&rtc->irq_lock); | 448 | spin_lock_init(&rtc->irq_lock); |
| 413 | init_waitqueue_head(&rtc->irq_queue); | 449 | init_waitqueue_head(&rtc->irq_queue); |
| @@ -418,100 +454,36 @@ static int rtc_dev_add_device(struct class_device *class_dev, | |||
| 418 | 454 | ||
| 419 | cdev_init(&rtc->char_dev, &rtc_dev_fops); | 455 | cdev_init(&rtc->char_dev, &rtc_dev_fops); |
| 420 | rtc->char_dev.owner = rtc->owner; | 456 | rtc->char_dev.owner = rtc->owner; |
| 457 | } | ||
| 421 | 458 | ||
| 422 | if (cdev_add(&rtc->char_dev, MKDEV(MAJOR(rtc_devt), rtc->id), 1)) { | 459 | void rtc_dev_add_device(struct rtc_device *rtc) |
| 423 | dev_err(class_dev->dev, | 460 | { |
| 424 | "failed to add char device %d:%d\n", | 461 | if (cdev_add(&rtc->char_dev, rtc->dev.devt, 1)) |
| 462 | printk(KERN_WARNING "%s: failed to add char device %d:%d\n", | ||
| 463 | rtc->name, MAJOR(rtc_devt), rtc->id); | ||
| 464 | else | ||
| 465 | pr_debug("%s: dev (%d:%d)\n", rtc->name, | ||
| 425 | MAJOR(rtc_devt), rtc->id); | 466 | MAJOR(rtc_devt), rtc->id); |
| 426 | return -ENODEV; | ||
| 427 | } | ||
| 428 | |||
| 429 | rtc->rtc_dev = class_device_create(rtc_dev_class, NULL, | ||
| 430 | MKDEV(MAJOR(rtc_devt), rtc->id), | ||
| 431 | class_dev->dev, "rtc%d", rtc->id); | ||
| 432 | if (IS_ERR(rtc->rtc_dev)) { | ||
| 433 | dev_err(class_dev->dev, "cannot create rtc_dev device\n"); | ||
| 434 | err = PTR_ERR(rtc->rtc_dev); | ||
| 435 | goto err_cdev_del; | ||
| 436 | } | ||
| 437 | |||
| 438 | dev_dbg(class_dev->dev, "rtc intf: dev (%d:%d)\n", | ||
| 439 | MAJOR(rtc->rtc_dev->devt), | ||
| 440 | MINOR(rtc->rtc_dev->devt)); | ||
| 441 | |||
| 442 | return 0; | ||
| 443 | |||
| 444 | err_cdev_del: | ||
| 445 | |||
| 446 | cdev_del(&rtc->char_dev); | ||
| 447 | return err; | ||
| 448 | } | 467 | } |
| 449 | 468 | ||
| 450 | static void rtc_dev_remove_device(struct class_device *class_dev, | 469 | void rtc_dev_del_device(struct rtc_device *rtc) |
| 451 | struct class_interface *class_intf) | ||
| 452 | { | 470 | { |
| 453 | struct rtc_device *rtc = to_rtc_device(class_dev); | 471 | if (rtc->dev.devt) |
| 454 | |||
| 455 | if (rtc->rtc_dev) { | ||
| 456 | dev_dbg(class_dev->dev, "removing char %d:%d\n", | ||
| 457 | MAJOR(rtc->rtc_dev->devt), | ||
| 458 | MINOR(rtc->rtc_dev->devt)); | ||
| 459 | |||
| 460 | class_device_unregister(rtc->rtc_dev); | ||
| 461 | cdev_del(&rtc->char_dev); | 472 | cdev_del(&rtc->char_dev); |
| 462 | } | ||
| 463 | } | 473 | } |
| 464 | 474 | ||
| 465 | /* interface registration */ | 475 | void __init rtc_dev_init(void) |
| 466 | |||
| 467 | static struct class_interface rtc_dev_interface = { | ||
| 468 | .add = &rtc_dev_add_device, | ||
| 469 | .remove = &rtc_dev_remove_device, | ||
| 470 | }; | ||
| 471 | |||
| 472 | static int __init rtc_dev_init(void) | ||
| 473 | { | 476 | { |
| 474 | int err; | 477 | int err; |
| 475 | 478 | ||
| 476 | rtc_dev_class = class_create(THIS_MODULE, "rtc-dev"); | ||
| 477 | if (IS_ERR(rtc_dev_class)) | ||
| 478 | return PTR_ERR(rtc_dev_class); | ||
| 479 | |||
| 480 | err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc"); | 479 | err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc"); |
| 481 | if (err < 0) { | 480 | if (err < 0) |
| 482 | printk(KERN_ERR "%s: failed to allocate char dev region\n", | 481 | printk(KERN_ERR "%s: failed to allocate char dev region\n", |
| 483 | __FILE__); | 482 | __FILE__); |
| 484 | goto err_destroy_class; | ||
| 485 | } | ||
| 486 | |||
| 487 | err = rtc_interface_register(&rtc_dev_interface); | ||
| 488 | if (err < 0) { | ||
| 489 | printk(KERN_ERR "%s: failed to register the interface\n", | ||
| 490 | __FILE__); | ||
| 491 | goto err_unregister_chrdev; | ||
| 492 | } | ||
| 493 | |||
| 494 | return 0; | ||
| 495 | |||
| 496 | err_unregister_chrdev: | ||
| 497 | unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); | ||
| 498 | |||
| 499 | err_destroy_class: | ||
| 500 | class_destroy(rtc_dev_class); | ||
| 501 | |||
| 502 | return err; | ||
| 503 | } | 483 | } |
| 504 | 484 | ||
| 505 | static void __exit rtc_dev_exit(void) | 485 | void __exit rtc_dev_exit(void) |
| 506 | { | 486 | { |
| 507 | class_interface_unregister(&rtc_dev_interface); | 487 | if (rtc_devt) |
| 508 | class_destroy(rtc_dev_class); | 488 | unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); |
| 509 | unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); | ||
| 510 | } | 489 | } |
| 511 | |||
| 512 | subsys_initcall(rtc_dev_init); | ||
| 513 | module_exit(rtc_dev_exit); | ||
| 514 | |||
| 515 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 516 | MODULE_DESCRIPTION("RTC class dev interface"); | ||
| 517 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index e27176c0e18f..afa64c7fa2e2 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
| @@ -203,7 +203,7 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id) | |||
| 203 | events |= RTC_UF; | 203 | events |= RTC_UF; |
| 204 | else | 204 | else |
| 205 | events |= RTC_AF; | 205 | events |= RTC_AF; |
| 206 | rtc_update_irq(&pdata->rtc->class_dev, 1, events); | 206 | rtc_update_irq(pdata->rtc, 1, events); |
| 207 | return IRQ_HANDLED; | 207 | return IRQ_HANDLED; |
| 208 | } | 208 | } |
| 209 | 209 | ||
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index 7bbc26a34bd2..ba795a4db1e9 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
| @@ -117,85 +117,4 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | |||
| 117 | } | 117 | } |
| 118 | EXPORT_SYMBOL(rtc_tm_to_time); | 118 | EXPORT_SYMBOL(rtc_tm_to_time); |
| 119 | 119 | ||
| 120 | |||
| 121 | /* Merge the valid (i.e. non-negative) fields of alarm into the current | ||
| 122 | * time. If the valid alarm fields are earlier than the equivalent | ||
| 123 | * fields in the time, carry one into the least significant invalid | ||
| 124 | * field, so that the alarm expiry is in the future. It assumes that the | ||
| 125 | * least significant invalid field is more significant than the most | ||
| 126 | * significant valid field, and that the seconds field is valid. | ||
| 127 | * | ||
| 128 | * This is used by alarms that take relative (rather than absolute) | ||
| 129 | * times, and/or have a simple binary second counter instead of | ||
| 130 | * day/hour/minute/sec registers. | ||
| 131 | */ | ||
| 132 | void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm) | ||
| 133 | { | ||
| 134 | int *alarmp = &alarm->tm_sec; | ||
| 135 | int *timep = &now->tm_sec; | ||
| 136 | int carry_into, i; | ||
| 137 | |||
| 138 | /* Ignore everything past the 6th element (tm_year). */ | ||
| 139 | for (i = 5; i > 0; i--) { | ||
| 140 | if (alarmp[i] < 0) | ||
| 141 | alarmp[i] = timep[i]; | ||
| 142 | else | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* No carry needed if all fields are valid. */ | ||
| 147 | if (i == 5) | ||
| 148 | return; | ||
| 149 | |||
| 150 | for (carry_into = i + 1; i >= 0; i--) { | ||
| 151 | if (alarmp[i] < timep[i]) | ||
| 152 | break; | ||
| 153 | |||
| 154 | if (alarmp[i] > timep[i]) | ||
| 155 | return; | ||
| 156 | } | ||
| 157 | |||
| 158 | switch (carry_into) { | ||
| 159 | case 1: | ||
| 160 | alarm->tm_min++; | ||
| 161 | |||
| 162 | if (alarm->tm_min < 60) | ||
| 163 | return; | ||
| 164 | |||
| 165 | alarm->tm_min = 0; | ||
| 166 | /* fall-through */ | ||
| 167 | |||
| 168 | case 2: | ||
| 169 | alarm->tm_hour++; | ||
| 170 | |||
| 171 | if (alarm->tm_hour < 60) | ||
| 172 | return; | ||
| 173 | |||
| 174 | alarm->tm_hour = 0; | ||
| 175 | /* fall-through */ | ||
| 176 | |||
| 177 | case 3: | ||
| 178 | alarm->tm_mday++; | ||
| 179 | |||
| 180 | if (alarm->tm_mday <= rtc_days_in_month[alarm->tm_mon]) | ||
| 181 | return; | ||
| 182 | |||
| 183 | alarm->tm_mday = 1; | ||
| 184 | /* fall-through */ | ||
| 185 | |||
| 186 | case 4: | ||
| 187 | alarm->tm_mon++; | ||
| 188 | |||
| 189 | if (alarm->tm_mon <= 12) | ||
| 190 | return; | ||
| 191 | |||
| 192 | alarm->tm_mon = 1; | ||
| 193 | /* fall-through */ | ||
| 194 | |||
| 195 | case 5: | ||
| 196 | alarm->tm_year++; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | EXPORT_SYMBOL(rtc_merge_alarm); | ||
| 200 | |||
| 201 | MODULE_LICENSE("GPL"); | 120 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c new file mode 100644 index 000000000000..eee4ee5bb75a --- /dev/null +++ b/drivers/rtc/rtc-max6900.c | |||
| @@ -0,0 +1,311 @@ | |||
| 1 | /* | ||
| 2 | * rtc class driver for the Maxim MAX6900 chip | ||
| 3 | * | ||
| 4 | * Author: Dale Farnsworth <dale@farnsworth.org> | ||
| 5 | * | ||
| 6 | * based on previously existing rtc class drivers | ||
| 7 | * | ||
| 8 | * 2007 (c) MontaVista, Software, Inc. This file is licensed under | ||
| 9 | * the terms of the GNU General Public License version 2. This program | ||
| 10 | * is licensed "as is" without any warranty of any kind, whether express | ||
| 11 | * or implied. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/i2c.h> | ||
| 16 | #include <linux/bcd.h> | ||
| 17 | #include <linux/rtc.h> | ||
| 18 | #include <linux/delay.h> | ||
| 19 | |||
| 20 | #define DRV_NAME "max6900" | ||
| 21 | #define DRV_VERSION "0.1" | ||
| 22 | |||
| 23 | /* | ||
| 24 | * register indices | ||
| 25 | */ | ||
| 26 | #define MAX6900_REG_SC 0 /* seconds 00-59 */ | ||
| 27 | #define MAX6900_REG_MN 1 /* minutes 00-59 */ | ||
| 28 | #define MAX6900_REG_HR 2 /* hours 00-23 */ | ||
| 29 | #define MAX6900_REG_DT 3 /* day of month 00-31 */ | ||
| 30 | #define MAX6900_REG_MO 4 /* month 01-12 */ | ||
| 31 | #define MAX6900_REG_DW 5 /* day of week 1-7 */ | ||
| 32 | #define MAX6900_REG_YR 6 /* year 00-99 */ | ||
| 33 | #define MAX6900_REG_CT 7 /* control */ | ||
| 34 | #define MAX6900_REG_LEN 8 | ||
| 35 | |||
| 36 | #define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */ | ||
| 37 | |||
| 38 | /* | ||
| 39 | * register read/write commands | ||
| 40 | */ | ||
| 41 | #define MAX6900_REG_CONTROL_WRITE 0x8e | ||
| 42 | #define MAX6900_REG_BURST_READ 0xbf | ||
| 43 | #define MAX6900_REG_BURST_WRITE 0xbe | ||
| 44 | #define MAX6900_REG_RESERVED_READ 0x96 | ||
| 45 | |||
| 46 | #define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ | ||
| 47 | |||
| 48 | #define MAX6900_I2C_ADDR 0xa0 | ||
| 49 | |||
| 50 | static unsigned short normal_i2c[] = { | ||
| 51 | MAX6900_I2C_ADDR >> 1, | ||
| 52 | I2C_CLIENT_END | ||
| 53 | }; | ||
| 54 | |||
| 55 | I2C_CLIENT_INSMOD; /* defines addr_data */ | ||
| 56 | |||
| 57 | static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind); | ||
| 58 | |||
| 59 | static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) | ||
| 60 | { | ||
| 61 | u8 reg_addr[1] = { MAX6900_REG_BURST_READ }; | ||
| 62 | struct i2c_msg msgs[2] = { | ||
| 63 | { | ||
| 64 | .addr = client->addr, | ||
| 65 | .flags = 0, /* write */ | ||
| 66 | .len = sizeof(reg_addr), | ||
| 67 | .buf = reg_addr | ||
| 68 | }, | ||
| 69 | { | ||
| 70 | .addr = client->addr, | ||
| 71 | .flags = I2C_M_RD, | ||
| 72 | .len = MAX6900_REG_LEN, | ||
| 73 | .buf = buf | ||
| 74 | } | ||
| 75 | }; | ||
| 76 | int rc; | ||
| 77 | |||
| 78 | rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 79 | if (rc != ARRAY_SIZE(msgs)) { | ||
| 80 | dev_err(&client->dev, "%s: register read failed\n", | ||
| 81 | __FUNCTION__); | ||
| 82 | return -EIO; | ||
| 83 | } | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | ||
| 88 | { | ||
| 89 | u8 i2c_buf[MAX6900_REG_LEN + 1] = { MAX6900_REG_BURST_WRITE }; | ||
| 90 | struct i2c_msg msgs[1] = { | ||
| 91 | { | ||
| 92 | .addr = client->addr, | ||
| 93 | .flags = 0, /* write */ | ||
| 94 | .len = MAX6900_REG_LEN + 1, | ||
| 95 | .buf = i2c_buf | ||
| 96 | } | ||
| 97 | }; | ||
| 98 | int rc; | ||
| 99 | |||
| 100 | memcpy(&i2c_buf[1], buf, MAX6900_REG_LEN); | ||
| 101 | |||
| 102 | rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 103 | if (rc != ARRAY_SIZE(msgs)) { | ||
| 104 | dev_err(&client->dev, "%s: register write failed\n", | ||
| 105 | __FUNCTION__); | ||
| 106 | return -EIO; | ||
| 107 | } | ||
| 108 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | static int max6900_i2c_validate_client(struct i2c_client *client) | ||
| 113 | { | ||
| 114 | u8 regs[MAX6900_REG_LEN]; | ||
| 115 | u8 zero_mask[MAX6900_REG_LEN] = { | ||
| 116 | 0x80, /* seconds */ | ||
| 117 | 0x80, /* minutes */ | ||
| 118 | 0x40, /* hours */ | ||
| 119 | 0xc0, /* day of month */ | ||
| 120 | 0xe0, /* month */ | ||
| 121 | 0xf8, /* day of week */ | ||
| 122 | 0x00, /* year */ | ||
| 123 | 0x7f, /* control */ | ||
| 124 | }; | ||
| 125 | int i; | ||
| 126 | int rc; | ||
| 127 | int reserved; | ||
| 128 | |||
| 129 | reserved = i2c_smbus_read_byte_data(client, MAX6900_REG_RESERVED_READ); | ||
| 130 | if (reserved != 0x07) | ||
| 131 | return -ENODEV; | ||
| 132 | |||
| 133 | rc = max6900_i2c_read_regs(client, regs); | ||
| 134 | if (rc < 0) | ||
| 135 | return rc; | ||
| 136 | |||
| 137 | for (i = 0; i < MAX6900_REG_LEN; ++i) { | ||
| 138 | if (regs[i] & zero_mask[i]) | ||
| 139 | return -ENODEV; | ||
| 140 | } | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | ||
| 146 | { | ||
| 147 | int rc; | ||
| 148 | u8 regs[MAX6900_REG_LEN]; | ||
| 149 | |||
| 150 | rc = max6900_i2c_read_regs(client, regs); | ||
| 151 | if (rc < 0) | ||
| 152 | return rc; | ||
| 153 | |||
| 154 | tm->tm_sec = BCD2BIN(regs[MAX6900_REG_SC]); | ||
| 155 | tm->tm_min = BCD2BIN(regs[MAX6900_REG_MN]); | ||
| 156 | tm->tm_hour = BCD2BIN(regs[MAX6900_REG_HR] & 0x3f); | ||
| 157 | tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]); | ||
| 158 | tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1; | ||
| 159 | tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) + 100; | ||
| 160 | tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]); | ||
| 161 | |||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) | ||
| 166 | { | ||
| 167 | int rc; | ||
| 168 | rc = i2c_smbus_write_byte_data (client, MAX6900_REG_CONTROL_WRITE, 0); | ||
| 169 | if (rc < 0) { | ||
| 170 | dev_err(&client->dev, "%s: control register write failed\n", | ||
| 171 | __FUNCTION__); | ||
| 172 | return -EIO; | ||
| 173 | } | ||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | static int max6900_i2c_set_time(struct i2c_client *client, | ||
| 178 | struct rtc_time const *tm) | ||
| 179 | { | ||
| 180 | u8 regs[MAX6900_REG_LEN]; | ||
| 181 | int rc; | ||
| 182 | |||
| 183 | rc = max6900_i2c_clear_write_protect(client); | ||
| 184 | if (rc < 0) | ||
| 185 | return rc; | ||
| 186 | |||
| 187 | regs[MAX6900_REG_SC] = BIN2BCD(tm->tm_sec); | ||
| 188 | regs[MAX6900_REG_MN] = BIN2BCD(tm->tm_min); | ||
| 189 | regs[MAX6900_REG_HR] = BIN2BCD(tm->tm_hour); | ||
| 190 | regs[MAX6900_REG_DT] = BIN2BCD(tm->tm_mday); | ||
| 191 | regs[MAX6900_REG_MO] = BIN2BCD(tm->tm_mon + 1); | ||
| 192 | regs[MAX6900_REG_YR] = BIN2BCD(tm->tm_year - 100); | ||
| 193 | regs[MAX6900_REG_DW] = BIN2BCD(tm->tm_wday); | ||
| 194 | regs[MAX6900_REG_CT] = MAX6900_REG_CT_WP; /* set write protect */ | ||
| 195 | |||
| 196 | rc = max6900_i2c_write_regs(client, regs); | ||
| 197 | if (rc < 0) | ||
| 198 | return rc; | ||
| 199 | |||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | static int max6900_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 204 | { | ||
| 205 | return max6900_i2c_read_time(to_i2c_client(dev), tm); | ||
| 206 | } | ||
| 207 | |||
| 208 | static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 209 | { | ||
| 210 | return max6900_i2c_set_time(to_i2c_client(dev), tm); | ||
| 211 | } | ||
| 212 | |||
| 213 | static int max6900_attach_adapter(struct i2c_adapter *adapter) | ||
| 214 | { | ||
| 215 | return i2c_probe(adapter, &addr_data, max6900_probe); | ||
| 216 | } | ||
| 217 | |||
| 218 | static int max6900_detach_client(struct i2c_client *client) | ||
| 219 | { | ||
| 220 | struct rtc_device *const rtc = i2c_get_clientdata(client); | ||
| 221 | |||
| 222 | if (rtc) | ||
| 223 | rtc_device_unregister(rtc); | ||
| 224 | |||
| 225 | return i2c_detach_client(client); | ||
| 226 | } | ||
| 227 | |||
| 228 | static struct i2c_driver max6900_driver = { | ||
| 229 | .driver = { | ||
| 230 | .name = DRV_NAME, | ||
| 231 | }, | ||
| 232 | .id = I2C_DRIVERID_MAX6900, | ||
| 233 | .attach_adapter = max6900_attach_adapter, | ||
| 234 | .detach_client = max6900_detach_client, | ||
| 235 | }; | ||
| 236 | |||
| 237 | static const struct rtc_class_ops max6900_rtc_ops = { | ||
| 238 | .read_time = max6900_rtc_read_time, | ||
| 239 | .set_time = max6900_rtc_set_time, | ||
| 240 | }; | ||
| 241 | |||
| 242 | static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind) | ||
| 243 | { | ||
| 244 | int rc = 0; | ||
| 245 | struct i2c_client *client = NULL; | ||
| 246 | struct rtc_device *rtc = NULL; | ||
| 247 | |||
| 248 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
| 249 | rc = -ENODEV; | ||
| 250 | goto failout; | ||
| 251 | } | ||
| 252 | |||
| 253 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
| 254 | if (client == NULL) { | ||
| 255 | rc = -ENOMEM; | ||
| 256 | goto failout; | ||
| 257 | } | ||
| 258 | |||
| 259 | client->addr = addr; | ||
| 260 | client->adapter = adapter; | ||
| 261 | client->driver = &max6900_driver; | ||
| 262 | strlcpy(client->name, DRV_NAME, I2C_NAME_SIZE); | ||
| 263 | |||
| 264 | if (kind < 0) { | ||
| 265 | rc = max6900_i2c_validate_client(client); | ||
| 266 | if (rc < 0) | ||
| 267 | goto failout; | ||
| 268 | } | ||
| 269 | |||
| 270 | rc = i2c_attach_client(client); | ||
| 271 | if (rc < 0) | ||
| 272 | goto failout; | ||
| 273 | |||
| 274 | dev_info(&client->dev, | ||
| 275 | "chip found, driver version " DRV_VERSION "\n"); | ||
| 276 | |||
| 277 | rtc = rtc_device_register(max6900_driver.driver.name, | ||
| 278 | &client->dev, | ||
| 279 | &max6900_rtc_ops, THIS_MODULE); | ||
| 280 | if (IS_ERR(rtc)) { | ||
| 281 | rc = PTR_ERR(rtc); | ||
| 282 | goto failout_detach; | ||
| 283 | } | ||
| 284 | |||
| 285 | i2c_set_clientdata(client, rtc); | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | |||
| 289 | failout_detach: | ||
| 290 | i2c_detach_client(client); | ||
| 291 | failout: | ||
| 292 | kfree(client); | ||
| 293 | return rc; | ||
| 294 | } | ||
| 295 | |||
| 296 | static int __init max6900_init(void) | ||
| 297 | { | ||
| 298 | return i2c_add_driver(&max6900_driver); | ||
| 299 | } | ||
| 300 | |||
| 301 | static void __exit max6900_exit(void) | ||
| 302 | { | ||
| 303 | i2c_del_driver(&max6900_driver); | ||
| 304 | } | ||
| 305 | |||
| 306 | MODULE_DESCRIPTION("Maxim MAX6900 RTC driver"); | ||
| 307 | MODULE_LICENSE("GPL"); | ||
| 308 | MODULE_VERSION(DRV_VERSION); | ||
| 309 | |||
| 310 | module_init(max6900_init); | ||
| 311 | module_exit(max6900_exit); | ||
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 9de8d67f4f8d..60a8a4bb8bd2 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
| @@ -124,7 +124,7 @@ static void rtc_wait_not_busy(void) | |||
| 124 | /* now we have ~15 usec to read/write various registers */ | 124 | /* now we have ~15 usec to read/write various registers */ |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static irqreturn_t rtc_irq(int irq, void *class_dev) | 127 | static irqreturn_t rtc_irq(int irq, void *rtc) |
| 128 | { | 128 | { |
| 129 | unsigned long events = 0; | 129 | unsigned long events = 0; |
| 130 | u8 irq_data; | 130 | u8 irq_data; |
| @@ -141,7 +141,7 @@ static irqreturn_t rtc_irq(int irq, void *class_dev) | |||
| 141 | if (irq_data & OMAP_RTC_STATUS_1S_EVENT) | 141 | if (irq_data & OMAP_RTC_STATUS_1S_EVENT) |
| 142 | events |= RTC_IRQF | RTC_UF; | 142 | events |= RTC_IRQF | RTC_UF; |
| 143 | 143 | ||
| 144 | rtc_update_irq(class_dev, 1, events); | 144 | rtc_update_irq(rtc, 1, events); |
| 145 | 145 | ||
| 146 | return IRQ_HANDLED; | 146 | return IRQ_HANDLED; |
| 147 | } | 147 | } |
| @@ -289,34 +289,6 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
| 289 | { | 289 | { |
| 290 | u8 reg; | 290 | u8 reg; |
| 291 | 291 | ||
| 292 | /* Much userspace code uses RTC_ALM_SET, thus "don't care" for | ||
| 293 | * day/month/year specifies alarms up to 24 hours in the future. | ||
| 294 | * So we need to handle that ... but let's ignore the "don't care" | ||
| 295 | * values for hours/minutes/seconds. | ||
| 296 | */ | ||
| 297 | if (alm->time.tm_mday <= 0 | ||
| 298 | && alm->time.tm_mon < 0 | ||
| 299 | && alm->time.tm_year < 0) { | ||
| 300 | struct rtc_time tm; | ||
| 301 | unsigned long now, then; | ||
| 302 | |||
| 303 | omap_rtc_read_time(dev, &tm); | ||
| 304 | rtc_tm_to_time(&tm, &now); | ||
| 305 | |||
| 306 | alm->time.tm_mday = tm.tm_mday; | ||
| 307 | alm->time.tm_mon = tm.tm_mon; | ||
| 308 | alm->time.tm_year = tm.tm_year; | ||
| 309 | rtc_tm_to_time(&alm->time, &then); | ||
| 310 | |||
| 311 | /* sometimes the alarm wraps into tomorrow */ | ||
| 312 | if (then < now) { | ||
| 313 | rtc_time_to_tm(now + 24 * 60 * 60, &tm); | ||
| 314 | alm->time.tm_mday = tm.tm_mday; | ||
| 315 | alm->time.tm_mon = tm.tm_mon; | ||
| 316 | alm->time.tm_year = tm.tm_year; | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | if (tm2bcd(&alm->time) < 0) | 292 | if (tm2bcd(&alm->time) < 0) |
| 321 | return -EINVAL; | 293 | return -EINVAL; |
| 322 | 294 | ||
| @@ -399,7 +371,7 @@ static int __devinit omap_rtc_probe(struct platform_device *pdev) | |||
| 399 | goto fail; | 371 | goto fail; |
| 400 | } | 372 | } |
| 401 | platform_set_drvdata(pdev, rtc); | 373 | platform_set_drvdata(pdev, rtc); |
| 402 | class_set_devdata(&rtc->class_dev, mem); | 374 | dev_set_devdata(&rtc->dev, mem); |
| 403 | 375 | ||
| 404 | /* clear pending irqs, and set 1/second periodic, | 376 | /* clear pending irqs, and set 1/second periodic, |
| 405 | * which we'll use instead of update irqs | 377 | * which we'll use instead of update irqs |
| @@ -418,13 +390,13 @@ static int __devinit omap_rtc_probe(struct platform_device *pdev) | |||
| 418 | 390 | ||
| 419 | /* handle periodic and alarm irqs */ | 391 | /* handle periodic and alarm irqs */ |
| 420 | if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED, | 392 | if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED, |
| 421 | rtc->class_dev.class_id, &rtc->class_dev)) { | 393 | rtc->dev.bus_id, rtc)) { |
| 422 | pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", | 394 | pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", |
| 423 | pdev->name, omap_rtc_timer); | 395 | pdev->name, omap_rtc_timer); |
| 424 | goto fail0; | 396 | goto fail0; |
| 425 | } | 397 | } |
| 426 | if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, | 398 | if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, |
| 427 | rtc->class_dev.class_id, &rtc->class_dev)) { | 399 | rtc->dev.bus_id, rtc)) { |
| 428 | pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", | 400 | pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", |
| 429 | pdev->name, omap_rtc_alarm); | 401 | pdev->name, omap_rtc_alarm); |
| 430 | goto fail1; | 402 | goto fail1; |
| @@ -481,26 +453,17 @@ static int __devexit omap_rtc_remove(struct platform_device *pdev) | |||
| 481 | free_irq(omap_rtc_timer, rtc); | 453 | free_irq(omap_rtc_timer, rtc); |
| 482 | free_irq(omap_rtc_alarm, rtc); | 454 | free_irq(omap_rtc_alarm, rtc); |
| 483 | 455 | ||
| 484 | release_resource(class_get_devdata(&rtc->class_dev)); | 456 | release_resource(dev_get_devdata(&rtc->dev)); |
| 485 | rtc_device_unregister(rtc); | 457 | rtc_device_unregister(rtc); |
| 486 | return 0; | 458 | return 0; |
| 487 | } | 459 | } |
| 488 | 460 | ||
| 489 | #ifdef CONFIG_PM | 461 | #ifdef CONFIG_PM |
| 490 | 462 | ||
| 491 | static struct timespec rtc_delta; | ||
| 492 | static u8 irqstat; | 463 | static u8 irqstat; |
| 493 | 464 | ||
| 494 | static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 465 | static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
| 495 | { | 466 | { |
| 496 | struct rtc_time rtc_tm; | ||
| 497 | struct timespec time; | ||
| 498 | |||
| 499 | time.tv_nsec = 0; | ||
| 500 | omap_rtc_read_time(NULL, &rtc_tm); | ||
| 501 | rtc_tm_to_time(&rtc_tm, &time.tv_sec); | ||
| 502 | |||
| 503 | save_time_delta(&rtc_delta, &time); | ||
| 504 | irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); | 467 | irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); |
| 505 | 468 | ||
| 506 | /* FIXME the RTC alarm is not currently acting as a wakeup event | 469 | /* FIXME the RTC alarm is not currently acting as a wakeup event |
| @@ -517,14 +480,6 @@ static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 517 | 480 | ||
| 518 | static int omap_rtc_resume(struct platform_device *pdev) | 481 | static int omap_rtc_resume(struct platform_device *pdev) |
| 519 | { | 482 | { |
| 520 | struct rtc_time rtc_tm; | ||
| 521 | struct timespec time; | ||
| 522 | |||
| 523 | time.tv_nsec = 0; | ||
| 524 | omap_rtc_read_time(NULL, &rtc_tm); | ||
| 525 | rtc_tm_to_time(&rtc_tm, &time.tv_sec); | ||
| 526 | |||
| 527 | restore_time_delta(&rtc_delta, &time); | ||
| 528 | if (device_may_wakeup(&pdev->dev)) | 483 | if (device_may_wakeup(&pdev->dev)) |
| 529 | disable_irq_wake(omap_rtc_alarm); | 484 | disable_irq_wake(omap_rtc_alarm); |
| 530 | else | 485 | else |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index f13daa9fecaa..e4bf68ca96f7 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
| @@ -51,7 +51,7 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id) | |||
| 51 | { | 51 | { |
| 52 | struct rtc_device *rtc = dev_id; | 52 | struct rtc_device *rtc = dev_id; |
| 53 | 53 | ||
| 54 | rtc_update_irq(&rtc->class_dev, 1, RTC_AF); | 54 | rtc_update_irq(rtc, 1, RTC_AF); |
| 55 | 55 | ||
| 56 | return IRQ_HANDLED; | 56 | return IRQ_HANDLED; |
| 57 | } | 57 | } |
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c index 1bd624fc685c..8d300e6d0d9e 100644 --- a/drivers/rtc/rtc-proc.c +++ b/drivers/rtc/rtc-proc.c | |||
| @@ -16,18 +16,18 @@ | |||
| 16 | #include <linux/proc_fs.h> | 16 | #include <linux/proc_fs.h> |
| 17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
| 18 | 18 | ||
| 19 | static struct class_device *rtc_dev = NULL; | 19 | #include "rtc-core.h" |
| 20 | static DEFINE_MUTEX(rtc_lock); | 20 | |
| 21 | 21 | ||
| 22 | static int rtc_proc_show(struct seq_file *seq, void *offset) | 22 | static int rtc_proc_show(struct seq_file *seq, void *offset) |
| 23 | { | 23 | { |
| 24 | int err; | 24 | int err; |
| 25 | struct class_device *class_dev = seq->private; | 25 | struct rtc_device *rtc = seq->private; |
| 26 | const struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops; | 26 | const struct rtc_class_ops *ops = rtc->ops; |
| 27 | struct rtc_wkalrm alrm; | 27 | struct rtc_wkalrm alrm; |
| 28 | struct rtc_time tm; | 28 | struct rtc_time tm; |
| 29 | 29 | ||
| 30 | err = rtc_read_time(class_dev, &tm); | 30 | err = rtc_read_time(rtc, &tm); |
| 31 | if (err == 0) { | 31 | if (err == 0) { |
| 32 | seq_printf(seq, | 32 | seq_printf(seq, |
| 33 | "rtc_time\t: %02d:%02d:%02d\n" | 33 | "rtc_time\t: %02d:%02d:%02d\n" |
| @@ -36,7 +36,7 @@ static int rtc_proc_show(struct seq_file *seq, void *offset) | |||
| 36 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | 36 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | err = rtc_read_alarm(class_dev, &alrm); | 39 | err = rtc_read_alarm(rtc, &alrm); |
| 40 | if (err == 0) { | 40 | if (err == 0) { |
| 41 | seq_printf(seq, "alrm_time\t: "); | 41 | seq_printf(seq, "alrm_time\t: "); |
| 42 | if ((unsigned int)alrm.time.tm_hour <= 24) | 42 | if ((unsigned int)alrm.time.tm_hour <= 24) |
| @@ -74,19 +74,19 @@ static int rtc_proc_show(struct seq_file *seq, void *offset) | |||
| 74 | seq_printf(seq, "24hr\t\t: yes\n"); | 74 | seq_printf(seq, "24hr\t\t: yes\n"); |
| 75 | 75 | ||
| 76 | if (ops->proc) | 76 | if (ops->proc) |
| 77 | ops->proc(class_dev->dev, seq); | 77 | ops->proc(rtc->dev.parent, seq); |
| 78 | 78 | ||
| 79 | return 0; | 79 | return 0; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static int rtc_proc_open(struct inode *inode, struct file *file) | 82 | static int rtc_proc_open(struct inode *inode, struct file *file) |
| 83 | { | 83 | { |
| 84 | struct class_device *class_dev = PDE(inode)->data; | 84 | struct rtc_device *rtc = PDE(inode)->data; |
| 85 | 85 | ||
| 86 | if (!try_module_get(THIS_MODULE)) | 86 | if (!try_module_get(THIS_MODULE)) |
| 87 | return -ENODEV; | 87 | return -ENODEV; |
| 88 | 88 | ||
| 89 | return single_open(file, rtc_proc_show, class_dev); | 89 | return single_open(file, rtc_proc_show, rtc); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | static int rtc_proc_release(struct inode *inode, struct file *file) | 92 | static int rtc_proc_release(struct inode *inode, struct file *file) |
| @@ -103,62 +103,22 @@ static const struct file_operations rtc_proc_fops = { | |||
| 103 | .release = rtc_proc_release, | 103 | .release = rtc_proc_release, |
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | static int rtc_proc_add_device(struct class_device *class_dev, | 106 | void rtc_proc_add_device(struct rtc_device *rtc) |
| 107 | struct class_interface *class_intf) | ||
| 108 | { | 107 | { |
| 109 | mutex_lock(&rtc_lock); | 108 | if (rtc->id == 0) { |
| 110 | if (rtc_dev == NULL) { | ||
| 111 | struct proc_dir_entry *ent; | 109 | struct proc_dir_entry *ent; |
| 112 | 110 | ||
| 113 | rtc_dev = class_dev; | ||
| 114 | |||
| 115 | ent = create_proc_entry("driver/rtc", 0, NULL); | 111 | ent = create_proc_entry("driver/rtc", 0, NULL); |
| 116 | if (ent) { | 112 | if (ent) { |
| 117 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 118 | |||
| 119 | ent->proc_fops = &rtc_proc_fops; | 113 | ent->proc_fops = &rtc_proc_fops; |
| 120 | ent->owner = rtc->owner; | 114 | ent->owner = rtc->owner; |
| 121 | ent->data = class_dev; | 115 | ent->data = rtc; |
| 122 | |||
| 123 | dev_dbg(class_dev->dev, "rtc intf: proc\n"); | ||
| 124 | } | 116 | } |
| 125 | else | ||
| 126 | rtc_dev = NULL; | ||
| 127 | } | 117 | } |
| 128 | mutex_unlock(&rtc_lock); | ||
| 129 | |||
| 130 | return 0; | ||
| 131 | } | 118 | } |
| 132 | 119 | ||
| 133 | static void rtc_proc_remove_device(struct class_device *class_dev, | 120 | void rtc_proc_del_device(struct rtc_device *rtc) |
| 134 | struct class_interface *class_intf) | ||
| 135 | { | 121 | { |
| 136 | mutex_lock(&rtc_lock); | 122 | if (rtc->id == 0) |
| 137 | if (rtc_dev == class_dev) { | ||
| 138 | remove_proc_entry("driver/rtc", NULL); | 123 | remove_proc_entry("driver/rtc", NULL); |
| 139 | rtc_dev = NULL; | ||
| 140 | } | ||
| 141 | mutex_unlock(&rtc_lock); | ||
| 142 | } | ||
| 143 | |||
| 144 | static struct class_interface rtc_proc_interface = { | ||
| 145 | .add = &rtc_proc_add_device, | ||
| 146 | .remove = &rtc_proc_remove_device, | ||
| 147 | }; | ||
| 148 | |||
| 149 | static int __init rtc_proc_init(void) | ||
| 150 | { | ||
| 151 | return rtc_interface_register(&rtc_proc_interface); | ||
| 152 | } | 124 | } |
| 153 | |||
| 154 | static void __exit rtc_proc_exit(void) | ||
| 155 | { | ||
| 156 | class_interface_unregister(&rtc_proc_interface); | ||
| 157 | } | ||
| 158 | |||
| 159 | subsys_initcall(rtc_proc_init); | ||
| 160 | module_exit(rtc_proc_exit); | ||
| 161 | |||
| 162 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 163 | MODULE_DESCRIPTION("RTC class proc interface"); | ||
| 164 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c new file mode 100644 index 000000000000..9d6de371495b --- /dev/null +++ b/drivers/rtc/rtc-rs5c313.c | |||
| @@ -0,0 +1,405 @@ | |||
| 1 | /* | ||
| 2 | * Ricoh RS5C313 RTC device/driver | ||
| 3 | * Copyright (C) 2007 Nobuhiro Iwamatsu | ||
| 4 | * | ||
| 5 | * 2005-09-19 modifed by kogiidena | ||
| 6 | * | ||
| 7 | * Based on the old drivers/char/rs5c313_rtc.c by: | ||
| 8 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> | ||
| 9 | * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka | ||
| 10 | * | ||
| 11 | * Based on code written by Paul Gortmaker. | ||
| 12 | * Copyright (C) 1996 Paul Gortmaker | ||
| 13 | * | ||
| 14 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 15 | * License. See the file "COPYING" in the main directory of this archive | ||
| 16 | * for more details. | ||
| 17 | * | ||
| 18 | * Based on other minimal char device drivers, like Alan's | ||
| 19 | * watchdog, Ted's random, etc. etc. | ||
| 20 | * | ||
| 21 | * 1.07 Paul Gortmaker. | ||
| 22 | * 1.08 Miquel van Smoorenburg: disallow certain things on the | ||
| 23 | * DEC Alpha as the CMOS clock is also used for other things. | ||
| 24 | * 1.09 Nikita Schmidt: epoch support and some Alpha cleanup. | ||
| 25 | * 1.09a Pete Zaitcev: Sun SPARC | ||
| 26 | * 1.09b Jeff Garzik: Modularize, init cleanup | ||
| 27 | * 1.09c Jeff Garzik: SMP cleanup | ||
| 28 | * 1.10 Paul Barton-Davis: add support for async I/O | ||
| 29 | * 1.10a Andrea Arcangeli: Alpha updates | ||
| 30 | * 1.10b Andrew Morton: SMP lock fix | ||
| 31 | * 1.10c Cesar Barros: SMP locking fixes and cleanup | ||
| 32 | * 1.10d Paul Gortmaker: delete paranoia check in rtc_exit | ||
| 33 | * 1.10e Maciej W. Rozycki: Handle DECstation's year weirdness. | ||
| 34 | * 1.11 Takashi Iwai: Kernel access functions | ||
| 35 | * rtc_register/rtc_unregister/rtc_control | ||
| 36 | * 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init | ||
| 37 | * 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer | ||
| 38 | * CONFIG_HPET_EMULATE_RTC | ||
| 39 | * 1.13 Nobuhiro Iwamatsu: Updata driver. | ||
| 40 | */ | ||
| 41 | |||
| 42 | #include <linux/module.h> | ||
| 43 | #include <linux/err.h> | ||
| 44 | #include <linux/rtc.h> | ||
| 45 | #include <linux/platform_device.h> | ||
| 46 | #include <linux/bcd.h> | ||
| 47 | #include <linux/delay.h> | ||
| 48 | #include <asm/io.h> | ||
| 49 | |||
| 50 | #define DRV_NAME "rs5c313" | ||
| 51 | #define DRV_VERSION "1.13" | ||
| 52 | |||
| 53 | #ifdef CONFIG_SH_LANDISK | ||
| 54 | /*****************************************************/ | ||
| 55 | /* LANDISK dependence part of RS5C313 */ | ||
| 56 | /*****************************************************/ | ||
| 57 | |||
| 58 | #define SCSMR1 0xFFE00000 | ||
| 59 | #define SCSCR1 0xFFE00008 | ||
| 60 | #define SCSMR1_CA 0x80 | ||
| 61 | #define SCSCR1_CKE 0x03 | ||
| 62 | #define SCSPTR1 0xFFE0001C | ||
| 63 | #define SCSPTR1_EIO 0x80 | ||
| 64 | #define SCSPTR1_SPB1IO 0x08 | ||
| 65 | #define SCSPTR1_SPB1DT 0x04 | ||
| 66 | #define SCSPTR1_SPB0IO 0x02 | ||
| 67 | #define SCSPTR1_SPB0DT 0x01 | ||
| 68 | |||
| 69 | #define SDA_OEN SCSPTR1_SPB1IO | ||
| 70 | #define SDA SCSPTR1_SPB1DT | ||
| 71 | #define SCL_OEN SCSPTR1_SPB0IO | ||
| 72 | #define SCL SCSPTR1_SPB0DT | ||
| 73 | |||
| 74 | /* RICOH RS5C313 CE port */ | ||
| 75 | #define RS5C313_CE 0xB0000003 | ||
| 76 | |||
| 77 | /* RICOH RS5C313 CE port bit */ | ||
| 78 | #define RS5C313_CE_RTCCE 0x02 | ||
| 79 | |||
| 80 | /* SCSPTR1 data */ | ||
| 81 | unsigned char scsptr1_data; | ||
| 82 | |||
| 83 | #define RS5C313_CEENABLE ctrl_outb(RS5C313_CE_RTCCE, RS5C313_CE); | ||
| 84 | #define RS5C313_CEDISABLE ctrl_outb(0x00, RS5C313_CE) | ||
| 85 | #define RS5C313_MISCOP ctrl_outb(0x02, 0xB0000008) | ||
| 86 | |||
| 87 | static void rs5c313_init_port(void) | ||
| 88 | { | ||
| 89 | /* Set SCK as I/O port and Initialize SCSPTR1 data & I/O port. */ | ||
| 90 | ctrl_outb(ctrl_inb(SCSMR1) & ~SCSMR1_CA, SCSMR1); | ||
| 91 | ctrl_outb(ctrl_inb(SCSCR1) & ~SCSCR1_CKE, SCSCR1); | ||
| 92 | |||
| 93 | /* And Initialize SCL for RS5C313 clock */ | ||
| 94 | scsptr1_data = ctrl_inb(SCSPTR1) | SCL; /* SCL:H */ | ||
| 95 | ctrl_outb(scsptr1_data, SCSPTR1); | ||
| 96 | scsptr1_data = ctrl_inb(SCSPTR1) | SCL_OEN; /* SCL output enable */ | ||
| 97 | ctrl_outb(scsptr1_data, SCSPTR1); | ||
| 98 | RS5C313_CEDISABLE; /* CE:L */ | ||
| 99 | } | ||
| 100 | |||
| 101 | static void rs5c313_write_data(unsigned char data) | ||
| 102 | { | ||
| 103 | int i; | ||
| 104 | |||
| 105 | for (i = 0; i < 8; i++) { | ||
| 106 | /* SDA:Write Data */ | ||
| 107 | scsptr1_data = (scsptr1_data & ~SDA) | | ||
| 108 | ((((0x80 >> i) & data) >> (7 - i)) << 2); | ||
| 109 | ctrl_outb(scsptr1_data, SCSPTR1); | ||
| 110 | if (i == 0) { | ||
| 111 | scsptr1_data |= SDA_OEN; /* SDA:output enable */ | ||
| 112 | ctrl_outb(scsptr1_data, SCSPTR1); | ||
| 113 | } | ||
| 114 | ndelay(700); | ||
| 115 | scsptr1_data &= ~SCL; /* SCL:L */ | ||
| 116 | ctrl_outb(scsptr1_data, SCSPTR1); | ||
| 117 | ndelay(700); | ||
| 118 | scsptr1_data |= SCL; /* SCL:H */ | ||
| 119 | ctrl_outb(scsptr1_data, SCSPTR1); | ||
| 120 | } | ||
| 121 | |||
| 122 | scsptr1_data &= ~SDA_OEN; /* SDA:output disable */ | ||
| 123 | ctrl_outb(scsptr1_data, SCSPTR1); | ||
| 124 | } | ||
| 125 | |||
| 126 | static unsigned char rs5c313_read_data(void) | ||
| 127 | { | ||
| 128 | int i; | ||
| 129 | unsigned char data; | ||
| 130 | |||
| 131 | for (i = 0; i < 8; i++) { | ||
| 132 | ndelay(700); | ||
| 133 | /* SDA:Read Data */ | ||
| 134 | data |= ((ctrl_inb(SCSPTR1) & SDA) >> 2) << (7 - i); | ||
| 135 | scsptr1_data &= ~SCL; /* SCL:L */ | ||
| 136 | ctrl_outb(scsptr1_data, SCSPTR1); | ||
| 137 | ndelay(700); | ||
| 138 | scsptr1_data |= SCL; /* SCL:H */ | ||
| 139 | ctrl_outb(scsptr1_data, SCSPTR1); | ||
| 140 | } | ||
| 141 | return data & 0x0F; | ||
| 142 | } | ||
| 143 | |||
| 144 | #endif /* CONFIG_SH_LANDISK */ | ||
| 145 | |||
| 146 | /*****************************************************/ | ||
| 147 | /* machine independence part of RS5C313 */ | ||
| 148 | /*****************************************************/ | ||
| 149 | |||
| 150 | /* RICOH RS5C313 address */ | ||
| 151 | #define RS5C313_ADDR_SEC 0x00 | ||
| 152 | #define RS5C313_ADDR_SEC10 0x01 | ||
| 153 | #define RS5C313_ADDR_MIN 0x02 | ||
| 154 | #define RS5C313_ADDR_MIN10 0x03 | ||
| 155 | #define RS5C313_ADDR_HOUR 0x04 | ||
| 156 | #define RS5C313_ADDR_HOUR10 0x05 | ||
| 157 | #define RS5C313_ADDR_WEEK 0x06 | ||
| 158 | #define RS5C313_ADDR_INTINTVREG 0x07 | ||
| 159 | #define RS5C313_ADDR_DAY 0x08 | ||
| 160 | #define RS5C313_ADDR_DAY10 0x09 | ||
| 161 | #define RS5C313_ADDR_MON 0x0A | ||
| 162 | #define RS5C313_ADDR_MON10 0x0B | ||
| 163 | #define RS5C313_ADDR_YEAR 0x0C | ||
| 164 | #define RS5C313_ADDR_YEAR10 0x0D | ||
| 165 | #define RS5C313_ADDR_CNTREG 0x0E | ||
| 166 | #define RS5C313_ADDR_TESTREG 0x0F | ||
| 167 | |||
| 168 | /* RICOH RS5C313 control register */ | ||
| 169 | #define RS5C313_CNTREG_ADJ_BSY 0x01 | ||
| 170 | #define RS5C313_CNTREG_WTEN_XSTP 0x02 | ||
| 171 | #define RS5C313_CNTREG_12_24 0x04 | ||
| 172 | #define RS5C313_CNTREG_CTFG 0x08 | ||
| 173 | |||
| 174 | /* RICOH RS5C313 test register */ | ||
| 175 | #define RS5C313_TESTREG_TEST 0x01 | ||
| 176 | |||
| 177 | /* RICOH RS5C313 control bit */ | ||
| 178 | #define RS5C313_CNTBIT_READ 0x40 | ||
| 179 | #define RS5C313_CNTBIT_AD 0x20 | ||
| 180 | #define RS5C313_CNTBIT_DT 0x10 | ||
| 181 | |||
| 182 | static unsigned char rs5c313_read_reg(unsigned char addr) | ||
| 183 | { | ||
| 184 | |||
| 185 | rs5c313_write_data(addr | RS5C313_CNTBIT_READ | RS5C313_CNTBIT_AD); | ||
| 186 | return rs5c313_read_data(); | ||
| 187 | } | ||
| 188 | |||
| 189 | static void rs5c313_write_reg(unsigned char addr, unsigned char data) | ||
| 190 | { | ||
| 191 | data &= 0x0f; | ||
| 192 | rs5c313_write_data(addr | RS5C313_CNTBIT_AD); | ||
| 193 | rs5c313_write_data(data | RS5C313_CNTBIT_DT); | ||
| 194 | return; | ||
| 195 | } | ||
| 196 | |||
| 197 | static inline unsigned char rs5c313_read_cntreg(unsigned char addr) | ||
| 198 | { | ||
| 199 | return rs5c313_read_reg(RS5C313_ADDR_CNTREG); | ||
| 200 | } | ||
| 201 | |||
| 202 | static inline void rs5c313_write_cntreg(unsigned char data) | ||
| 203 | { | ||
| 204 | rs5c313_write_reg(RS5C313_ADDR_CNTREG, data); | ||
| 205 | } | ||
| 206 | |||
| 207 | static inline void rs5c313_write_intintvreg(unsigned char data) | ||
| 208 | { | ||
| 209 | rs5c313_write_reg(RS5C313_ADDR_INTINTVREG, data); | ||
| 210 | } | ||
| 211 | |||
| 212 | static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 213 | { | ||
| 214 | int data; | ||
| 215 | |||
| 216 | while (1) { | ||
| 217 | RS5C313_CEENABLE; /* CE:H */ | ||
| 218 | |||
| 219 | /* Initialize control reg. 24 hour */ | ||
| 220 | rs5c313_write_cntreg(0x04); | ||
| 221 | |||
| 222 | if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)) | ||
| 223 | break; | ||
| 224 | |||
| 225 | RS5C313_CEDISABLE; | ||
| 226 | ndelay(700); /* CE:L */ | ||
| 227 | |||
| 228 | } | ||
| 229 | |||
| 230 | data = rs5c313_read_reg(RS5C313_ADDR_SEC); | ||
| 231 | data |= (rs5c313_read_reg(RS5C313_ADDR_SEC10) << 4); | ||
| 232 | tm->tm_sec = BCD2BIN(data); | ||
| 233 | |||
| 234 | data = rs5c313_read_reg(RS5C313_ADDR_MIN); | ||
| 235 | data |= (rs5c313_read_reg(RS5C313_ADDR_MIN10) << 4); | ||
| 236 | tm->tm_min = BCD2BIN(data); | ||
| 237 | |||
| 238 | data = rs5c313_read_reg(RS5C313_ADDR_HOUR); | ||
| 239 | data |= (rs5c313_read_reg(RS5C313_ADDR_HOUR10) << 4); | ||
| 240 | tm->tm_hour = BCD2BIN(data); | ||
| 241 | |||
| 242 | data = rs5c313_read_reg(RS5C313_ADDR_DAY); | ||
| 243 | data |= (rs5c313_read_reg(RS5C313_ADDR_DAY10) << 4); | ||
| 244 | tm->tm_mday = BCD2BIN(data); | ||
| 245 | |||
| 246 | data = rs5c313_read_reg(RS5C313_ADDR_MON); | ||
| 247 | data |= (rs5c313_read_reg(RS5C313_ADDR_MON10) << 4); | ||
| 248 | tm->tm_mon = BCD2BIN(data) - 1; | ||
| 249 | |||
| 250 | data = rs5c313_read_reg(RS5C313_ADDR_YEAR); | ||
| 251 | data |= (rs5c313_read_reg(RS5C313_ADDR_YEAR10) << 4); | ||
| 252 | tm->tm_year = BCD2BIN(data); | ||
| 253 | |||
| 254 | if (tm->tm_year < 70) | ||
| 255 | tm->tm_year += 100; | ||
| 256 | |||
| 257 | data = rs5c313_read_reg(RS5C313_ADDR_WEEK); | ||
| 258 | tm->tm_wday = BCD2BIN(data); | ||
| 259 | |||
| 260 | RS5C313_CEDISABLE; | ||
| 261 | ndelay(700); /* CE:L */ | ||
| 262 | |||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | |||
| 266 | static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 267 | { | ||
| 268 | int data; | ||
| 269 | |||
| 270 | /* busy check. */ | ||
| 271 | while (1) { | ||
| 272 | RS5C313_CEENABLE; /* CE:H */ | ||
| 273 | |||
| 274 | /* Initiatlize control reg. 24 hour */ | ||
| 275 | rs5c313_write_cntreg(0x04); | ||
| 276 | |||
| 277 | if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)) | ||
| 278 | break; | ||
| 279 | RS5C313_MISCOP; | ||
| 280 | RS5C313_CEDISABLE; | ||
| 281 | ndelay(700); /* CE:L */ | ||
| 282 | } | ||
| 283 | |||
| 284 | data = BIN2BCD(tm->tm_sec); | ||
| 285 | rs5c313_write_reg(RS5C313_ADDR_SEC, data); | ||
| 286 | rs5c313_write_reg(RS5C313_ADDR_SEC10, (data >> 4)); | ||
| 287 | |||
| 288 | data = BIN2BCD(tm->tm_min); | ||
| 289 | rs5c313_write_reg(RS5C313_ADDR_MIN, data ); | ||
| 290 | rs5c313_write_reg(RS5C313_ADDR_MIN10, (data >> 4)); | ||
| 291 | |||
| 292 | data = BIN2BCD(tm->tm_hour); | ||
| 293 | rs5c313_write_reg(RS5C313_ADDR_HOUR, data); | ||
| 294 | rs5c313_write_reg(RS5C313_ADDR_HOUR10, (data >> 4)); | ||
| 295 | |||
| 296 | data = BIN2BCD(tm->tm_mday); | ||
| 297 | rs5c313_write_reg(RS5C313_ADDR_DAY, data); | ||
| 298 | rs5c313_write_reg(RS5C313_ADDR_DAY10, (data>> 4)); | ||
| 299 | |||
| 300 | data = BIN2BCD(tm->tm_mon + 1); | ||
| 301 | rs5c313_write_reg(RS5C313_ADDR_MON, data); | ||
| 302 | rs5c313_write_reg(RS5C313_ADDR_MON10, (data >> 4)); | ||
| 303 | |||
| 304 | data = BIN2BCD(tm->tm_year % 100); | ||
| 305 | rs5c313_write_reg(RS5C313_ADDR_YEAR, data); | ||
| 306 | rs5c313_write_reg(RS5C313_ADDR_YEAR10, (data >> 4)); | ||
| 307 | |||
| 308 | data = BIN2BCD(tm->tm_wday); | ||
| 309 | rs5c313_write_reg(RS5C313_ADDR_WEEK, data); | ||
| 310 | |||
| 311 | RS5C313_CEDISABLE; /* CE:H */ | ||
| 312 | ndelay(700); | ||
| 313 | |||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | static void rs5c313_check_xstp_bit(void) | ||
| 318 | { | ||
| 319 | struct rtc_time tm; | ||
| 320 | |||
| 321 | RS5C313_CEENABLE; /* CE:H */ | ||
| 322 | if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) { | ||
| 323 | /* INT interval reg. OFF */ | ||
| 324 | rs5c313_write_intintvreg(0x00); | ||
| 325 | /* Initialize control reg. 24 hour & adjust */ | ||
| 326 | rs5c313_write_cntreg(0x07); | ||
| 327 | |||
| 328 | /* busy check. */ | ||
| 329 | while (rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY) | ||
| 330 | RS5C313_MISCOP; | ||
| 331 | |||
| 332 | memset(&tm, 0, sizeof(struct rtc_time)); | ||
| 333 | tm.tm_mday = 1; | ||
| 334 | tm.tm_mon = 1; | ||
| 335 | |||
| 336 | rs5c313_rtc_set_time(NULL, &tm); | ||
| 337 | printk(KERN_ERR "RICHO RS5C313: invalid value, resetting to " | ||
| 338 | "1 Jan 2000\n"); | ||
| 339 | } | ||
| 340 | RS5C313_CEDISABLE; | ||
| 341 | ndelay(700); /* CE:L */ | ||
| 342 | } | ||
| 343 | |||
| 344 | static const struct rtc_class_ops rs5c313_rtc_ops = { | ||
| 345 | .read_time = rs5c313_rtc_read_time, | ||
| 346 | .set_time = rs5c313_rtc_set_time, | ||
| 347 | }; | ||
| 348 | |||
| 349 | static int rs5c313_rtc_probe(struct platform_device *pdev) | ||
| 350 | { | ||
| 351 | struct rtc_device *rtc = rtc_device_register("rs5c313", &pdev->dev, | ||
| 352 | &rs5c313_rtc_ops, THIS_MODULE); | ||
| 353 | |||
| 354 | if (IS_ERR(rtc)) | ||
| 355 | return PTR_ERR(rtc); | ||
| 356 | |||
| 357 | platform_set_drvdata(pdev, rtc); | ||
| 358 | |||
| 359 | return err; | ||
| 360 | } | ||
| 361 | |||
| 362 | static int __devexit rs5c313_rtc_remove(struct platform_device *pdev) | ||
| 363 | { | ||
| 364 | struct rtc_device *rtc = platform_get_drvdata( pdev ); | ||
| 365 | |||
| 366 | rtc_device_unregister(rtc); | ||
| 367 | |||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | static struct platform_driver rs5c313_rtc_platform_driver = { | ||
| 372 | .driver = { | ||
| 373 | .name = DRV_NAME, | ||
| 374 | .owner = THIS_MODULE, | ||
| 375 | }, | ||
| 376 | .probe = rs5c313_rtc_probe, | ||
| 377 | .remove = __devexit_p( rs5c313_rtc_remove ), | ||
| 378 | }; | ||
| 379 | |||
| 380 | static int __init rs5c313_rtc_init(void) | ||
| 381 | { | ||
| 382 | int err; | ||
| 383 | |||
| 384 | err = platform_driver_register(&rs5c313_rtc_platform_driver); | ||
| 385 | if (err) | ||
| 386 | return err; | ||
| 387 | |||
| 388 | rs5c313_init_port(); | ||
| 389 | rs5c313_check_xstp_bit(); | ||
| 390 | |||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | static void __exit rs5c313_rtc_exit(void) | ||
| 395 | { | ||
| 396 | platform_driver_unregister( &rs5c313_rtc_platform_driver ); | ||
| 397 | } | ||
| 398 | |||
| 399 | module_init(rs5c313_rtc_init); | ||
| 400 | module_exit(rs5c313_rtc_exit); | ||
| 401 | |||
| 402 | MODULE_VERSION(DRV_VERSION); | ||
| 403 | MODULE_AUTHOR("kogiidena , Nobuhiro Iwamatsu <iwamatsu@nigauri.org>"); | ||
| 404 | MODULE_DESCRIPTION("Ricoh RS5C313 RTC device driver"); | ||
| 405 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 9a79a24a7487..54b613053468 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
| @@ -50,7 +50,7 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) | |||
| 50 | { | 50 | { |
| 51 | struct rtc_device *rdev = id; | 51 | struct rtc_device *rdev = id; |
| 52 | 52 | ||
| 53 | rtc_update_irq(&rdev->class_dev, 1, RTC_AF | RTC_IRQF); | 53 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); |
| 54 | return IRQ_HANDLED; | 54 | return IRQ_HANDLED; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| @@ -58,7 +58,7 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
| 58 | { | 58 | { |
| 59 | struct rtc_device *rdev = id; | 59 | struct rtc_device *rdev = id; |
| 60 | 60 | ||
| 61 | rtc_update_irq(&rdev->class_dev, tick_count++, RTC_PF | RTC_IRQF); | 61 | rtc_update_irq(rdev, tick_count++, RTC_PF | RTC_IRQF); |
| 62 | return IRQ_HANDLED; | 62 | return IRQ_HANDLED; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| @@ -548,37 +548,15 @@ static int ticnt_save; | |||
| 548 | 548 | ||
| 549 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 549 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
| 550 | { | 550 | { |
| 551 | struct rtc_time tm; | ||
| 552 | struct timespec time; | ||
| 553 | |||
| 554 | time.tv_nsec = 0; | ||
| 555 | |||
| 556 | /* save TICNT for anyone using periodic interrupts */ | 551 | /* save TICNT for anyone using periodic interrupts */ |
| 557 | |||
| 558 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 552 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
| 559 | |||
| 560 | /* calculate time delta for suspend */ | ||
| 561 | |||
| 562 | s3c_rtc_gettime(&pdev->dev, &tm); | ||
| 563 | rtc_tm_to_time(&tm, &time.tv_sec); | ||
| 564 | save_time_delta(&s3c_rtc_delta, &time); | ||
| 565 | s3c_rtc_enable(pdev, 0); | 553 | s3c_rtc_enable(pdev, 0); |
| 566 | |||
| 567 | return 0; | 554 | return 0; |
| 568 | } | 555 | } |
| 569 | 556 | ||
| 570 | static int s3c_rtc_resume(struct platform_device *pdev) | 557 | static int s3c_rtc_resume(struct platform_device *pdev) |
| 571 | { | 558 | { |
| 572 | struct rtc_time tm; | ||
| 573 | struct timespec time; | ||
| 574 | |||
| 575 | time.tv_nsec = 0; | ||
| 576 | |||
| 577 | s3c_rtc_enable(pdev, 1); | 559 | s3c_rtc_enable(pdev, 1); |
| 578 | s3c_rtc_gettime(&pdev->dev, &tm); | ||
| 579 | rtc_tm_to_time(&tm, &time.tv_sec); | ||
| 580 | restore_time_delta(&s3c_rtc_delta, &time); | ||
| 581 | |||
| 582 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 560 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
| 583 | return 0; | 561 | return 0; |
| 584 | } | 562 | } |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 677bae820dc3..0918b787c4dd 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
| @@ -93,7 +93,7 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
| 93 | if (rtsr & RTSR_HZ) | 93 | if (rtsr & RTSR_HZ) |
| 94 | events |= RTC_UF | RTC_IRQF; | 94 | events |= RTC_UF | RTC_IRQF; |
| 95 | 95 | ||
| 96 | rtc_update_irq(&rtc->class_dev, 1, events); | 96 | rtc_update_irq(rtc, 1, events); |
| 97 | 97 | ||
| 98 | if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) | 98 | if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) |
| 99 | rtc_update_alarm(&rtc_alarm); | 99 | rtc_update_alarm(&rtc_alarm); |
| @@ -119,7 +119,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) | |||
| 119 | */ | 119 | */ |
| 120 | OSSR = OSSR_M1; /* clear match on timer1 */ | 120 | OSSR = OSSR_M1; /* clear match on timer1 */ |
| 121 | 121 | ||
| 122 | rtc_update_irq(&rtc->class_dev, rtc_timer1_count, RTC_PF | RTC_IRQF); | 122 | rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF); |
| 123 | 123 | ||
| 124 | if (rtc_timer1_count == 1) | 124 | if (rtc_timer1_count == 1) |
| 125 | rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))); | 125 | rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))); |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 198b9f22fbff..6abf4811958c 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
| @@ -104,7 +104,7 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) | |||
| 104 | 104 | ||
| 105 | writeb(tmp, rtc->regbase + RCR1); | 105 | writeb(tmp, rtc->regbase + RCR1); |
| 106 | 106 | ||
| 107 | rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events); | 107 | rtc_update_irq(&rtc->rtc_dev, 1, events); |
| 108 | 108 | ||
| 109 | spin_unlock(&rtc->lock); | 109 | spin_unlock(&rtc->lock); |
| 110 | 110 | ||
| @@ -139,7 +139,7 @@ static irqreturn_t sh_rtc_alarm(int irq, void *dev_id) | |||
| 139 | 139 | ||
| 140 | rtc->rearm_aie = 1; | 140 | rtc->rearm_aie = 1; |
| 141 | 141 | ||
| 142 | rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events); | 142 | rtc_update_irq(&rtc->rtc_dev, 1, events); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | spin_unlock(&rtc->lock); | 145 | spin_unlock(&rtc->lock); |
| @@ -153,7 +153,7 @@ static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) | |||
| 153 | 153 | ||
| 154 | spin_lock(&rtc->lock); | 154 | spin_lock(&rtc->lock); |
| 155 | 155 | ||
| 156 | rtc_update_irq(&rtc->rtc_dev->class_dev, 1, RTC_PF | RTC_IRQF); | 156 | rtc_update_irq(&rtc->rtc_dev, 1, RTC_PF | RTC_IRQF); |
| 157 | 157 | ||
| 158 | spin_unlock(&rtc->lock); | 158 | spin_unlock(&rtc->lock); |
| 159 | 159 | ||
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 899ab8c514fa..69df94b44841 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
| @@ -12,20 +12,26 @@ | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
| 14 | 14 | ||
| 15 | #include "rtc-core.h" | ||
| 16 | |||
| 17 | |||
| 15 | /* device attributes */ | 18 | /* device attributes */ |
| 16 | 19 | ||
| 17 | static ssize_t rtc_sysfs_show_name(struct class_device *dev, char *buf) | 20 | static ssize_t |
| 21 | rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, | ||
| 22 | char *buf) | ||
| 18 | { | 23 | { |
| 19 | return sprintf(buf, "%s\n", to_rtc_device(dev)->name); | 24 | return sprintf(buf, "%s\n", to_rtc_device(dev)->name); |
| 20 | } | 25 | } |
| 21 | static CLASS_DEVICE_ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL); | ||
| 22 | 26 | ||
| 23 | static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf) | 27 | static ssize_t |
| 28 | rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr, | ||
| 29 | char *buf) | ||
| 24 | { | 30 | { |
| 25 | ssize_t retval; | 31 | ssize_t retval; |
| 26 | struct rtc_time tm; | 32 | struct rtc_time tm; |
| 27 | 33 | ||
| 28 | retval = rtc_read_time(dev, &tm); | 34 | retval = rtc_read_time(to_rtc_device(dev), &tm); |
| 29 | if (retval == 0) { | 35 | if (retval == 0) { |
| 30 | retval = sprintf(buf, "%04d-%02d-%02d\n", | 36 | retval = sprintf(buf, "%04d-%02d-%02d\n", |
| 31 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | 37 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); |
| @@ -33,14 +39,15 @@ static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf) | |||
| 33 | 39 | ||
| 34 | return retval; | 40 | return retval; |
| 35 | } | 41 | } |
| 36 | static CLASS_DEVICE_ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL); | ||
| 37 | 42 | ||
| 38 | static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf) | 43 | static ssize_t |
| 44 | rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr, | ||
| 45 | char *buf) | ||
| 39 | { | 46 | { |
| 40 | ssize_t retval; | 47 | ssize_t retval; |
| 41 | struct rtc_time tm; | 48 | struct rtc_time tm; |
| 42 | 49 | ||
| 43 | retval = rtc_read_time(dev, &tm); | 50 | retval = rtc_read_time(to_rtc_device(dev), &tm); |
| 44 | if (retval == 0) { | 51 | if (retval == 0) { |
| 45 | retval = sprintf(buf, "%02d:%02d:%02d\n", | 52 | retval = sprintf(buf, "%02d:%02d:%02d\n", |
| 46 | tm.tm_hour, tm.tm_min, tm.tm_sec); | 53 | tm.tm_hour, tm.tm_min, tm.tm_sec); |
| @@ -48,14 +55,15 @@ static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf) | |||
| 48 | 55 | ||
| 49 | return retval; | 56 | return retval; |
| 50 | } | 57 | } |
| 51 | static CLASS_DEVICE_ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL); | ||
| 52 | 58 | ||
| 53 | static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf) | 59 | static ssize_t |
| 60 | rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr, | ||
| 61 | char *buf) | ||
| 54 | { | 62 | { |
| 55 | ssize_t retval; | 63 | ssize_t retval; |
| 56 | struct rtc_time tm; | 64 | struct rtc_time tm; |
| 57 | 65 | ||
| 58 | retval = rtc_read_time(dev, &tm); | 66 | retval = rtc_read_time(to_rtc_device(dev), &tm); |
| 59 | if (retval == 0) { | 67 | if (retval == 0) { |
| 60 | unsigned long time; | 68 | unsigned long time; |
| 61 | rtc_tm_to_time(&tm, &time); | 69 | rtc_tm_to_time(&tm, &time); |
| @@ -64,23 +72,18 @@ static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf) | |||
| 64 | 72 | ||
| 65 | return retval; | 73 | return retval; |
| 66 | } | 74 | } |
| 67 | static CLASS_DEVICE_ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL); | ||
| 68 | |||
| 69 | static struct attribute *rtc_attrs[] = { | ||
| 70 | &class_device_attr_name.attr, | ||
| 71 | &class_device_attr_date.attr, | ||
| 72 | &class_device_attr_time.attr, | ||
| 73 | &class_device_attr_since_epoch.attr, | ||
| 74 | NULL, | ||
| 75 | }; | ||
| 76 | 75 | ||
| 77 | static struct attribute_group rtc_attr_group = { | 76 | static struct device_attribute rtc_attrs[] = { |
| 78 | .attrs = rtc_attrs, | 77 | __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), |
| 78 | __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), | ||
| 79 | __ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL), | ||
| 80 | __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), | ||
| 81 | { }, | ||
| 79 | }; | 82 | }; |
| 80 | 83 | ||
| 81 | |||
| 82 | static ssize_t | 84 | static ssize_t |
| 83 | rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf) | 85 | rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, |
| 86 | char *buf) | ||
| 84 | { | 87 | { |
| 85 | ssize_t retval; | 88 | ssize_t retval; |
| 86 | unsigned long alarm; | 89 | unsigned long alarm; |
| @@ -94,7 +97,7 @@ rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf) | |||
| 94 | * REVISIT maybe we should require RTC implementations to | 97 | * REVISIT maybe we should require RTC implementations to |
| 95 | * disable the RTC alarm after it triggers, for uniformity. | 98 | * disable the RTC alarm after it triggers, for uniformity. |
| 96 | */ | 99 | */ |
| 97 | retval = rtc_read_alarm(dev, &alm); | 100 | retval = rtc_read_alarm(to_rtc_device(dev), &alm); |
| 98 | if (retval == 0 && alm.enabled) { | 101 | if (retval == 0 && alm.enabled) { |
| 99 | rtc_tm_to_time(&alm.time, &alarm); | 102 | rtc_tm_to_time(&alm.time, &alarm); |
| 100 | retval = sprintf(buf, "%lu\n", alarm); | 103 | retval = sprintf(buf, "%lu\n", alarm); |
| @@ -104,16 +107,18 @@ rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf) | |||
| 104 | } | 107 | } |
| 105 | 108 | ||
| 106 | static ssize_t | 109 | static ssize_t |
| 107 | rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n) | 110 | rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr, |
| 111 | const char *buf, size_t n) | ||
| 108 | { | 112 | { |
| 109 | ssize_t retval; | 113 | ssize_t retval; |
| 110 | unsigned long now, alarm; | 114 | unsigned long now, alarm; |
| 111 | struct rtc_wkalrm alm; | 115 | struct rtc_wkalrm alm; |
| 116 | struct rtc_device *rtc = to_rtc_device(dev); | ||
| 112 | 117 | ||
| 113 | /* Only request alarms that trigger in the future. Disable them | 118 | /* Only request alarms that trigger in the future. Disable them |
| 114 | * by writing another time, e.g. 0 meaning Jan 1 1970 UTC. | 119 | * by writing another time, e.g. 0 meaning Jan 1 1970 UTC. |
| 115 | */ | 120 | */ |
| 116 | retval = rtc_read_time(dev, &alm.time); | 121 | retval = rtc_read_time(rtc, &alm.time); |
| 117 | if (retval < 0) | 122 | if (retval < 0) |
| 118 | return retval; | 123 | return retval; |
| 119 | rtc_tm_to_time(&alm.time, &now); | 124 | rtc_tm_to_time(&alm.time, &now); |
| @@ -124,7 +129,7 @@ rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n) | |||
| 124 | * entirely prevent that here, without even the minimal | 129 | * entirely prevent that here, without even the minimal |
| 125 | * locking from the /dev/rtcN api. | 130 | * locking from the /dev/rtcN api. |
| 126 | */ | 131 | */ |
| 127 | retval = rtc_read_alarm(dev, &alm); | 132 | retval = rtc_read_alarm(rtc, &alm); |
| 128 | if (retval < 0) | 133 | if (retval < 0) |
| 129 | return retval; | 134 | return retval; |
| 130 | if (alm.enabled) | 135 | if (alm.enabled) |
| @@ -141,10 +146,10 @@ rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n) | |||
| 141 | } | 146 | } |
| 142 | rtc_time_to_tm(alarm, &alm.time); | 147 | rtc_time_to_tm(alarm, &alm.time); |
| 143 | 148 | ||
| 144 | retval = rtc_set_alarm(dev, &alm); | 149 | retval = rtc_set_alarm(rtc, &alm); |
| 145 | return (retval < 0) ? retval : n; | 150 | return (retval < 0) ? retval : n; |
| 146 | } | 151 | } |
| 147 | static const CLASS_DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR, | 152 | static DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR, |
| 148 | rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm); | 153 | rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm); |
| 149 | 154 | ||
| 150 | 155 | ||
| @@ -153,71 +158,37 @@ static const CLASS_DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR, | |||
| 153 | * suspend-to-disk. So: no attribute unless that side effect is possible. | 158 | * suspend-to-disk. So: no attribute unless that side effect is possible. |
| 154 | * (Userspace may disable that mechanism later.) | 159 | * (Userspace may disable that mechanism later.) |
| 155 | */ | 160 | */ |
| 156 | static inline int rtc_does_wakealarm(struct class_device *class_dev) | 161 | static inline int rtc_does_wakealarm(struct rtc_device *rtc) |
| 157 | { | 162 | { |
| 158 | struct rtc_device *rtc; | 163 | if (!device_can_wakeup(rtc->dev.parent)) |
| 159 | |||
| 160 | if (!device_can_wakeup(class_dev->dev)) | ||
| 161 | return 0; | 164 | return 0; |
| 162 | rtc = to_rtc_device(class_dev); | ||
| 163 | return rtc->ops->set_alarm != NULL; | 165 | return rtc->ops->set_alarm != NULL; |
| 164 | } | 166 | } |
| 165 | 167 | ||
| 166 | 168 | ||
| 167 | static int rtc_sysfs_add_device(struct class_device *class_dev, | 169 | void rtc_sysfs_add_device(struct rtc_device *rtc) |
| 168 | struct class_interface *class_intf) | ||
| 169 | { | 170 | { |
| 170 | int err; | 171 | int err; |
| 171 | 172 | ||
| 172 | dev_dbg(class_dev->dev, "rtc intf: sysfs\n"); | 173 | /* not all RTCs support both alarms and wakeup */ |
| 174 | if (!rtc_does_wakealarm(rtc)) | ||
| 175 | return; | ||
| 173 | 176 | ||
| 174 | err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group); | 177 | err = device_create_file(&rtc->dev, &dev_attr_wakealarm); |
| 175 | if (err) | 178 | if (err) |
| 176 | dev_err(class_dev->dev, "failed to create %s\n", | 179 | dev_err(rtc->dev.parent, "failed to create " |
| 177 | "sysfs attributes"); | 180 | "alarm attribute, %d", |
| 178 | else if (rtc_does_wakealarm(class_dev)) { | 181 | err); |
| 179 | /* not all RTCs support both alarms and wakeup */ | ||
| 180 | err = class_device_create_file(class_dev, | ||
| 181 | &class_device_attr_wakealarm); | ||
| 182 | if (err) { | ||
| 183 | dev_err(class_dev->dev, "failed to create %s\n", | ||
| 184 | "alarm attribute"); | ||
| 185 | sysfs_remove_group(&class_dev->kobj, &rtc_attr_group); | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | return err; | ||
| 190 | } | 182 | } |
| 191 | 183 | ||
| 192 | static void rtc_sysfs_remove_device(struct class_device *class_dev, | 184 | void rtc_sysfs_del_device(struct rtc_device *rtc) |
| 193 | struct class_interface *class_intf) | ||
| 194 | { | 185 | { |
| 195 | if (rtc_does_wakealarm(class_dev)) | 186 | /* REVISIT did we add it successfully? */ |
| 196 | class_device_remove_file(class_dev, | 187 | if (rtc_does_wakealarm(rtc)) |
| 197 | &class_device_attr_wakealarm); | 188 | device_remove_file(&rtc->dev, &dev_attr_wakealarm); |
| 198 | sysfs_remove_group(&class_dev->kobj, &rtc_attr_group); | ||
| 199 | } | 189 | } |
| 200 | 190 | ||
| 201 | /* interface registration */ | 191 | void __init rtc_sysfs_init(struct class *rtc_class) |
| 202 | |||
| 203 | static struct class_interface rtc_sysfs_interface = { | ||
| 204 | .add = &rtc_sysfs_add_device, | ||
| 205 | .remove = &rtc_sysfs_remove_device, | ||
| 206 | }; | ||
| 207 | |||
| 208 | static int __init rtc_sysfs_init(void) | ||
| 209 | { | 192 | { |
| 210 | return rtc_interface_register(&rtc_sysfs_interface); | 193 | rtc_class->dev_attrs = rtc_attrs; |
| 211 | } | 194 | } |
| 212 | |||
| 213 | static void __exit rtc_sysfs_exit(void) | ||
| 214 | { | ||
| 215 | class_interface_unregister(&rtc_sysfs_interface); | ||
| 216 | } | ||
| 217 | |||
| 218 | subsys_initcall(rtc_sysfs_init); | ||
| 219 | module_exit(rtc_sysfs_exit); | ||
| 220 | |||
| 221 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 222 | MODULE_DESCRIPTION("RTC class sysfs interface"); | ||
| 223 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index f50a1b8e1607..254c9fce27da 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c | |||
| @@ -101,11 +101,11 @@ static ssize_t test_irq_store(struct device *dev, | |||
| 101 | retval = count; | 101 | retval = count; |
| 102 | local_irq_disable(); | 102 | local_irq_disable(); |
| 103 | if (strncmp(buf, "tick", 4) == 0) | 103 | if (strncmp(buf, "tick", 4) == 0) |
| 104 | rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF); | 104 | rtc_update_irq(rtc, 1, RTC_PF | RTC_IRQF); |
| 105 | else if (strncmp(buf, "alarm", 5) == 0) | 105 | else if (strncmp(buf, "alarm", 5) == 0) |
| 106 | rtc_update_irq(&rtc->class_dev, 1, RTC_AF | RTC_IRQF); | 106 | rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF); |
| 107 | else if (strncmp(buf, "update", 6) == 0) | 107 | else if (strncmp(buf, "update", 6) == 0) |
| 108 | rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF); | 108 | rtc_update_irq(rtc, 1, RTC_UF | RTC_IRQF); |
| 109 | else | 109 | else |
| 110 | retval = -EINVAL; | 110 | retval = -EINVAL; |
| 111 | local_irq_enable(); | 111 | local_irq_enable(); |
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index e40322b71938..af7596ef29e2 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
| @@ -97,6 +97,7 @@ static DEFINE_SPINLOCK(rtc_lock); | |||
| 97 | static char rtc_name[] = "RTC"; | 97 | static char rtc_name[] = "RTC"; |
| 98 | static unsigned long periodic_frequency; | 98 | static unsigned long periodic_frequency; |
| 99 | static unsigned long periodic_count; | 99 | static unsigned long periodic_count; |
| 100 | static unsigned int alarm_enabled; | ||
| 100 | 101 | ||
| 101 | struct resource rtc_resource[2] = { | 102 | struct resource rtc_resource[2] = { |
| 102 | { .name = rtc_name, | 103 | { .name = rtc_name, |
| @@ -188,6 +189,7 @@ static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
| 188 | low = rtc1_read(ECMPLREG); | 189 | low = rtc1_read(ECMPLREG); |
| 189 | mid = rtc1_read(ECMPMREG); | 190 | mid = rtc1_read(ECMPMREG); |
| 190 | high = rtc1_read(ECMPHREG); | 191 | high = rtc1_read(ECMPHREG); |
| 192 | wkalrm->enabled = alarm_enabled; | ||
| 191 | 193 | ||
| 192 | spin_unlock_irq(&rtc_lock); | 194 | spin_unlock_irq(&rtc_lock); |
| 193 | 195 | ||
| @@ -206,10 +208,18 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
| 206 | 208 | ||
| 207 | spin_lock_irq(&rtc_lock); | 209 | spin_lock_irq(&rtc_lock); |
| 208 | 210 | ||
| 211 | if (alarm_enabled) | ||
| 212 | disable_irq(ELAPSEDTIME_IRQ); | ||
| 213 | |||
| 209 | rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15)); | 214 | rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15)); |
| 210 | rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1)); | 215 | rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1)); |
| 211 | rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17)); | 216 | rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17)); |
| 212 | 217 | ||
| 218 | if (wkalrm->enabled) | ||
| 219 | enable_irq(ELAPSEDTIME_IRQ); | ||
| 220 | |||
| 221 | alarm_enabled = wkalrm->enabled; | ||
| 222 | |||
| 213 | spin_unlock_irq(&rtc_lock); | 223 | spin_unlock_irq(&rtc_lock); |
| 214 | 224 | ||
| 215 | return 0; | 225 | return 0; |
| @@ -221,10 +231,24 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long | |||
| 221 | 231 | ||
| 222 | switch (cmd) { | 232 | switch (cmd) { |
| 223 | case RTC_AIE_ON: | 233 | case RTC_AIE_ON: |
| 224 | enable_irq(ELAPSEDTIME_IRQ); | 234 | spin_lock_irq(&rtc_lock); |
| 235 | |||
| 236 | if (!alarm_enabled) { | ||
| 237 | enable_irq(ELAPSEDTIME_IRQ); | ||
| 238 | alarm_enabled = 1; | ||
| 239 | } | ||
| 240 | |||
| 241 | spin_unlock_irq(&rtc_lock); | ||
| 225 | break; | 242 | break; |
| 226 | case RTC_AIE_OFF: | 243 | case RTC_AIE_OFF: |
| 227 | disable_irq(ELAPSEDTIME_IRQ); | 244 | spin_lock_irq(&rtc_lock); |
| 245 | |||
| 246 | if (alarm_enabled) { | ||
| 247 | disable_irq(ELAPSEDTIME_IRQ); | ||
| 248 | alarm_enabled = 0; | ||
| 249 | } | ||
| 250 | |||
| 251 | spin_unlock_irq(&rtc_lock); | ||
| 228 | break; | 252 | break; |
| 229 | case RTC_PIE_ON: | 253 | case RTC_PIE_ON: |
| 230 | enable_irq(RTCLONG1_IRQ); | 254 | enable_irq(RTCLONG1_IRQ); |
| @@ -275,7 +299,7 @@ static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id) | |||
| 275 | 299 | ||
| 276 | rtc2_write(RTCINTREG, ELAPSEDTIME_INT); | 300 | rtc2_write(RTCINTREG, ELAPSEDTIME_INT); |
| 277 | 301 | ||
| 278 | rtc_update_irq(&rtc->class_dev, 1, RTC_AF); | 302 | rtc_update_irq(rtc, 1, RTC_AF); |
| 279 | 303 | ||
| 280 | return IRQ_HANDLED; | 304 | return IRQ_HANDLED; |
| 281 | } | 305 | } |
| @@ -291,7 +315,7 @@ static irqreturn_t rtclong1_interrupt(int irq, void *dev_id) | |||
| 291 | rtc1_write(RTCL1LREG, count); | 315 | rtc1_write(RTCL1LREG, count); |
| 292 | rtc1_write(RTCL1HREG, count >> 16); | 316 | rtc1_write(RTCL1HREG, count >> 16); |
| 293 | 317 | ||
| 294 | rtc_update_irq(&rtc->class_dev, 1, RTC_PF); | 318 | rtc_update_irq(rtc, 1, RTC_PF); |
| 295 | 319 | ||
| 296 | return IRQ_HANDLED; | 320 | return IRQ_HANDLED; |
| 297 | } | 321 | } |
