diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/rtc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/rtc/class.c | 1 | ||||
| -rw-r--r-- | drivers/rtc/interface.c | 122 | ||||
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 64 | ||||
| -rw-r--r-- | drivers/rtc/rtc-dev.c | 44 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1374.c | 449 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1553.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1742.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf8583.c | 3 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pl031.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sa1100.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sh.c | 51 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sysfs.c | 29 |
14 files changed, 698 insertions, 87 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ff9e35cb308d..cbde770eb121 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -139,6 +139,17 @@ config RTC_DRV_DS1307 | |||
| 139 | This driver can also be built as a module. If so, the module | 139 | This driver can also be built as a module. If so, the module |
| 140 | will be called rtc-ds1307. | 140 | will be called rtc-ds1307. |
| 141 | 141 | ||
| 142 | config RTC_DRV_DS1374 | ||
| 143 | tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock" | ||
| 144 | depends on RTC_CLASS && I2C | ||
| 145 | help | ||
| 146 | If you say yes here you get support for Dallas Semiconductor | ||
| 147 | DS1374 real-time clock chips. If an interrupt is associated | ||
| 148 | with the device, the alarm functionality is supported. | ||
| 149 | |||
| 150 | This driver can also be built as a module. If so, the module | ||
| 151 | will be called rtc-ds1374. | ||
| 152 | |||
| 142 | config RTC_DRV_DS1672 | 153 | config RTC_DRV_DS1672 |
| 143 | tristate "Dallas/Maxim DS1672" | 154 | tristate "Dallas/Maxim DS1672" |
| 144 | help | 155 | help |
| @@ -229,7 +240,7 @@ config RTC_DRV_TWL92330 | |||
| 229 | depends on MENELAUS | 240 | depends on MENELAUS |
| 230 | help | 241 | help |
| 231 | If you say yes here you get support for the RTC on the | 242 | If you say yes here you get support for the RTC on the |
| 232 | TWL92330 "Menelaus" power mangement chip, used with OMAP2 | 243 | TWL92330 "Menelaus" power management chip, used with OMAP2 |
| 233 | platforms. The support is integrated with the rest of | 244 | platforms. The support is integrated with the rest of |
| 234 | the Menelaus driver; it's not separate module. | 245 | the Menelaus driver; it's not separate module. |
| 235 | 246 | ||
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index d3a33aa2696f..465db4dd50b2 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | |||
| 23 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 23 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
| 24 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 24 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
| 25 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 25 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
| 26 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o | ||
| 26 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 27 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
| 27 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 28 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
| 28 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 29 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 10ab3b71ffc6..4dfdf019fccc 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -153,6 +153,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
| 153 | mutex_init(&rtc->ops_lock); | 153 | mutex_init(&rtc->ops_lock); |
| 154 | spin_lock_init(&rtc->irq_lock); | 154 | spin_lock_init(&rtc->irq_lock); |
| 155 | spin_lock_init(&rtc->irq_task_lock); | 155 | spin_lock_init(&rtc->irq_task_lock); |
| 156 | init_waitqueue_head(&rtc->irq_queue); | ||
| 156 | 157 | ||
| 157 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); | 158 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); |
| 158 | snprintf(rtc->dev.bus_id, BUS_ID_SIZE, "rtc%d", id); | 159 | snprintf(rtc->dev.bus_id, BUS_ID_SIZE, "rtc%d", id); |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index ad66c6ecf365..de0da545c7a1 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
| 15 | #include <linux/log2.h> | ||
| 15 | 16 | ||
| 16 | int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | 17 | int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) |
| 17 | { | 18 | { |
| @@ -99,7 +100,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) | |||
| 99 | } | 100 | } |
| 100 | EXPORT_SYMBOL_GPL(rtc_set_mmss); | 101 | EXPORT_SYMBOL_GPL(rtc_set_mmss); |
| 101 | 102 | ||
| 102 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 103 | static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
| 103 | { | 104 | { |
| 104 | int err; | 105 | int err; |
| 105 | 106 | ||
| @@ -119,6 +120,87 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
| 119 | mutex_unlock(&rtc->ops_lock); | 120 | mutex_unlock(&rtc->ops_lock); |
| 120 | return err; | 121 | return err; |
| 121 | } | 122 | } |
| 123 | |||
| 124 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | ||
| 125 | { | ||
| 126 | int err; | ||
| 127 | struct rtc_time before, now; | ||
| 128 | int first_time = 1; | ||
| 129 | |||
| 130 | /* The lower level RTC driver may not be capable of filling | ||
| 131 | * in all fields of the rtc_time struct (eg. rtc-cmos), | ||
| 132 | * and so might instead return -1 in some fields. | ||
| 133 | * We deal with that here by grabbing a current RTC timestamp | ||
| 134 | * and using values from that for any missing (-1) values. | ||
| 135 | * | ||
| 136 | * But this can be racey, because some fields of the RTC timestamp | ||
| 137 | * may have wrapped in the interval since we read the RTC alarm, | ||
| 138 | * which would lead to us inserting inconsistent values in place | ||
| 139 | * of the -1 fields. | ||
| 140 | * | ||
| 141 | * Reading the alarm and timestamp in the reverse sequence | ||
| 142 | * would have the same race condition, and not solve the issue. | ||
| 143 | * | ||
| 144 | * So, we must first read the RTC timestamp, | ||
| 145 | * then read the RTC alarm value, | ||
| 146 | * and then read a second RTC timestamp. | ||
| 147 | * | ||
| 148 | * If any fields of the second timestamp have changed | ||
| 149 | * when compared with the first timestamp, then we know | ||
| 150 | * our timestamp may be inconsistent with that used by | ||
| 151 | * the low-level rtc_read_alarm_internal() function. | ||
| 152 | * | ||
| 153 | * So, when the two timestamps disagree, we just loop and do | ||
| 154 | * the process again to get a fully consistent set of values. | ||
| 155 | * | ||
| 156 | * This could all instead be done in the lower level driver, | ||
| 157 | * but since more than one lower level RTC implementation needs it, | ||
| 158 | * then it's probably best best to do it here instead of there.. | ||
| 159 | */ | ||
| 160 | |||
| 161 | /* Get the "before" timestamp */ | ||
| 162 | err = rtc_read_time(rtc, &before); | ||
| 163 | if (err < 0) | ||
| 164 | return err; | ||
| 165 | do { | ||
| 166 | if (!first_time) | ||
| 167 | memcpy(&before, &now, sizeof(struct rtc_time)); | ||
| 168 | first_time = 0; | ||
| 169 | |||
| 170 | /* get the RTC alarm values, which may be incomplete */ | ||
| 171 | err = rtc_read_alarm_internal(rtc, alarm); | ||
| 172 | if (err) | ||
| 173 | return err; | ||
| 174 | if (!alarm->enabled) | ||
| 175 | return 0; | ||
| 176 | |||
| 177 | /* get the "after" timestamp, to detect wrapped fields */ | ||
| 178 | err = rtc_read_time(rtc, &now); | ||
| 179 | if (err < 0) | ||
| 180 | return err; | ||
| 181 | |||
| 182 | /* note that tm_sec is a "don't care" value here: */ | ||
| 183 | } while ( before.tm_min != now.tm_min | ||
| 184 | || before.tm_hour != now.tm_hour | ||
| 185 | || before.tm_mon != now.tm_mon | ||
| 186 | || before.tm_year != now.tm_year | ||
| 187 | || before.tm_isdst != now.tm_isdst); | ||
| 188 | |||
| 189 | /* Fill in any missing alarm fields using the timestamp */ | ||
| 190 | if (alarm->time.tm_sec == -1) | ||
| 191 | alarm->time.tm_sec = now.tm_sec; | ||
| 192 | if (alarm->time.tm_min == -1) | ||
| 193 | alarm->time.tm_min = now.tm_min; | ||
| 194 | if (alarm->time.tm_hour == -1) | ||
| 195 | alarm->time.tm_hour = now.tm_hour; | ||
| 196 | if (alarm->time.tm_mday == -1) | ||
| 197 | alarm->time.tm_mday = now.tm_mday; | ||
| 198 | if (alarm->time.tm_mon == -1) | ||
| 199 | alarm->time.tm_mon = now.tm_mon; | ||
| 200 | if (alarm->time.tm_year == -1) | ||
| 201 | alarm->time.tm_year = now.tm_year; | ||
| 202 | return 0; | ||
| 203 | } | ||
| 122 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | 204 | EXPORT_SYMBOL_GPL(rtc_read_alarm); |
| 123 | 205 | ||
| 124 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 206 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
| @@ -210,6 +292,10 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) | |||
| 210 | if (task == NULL || task->func == NULL) | 292 | if (task == NULL || task->func == NULL) |
| 211 | return -EINVAL; | 293 | return -EINVAL; |
| 212 | 294 | ||
| 295 | /* Cannot register while the char dev is in use */ | ||
| 296 | if (!(mutex_trylock(&rtc->char_lock))) | ||
| 297 | return -EBUSY; | ||
| 298 | |||
| 213 | spin_lock_irq(&rtc->irq_task_lock); | 299 | spin_lock_irq(&rtc->irq_task_lock); |
| 214 | if (rtc->irq_task == NULL) { | 300 | if (rtc->irq_task == NULL) { |
| 215 | rtc->irq_task = task; | 301 | rtc->irq_task = task; |
| @@ -217,13 +303,14 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) | |||
| 217 | } | 303 | } |
| 218 | spin_unlock_irq(&rtc->irq_task_lock); | 304 | spin_unlock_irq(&rtc->irq_task_lock); |
| 219 | 305 | ||
| 306 | mutex_unlock(&rtc->char_lock); | ||
| 307 | |||
| 220 | return retval; | 308 | return retval; |
| 221 | } | 309 | } |
| 222 | EXPORT_SYMBOL_GPL(rtc_irq_register); | 310 | EXPORT_SYMBOL_GPL(rtc_irq_register); |
| 223 | 311 | ||
| 224 | void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) | 312 | void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) |
| 225 | { | 313 | { |
| 226 | |||
| 227 | spin_lock_irq(&rtc->irq_task_lock); | 314 | spin_lock_irq(&rtc->irq_task_lock); |
| 228 | if (rtc->irq_task == task) | 315 | if (rtc->irq_task == task) |
| 229 | rtc->irq_task = NULL; | 316 | rtc->irq_task = NULL; |
| @@ -231,6 +318,16 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) | |||
| 231 | } | 318 | } |
| 232 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); | 319 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); |
| 233 | 320 | ||
| 321 | /** | ||
| 322 | * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs | ||
| 323 | * @rtc: the rtc device | ||
| 324 | * @task: currently registered with rtc_irq_register() | ||
| 325 | * @enabled: true to enable periodic IRQs | ||
| 326 | * Context: any | ||
| 327 | * | ||
| 328 | * Note that rtc_irq_set_freq() should previously have been used to | ||
| 329 | * specify the desired frequency of periodic IRQ task->func() callbacks. | ||
| 330 | */ | ||
| 234 | int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) | 331 | int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) |
| 235 | { | 332 | { |
| 236 | int err = 0; | 333 | int err = 0; |
| @@ -240,8 +337,10 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled | |||
| 240 | return -ENXIO; | 337 | return -ENXIO; |
| 241 | 338 | ||
| 242 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 339 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
| 340 | if (rtc->irq_task != NULL && task == NULL) | ||
| 341 | err = -EBUSY; | ||
| 243 | if (rtc->irq_task != task) | 342 | if (rtc->irq_task != task) |
| 244 | err = -ENXIO; | 343 | err = -EACCES; |
| 245 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | 344 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
| 246 | 345 | ||
| 247 | if (err == 0) | 346 | if (err == 0) |
| @@ -251,6 +350,16 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled | |||
| 251 | } | 350 | } |
| 252 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); | 351 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); |
| 253 | 352 | ||
| 353 | /** | ||
| 354 | * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ | ||
| 355 | * @rtc: the rtc device | ||
| 356 | * @task: currently registered with rtc_irq_register() | ||
| 357 | * @freq: positive frequency with which task->func() will be called | ||
| 358 | * Context: any | ||
| 359 | * | ||
| 360 | * Note that rtc_irq_set_state() is used to enable or disable the | ||
| 361 | * periodic IRQs. | ||
| 362 | */ | ||
| 254 | int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | 363 | int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) |
| 255 | { | 364 | { |
| 256 | int err = 0; | 365 | int err = 0; |
| @@ -259,9 +368,14 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | |||
| 259 | if (rtc->ops->irq_set_freq == NULL) | 368 | if (rtc->ops->irq_set_freq == NULL) |
| 260 | return -ENXIO; | 369 | return -ENXIO; |
| 261 | 370 | ||
| 371 | if (!is_power_of_2(freq)) | ||
| 372 | return -EINVAL; | ||
| 373 | |||
| 262 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 374 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
| 375 | if (rtc->irq_task != NULL && task == NULL) | ||
| 376 | err = -EBUSY; | ||
| 263 | if (rtc->irq_task != task) | 377 | if (rtc->irq_task != task) |
| 264 | err = -ENXIO; | 378 | err = -EACCES; |
| 265 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | 379 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
| 266 | 380 | ||
| 267 | if (err == 0) { | 381 | if (err == 0) { |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 5d760bb6c2cd..e3fe83a23cf7 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
| @@ -246,11 +246,9 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
| 246 | 246 | ||
| 247 | /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */ | 247 | /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */ |
| 248 | f = ffs(freq); | 248 | f = ffs(freq); |
| 249 | if (f != 0) { | 249 | if (f-- > 16) |
| 250 | if (f-- > 16 || freq != (1 << f)) | 250 | return -EINVAL; |
| 251 | return -EINVAL; | 251 | f = 16 - f; |
| 252 | f = 16 - f; | ||
| 253 | } | ||
| 254 | 252 | ||
| 255 | spin_lock_irqsave(&rtc_lock, flags); | 253 | spin_lock_irqsave(&rtc_lock, flags); |
| 256 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | 254 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); |
| @@ -435,6 +433,19 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 435 | if (!ports) | 433 | if (!ports) |
| 436 | return -ENODEV; | 434 | return -ENODEV; |
| 437 | 435 | ||
| 436 | /* Claim I/O ports ASAP, minimizing conflict with legacy driver. | ||
| 437 | * | ||
| 438 | * REVISIT non-x86 systems may instead use memory space resources | ||
| 439 | * (needing ioremap etc), not i/o space resources like this ... | ||
| 440 | */ | ||
| 441 | ports = request_region(ports->start, | ||
| 442 | ports->end + 1 - ports->start, | ||
| 443 | driver_name); | ||
| 444 | if (!ports) { | ||
| 445 | dev_dbg(dev, "i/o registers already in use\n"); | ||
| 446 | return -EBUSY; | ||
| 447 | } | ||
| 448 | |||
| 438 | cmos_rtc.irq = rtc_irq; | 449 | cmos_rtc.irq = rtc_irq; |
| 439 | cmos_rtc.iomem = ports; | 450 | cmos_rtc.iomem = ports; |
| 440 | 451 | ||
| @@ -456,24 +467,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 456 | 467 | ||
| 457 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, | 468 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, |
| 458 | &cmos_rtc_ops, THIS_MODULE); | 469 | &cmos_rtc_ops, THIS_MODULE); |
| 459 | if (IS_ERR(cmos_rtc.rtc)) | 470 | if (IS_ERR(cmos_rtc.rtc)) { |
| 460 | return PTR_ERR(cmos_rtc.rtc); | 471 | retval = PTR_ERR(cmos_rtc.rtc); |
| 472 | goto cleanup0; | ||
| 473 | } | ||
| 461 | 474 | ||
| 462 | cmos_rtc.dev = dev; | 475 | cmos_rtc.dev = dev; |
| 463 | dev_set_drvdata(dev, &cmos_rtc); | 476 | dev_set_drvdata(dev, &cmos_rtc); |
| 464 | |||
| 465 | /* platform and pnp busses handle resources incompatibly. | ||
| 466 | * | ||
| 467 | * REVISIT for non-x86 systems we may need to handle io memory | ||
| 468 | * resources: ioremap them, and request_mem_region(). | ||
| 469 | */ | ||
| 470 | if (is_pnp()) { | ||
| 471 | retval = request_resource(&ioport_resource, ports); | ||
| 472 | if (retval < 0) { | ||
| 473 | dev_dbg(dev, "i/o registers already in use\n"); | ||
| 474 | goto cleanup0; | ||
| 475 | } | ||
| 476 | } | ||
| 477 | rename_region(ports, cmos_rtc.rtc->dev.bus_id); | 477 | rename_region(ports, cmos_rtc.rtc->dev.bus_id); |
| 478 | 478 | ||
| 479 | spin_lock_irq(&rtc_lock); | 479 | spin_lock_irq(&rtc_lock); |
| @@ -536,9 +536,10 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 536 | return 0; | 536 | return 0; |
| 537 | 537 | ||
| 538 | cleanup1: | 538 | cleanup1: |
| 539 | rename_region(ports, NULL); | 539 | cmos_rtc.dev = NULL; |
| 540 | cleanup0: | ||
| 541 | rtc_device_unregister(cmos_rtc.rtc); | 540 | rtc_device_unregister(cmos_rtc.rtc); |
| 541 | cleanup0: | ||
| 542 | release_region(ports->start, ports->end + 1 - ports->start); | ||
| 542 | return retval; | 543 | return retval; |
| 543 | } | 544 | } |
| 544 | 545 | ||
| @@ -557,19 +558,21 @@ static void cmos_do_shutdown(void) | |||
| 557 | static void __exit cmos_do_remove(struct device *dev) | 558 | static void __exit cmos_do_remove(struct device *dev) |
| 558 | { | 559 | { |
| 559 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 560 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
| 561 | struct resource *ports; | ||
| 560 | 562 | ||
| 561 | cmos_do_shutdown(); | 563 | cmos_do_shutdown(); |
| 562 | 564 | ||
| 563 | if (is_pnp()) | ||
| 564 | release_resource(cmos->iomem); | ||
| 565 | rename_region(cmos->iomem, NULL); | ||
| 566 | |||
| 567 | if (is_valid_irq(cmos->irq)) | 565 | if (is_valid_irq(cmos->irq)) |
| 568 | free_irq(cmos->irq, cmos_rtc.rtc); | 566 | free_irq(cmos->irq, cmos->rtc); |
| 569 | 567 | ||
| 570 | rtc_device_unregister(cmos_rtc.rtc); | 568 | rtc_device_unregister(cmos->rtc); |
| 569 | cmos->rtc = NULL; | ||
| 571 | 570 | ||
| 572 | cmos_rtc.dev = NULL; | 571 | ports = cmos->iomem; |
| 572 | release_region(ports->start, ports->end + 1 - ports->start); | ||
| 573 | cmos->iomem = NULL; | ||
| 574 | |||
| 575 | cmos->dev = NULL; | ||
| 573 | dev_set_drvdata(dev, NULL); | 576 | dev_set_drvdata(dev, NULL); |
| 574 | } | 577 | } |
| 575 | 578 | ||
| @@ -656,7 +659,8 @@ static int cmos_resume(struct device *dev) | |||
| 656 | /*----------------------------------------------------------------*/ | 659 | /*----------------------------------------------------------------*/ |
| 657 | 660 | ||
| 658 | /* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems, | 661 | /* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems, |
| 659 | * the device node will always be created as a PNPACPI device. | 662 | * the device node will always be created as a PNPACPI device. Plus |
| 663 | * pre-ACPI PCs probably list it in the PNPBIOS tables. | ||
| 660 | */ | 664 | */ |
| 661 | 665 | ||
| 662 | #ifdef CONFIG_PNP | 666 | #ifdef CONFIG_PNP |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 005fff3a3508..814583bd2fe7 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
| @@ -142,7 +142,7 @@ static int set_uie(struct rtc_device *rtc) | |||
| 142 | static ssize_t | 142 | static ssize_t |
| 143 | rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 143 | rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) |
| 144 | { | 144 | { |
| 145 | struct rtc_device *rtc = to_rtc_device(file->private_data); | 145 | struct rtc_device *rtc = file->private_data; |
| 146 | 146 | ||
| 147 | DECLARE_WAITQUEUE(wait, current); | 147 | DECLARE_WAITQUEUE(wait, current); |
| 148 | unsigned long data; | 148 | unsigned long data; |
| @@ -196,7 +196,7 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 196 | 196 | ||
| 197 | static unsigned int rtc_dev_poll(struct file *file, poll_table *wait) | 197 | static unsigned int rtc_dev_poll(struct file *file, poll_table *wait) |
| 198 | { | 198 | { |
| 199 | struct rtc_device *rtc = to_rtc_device(file->private_data); | 199 | struct rtc_device *rtc = file->private_data; |
| 200 | unsigned long data; | 200 | unsigned long data; |
| 201 | 201 | ||
| 202 | poll_wait(file, &rtc->irq_queue, wait); | 202 | poll_wait(file, &rtc->irq_queue, wait); |
| @@ -233,22 +233,12 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 233 | break; | 233 | break; |
| 234 | 234 | ||
| 235 | case RTC_PIE_ON: | 235 | case RTC_PIE_ON: |
| 236 | if (!capable(CAP_SYS_RESOURCE)) | 236 | if (rtc->irq_freq > rtc->max_user_freq && |
| 237 | !capable(CAP_SYS_RESOURCE)) | ||
| 237 | return -EACCES; | 238 | return -EACCES; |
| 238 | break; | 239 | break; |
| 239 | } | 240 | } |
| 240 | 241 | ||
| 241 | /* avoid conflicting IRQ users */ | ||
| 242 | if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) { | ||
| 243 | spin_lock_irq(&rtc->irq_task_lock); | ||
| 244 | if (rtc->irq_task) | ||
| 245 | err = -EBUSY; | ||
| 246 | spin_unlock_irq(&rtc->irq_task_lock); | ||
| 247 | |||
| 248 | if (err < 0) | ||
| 249 | return err; | ||
| 250 | } | ||
| 251 | |||
| 252 | /* try the driver's ioctl interface */ | 242 | /* try the driver's ioctl interface */ |
| 253 | if (ops->ioctl) { | 243 | if (ops->ioctl) { |
| 254 | err = ops->ioctl(rtc->dev.parent, cmd, arg); | 244 | err = ops->ioctl(rtc->dev.parent, cmd, arg); |
| @@ -338,18 +328,20 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 338 | err = rtc_set_time(rtc, &tm); | 328 | err = rtc_set_time(rtc, &tm); |
| 339 | break; | 329 | break; |
| 340 | 330 | ||
| 341 | case RTC_IRQP_READ: | 331 | case RTC_PIE_ON: |
| 342 | if (ops->irq_set_freq) | 332 | err = rtc_irq_set_state(rtc, NULL, 1); |
| 343 | err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); | 333 | break; |
| 344 | else | 334 | |
| 345 | err = -ENOTTY; | 335 | case RTC_PIE_OFF: |
| 336 | err = rtc_irq_set_state(rtc, NULL, 0); | ||
| 346 | break; | 337 | break; |
| 347 | 338 | ||
| 348 | case RTC_IRQP_SET: | 339 | case RTC_IRQP_SET: |
| 349 | if (ops->irq_set_freq) | 340 | err = rtc_irq_set_freq(rtc, NULL, arg); |
| 350 | err = rtc_irq_set_freq(rtc, rtc->irq_task, arg); | 341 | break; |
| 351 | else | 342 | |
| 352 | err = -ENOTTY; | 343 | case RTC_IRQP_READ: |
| 344 | err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); | ||
| 353 | break; | 345 | break; |
| 354 | 346 | ||
| 355 | #if 0 | 347 | #if 0 |
| @@ -405,7 +397,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
| 405 | 397 | ||
| 406 | static int rtc_dev_release(struct inode *inode, struct file *file) | 398 | static int rtc_dev_release(struct inode *inode, struct file *file) |
| 407 | { | 399 | { |
| 408 | struct rtc_device *rtc = to_rtc_device(file->private_data); | 400 | struct rtc_device *rtc = file->private_data; |
| 409 | 401 | ||
| 410 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 402 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL |
| 411 | clear_uie(rtc); | 403 | clear_uie(rtc); |
| @@ -419,7 +411,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) | |||
| 419 | 411 | ||
| 420 | static int rtc_dev_fasync(int fd, struct file *file, int on) | 412 | static int rtc_dev_fasync(int fd, struct file *file, int on) |
| 421 | { | 413 | { |
| 422 | struct rtc_device *rtc = to_rtc_device(file->private_data); | 414 | struct rtc_device *rtc = file->private_data; |
| 423 | return fasync_helper(fd, file, on, &rtc->async_queue); | 415 | return fasync_helper(fd, file, on, &rtc->async_queue); |
| 424 | } | 416 | } |
| 425 | 417 | ||
| @@ -449,8 +441,6 @@ void rtc_dev_prepare(struct rtc_device *rtc) | |||
| 449 | rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); | 441 | rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); |
| 450 | 442 | ||
| 451 | mutex_init(&rtc->char_lock); | 443 | mutex_init(&rtc->char_lock); |
| 452 | spin_lock_init(&rtc->irq_lock); | ||
| 453 | init_waitqueue_head(&rtc->irq_queue); | ||
| 454 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 444 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL |
| 455 | INIT_WORK(&rtc->uie_task, rtc_uie_task); | 445 | INIT_WORK(&rtc->uie_task, rtc_uie_task); |
| 456 | setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); | 446 | setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c new file mode 100644 index 000000000000..45bda186befc --- /dev/null +++ b/drivers/rtc/rtc-ds1374.c | |||
| @@ -0,0 +1,449 @@ | |||
| 1 | /* | ||
| 2 | * RTC client/driver for the Maxim/Dallas DS1374 Real-Time Clock over I2C | ||
| 3 | * | ||
| 4 | * Based on code by Randy Vinson <rvinson@mvista.com>, | ||
| 5 | * which was based on the m41t00.c by Mark Greer <mgreer@mvista.com>. | ||
| 6 | * | ||
| 7 | * Copyright (C) 2006-2007 Freescale Semiconductor | ||
| 8 | * | ||
| 9 | * 2005 (c) MontaVista Software, Inc. This file is licensed under | ||
| 10 | * the terms of the GNU General Public License version 2. This program | ||
| 11 | * is licensed "as is" without any warranty of any kind, whether express | ||
| 12 | * or implied. | ||
| 13 | */ | ||
| 14 | /* | ||
| 15 | * It would be more efficient to use i2c msgs/i2c_transfer directly but, as | ||
| 16 | * recommened in .../Documentation/i2c/writing-clients section | ||
| 17 | * "Sending and receiving", using SMBus level communication is preferred. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/i2c.h> | ||
| 24 | #include <linux/rtc.h> | ||
| 25 | #include <linux/bcd.h> | ||
| 26 | #include <linux/workqueue.h> | ||
| 27 | |||
| 28 | #define DS1374_REG_TOD0 0x00 /* Time of Day */ | ||
| 29 | #define DS1374_REG_TOD1 0x01 | ||
| 30 | #define DS1374_REG_TOD2 0x02 | ||
| 31 | #define DS1374_REG_TOD3 0x03 | ||
| 32 | #define DS1374_REG_WDALM0 0x04 /* Watchdog/Alarm */ | ||
| 33 | #define DS1374_REG_WDALM1 0x05 | ||
| 34 | #define DS1374_REG_WDALM2 0x06 | ||
| 35 | #define DS1374_REG_CR 0x07 /* Control */ | ||
| 36 | #define DS1374_REG_CR_AIE 0x01 /* Alarm Int. Enable */ | ||
| 37 | #define DS1374_REG_CR_WDALM 0x20 /* 1=Watchdog, 0=Alarm */ | ||
| 38 | #define DS1374_REG_CR_WACE 0x40 /* WD/Alarm counter enable */ | ||
| 39 | #define DS1374_REG_SR 0x08 /* Status */ | ||
| 40 | #define DS1374_REG_SR_OSF 0x80 /* Oscillator Stop Flag */ | ||
| 41 | #define DS1374_REG_SR_AF 0x01 /* Alarm Flag */ | ||
| 42 | #define DS1374_REG_TCR 0x09 /* Trickle Charge */ | ||
| 43 | |||
| 44 | struct ds1374 { | ||
| 45 | struct i2c_client *client; | ||
| 46 | struct rtc_device *rtc; | ||
| 47 | struct work_struct work; | ||
| 48 | |||
| 49 | /* The mutex protects alarm operations, and prevents a race | ||
| 50 | * between the enable_irq() in the workqueue and the free_irq() | ||
| 51 | * in the remove function. | ||
| 52 | */ | ||
| 53 | struct mutex mutex; | ||
| 54 | int exiting; | ||
| 55 | }; | ||
| 56 | |||
| 57 | static struct i2c_driver ds1374_driver; | ||
| 58 | |||
| 59 | static int ds1374_read_rtc(struct i2c_client *client, u32 *time, | ||
| 60 | int reg, int nbytes) | ||
| 61 | { | ||
| 62 | u8 buf[4]; | ||
| 63 | int ret; | ||
| 64 | int i; | ||
| 65 | |||
| 66 | if (nbytes > 4) { | ||
| 67 | WARN_ON(1); | ||
| 68 | return -EINVAL; | ||
| 69 | } | ||
| 70 | |||
| 71 | ret = i2c_smbus_read_i2c_block_data(client, reg, nbytes, buf); | ||
| 72 | |||
| 73 | if (ret < 0) | ||
| 74 | return ret; | ||
| 75 | if (ret < nbytes) | ||
| 76 | return -EIO; | ||
| 77 | |||
| 78 | for (i = nbytes - 1, *time = 0; i >= 0; i--) | ||
| 79 | *time = (*time << 8) | buf[i]; | ||
| 80 | |||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | static int ds1374_write_rtc(struct i2c_client *client, u32 time, | ||
| 85 | int reg, int nbytes) | ||
| 86 | { | ||
| 87 | u8 buf[4]; | ||
| 88 | int i; | ||
| 89 | |||
| 90 | if (nbytes > 4) { | ||
| 91 | WARN_ON(1); | ||
| 92 | return -EINVAL; | ||
| 93 | } | ||
| 94 | |||
| 95 | for (i = 0; i < nbytes; i++) { | ||
| 96 | buf[i] = time & 0xff; | ||
| 97 | time >>= 8; | ||
| 98 | } | ||
| 99 | |||
| 100 | return i2c_smbus_write_i2c_block_data(client, reg, nbytes, buf); | ||
| 101 | } | ||
| 102 | |||
| 103 | static int ds1374_check_rtc_status(struct i2c_client *client) | ||
| 104 | { | ||
| 105 | int ret = 0; | ||
| 106 | int control, stat; | ||
| 107 | |||
| 108 | stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); | ||
| 109 | if (stat < 0) | ||
| 110 | return stat; | ||
| 111 | |||
| 112 | if (stat & DS1374_REG_SR_OSF) | ||
| 113 | dev_warn(&client->dev, | ||
| 114 | "oscillator discontinuity flagged, " | ||
| 115 | "time unreliable\n"); | ||
| 116 | |||
| 117 | stat &= ~(DS1374_REG_SR_OSF | DS1374_REG_SR_AF); | ||
| 118 | |||
| 119 | ret = i2c_smbus_write_byte_data(client, DS1374_REG_SR, stat); | ||
| 120 | if (ret < 0) | ||
| 121 | return ret; | ||
| 122 | |||
| 123 | /* If the alarm is pending, clear it before requesting | ||
| 124 | * the interrupt, so an interrupt event isn't reported | ||
| 125 | * before everything is initialized. | ||
| 126 | */ | ||
| 127 | |||
| 128 | control = i2c_smbus_read_byte_data(client, DS1374_REG_CR); | ||
| 129 | if (control < 0) | ||
| 130 | return control; | ||
| 131 | |||
| 132 | control &= ~(DS1374_REG_CR_WACE | DS1374_REG_CR_AIE); | ||
| 133 | return i2c_smbus_write_byte_data(client, DS1374_REG_CR, control); | ||
| 134 | } | ||
| 135 | |||
| 136 | static int ds1374_read_time(struct device *dev, struct rtc_time *time) | ||
| 137 | { | ||
| 138 | struct i2c_client *client = to_i2c_client(dev); | ||
| 139 | u32 itime; | ||
| 140 | int ret; | ||
| 141 | |||
| 142 | ret = ds1374_read_rtc(client, &itime, DS1374_REG_TOD0, 4); | ||
| 143 | if (!ret) | ||
| 144 | rtc_time_to_tm(itime, time); | ||
| 145 | |||
| 146 | return ret; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int ds1374_set_time(struct device *dev, struct rtc_time *time) | ||
| 150 | { | ||
| 151 | struct i2c_client *client = to_i2c_client(dev); | ||
| 152 | unsigned long itime; | ||
| 153 | |||
| 154 | rtc_tm_to_time(time, &itime); | ||
| 155 | return ds1374_write_rtc(client, itime, DS1374_REG_TOD0, 4); | ||
| 156 | } | ||
| 157 | |||
| 158 | /* The ds1374 has a decrementer for an alarm, rather than a comparator. | ||
| 159 | * If the time of day is changed, then the alarm will need to be | ||
| 160 | * reset. | ||
| 161 | */ | ||
| 162 | static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 163 | { | ||
| 164 | struct i2c_client *client = to_i2c_client(dev); | ||
| 165 | struct ds1374 *ds1374 = i2c_get_clientdata(client); | ||
| 166 | u32 now, cur_alarm; | ||
| 167 | int cr, sr; | ||
| 168 | int ret = 0; | ||
| 169 | |||
| 170 | if (client->irq < 0) | ||
| 171 | return -EINVAL; | ||
| 172 | |||
| 173 | mutex_lock(&ds1374->mutex); | ||
| 174 | |||
| 175 | cr = ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); | ||
| 176 | if (ret < 0) | ||
| 177 | goto out; | ||
| 178 | |||
| 179 | sr = ret = i2c_smbus_read_byte_data(client, DS1374_REG_SR); | ||
| 180 | if (ret < 0) | ||
| 181 | goto out; | ||
| 182 | |||
| 183 | ret = ds1374_read_rtc(client, &now, DS1374_REG_TOD0, 4); | ||
| 184 | if (ret) | ||
| 185 | goto out; | ||
| 186 | |||
| 187 | ret = ds1374_read_rtc(client, &cur_alarm, DS1374_REG_WDALM0, 3); | ||
| 188 | if (ret) | ||
| 189 | goto out; | ||
| 190 | |||
| 191 | rtc_time_to_tm(now + cur_alarm, &alarm->time); | ||
| 192 | alarm->enabled = !!(cr & DS1374_REG_CR_WACE); | ||
| 193 | alarm->pending = !!(sr & DS1374_REG_SR_AF); | ||
| 194 | |||
| 195 | out: | ||
| 196 | mutex_unlock(&ds1374->mutex); | ||
| 197 | return ret; | ||
| 198 | } | ||
| 199 | |||
| 200 | static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 201 | { | ||
| 202 | struct i2c_client *client = to_i2c_client(dev); | ||
| 203 | struct ds1374 *ds1374 = i2c_get_clientdata(client); | ||
| 204 | struct rtc_time now; | ||
| 205 | unsigned long new_alarm, itime; | ||
| 206 | int cr; | ||
| 207 | int ret = 0; | ||
| 208 | |||
| 209 | if (client->irq < 0) | ||
| 210 | return -EINVAL; | ||
| 211 | |||
| 212 | ret = ds1374_read_time(dev, &now); | ||
| 213 | if (ret < 0) | ||
| 214 | return ret; | ||
| 215 | |||
| 216 | rtc_tm_to_time(&alarm->time, &new_alarm); | ||
| 217 | rtc_tm_to_time(&now, &itime); | ||
| 218 | |||
| 219 | new_alarm -= itime; | ||
| 220 | |||
| 221 | /* This can happen due to races, in addition to dates that are | ||
| 222 | * truly in the past. To avoid requiring the caller to check for | ||
| 223 | * races, dates in the past are assumed to be in the recent past | ||
| 224 | * (i.e. not something that we'd rather the caller know about via | ||
| 225 | * an error), and the alarm is set to go off as soon as possible. | ||
| 226 | */ | ||
| 227 | if (new_alarm <= 0) | ||
| 228 | new_alarm = 1; | ||
| 229 | |||
| 230 | mutex_lock(&ds1374->mutex); | ||
| 231 | |||
| 232 | ret = cr = i2c_smbus_read_byte_data(client, DS1374_REG_CR); | ||
| 233 | if (ret < 0) | ||
| 234 | goto out; | ||
| 235 | |||
| 236 | /* Disable any existing alarm before setting the new one | ||
| 237 | * (or lack thereof). */ | ||
| 238 | cr &= ~DS1374_REG_CR_WACE; | ||
| 239 | |||
| 240 | ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, cr); | ||
| 241 | if (ret < 0) | ||
| 242 | goto out; | ||
| 243 | |||
| 244 | ret = ds1374_write_rtc(client, new_alarm, DS1374_REG_WDALM0, 3); | ||
| 245 | if (ret) | ||
| 246 | goto out; | ||
| 247 | |||
| 248 | if (alarm->enabled) { | ||
| 249 | cr |= DS1374_REG_CR_WACE | DS1374_REG_CR_AIE; | ||
| 250 | cr &= ~DS1374_REG_CR_WDALM; | ||
| 251 | |||
| 252 | ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, cr); | ||
| 253 | } | ||
| 254 | |||
| 255 | out: | ||
| 256 | mutex_unlock(&ds1374->mutex); | ||
| 257 | return ret; | ||
| 258 | } | ||
| 259 | |||
| 260 | static irqreturn_t ds1374_irq(int irq, void *dev_id) | ||
| 261 | { | ||
| 262 | struct i2c_client *client = dev_id; | ||
| 263 | struct ds1374 *ds1374 = i2c_get_clientdata(client); | ||
| 264 | |||
| 265 | disable_irq_nosync(irq); | ||
| 266 | schedule_work(&ds1374->work); | ||
| 267 | return IRQ_HANDLED; | ||
| 268 | } | ||
| 269 | |||
| 270 | static void ds1374_work(struct work_struct *work) | ||
| 271 | { | ||
| 272 | struct ds1374 *ds1374 = container_of(work, struct ds1374, work); | ||
| 273 | struct i2c_client *client = ds1374->client; | ||
| 274 | int stat, control; | ||
| 275 | |||
| 276 | mutex_lock(&ds1374->mutex); | ||
| 277 | |||
| 278 | stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); | ||
| 279 | if (stat < 0) | ||
| 280 | return; | ||
| 281 | |||
| 282 | if (stat & DS1374_REG_SR_AF) { | ||
| 283 | stat &= ~DS1374_REG_SR_AF; | ||
| 284 | i2c_smbus_write_byte_data(client, DS1374_REG_SR, stat); | ||
| 285 | |||
| 286 | control = i2c_smbus_read_byte_data(client, DS1374_REG_CR); | ||
| 287 | if (control < 0) | ||
| 288 | goto out; | ||
| 289 | |||
| 290 | control &= ~(DS1374_REG_CR_WACE | DS1374_REG_CR_AIE); | ||
| 291 | i2c_smbus_write_byte_data(client, DS1374_REG_CR, control); | ||
| 292 | |||
| 293 | /* rtc_update_irq() assumes that it is called | ||
| 294 | * from IRQ-disabled context. | ||
| 295 | */ | ||
| 296 | local_irq_disable(); | ||
| 297 | rtc_update_irq(ds1374->rtc, 1, RTC_AF | RTC_IRQF); | ||
| 298 | local_irq_enable(); | ||
| 299 | } | ||
| 300 | |||
| 301 | out: | ||
| 302 | if (!ds1374->exiting) | ||
| 303 | enable_irq(client->irq); | ||
| 304 | |||
| 305 | mutex_unlock(&ds1374->mutex); | ||
| 306 | } | ||
| 307 | |||
| 308 | static int ds1374_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
| 309 | { | ||
| 310 | struct i2c_client *client = to_i2c_client(dev); | ||
| 311 | struct ds1374 *ds1374 = i2c_get_clientdata(client); | ||
| 312 | int ret = -ENOIOCTLCMD; | ||
| 313 | |||
| 314 | mutex_lock(&ds1374->mutex); | ||
| 315 | |||
| 316 | switch (cmd) { | ||
| 317 | case RTC_AIE_OFF: | ||
| 318 | ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); | ||
| 319 | if (ret < 0) | ||
| 320 | goto out; | ||
| 321 | |||
| 322 | ret &= ~DS1374_REG_CR_WACE; | ||
| 323 | |||
| 324 | ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); | ||
| 325 | if (ret < 0) | ||
| 326 | goto out; | ||
| 327 | |||
| 328 | break; | ||
| 329 | |||
| 330 | case RTC_AIE_ON: | ||
| 331 | ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); | ||
| 332 | if (ret < 0) | ||
| 333 | goto out; | ||
| 334 | |||
| 335 | ret |= DS1374_REG_CR_WACE | DS1374_REG_CR_AIE; | ||
| 336 | ret &= ~DS1374_REG_CR_WDALM; | ||
| 337 | |||
| 338 | ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); | ||
| 339 | if (ret < 0) | ||
| 340 | goto out; | ||
| 341 | |||
| 342 | break; | ||
| 343 | } | ||
| 344 | |||
| 345 | out: | ||
| 346 | mutex_unlock(&ds1374->mutex); | ||
| 347 | return ret; | ||
| 348 | } | ||
| 349 | |||
| 350 | static const struct rtc_class_ops ds1374_rtc_ops = { | ||
| 351 | .read_time = ds1374_read_time, | ||
| 352 | .set_time = ds1374_set_time, | ||
| 353 | .read_alarm = ds1374_read_alarm, | ||
| 354 | .set_alarm = ds1374_set_alarm, | ||
| 355 | .ioctl = ds1374_ioctl, | ||
| 356 | }; | ||
| 357 | |||
| 358 | static int ds1374_probe(struct i2c_client *client) | ||
| 359 | { | ||
| 360 | struct ds1374 *ds1374; | ||
| 361 | int ret; | ||
| 362 | |||
| 363 | ds1374 = kzalloc(sizeof(struct ds1374), GFP_KERNEL); | ||
| 364 | if (!ds1374) | ||
| 365 | return -ENOMEM; | ||
| 366 | |||
| 367 | ds1374->client = client; | ||
| 368 | i2c_set_clientdata(client, ds1374); | ||
| 369 | |||
| 370 | INIT_WORK(&ds1374->work, ds1374_work); | ||
| 371 | mutex_init(&ds1374->mutex); | ||
| 372 | |||
| 373 | ret = ds1374_check_rtc_status(client); | ||
| 374 | if (ret) | ||
| 375 | goto out_free; | ||
| 376 | |||
| 377 | if (client->irq >= 0) { | ||
| 378 | ret = request_irq(client->irq, ds1374_irq, 0, | ||
| 379 | "ds1374", client); | ||
| 380 | if (ret) { | ||
| 381 | dev_err(&client->dev, "unable to request IRQ\n"); | ||
| 382 | goto out_free; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | ds1374->rtc = rtc_device_register(client->name, &client->dev, | ||
| 387 | &ds1374_rtc_ops, THIS_MODULE); | ||
| 388 | if (IS_ERR(ds1374->rtc)) { | ||
| 389 | ret = PTR_ERR(ds1374->rtc); | ||
| 390 | dev_err(&client->dev, "unable to register the class device\n"); | ||
| 391 | goto out_irq; | ||
| 392 | } | ||
| 393 | |||
| 394 | return 0; | ||
| 395 | |||
| 396 | out_irq: | ||
| 397 | if (client->irq >= 0) | ||
| 398 | free_irq(client->irq, client); | ||
| 399 | |||
| 400 | out_free: | ||
| 401 | i2c_set_clientdata(client, NULL); | ||
| 402 | kfree(ds1374); | ||
| 403 | return ret; | ||
| 404 | } | ||
| 405 | |||
| 406 | static int __devexit ds1374_remove(struct i2c_client *client) | ||
| 407 | { | ||
| 408 | struct ds1374 *ds1374 = i2c_get_clientdata(client); | ||
| 409 | |||
| 410 | if (client->irq >= 0) { | ||
| 411 | mutex_lock(&ds1374->mutex); | ||
| 412 | ds1374->exiting = 1; | ||
| 413 | mutex_unlock(&ds1374->mutex); | ||
| 414 | |||
| 415 | free_irq(client->irq, client); | ||
| 416 | flush_scheduled_work(); | ||
| 417 | } | ||
| 418 | |||
| 419 | rtc_device_unregister(ds1374->rtc); | ||
| 420 | i2c_set_clientdata(client, NULL); | ||
| 421 | kfree(ds1374); | ||
| 422 | return 0; | ||
| 423 | } | ||
| 424 | |||
| 425 | static struct i2c_driver ds1374_driver = { | ||
| 426 | .driver = { | ||
| 427 | .name = "rtc-ds1374", | ||
| 428 | .owner = THIS_MODULE, | ||
| 429 | }, | ||
| 430 | .probe = ds1374_probe, | ||
| 431 | .remove = __devexit_p(ds1374_remove), | ||
| 432 | }; | ||
| 433 | |||
| 434 | static int __init ds1374_init(void) | ||
| 435 | { | ||
| 436 | return i2c_add_driver(&ds1374_driver); | ||
| 437 | } | ||
| 438 | |||
| 439 | static void __exit ds1374_exit(void) | ||
| 440 | { | ||
| 441 | i2c_del_driver(&ds1374_driver); | ||
| 442 | } | ||
| 443 | |||
| 444 | module_init(ds1374_init); | ||
| 445 | module_exit(ds1374_exit); | ||
| 446 | |||
| 447 | MODULE_AUTHOR("Scott Wood <scottwood@freescale.com>"); | ||
| 448 | MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC Driver"); | ||
| 449 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 5ab3492817d1..bb53c09bad16 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
| @@ -395,7 +395,7 @@ static struct platform_driver ds1553_rtc_driver = { | |||
| 395 | .probe = ds1553_rtc_probe, | 395 | .probe = ds1553_rtc_probe, |
| 396 | .remove = __devexit_p(ds1553_rtc_remove), | 396 | .remove = __devexit_p(ds1553_rtc_remove), |
| 397 | .driver = { | 397 | .driver = { |
| 398 | .name = "ds1553", | 398 | .name = "rtc-ds1553", |
| 399 | .owner = THIS_MODULE, | 399 | .owner = THIS_MODULE, |
| 400 | }, | 400 | }, |
| 401 | }; | 401 | }; |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 67291b0f8283..c535b78698e2 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
| @@ -251,7 +251,7 @@ static struct platform_driver ds1742_rtc_driver = { | |||
| 251 | .probe = ds1742_rtc_probe, | 251 | .probe = ds1742_rtc_probe, |
| 252 | .remove = __devexit_p(ds1742_rtc_remove), | 252 | .remove = __devexit_p(ds1742_rtc_remove), |
| 253 | .driver = { | 253 | .driver = { |
| 254 | .name = "ds1742", | 254 | .name = "rtc-ds1742", |
| 255 | .owner = THIS_MODULE, | 255 | .owner = THIS_MODULE, |
| 256 | }, | 256 | }, |
| 257 | }; | 257 | }; |
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index d48b03374586..556d0e7da35b 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
| @@ -332,6 +332,9 @@ static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind) | |||
| 332 | } | 332 | } |
| 333 | }; | 333 | }; |
| 334 | 334 | ||
| 335 | if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) | ||
| 336 | return 0; | ||
| 337 | |||
| 335 | pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); | 338 | pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); |
| 336 | if (!pcf) | 339 | if (!pcf) |
| 337 | return -ENOMEM; | 340 | return -ENOMEM; |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index e4bf68ca96f7..2fd49edcc712 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
| @@ -21,11 +21,11 @@ | |||
| 21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
| 22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
| 23 | #include <linux/pm.h> | 23 | #include <linux/pm.h> |
| 24 | #include <linux/bitops.h> | ||
| 24 | 25 | ||
| 25 | #include <linux/amba/bus.h> | 26 | #include <linux/amba/bus.h> |
| 26 | 27 | ||
| 27 | #include <asm/io.h> | 28 | #include <asm/io.h> |
| 28 | #include <asm/bitops.h> | ||
| 29 | #include <asm/hardware.h> | 29 | #include <asm/hardware.h> |
| 30 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
| 31 | #include <asm/rtc.h> | 31 | #include <asm/rtc.h> |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 0918b787c4dd..6f1e9a9804bc 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
| @@ -29,8 +29,8 @@ | |||
| 29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
| 30 | #include <linux/string.h> | 30 | #include <linux/string.h> |
| 31 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
| 32 | #include <linux/bitops.h> | ||
| 32 | 33 | ||
| 33 | #include <asm/bitops.h> | ||
| 34 | #include <asm/hardware.h> | 34 | #include <asm/hardware.h> |
| 35 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
| 36 | #include <asm/rtc.h> | 36 | #include <asm/rtc.h> |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 93ee05eeaeba..78277a118b67 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * SuperH On-Chip RTC Support | 2 | * SuperH On-Chip RTC Support |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2006 Paul Mundt | 4 | * Copyright (C) 2006, 2007 Paul Mundt |
| 5 | * Copyright (C) 2006 Jamie Lenehan | 5 | * Copyright (C) 2006 Jamie Lenehan |
| 6 | * | 6 | * |
| 7 | * Based on the old arch/sh/kernel/cpu/rtc.c by: | 7 | * Based on the old arch/sh/kernel/cpu/rtc.c by: |
| @@ -23,16 +23,19 @@ | |||
| 23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| 24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
| 25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| 26 | #include <asm/rtc.h> | ||
| 26 | 27 | ||
| 27 | #define DRV_NAME "sh-rtc" | 28 | #define DRV_NAME "sh-rtc" |
| 28 | #define DRV_VERSION "0.1.2" | 29 | #define DRV_VERSION "0.1.3" |
| 29 | 30 | ||
| 30 | #ifdef CONFIG_CPU_SH3 | 31 | #ifdef CONFIG_CPU_SH3 |
| 31 | #define rtc_reg_size sizeof(u16) | 32 | #define rtc_reg_size sizeof(u16) |
| 32 | #define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */ | 33 | #define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */ |
| 34 | #define RTC_DEF_CAPABILITIES 0UL | ||
| 33 | #elif defined(CONFIG_CPU_SH4) | 35 | #elif defined(CONFIG_CPU_SH4) |
| 34 | #define rtc_reg_size sizeof(u32) | 36 | #define rtc_reg_size sizeof(u32) |
| 35 | #define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */ | 37 | #define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */ |
| 38 | #define RTC_DEF_CAPABILITIES RTC_CAP_4_DIGIT_YEAR | ||
| 36 | #endif | 39 | #endif |
| 37 | 40 | ||
| 38 | #define RTC_REG(r) ((r) * rtc_reg_size) | 41 | #define RTC_REG(r) ((r) * rtc_reg_size) |
| @@ -80,6 +83,7 @@ struct sh_rtc { | |||
| 80 | struct rtc_device *rtc_dev; | 83 | struct rtc_device *rtc_dev; |
| 81 | spinlock_t lock; | 84 | spinlock_t lock; |
| 82 | int rearm_aie; | 85 | int rearm_aie; |
| 86 | unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */ | ||
| 83 | }; | 87 | }; |
| 84 | 88 | ||
| 85 | static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) | 89 | static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) |
| @@ -319,14 +323,14 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 319 | tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT)); | 323 | tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT)); |
| 320 | tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1; | 324 | tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1; |
| 321 | 325 | ||
| 322 | #if defined(CONFIG_CPU_SH4) | 326 | if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) { |
| 323 | yr = readw(rtc->regbase + RYRCNT); | 327 | yr = readw(rtc->regbase + RYRCNT); |
| 324 | yr100 = BCD2BIN(yr >> 8); | 328 | yr100 = BCD2BIN(yr >> 8); |
| 325 | yr &= 0xff; | 329 | yr &= 0xff; |
| 326 | #else | 330 | } else { |
| 327 | yr = readb(rtc->regbase + RYRCNT); | 331 | yr = readb(rtc->regbase + RYRCNT); |
| 328 | yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20); | 332 | yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20); |
| 329 | #endif | 333 | } |
| 330 | 334 | ||
| 331 | tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900; | 335 | tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900; |
| 332 | 336 | ||
| @@ -375,14 +379,14 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 375 | writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT); | 379 | writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT); |
| 376 | writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT); | 380 | writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT); |
| 377 | 381 | ||
| 378 | #ifdef CONFIG_CPU_SH3 | 382 | if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) { |
| 379 | year = tm->tm_year % 100; | 383 | year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) | |
| 380 | writeb(BIN2BCD(year), rtc->regbase + RYRCNT); | 384 | BIN2BCD(tm->tm_year % 100); |
| 381 | #else | 385 | writew(year, rtc->regbase + RYRCNT); |
| 382 | year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) | | 386 | } else { |
| 383 | BIN2BCD(tm->tm_year % 100); | 387 | year = tm->tm_year % 100; |
| 384 | writew(year, rtc->regbase + RYRCNT); | 388 | writeb(BIN2BCD(year), rtc->regbase + RYRCNT); |
| 385 | #endif | 389 | } |
| 386 | 390 | ||
| 387 | /* Start RTC */ | 391 | /* Start RTC */ |
| 388 | tmp = readb(rtc->regbase + RCR2); | 392 | tmp = readb(rtc->regbase + RCR2); |
| @@ -589,6 +593,17 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
| 589 | goto err_badmap; | 593 | goto err_badmap; |
| 590 | } | 594 | } |
| 591 | 595 | ||
| 596 | rtc->capabilities = RTC_DEF_CAPABILITIES; | ||
| 597 | if (pdev->dev.platform_data) { | ||
| 598 | struct sh_rtc_platform_info *pinfo = pdev->dev.platform_data; | ||
| 599 | |||
| 600 | /* | ||
| 601 | * Some CPUs have special capabilities in addition to the | ||
| 602 | * default set. Add those in here. | ||
| 603 | */ | ||
| 604 | rtc->capabilities |= pinfo->capabilities; | ||
| 605 | } | ||
| 606 | |||
| 592 | platform_set_drvdata(pdev, rtc); | 607 | platform_set_drvdata(pdev, rtc); |
| 593 | 608 | ||
| 594 | return 0; | 609 | return 0; |
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 69df94b44841..2ae0e8304d3a 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
| @@ -73,11 +73,35 @@ rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr, | |||
| 73 | return retval; | 73 | return retval; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static ssize_t | ||
| 77 | rtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr, | ||
| 78 | char *buf) | ||
| 79 | { | ||
| 80 | return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq); | ||
| 81 | } | ||
| 82 | |||
| 83 | static ssize_t | ||
| 84 | rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, | ||
| 85 | const char *buf, size_t n) | ||
| 86 | { | ||
| 87 | struct rtc_device *rtc = to_rtc_device(dev); | ||
| 88 | unsigned long val = simple_strtoul(buf, NULL, 0); | ||
| 89 | |||
| 90 | if (val >= 4096 || val == 0) | ||
| 91 | return -EINVAL; | ||
| 92 | |||
| 93 | rtc->max_user_freq = (int)val; | ||
| 94 | |||
| 95 | return n; | ||
| 96 | } | ||
| 97 | |||
| 76 | static struct device_attribute rtc_attrs[] = { | 98 | static struct device_attribute rtc_attrs[] = { |
| 77 | __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), | 99 | __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), |
| 78 | __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), | 100 | __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), |
| 79 | __ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL), | 101 | __ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL), |
| 80 | __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), | 102 | __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), |
| 103 | __ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq, | ||
| 104 | rtc_sysfs_set_max_user_freq), | ||
| 81 | { }, | 105 | { }, |
| 82 | }; | 106 | }; |
| 83 | 107 | ||
| @@ -176,9 +200,8 @@ void rtc_sysfs_add_device(struct rtc_device *rtc) | |||
| 176 | 200 | ||
| 177 | err = device_create_file(&rtc->dev, &dev_attr_wakealarm); | 201 | err = device_create_file(&rtc->dev, &dev_attr_wakealarm); |
| 178 | if (err) | 202 | if (err) |
| 179 | dev_err(rtc->dev.parent, "failed to create " | 203 | dev_err(rtc->dev.parent, |
| 180 | "alarm attribute, %d", | 204 | "failed to create alarm attribute, %d\n", err); |
| 181 | err); | ||
| 182 | } | 205 | } |
| 183 | 206 | ||
| 184 | void rtc_sysfs_del_device(struct rtc_device *rtc) | 207 | void rtc_sysfs_del_device(struct rtc_device *rtc) |
