diff options
Diffstat (limited to 'drivers')
29 files changed, 1897 insertions, 282 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 56a027d6115e..fb31b8ee4372 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
| @@ -243,14 +243,11 @@ static int nbd_send_req(struct nbd_device *nbd, struct request *req) | |||
| 243 | struct nbd_request request; | 243 | struct nbd_request request; |
| 244 | unsigned long size = blk_rq_bytes(req); | 244 | unsigned long size = blk_rq_bytes(req); |
| 245 | 245 | ||
| 246 | memset(&request, 0, sizeof(request)); | ||
| 246 | request.magic = htonl(NBD_REQUEST_MAGIC); | 247 | request.magic = htonl(NBD_REQUEST_MAGIC); |
| 247 | request.type = htonl(nbd_cmd(req)); | 248 | request.type = htonl(nbd_cmd(req)); |
| 248 | 249 | ||
| 249 | if (nbd_cmd(req) == NBD_CMD_FLUSH) { | 250 | if (nbd_cmd(req) != NBD_CMD_FLUSH && nbd_cmd(req) != NBD_CMD_DISC) { |
| 250 | /* Other values are reserved for FLUSH requests. */ | ||
| 251 | request.from = 0; | ||
| 252 | request.len = 0; | ||
| 253 | } else { | ||
| 254 | request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); | 251 | request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); |
| 255 | request.len = htonl(size); | 252 | request.len = htonl(size); |
| 256 | } | 253 | } |
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 49ac5662585b..2a44767891f5 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c | |||
| @@ -3470,7 +3470,7 @@ static int cdrom_print_info(const char *header, int val, char *info, | |||
| 3470 | return 0; | 3470 | return 0; |
| 3471 | } | 3471 | } |
| 3472 | 3472 | ||
| 3473 | static int cdrom_sysctl_info(ctl_table *ctl, int write, | 3473 | static int cdrom_sysctl_info(struct ctl_table *ctl, int write, |
| 3474 | void __user *buffer, size_t *lenp, loff_t *ppos) | 3474 | void __user *buffer, size_t *lenp, loff_t *ppos) |
| 3475 | { | 3475 | { |
| 3476 | int pos; | 3476 | int pos; |
| @@ -3583,7 +3583,7 @@ static void cdrom_update_settings(void) | |||
| 3583 | mutex_unlock(&cdrom_mutex); | 3583 | mutex_unlock(&cdrom_mutex); |
| 3584 | } | 3584 | } |
| 3585 | 3585 | ||
| 3586 | static int cdrom_sysctl_handler(ctl_table *ctl, int write, | 3586 | static int cdrom_sysctl_handler(struct ctl_table *ctl, int write, |
| 3587 | void __user *buffer, size_t *lenp, loff_t *ppos) | 3587 | void __user *buffer, size_t *lenp, loff_t *ppos) |
| 3588 | { | 3588 | { |
| 3589 | int ret; | 3589 | int ret; |
| @@ -3609,7 +3609,7 @@ static int cdrom_sysctl_handler(ctl_table *ctl, int write, | |||
| 3609 | } | 3609 | } |
| 3610 | 3610 | ||
| 3611 | /* Place files in /proc/sys/dev/cdrom */ | 3611 | /* Place files in /proc/sys/dev/cdrom */ |
| 3612 | static ctl_table cdrom_table[] = { | 3612 | static struct ctl_table cdrom_table[] = { |
| 3613 | { | 3613 | { |
| 3614 | .procname = "info", | 3614 | .procname = "info", |
| 3615 | .data = &cdrom_sysctl_settings.info, | 3615 | .data = &cdrom_sysctl_settings.info, |
| @@ -3655,7 +3655,7 @@ static ctl_table cdrom_table[] = { | |||
| 3655 | { } | 3655 | { } |
| 3656 | }; | 3656 | }; |
| 3657 | 3657 | ||
| 3658 | static ctl_table cdrom_cdrom_table[] = { | 3658 | static struct ctl_table cdrom_cdrom_table[] = { |
| 3659 | { | 3659 | { |
| 3660 | .procname = "cdrom", | 3660 | .procname = "cdrom", |
| 3661 | .maxlen = 0, | 3661 | .maxlen = 0, |
| @@ -3666,7 +3666,7 @@ static ctl_table cdrom_cdrom_table[] = { | |||
| 3666 | }; | 3666 | }; |
| 3667 | 3667 | ||
| 3668 | /* Make sure that /proc/sys/dev is there */ | 3668 | /* Make sure that /proc/sys/dev is there */ |
| 3669 | static ctl_table cdrom_root_table[] = { | 3669 | static struct ctl_table cdrom_root_table[] = { |
| 3670 | { | 3670 | { |
| 3671 | .procname = "dev", | 3671 | .procname = "dev", |
| 3672 | .maxlen = 0, | 3672 | .maxlen = 0, |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 06cea7ff3a7c..4ad71ef2cd59 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -1582,10 +1582,10 @@ static int proc_do_uuid(struct ctl_table *table, int write, | |||
| 1582 | /* | 1582 | /* |
| 1583 | * Return entropy available scaled to integral bits | 1583 | * Return entropy available scaled to integral bits |
| 1584 | */ | 1584 | */ |
| 1585 | static int proc_do_entropy(ctl_table *table, int write, | 1585 | static int proc_do_entropy(struct ctl_table *table, int write, |
| 1586 | void __user *buffer, size_t *lenp, loff_t *ppos) | 1586 | void __user *buffer, size_t *lenp, loff_t *ppos) |
| 1587 | { | 1587 | { |
| 1588 | ctl_table fake_table; | 1588 | struct ctl_table fake_table; |
| 1589 | int entropy_count; | 1589 | int entropy_count; |
| 1590 | 1590 | ||
| 1591 | entropy_count = *(int *)table->data >> ENTROPY_SHIFT; | 1591 | entropy_count = *(int *)table->data >> ENTROPY_SHIFT; |
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index 92ed045a5f93..3b470801a04f 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #define PARPORT_MIN_SPINTIME_VALUE 1 | 31 | #define PARPORT_MIN_SPINTIME_VALUE 1 |
| 32 | #define PARPORT_MAX_SPINTIME_VALUE 1000 | 32 | #define PARPORT_MAX_SPINTIME_VALUE 1000 |
| 33 | 33 | ||
| 34 | static int do_active_device(ctl_table *table, int write, | 34 | static int do_active_device(struct ctl_table *table, int write, |
| 35 | void __user *result, size_t *lenp, loff_t *ppos) | 35 | void __user *result, size_t *lenp, loff_t *ppos) |
| 36 | { | 36 | { |
| 37 | struct parport *port = (struct parport *)table->extra1; | 37 | struct parport *port = (struct parport *)table->extra1; |
| @@ -68,7 +68,7 @@ static int do_active_device(ctl_table *table, int write, | |||
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | #ifdef CONFIG_PARPORT_1284 | 70 | #ifdef CONFIG_PARPORT_1284 |
| 71 | static int do_autoprobe(ctl_table *table, int write, | 71 | static int do_autoprobe(struct ctl_table *table, int write, |
| 72 | void __user *result, size_t *lenp, loff_t *ppos) | 72 | void __user *result, size_t *lenp, loff_t *ppos) |
| 73 | { | 73 | { |
| 74 | struct parport_device_info *info = table->extra2; | 74 | struct parport_device_info *info = table->extra2; |
| @@ -110,9 +110,9 @@ static int do_autoprobe(ctl_table *table, int write, | |||
| 110 | } | 110 | } |
| 111 | #endif /* IEEE1284.3 support. */ | 111 | #endif /* IEEE1284.3 support. */ |
| 112 | 112 | ||
| 113 | static int do_hardware_base_addr (ctl_table *table, int write, | 113 | static int do_hardware_base_addr(struct ctl_table *table, int write, |
| 114 | void __user *result, | 114 | void __user *result, |
| 115 | size_t *lenp, loff_t *ppos) | 115 | size_t *lenp, loff_t *ppos) |
| 116 | { | 116 | { |
| 117 | struct parport *port = (struct parport *)table->extra1; | 117 | struct parport *port = (struct parport *)table->extra1; |
| 118 | char buffer[20]; | 118 | char buffer[20]; |
| @@ -138,9 +138,9 @@ static int do_hardware_base_addr (ctl_table *table, int write, | |||
| 138 | return copy_to_user(result, buffer, len) ? -EFAULT : 0; | 138 | return copy_to_user(result, buffer, len) ? -EFAULT : 0; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static int do_hardware_irq (ctl_table *table, int write, | 141 | static int do_hardware_irq(struct ctl_table *table, int write, |
| 142 | void __user *result, | 142 | void __user *result, |
| 143 | size_t *lenp, loff_t *ppos) | 143 | size_t *lenp, loff_t *ppos) |
| 144 | { | 144 | { |
| 145 | struct parport *port = (struct parport *)table->extra1; | 145 | struct parport *port = (struct parport *)table->extra1; |
| 146 | char buffer[20]; | 146 | char buffer[20]; |
| @@ -166,9 +166,9 @@ static int do_hardware_irq (ctl_table *table, int write, | |||
| 166 | return copy_to_user(result, buffer, len) ? -EFAULT : 0; | 166 | return copy_to_user(result, buffer, len) ? -EFAULT : 0; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | static int do_hardware_dma (ctl_table *table, int write, | 169 | static int do_hardware_dma(struct ctl_table *table, int write, |
| 170 | void __user *result, | 170 | void __user *result, |
| 171 | size_t *lenp, loff_t *ppos) | 171 | size_t *lenp, loff_t *ppos) |
| 172 | { | 172 | { |
| 173 | struct parport *port = (struct parport *)table->extra1; | 173 | struct parport *port = (struct parport *)table->extra1; |
| 174 | char buffer[20]; | 174 | char buffer[20]; |
| @@ -194,9 +194,9 @@ static int do_hardware_dma (ctl_table *table, int write, | |||
| 194 | return copy_to_user(result, buffer, len) ? -EFAULT : 0; | 194 | return copy_to_user(result, buffer, len) ? -EFAULT : 0; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | static int do_hardware_modes (ctl_table *table, int write, | 197 | static int do_hardware_modes(struct ctl_table *table, int write, |
| 198 | void __user *result, | 198 | void __user *result, |
| 199 | size_t *lenp, loff_t *ppos) | 199 | size_t *lenp, loff_t *ppos) |
| 200 | { | 200 | { |
| 201 | struct parport *port = (struct parport *)table->extra1; | 201 | struct parport *port = (struct parport *)table->extra1; |
| 202 | char buffer[40]; | 202 | char buffer[40]; |
| @@ -255,11 +255,11 @@ PARPORT_MAX_SPINTIME_VALUE; | |||
| 255 | 255 | ||
| 256 | struct parport_sysctl_table { | 256 | struct parport_sysctl_table { |
| 257 | struct ctl_table_header *sysctl_header; | 257 | struct ctl_table_header *sysctl_header; |
| 258 | ctl_table vars[12]; | 258 | struct ctl_table vars[12]; |
| 259 | ctl_table device_dir[2]; | 259 | struct ctl_table device_dir[2]; |
| 260 | ctl_table port_dir[2]; | 260 | struct ctl_table port_dir[2]; |
| 261 | ctl_table parport_dir[2]; | 261 | struct ctl_table parport_dir[2]; |
| 262 | ctl_table dev_dir[2]; | 262 | struct ctl_table dev_dir[2]; |
| 263 | }; | 263 | }; |
| 264 | 264 | ||
| 265 | static const struct parport_sysctl_table parport_sysctl_template = { | 265 | static const struct parport_sysctl_table parport_sysctl_template = { |
| @@ -369,12 +369,12 @@ static const struct parport_sysctl_table parport_sysctl_template = { | |||
| 369 | struct parport_device_sysctl_table | 369 | struct parport_device_sysctl_table |
| 370 | { | 370 | { |
| 371 | struct ctl_table_header *sysctl_header; | 371 | struct ctl_table_header *sysctl_header; |
| 372 | ctl_table vars[2]; | 372 | struct ctl_table vars[2]; |
| 373 | ctl_table device_dir[2]; | 373 | struct ctl_table device_dir[2]; |
| 374 | ctl_table devices_root_dir[2]; | 374 | struct ctl_table devices_root_dir[2]; |
| 375 | ctl_table port_dir[2]; | 375 | struct ctl_table port_dir[2]; |
| 376 | ctl_table parport_dir[2]; | 376 | struct ctl_table parport_dir[2]; |
| 377 | ctl_table dev_dir[2]; | 377 | struct ctl_table dev_dir[2]; |
| 378 | }; | 378 | }; |
| 379 | 379 | ||
| 380 | static const struct parport_device_sysctl_table | 380 | static const struct parport_device_sysctl_table |
| @@ -422,10 +422,10 @@ parport_device_sysctl_template = { | |||
| 422 | struct parport_default_sysctl_table | 422 | struct parport_default_sysctl_table |
| 423 | { | 423 | { |
| 424 | struct ctl_table_header *sysctl_header; | 424 | struct ctl_table_header *sysctl_header; |
| 425 | ctl_table vars[3]; | 425 | struct ctl_table vars[3]; |
| 426 | ctl_table default_dir[2]; | 426 | struct ctl_table default_dir[2]; |
| 427 | ctl_table parport_dir[2]; | 427 | struct ctl_table parport_dir[2]; |
| 428 | ctl_table dev_dir[2]; | 428 | struct ctl_table dev_dir[2]; |
| 429 | }; | 429 | }; |
| 430 | 430 | ||
| 431 | static struct parport_default_sysctl_table | 431 | static struct parport_default_sysctl_table |
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 1753dc693c15..2ca1a0b3ad57 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c | |||
| @@ -768,15 +768,10 @@ static int tsi721_enable_msix(struct tsi721_device *priv) | |||
| 768 | } | 768 | } |
| 769 | #endif /* CONFIG_RAPIDIO_DMA_ENGINE */ | 769 | #endif /* CONFIG_RAPIDIO_DMA_ENGINE */ |
| 770 | 770 | ||
| 771 | err = pci_enable_msix(priv->pdev, entries, ARRAY_SIZE(entries)); | 771 | err = pci_enable_msix_exact(priv->pdev, entries, ARRAY_SIZE(entries)); |
| 772 | if (err) { | 772 | if (err) { |
| 773 | if (err > 0) | 773 | dev_err(&priv->pdev->dev, |
| 774 | dev_info(&priv->pdev->dev, | 774 | "Failed to enable MSI-X (err=%d)\n", err); |
| 775 | "Only %d MSI-X vectors available, " | ||
| 776 | "not using MSI-X\n", err); | ||
| 777 | else | ||
| 778 | dev_err(&priv->pdev->dev, | ||
| 779 | "Failed to enable MSI-X (err=%d)\n", err); | ||
| 780 | return err; | 775 | return err; |
| 781 | } | 776 | } |
| 782 | 777 | ||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 2e565f8e5165..71988b69eca6 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -386,12 +386,12 @@ config RTC_DRV_PCF8583 | |||
| 386 | will be called rtc-pcf8583. | 386 | will be called rtc-pcf8583. |
| 387 | 387 | ||
| 388 | config RTC_DRV_M41T80 | 388 | config RTC_DRV_M41T80 |
| 389 | tristate "ST M41T62/65/M41T80/81/82/83/84/85/87" | 389 | tristate "ST M41T62/65/M41T80/81/82/83/84/85/87 and compatible" |
| 390 | help | 390 | help |
| 391 | If you say Y here you will get support for the ST M41T60 | 391 | If you say Y here you will get support for the ST M41T60 |
| 392 | and M41T80 RTC chips series. Currently, the following chips are | 392 | and M41T80 RTC chips series. Currently, the following chips are |
| 393 | supported: M41T62, M41T65, M41T80, M41T81, M41T82, M41T83, M41ST84, | 393 | supported: M41T62, M41T65, M41T80, M41T81, M41T82, M41T83, M41ST84, |
| 394 | M41ST85, and M41ST87. | 394 | M41ST85, M41ST87, and MicroCrystal RV4162. |
| 395 | 395 | ||
| 396 | This driver can also be built as a module. If so, the module | 396 | This driver can also be built as a module. If so, the module |
| 397 | will be called rtc-m41t80. | 397 | will be called rtc-m41t80. |
| @@ -573,6 +573,17 @@ config RTC_DRV_DS1305 | |||
| 573 | This driver can also be built as a module. If so, the module | 573 | This driver can also be built as a module. If so, the module |
| 574 | will be called rtc-ds1305. | 574 | will be called rtc-ds1305. |
| 575 | 575 | ||
| 576 | config RTC_DRV_DS1343 | ||
| 577 | select REGMAP_SPI | ||
| 578 | tristate "Dallas/Maxim DS1343/DS1344" | ||
| 579 | help | ||
| 580 | If you say yes here you get support for the | ||
| 581 | Dallas/Maxim DS1343 and DS1344 real time clock chips. | ||
| 582 | Support for trickle charger, alarm is provided. | ||
| 583 | |||
| 584 | This driver can also be built as a module. If so, the module | ||
| 585 | will be called rtc-ds1343. | ||
| 586 | |||
| 576 | config RTC_DRV_DS1347 | 587 | config RTC_DRV_DS1347 |
| 577 | tristate "Dallas/Maxim DS1347" | 588 | tristate "Dallas/Maxim DS1347" |
| 578 | help | 589 | help |
| @@ -650,6 +661,14 @@ config RTC_DRV_RX4581 | |||
| 650 | This driver can also be built as a module. If so the module | 661 | This driver can also be built as a module. If so the module |
| 651 | will be called rtc-rx4581. | 662 | will be called rtc-rx4581. |
| 652 | 663 | ||
| 664 | config RTC_DRV_MCP795 | ||
| 665 | tristate "Microchip MCP795" | ||
| 666 | help | ||
| 667 | If you say yes here you will get support for the Microchip MCP795. | ||
| 668 | |||
| 669 | This driver can also be built as a module. If so the module | ||
| 670 | will be called rtc-mcp795. | ||
| 671 | |||
| 653 | endif # SPI_MASTER | 672 | endif # SPI_MASTER |
| 654 | 673 | ||
| 655 | comment "Platform RTC drivers" | 674 | comment "Platform RTC drivers" |
| @@ -758,6 +777,16 @@ config RTC_DRV_DA9055 | |||
| 758 | This driver can also be built as a module. If so, the module | 777 | This driver can also be built as a module. If so, the module |
| 759 | will be called rtc-da9055 | 778 | will be called rtc-da9055 |
| 760 | 779 | ||
| 780 | config RTC_DRV_DA9063 | ||
| 781 | tristate "Dialog Semiconductor DA9063 RTC" | ||
| 782 | depends on MFD_DA9063 | ||
| 783 | help | ||
| 784 | If you say yes here you will get support for the RTC subsystem | ||
| 785 | of the Dialog Semiconductor DA9063. | ||
| 786 | |||
| 787 | This driver can also be built as a module. If so, the module | ||
| 788 | will be called "rtc-da9063". | ||
| 789 | |||
| 761 | config RTC_DRV_EFI | 790 | config RTC_DRV_EFI |
| 762 | tristate "EFI RTC" | 791 | tristate "EFI RTC" |
| 763 | depends on IA64 | 792 | depends on IA64 |
| @@ -1327,6 +1356,15 @@ config RTC_DRV_MOXART | |||
| 1327 | This driver can also be built as a module. If so, the module | 1356 | This driver can also be built as a module. If so, the module |
| 1328 | will be called rtc-moxart | 1357 | will be called rtc-moxart |
| 1329 | 1358 | ||
| 1359 | config RTC_DRV_XGENE | ||
| 1360 | tristate "APM X-Gene RTC" | ||
| 1361 | help | ||
| 1362 | If you say yes here you get support for the APM X-Gene SoC real time | ||
| 1363 | clock. | ||
| 1364 | |||
| 1365 | This driver can also be built as a module, if so, the module | ||
| 1366 | will be called "rtc-xgene". | ||
| 1367 | |||
| 1330 | comment "HID Sensor RTC drivers" | 1368 | comment "HID Sensor RTC drivers" |
| 1331 | 1369 | ||
| 1332 | config RTC_DRV_HID_SENSOR_TIME | 1370 | config RTC_DRV_HID_SENSOR_TIME |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 40a09915c8f6..70347d041d10 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -32,6 +32,7 @@ obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | |||
| 32 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o | 32 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o |
| 33 | obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o | 33 | obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o |
| 34 | obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o | 34 | obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o |
| 35 | obj-$(CONFIG_RTC_DRV_DA9063) += rtc-da9063.o | ||
| 35 | obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o | 36 | obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o |
| 36 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o | 37 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o |
| 37 | obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o | 38 | obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o |
| @@ -40,6 +41,7 @@ obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o | |||
| 40 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | 41 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o |
| 41 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o | 42 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o |
| 42 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 43 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
| 44 | obj-$(CONFIG_RTC_DRV_DS1343) += rtc-ds1343.o | ||
| 43 | obj-$(CONFIG_RTC_DRV_DS1347) += rtc-ds1347.o | 45 | obj-$(CONFIG_RTC_DRV_DS1347) += rtc-ds1347.o |
| 44 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o | 46 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o |
| 45 | obj-$(CONFIG_RTC_DRV_DS1390) += rtc-ds1390.o | 47 | obj-$(CONFIG_RTC_DRV_DS1390) += rtc-ds1390.o |
| @@ -80,6 +82,7 @@ obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o | |||
| 80 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 82 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
| 81 | obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o | 83 | obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o |
| 82 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o | 84 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o |
| 85 | obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o | ||
| 83 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | 86 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o |
| 84 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | 87 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o |
| 85 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 88 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
| @@ -135,5 +138,6 @@ obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o | |||
| 135 | obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o | 138 | obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o |
| 136 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o | 139 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o |
| 137 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 140 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
| 141 | obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o | ||
| 138 | obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o | 142 | obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o |
| 139 | obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o | 143 | obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index c2eff6082363..5813fa52c3d4 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
| @@ -292,7 +292,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
| 292 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); | 292 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); |
| 293 | do { | 293 | do { |
| 294 | alarm->time.tm_year++; | 294 | alarm->time.tm_year++; |
| 295 | } while (rtc_valid_tm(&alarm->time) != 0); | 295 | } while (!is_leap_year(alarm->time.tm_year + 1900) |
| 296 | && rtc_valid_tm(&alarm->time) != 0); | ||
| 296 | break; | 297 | break; |
| 297 | 298 | ||
| 298 | default: | 299 | default: |
| @@ -300,7 +301,16 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
| 300 | } | 301 | } |
| 301 | 302 | ||
| 302 | done: | 303 | done: |
| 303 | return 0; | 304 | err = rtc_valid_tm(&alarm->time); |
| 305 | |||
| 306 | if (err) { | ||
| 307 | dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n", | ||
| 308 | alarm->time.tm_year + 1900, alarm->time.tm_mon + 1, | ||
| 309 | alarm->time.tm_mday, alarm->time.tm_hour, alarm->time.tm_min, | ||
| 310 | alarm->time.tm_sec); | ||
| 311 | } | ||
| 312 | |||
| 313 | return err; | ||
| 304 | } | 314 | } |
| 305 | 315 | ||
| 306 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 316 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 816504846cdd..0c6add1a38dc 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c | |||
| @@ -293,7 +293,7 @@ static int pm860x_rtc_dt_init(struct platform_device *pdev, | |||
| 293 | int ret; | 293 | int ret; |
| 294 | if (!np) | 294 | if (!np) |
| 295 | return -ENODEV; | 295 | return -ENODEV; |
| 296 | np = of_find_node_by_name(np, "rtc"); | 296 | np = of_get_child_by_name(np, "rtc"); |
| 297 | if (!np) { | 297 | if (!np) { |
| 298 | dev_err(&pdev->dev, "failed to find rtc node\n"); | 298 | dev_err(&pdev->dev, "failed to find rtc node\n"); |
| 299 | return -ENODEV; | 299 | return -ENODEV; |
| @@ -301,6 +301,7 @@ static int pm860x_rtc_dt_init(struct platform_device *pdev, | |||
| 301 | ret = of_property_read_u32(np, "marvell,88pm860x-vrtc", &info->vrtc); | 301 | ret = of_property_read_u32(np, "marvell,88pm860x-vrtc", &info->vrtc); |
| 302 | if (ret) | 302 | if (ret) |
| 303 | info->vrtc = 0; | 303 | info->vrtc = 0; |
| 304 | of_node_put(np); | ||
| 304 | return 0; | 305 | return 0; |
| 305 | } | 306 | } |
| 306 | #else | 307 | #else |
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 3281c90691c3..44fe83ee9bee 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
| @@ -48,6 +48,7 @@ struct at91_rtc_config { | |||
| 48 | 48 | ||
| 49 | static const struct at91_rtc_config *at91_rtc_config; | 49 | static const struct at91_rtc_config *at91_rtc_config; |
| 50 | static DECLARE_COMPLETION(at91_rtc_updated); | 50 | static DECLARE_COMPLETION(at91_rtc_updated); |
| 51 | static DECLARE_COMPLETION(at91_rtc_upd_rdy); | ||
| 51 | static unsigned int at91_alarm_year = AT91_RTC_EPOCH; | 52 | static unsigned int at91_alarm_year = AT91_RTC_EPOCH; |
| 52 | static void __iomem *at91_rtc_regs; | 53 | static void __iomem *at91_rtc_regs; |
| 53 | static int irq; | 54 | static int irq; |
| @@ -161,6 +162,8 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
| 161 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 162 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
| 162 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 163 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
| 163 | 164 | ||
| 165 | wait_for_completion(&at91_rtc_upd_rdy); | ||
| 166 | |||
| 164 | /* Stop Time/Calendar from counting */ | 167 | /* Stop Time/Calendar from counting */ |
| 165 | cr = at91_rtc_read(AT91_RTC_CR); | 168 | cr = at91_rtc_read(AT91_RTC_CR); |
| 166 | at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); | 169 | at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); |
| @@ -183,7 +186,9 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
| 183 | 186 | ||
| 184 | /* Restart Time/Calendar */ | 187 | /* Restart Time/Calendar */ |
| 185 | cr = at91_rtc_read(AT91_RTC_CR); | 188 | cr = at91_rtc_read(AT91_RTC_CR); |
| 189 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_SECEV); | ||
| 186 | at91_rtc_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM)); | 190 | at91_rtc_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM)); |
| 191 | at91_rtc_write_ier(AT91_RTC_SECEV); | ||
| 187 | 192 | ||
| 188 | return 0; | 193 | return 0; |
| 189 | } | 194 | } |
| @@ -290,8 +295,10 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id) | |||
| 290 | if (rtsr) { /* this interrupt is shared! Is it ours? */ | 295 | if (rtsr) { /* this interrupt is shared! Is it ours? */ |
| 291 | if (rtsr & AT91_RTC_ALARM) | 296 | if (rtsr & AT91_RTC_ALARM) |
| 292 | events |= (RTC_AF | RTC_IRQF); | 297 | events |= (RTC_AF | RTC_IRQF); |
| 293 | if (rtsr & AT91_RTC_SECEV) | 298 | if (rtsr & AT91_RTC_SECEV) { |
| 294 | events |= (RTC_UF | RTC_IRQF); | 299 | complete(&at91_rtc_upd_rdy); |
| 300 | at91_rtc_write_idr(AT91_RTC_SECEV); | ||
| 301 | } | ||
| 295 | if (rtsr & AT91_RTC_ACKUPD) | 302 | if (rtsr & AT91_RTC_ACKUPD) |
| 296 | complete(&at91_rtc_updated); | 303 | complete(&at91_rtc_updated); |
| 297 | 304 | ||
| @@ -413,6 +420,11 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
| 413 | return PTR_ERR(rtc); | 420 | return PTR_ERR(rtc); |
| 414 | platform_set_drvdata(pdev, rtc); | 421 | platform_set_drvdata(pdev, rtc); |
| 415 | 422 | ||
| 423 | /* enable SECEV interrupt in order to initialize at91_rtc_upd_rdy | ||
| 424 | * completion. | ||
| 425 | */ | ||
| 426 | at91_rtc_write_ier(AT91_RTC_SECEV); | ||
| 427 | |||
| 416 | dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n"); | 428 | dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n"); |
| 417 | return 0; | 429 | return 0; |
| 418 | } | 430 | } |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 0c53f452849d..fe4bdb06a55a 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
| @@ -346,7 +346,7 @@ static int bfin_rtc_probe(struct platform_device *pdev) | |||
| 346 | { | 346 | { |
| 347 | struct bfin_rtc *rtc; | 347 | struct bfin_rtc *rtc; |
| 348 | struct device *dev = &pdev->dev; | 348 | struct device *dev = &pdev->dev; |
| 349 | int ret = 0; | 349 | int ret; |
| 350 | unsigned long timeout = jiffies + HZ; | 350 | unsigned long timeout = jiffies + HZ; |
| 351 | 351 | ||
| 352 | dev_dbg_stamp(dev); | 352 | dev_dbg_stamp(dev); |
| @@ -361,16 +361,17 @@ static int bfin_rtc_probe(struct platform_device *pdev) | |||
| 361 | /* Register our RTC with the RTC framework */ | 361 | /* Register our RTC with the RTC framework */ |
| 362 | rtc->rtc_dev = devm_rtc_device_register(dev, pdev->name, &bfin_rtc_ops, | 362 | rtc->rtc_dev = devm_rtc_device_register(dev, pdev->name, &bfin_rtc_ops, |
| 363 | THIS_MODULE); | 363 | THIS_MODULE); |
| 364 | if (unlikely(IS_ERR(rtc->rtc_dev))) { | 364 | if (unlikely(IS_ERR(rtc->rtc_dev))) |
| 365 | ret = PTR_ERR(rtc->rtc_dev); | 365 | return PTR_ERR(rtc->rtc_dev); |
| 366 | goto err; | ||
| 367 | } | ||
| 368 | 366 | ||
| 369 | /* Grab the IRQ and init the hardware */ | 367 | /* Grab the IRQ and init the hardware */ |
| 370 | ret = devm_request_irq(dev, IRQ_RTC, bfin_rtc_interrupt, 0, | 368 | ret = devm_request_irq(dev, IRQ_RTC, bfin_rtc_interrupt, 0, |
| 371 | pdev->name, dev); | 369 | pdev->name, dev); |
| 372 | if (unlikely(ret)) | 370 | if (unlikely(ret)) |
| 373 | goto err; | 371 | dev_err(&pdev->dev, |
| 372 | "unable to request IRQ; alarm won't work, " | ||
| 373 | "and writes will be delayed\n"); | ||
| 374 | |||
| 374 | /* sometimes the bootloader touched things, but the write complete was not | 375 | /* sometimes the bootloader touched things, but the write complete was not |
| 375 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... | 376 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... |
| 376 | */ | 377 | */ |
| @@ -381,9 +382,6 @@ static int bfin_rtc_probe(struct platform_device *pdev) | |||
| 381 | bfin_write_RTC_SWCNT(0); | 382 | bfin_write_RTC_SWCNT(0); |
| 382 | 383 | ||
| 383 | return 0; | 384 | return 0; |
| 384 | |||
| 385 | err: | ||
| 386 | return ret; | ||
| 387 | } | 385 | } |
| 388 | 386 | ||
| 389 | static int bfin_rtc_remove(struct platform_device *pdev) | 387 | static int bfin_rtc_remove(struct platform_device *pdev) |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 0963c9309c74..b0e4a3eb33c7 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
| @@ -647,6 +647,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 647 | int retval = 0; | 647 | int retval = 0; |
| 648 | unsigned char rtc_control; | 648 | unsigned char rtc_control; |
| 649 | unsigned address_space; | 649 | unsigned address_space; |
| 650 | u32 flags = 0; | ||
| 650 | 651 | ||
| 651 | /* there can be only one ... */ | 652 | /* there can be only one ... */ |
| 652 | if (cmos_rtc.dev) | 653 | if (cmos_rtc.dev) |
| @@ -660,9 +661,12 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 660 | * REVISIT non-x86 systems may instead use memory space resources | 661 | * REVISIT non-x86 systems may instead use memory space resources |
| 661 | * (needing ioremap etc), not i/o space resources like this ... | 662 | * (needing ioremap etc), not i/o space resources like this ... |
| 662 | */ | 663 | */ |
| 663 | ports = request_region(ports->start, | 664 | if (RTC_IOMAPPED) |
| 664 | resource_size(ports), | 665 | ports = request_region(ports->start, resource_size(ports), |
| 665 | driver_name); | 666 | driver_name); |
| 667 | else | ||
| 668 | ports = request_mem_region(ports->start, resource_size(ports), | ||
| 669 | driver_name); | ||
| 666 | if (!ports) { | 670 | if (!ports) { |
| 667 | dev_dbg(dev, "i/o registers already in use\n"); | 671 | dev_dbg(dev, "i/o registers already in use\n"); |
| 668 | return -EBUSY; | 672 | return -EBUSY; |
| @@ -699,6 +703,11 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 699 | * expect CMOS_READ and friends to handle. | 703 | * expect CMOS_READ and friends to handle. |
| 700 | */ | 704 | */ |
| 701 | if (info) { | 705 | if (info) { |
| 706 | if (info->flags) | ||
| 707 | flags = info->flags; | ||
| 708 | if (info->address_space) | ||
| 709 | address_space = info->address_space; | ||
| 710 | |||
| 702 | if (info->rtc_day_alarm && info->rtc_day_alarm < 128) | 711 | if (info->rtc_day_alarm && info->rtc_day_alarm < 128) |
| 703 | cmos_rtc.day_alrm = info->rtc_day_alarm; | 712 | cmos_rtc.day_alrm = info->rtc_day_alarm; |
| 704 | if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128) | 713 | if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128) |
| @@ -726,18 +735,21 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 726 | 735 | ||
| 727 | spin_lock_irq(&rtc_lock); | 736 | spin_lock_irq(&rtc_lock); |
| 728 | 737 | ||
| 729 | /* force periodic irq to CMOS reset default of 1024Hz; | 738 | if (!(flags & CMOS_RTC_FLAGS_NOFREQ)) { |
| 730 | * | 739 | /* force periodic irq to CMOS reset default of 1024Hz; |
| 731 | * REVISIT it's been reported that at least one x86_64 ALI mobo | 740 | * |
| 732 | * doesn't use 32KHz here ... for portability we might need to | 741 | * REVISIT it's been reported that at least one x86_64 ALI |
| 733 | * do something about other clock frequencies. | 742 | * mobo doesn't use 32KHz here ... for portability we might |
| 734 | */ | 743 | * need to do something about other clock frequencies. |
| 735 | cmos_rtc.rtc->irq_freq = 1024; | 744 | */ |
| 736 | hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); | 745 | cmos_rtc.rtc->irq_freq = 1024; |
| 737 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | 746 | hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); |
| 747 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | ||
| 748 | } | ||
| 738 | 749 | ||
| 739 | /* disable irqs */ | 750 | /* disable irqs */ |
| 740 | cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE); | 751 | if (is_valid_irq(rtc_irq)) |
| 752 | cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE); | ||
| 741 | 753 | ||
| 742 | rtc_control = CMOS_READ(RTC_CONTROL); | 754 | rtc_control = CMOS_READ(RTC_CONTROL); |
| 743 | 755 | ||
| @@ -802,14 +814,18 @@ cleanup1: | |||
| 802 | cmos_rtc.dev = NULL; | 814 | cmos_rtc.dev = NULL; |
| 803 | rtc_device_unregister(cmos_rtc.rtc); | 815 | rtc_device_unregister(cmos_rtc.rtc); |
| 804 | cleanup0: | 816 | cleanup0: |
| 805 | release_region(ports->start, resource_size(ports)); | 817 | if (RTC_IOMAPPED) |
| 818 | release_region(ports->start, resource_size(ports)); | ||
| 819 | else | ||
| 820 | release_mem_region(ports->start, resource_size(ports)); | ||
| 806 | return retval; | 821 | return retval; |
| 807 | } | 822 | } |
| 808 | 823 | ||
| 809 | static void cmos_do_shutdown(void) | 824 | static void cmos_do_shutdown(int rtc_irq) |
| 810 | { | 825 | { |
| 811 | spin_lock_irq(&rtc_lock); | 826 | spin_lock_irq(&rtc_lock); |
| 812 | cmos_irq_disable(&cmos_rtc, RTC_IRQMASK); | 827 | if (is_valid_irq(rtc_irq)) |
| 828 | cmos_irq_disable(&cmos_rtc, RTC_IRQMASK); | ||
| 813 | spin_unlock_irq(&rtc_lock); | 829 | spin_unlock_irq(&rtc_lock); |
| 814 | } | 830 | } |
| 815 | 831 | ||
| @@ -818,7 +834,7 @@ static void __exit cmos_do_remove(struct device *dev) | |||
| 818 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 834 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
| 819 | struct resource *ports; | 835 | struct resource *ports; |
| 820 | 836 | ||
| 821 | cmos_do_shutdown(); | 837 | cmos_do_shutdown(cmos->irq); |
| 822 | 838 | ||
| 823 | sysfs_remove_bin_file(&dev->kobj, &nvram); | 839 | sysfs_remove_bin_file(&dev->kobj, &nvram); |
| 824 | 840 | ||
| @@ -831,7 +847,10 @@ static void __exit cmos_do_remove(struct device *dev) | |||
| 831 | cmos->rtc = NULL; | 847 | cmos->rtc = NULL; |
| 832 | 848 | ||
| 833 | ports = cmos->iomem; | 849 | ports = cmos->iomem; |
| 834 | release_region(ports->start, resource_size(ports)); | 850 | if (RTC_IOMAPPED) |
| 851 | release_region(ports->start, resource_size(ports)); | ||
| 852 | else | ||
| 853 | release_mem_region(ports->start, resource_size(ports)); | ||
| 835 | cmos->iomem = NULL; | 854 | cmos->iomem = NULL; |
| 836 | 855 | ||
| 837 | cmos->dev = NULL; | 856 | cmos->dev = NULL; |
| @@ -1065,10 +1084,13 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp) | |||
| 1065 | 1084 | ||
| 1066 | static void cmos_pnp_shutdown(struct pnp_dev *pnp) | 1085 | static void cmos_pnp_shutdown(struct pnp_dev *pnp) |
| 1067 | { | 1086 | { |
| 1068 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev)) | 1087 | struct device *dev = &pnp->dev; |
| 1088 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
| 1089 | |||
| 1090 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev)) | ||
| 1069 | return; | 1091 | return; |
| 1070 | 1092 | ||
| 1071 | cmos_do_shutdown(); | 1093 | cmos_do_shutdown(cmos->irq); |
| 1072 | } | 1094 | } |
| 1073 | 1095 | ||
| 1074 | static const struct pnp_device_id rtc_ids[] = { | 1096 | static const struct pnp_device_id rtc_ids[] = { |
| @@ -1143,11 +1165,21 @@ static inline void cmos_of_init(struct platform_device *pdev) {} | |||
| 1143 | 1165 | ||
| 1144 | static int __init cmos_platform_probe(struct platform_device *pdev) | 1166 | static int __init cmos_platform_probe(struct platform_device *pdev) |
| 1145 | { | 1167 | { |
| 1168 | struct resource *resource; | ||
| 1169 | int irq; | ||
| 1170 | |||
| 1146 | cmos_of_init(pdev); | 1171 | cmos_of_init(pdev); |
| 1147 | cmos_wake_setup(&pdev->dev); | 1172 | cmos_wake_setup(&pdev->dev); |
| 1148 | return cmos_do_probe(&pdev->dev, | 1173 | |
| 1149 | platform_get_resource(pdev, IORESOURCE_IO, 0), | 1174 | if (RTC_IOMAPPED) |
| 1150 | platform_get_irq(pdev, 0)); | 1175 | resource = platform_get_resource(pdev, IORESOURCE_IO, 0); |
| 1176 | else | ||
| 1177 | resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1178 | irq = platform_get_irq(pdev, 0); | ||
| 1179 | if (irq < 0) | ||
| 1180 | irq = -1; | ||
| 1181 | |||
| 1182 | return cmos_do_probe(&pdev->dev, resource, irq); | ||
| 1151 | } | 1183 | } |
| 1152 | 1184 | ||
| 1153 | static int __exit cmos_platform_remove(struct platform_device *pdev) | 1185 | static int __exit cmos_platform_remove(struct platform_device *pdev) |
| @@ -1158,10 +1190,13 @@ static int __exit cmos_platform_remove(struct platform_device *pdev) | |||
| 1158 | 1190 | ||
| 1159 | static void cmos_platform_shutdown(struct platform_device *pdev) | 1191 | static void cmos_platform_shutdown(struct platform_device *pdev) |
| 1160 | { | 1192 | { |
| 1161 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pdev->dev)) | 1193 | struct device *dev = &pdev->dev; |
| 1194 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | ||
| 1195 | |||
| 1196 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev)) | ||
| 1162 | return; | 1197 | return; |
| 1163 | 1198 | ||
| 1164 | cmos_do_shutdown(); | 1199 | cmos_do_shutdown(cmos->irq); |
| 1165 | } | 1200 | } |
| 1166 | 1201 | ||
| 1167 | /* work with hotplug and coldplug */ | 1202 | /* work with hotplug and coldplug */ |
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index a1cbf64242a5..e5c9486cf452 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c | |||
| @@ -20,28 +20,28 @@ | |||
| 20 | #include <linux/mfd/da9052/da9052.h> | 20 | #include <linux/mfd/da9052/da9052.h> |
| 21 | #include <linux/mfd/da9052/reg.h> | 21 | #include <linux/mfd/da9052/reg.h> |
| 22 | 22 | ||
| 23 | #define rtc_err(da9052, fmt, ...) \ | 23 | #define rtc_err(rtc, fmt, ...) \ |
| 24 | dev_err(da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__) | 24 | dev_err(rtc->da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__) |
| 25 | 25 | ||
| 26 | struct da9052_rtc { | 26 | struct da9052_rtc { |
| 27 | struct rtc_device *rtc; | 27 | struct rtc_device *rtc; |
| 28 | struct da9052 *da9052; | 28 | struct da9052 *da9052; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable) | 31 | static int da9052_rtc_enable_alarm(struct da9052_rtc *rtc, bool enable) |
| 32 | { | 32 | { |
| 33 | int ret; | 33 | int ret; |
| 34 | if (enable) { | 34 | if (enable) { |
| 35 | ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, | 35 | ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG, |
| 36 | DA9052_ALARM_Y_ALARM_ON, | 36 | DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON, |
| 37 | DA9052_ALARM_Y_ALARM_ON); | 37 | DA9052_ALARM_Y_ALARM_ON); |
| 38 | if (ret != 0) | 38 | if (ret != 0) |
| 39 | rtc_err(da9052, "Failed to enable ALM: %d\n", ret); | 39 | rtc_err(rtc, "Failed to enable ALM: %d\n", ret); |
| 40 | } else { | 40 | } else { |
| 41 | ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, | 41 | ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG, |
| 42 | DA9052_ALARM_Y_ALARM_ON, 0); | 42 | DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON, 0); |
| 43 | if (ret != 0) | 43 | if (ret != 0) |
| 44 | rtc_err(da9052, "Write error: %d\n", ret); | 44 | rtc_err(rtc, "Write error: %d\n", ret); |
| 45 | } | 45 | } |
| 46 | return ret; | 46 | return ret; |
| 47 | } | 47 | } |
| @@ -49,31 +49,20 @@ static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable) | |||
| 49 | static irqreturn_t da9052_rtc_irq(int irq, void *data) | 49 | static irqreturn_t da9052_rtc_irq(int irq, void *data) |
| 50 | { | 50 | { |
| 51 | struct da9052_rtc *rtc = data; | 51 | struct da9052_rtc *rtc = data; |
| 52 | int ret; | ||
| 53 | 52 | ||
| 54 | ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_MI_REG); | 53 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); |
| 55 | if (ret < 0) { | ||
| 56 | rtc_err(rtc->da9052, "Read error: %d\n", ret); | ||
| 57 | return IRQ_NONE; | ||
| 58 | } | ||
| 59 | |||
| 60 | if (ret & DA9052_ALARMMI_ALARMTYPE) { | ||
| 61 | da9052_rtc_enable_alarm(rtc->da9052, 0); | ||
| 62 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
| 63 | } else | ||
| 64 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_PF); | ||
| 65 | 54 | ||
| 66 | return IRQ_HANDLED; | 55 | return IRQ_HANDLED; |
| 67 | } | 56 | } |
| 68 | 57 | ||
| 69 | static int da9052_read_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) | 58 | static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) |
| 70 | { | 59 | { |
| 71 | int ret; | 60 | int ret; |
| 72 | uint8_t v[5]; | 61 | uint8_t v[5]; |
| 73 | 62 | ||
| 74 | ret = da9052_group_read(da9052, DA9052_ALARM_MI_REG, 5, v); | 63 | ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, v); |
| 75 | if (ret != 0) { | 64 | if (ret != 0) { |
| 76 | rtc_err(da9052, "Failed to group read ALM: %d\n", ret); | 65 | rtc_err(rtc, "Failed to group read ALM: %d\n", ret); |
| 77 | return ret; | 66 | return ret; |
| 78 | } | 67 | } |
| 79 | 68 | ||
| @@ -84,23 +73,33 @@ static int da9052_read_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) | |||
| 84 | rtc_tm->tm_min = v[0] & DA9052_RTC_MIN; | 73 | rtc_tm->tm_min = v[0] & DA9052_RTC_MIN; |
| 85 | 74 | ||
| 86 | ret = rtc_valid_tm(rtc_tm); | 75 | ret = rtc_valid_tm(rtc_tm); |
| 87 | if (ret != 0) | ||
| 88 | return ret; | ||
| 89 | return ret; | 76 | return ret; |
| 90 | } | 77 | } |
| 91 | 78 | ||
| 92 | static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) | 79 | static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) |
| 93 | { | 80 | { |
| 81 | struct da9052 *da9052 = rtc->da9052; | ||
| 82 | unsigned long alm_time; | ||
| 94 | int ret; | 83 | int ret; |
| 95 | uint8_t v[3]; | 84 | uint8_t v[3]; |
| 96 | 85 | ||
| 86 | ret = rtc_tm_to_time(rtc_tm, &alm_time); | ||
| 87 | if (ret != 0) | ||
| 88 | return ret; | ||
| 89 | |||
| 90 | if (rtc_tm->tm_sec > 0) { | ||
| 91 | alm_time += 60 - rtc_tm->tm_sec; | ||
| 92 | rtc_time_to_tm(alm_time, rtc_tm); | ||
| 93 | } | ||
| 94 | BUG_ON(rtc_tm->tm_sec); /* it will cause repeated irqs if not zero */ | ||
| 95 | |||
| 97 | rtc_tm->tm_year -= 100; | 96 | rtc_tm->tm_year -= 100; |
| 98 | rtc_tm->tm_mon += 1; | 97 | rtc_tm->tm_mon += 1; |
| 99 | 98 | ||
| 100 | ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG, | 99 | ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG, |
| 101 | DA9052_RTC_MIN, rtc_tm->tm_min); | 100 | DA9052_RTC_MIN, rtc_tm->tm_min); |
| 102 | if (ret != 0) { | 101 | if (ret != 0) { |
| 103 | rtc_err(da9052, "Failed to write ALRM MIN: %d\n", ret); | 102 | rtc_err(rtc, "Failed to write ALRM MIN: %d\n", ret); |
| 104 | return ret; | 103 | return ret; |
| 105 | } | 104 | } |
| 106 | 105 | ||
| @@ -115,22 +114,22 @@ static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) | |||
| 115 | ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, | 114 | ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, |
| 116 | DA9052_RTC_YEAR, rtc_tm->tm_year); | 115 | DA9052_RTC_YEAR, rtc_tm->tm_year); |
| 117 | if (ret != 0) | 116 | if (ret != 0) |
| 118 | rtc_err(da9052, "Failed to write ALRM YEAR: %d\n", ret); | 117 | rtc_err(rtc, "Failed to write ALRM YEAR: %d\n", ret); |
| 119 | 118 | ||
| 120 | return ret; | 119 | return ret; |
| 121 | } | 120 | } |
| 122 | 121 | ||
| 123 | static int da9052_rtc_get_alarm_status(struct da9052 *da9052) | 122 | static int da9052_rtc_get_alarm_status(struct da9052_rtc *rtc) |
| 124 | { | 123 | { |
| 125 | int ret; | 124 | int ret; |
| 126 | 125 | ||
| 127 | ret = da9052_reg_read(da9052, DA9052_ALARM_Y_REG); | 126 | ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_Y_REG); |
| 128 | if (ret < 0) { | 127 | if (ret < 0) { |
| 129 | rtc_err(da9052, "Failed to read ALM: %d\n", ret); | 128 | rtc_err(rtc, "Failed to read ALM: %d\n", ret); |
| 130 | return ret; | 129 | return ret; |
| 131 | } | 130 | } |
| 132 | ret &= DA9052_ALARM_Y_ALARM_ON; | 131 | |
| 133 | return (ret > 0) ? 1 : 0; | 132 | return !!(ret&DA9052_ALARM_Y_ALARM_ON); |
| 134 | } | 133 | } |
| 135 | 134 | ||
| 136 | static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | 135 | static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) |
| @@ -141,7 +140,7 @@ static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | |||
| 141 | 140 | ||
| 142 | ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v); | 141 | ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v); |
| 143 | if (ret < 0) { | 142 | if (ret < 0) { |
| 144 | rtc_err(rtc->da9052, "Failed to read RTC time : %d\n", ret); | 143 | rtc_err(rtc, "Failed to read RTC time : %d\n", ret); |
| 145 | return ret; | 144 | return ret; |
| 146 | } | 145 | } |
| 147 | 146 | ||
| @@ -153,18 +152,14 @@ static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | |||
| 153 | rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC; | 152 | rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC; |
| 154 | 153 | ||
| 155 | ret = rtc_valid_tm(rtc_tm); | 154 | ret = rtc_valid_tm(rtc_tm); |
| 156 | if (ret != 0) { | 155 | return ret; |
| 157 | rtc_err(rtc->da9052, "rtc_valid_tm failed: %d\n", ret); | ||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | 156 | } |
| 163 | 157 | ||
| 164 | static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) | 158 | static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) |
| 165 | { | 159 | { |
| 166 | struct da9052_rtc *rtc; | 160 | struct da9052_rtc *rtc; |
| 167 | uint8_t v[6]; | 161 | uint8_t v[6]; |
| 162 | int ret; | ||
| 168 | 163 | ||
| 169 | rtc = dev_get_drvdata(dev); | 164 | rtc = dev_get_drvdata(dev); |
| 170 | 165 | ||
| @@ -175,7 +170,10 @@ static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 175 | v[4] = tm->tm_mon + 1; | 170 | v[4] = tm->tm_mon + 1; |
| 176 | v[5] = tm->tm_year - 100; | 171 | v[5] = tm->tm_year - 100; |
| 177 | 172 | ||
| 178 | return da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v); | 173 | ret = da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v); |
| 174 | if (ret < 0) | ||
| 175 | rtc_err(rtc, "failed to set RTC time: %d\n", ret); | ||
| 176 | return ret; | ||
| 179 | } | 177 | } |
| 180 | 178 | ||
| 181 | static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 179 | static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| @@ -184,13 +182,13 @@ static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 184 | struct rtc_time *tm = &alrm->time; | 182 | struct rtc_time *tm = &alrm->time; |
| 185 | struct da9052_rtc *rtc = dev_get_drvdata(dev); | 183 | struct da9052_rtc *rtc = dev_get_drvdata(dev); |
| 186 | 184 | ||
| 187 | ret = da9052_read_alarm(rtc->da9052, tm); | 185 | ret = da9052_read_alarm(rtc, tm); |
| 188 | 186 | if (ret < 0) { | |
| 189 | if (ret) | 187 | rtc_err(rtc, "failed to read RTC alarm: %d\n", ret); |
| 190 | return ret; | 188 | return ret; |
| 189 | } | ||
| 191 | 190 | ||
| 192 | alrm->enabled = da9052_rtc_get_alarm_status(rtc->da9052); | 191 | alrm->enabled = da9052_rtc_get_alarm_status(rtc); |
| 193 | |||
| 194 | return 0; | 192 | return 0; |
| 195 | } | 193 | } |
| 196 | 194 | ||
| @@ -200,16 +198,15 @@ static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 200 | struct rtc_time *tm = &alrm->time; | 198 | struct rtc_time *tm = &alrm->time; |
| 201 | struct da9052_rtc *rtc = dev_get_drvdata(dev); | 199 | struct da9052_rtc *rtc = dev_get_drvdata(dev); |
| 202 | 200 | ||
| 203 | ret = da9052_rtc_enable_alarm(rtc->da9052, 0); | 201 | ret = da9052_rtc_enable_alarm(rtc, 0); |
| 204 | if (ret < 0) | 202 | if (ret < 0) |
| 205 | return ret; | 203 | return ret; |
| 206 | 204 | ||
| 207 | ret = da9052_set_alarm(rtc->da9052, tm); | 205 | ret = da9052_set_alarm(rtc, tm); |
| 208 | if (ret) | 206 | if (ret < 0) |
| 209 | return ret; | 207 | return ret; |
| 210 | 208 | ||
| 211 | ret = da9052_rtc_enable_alarm(rtc->da9052, 1); | 209 | ret = da9052_rtc_enable_alarm(rtc, 1); |
| 212 | |||
| 213 | return ret; | 210 | return ret; |
| 214 | } | 211 | } |
| 215 | 212 | ||
| @@ -217,7 +214,7 @@ static int da9052_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
| 217 | { | 214 | { |
| 218 | struct da9052_rtc *rtc = dev_get_drvdata(dev); | 215 | struct da9052_rtc *rtc = dev_get_drvdata(dev); |
| 219 | 216 | ||
| 220 | return da9052_rtc_enable_alarm(rtc->da9052, enabled); | 217 | return da9052_rtc_enable_alarm(rtc, enabled); |
| 221 | } | 218 | } |
| 222 | 219 | ||
| 223 | static const struct rtc_class_ops da9052_rtc_ops = { | 220 | static const struct rtc_class_ops da9052_rtc_ops = { |
| @@ -239,10 +236,23 @@ static int da9052_rtc_probe(struct platform_device *pdev) | |||
| 239 | 236 | ||
| 240 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); | 237 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); |
| 241 | platform_set_drvdata(pdev, rtc); | 238 | platform_set_drvdata(pdev, rtc); |
| 239 | |||
| 240 | ret = da9052_reg_write(rtc->da9052, DA9052_BBAT_CONT_REG, 0xFE); | ||
| 241 | if (ret < 0) { | ||
| 242 | rtc_err(rtc, | ||
| 243 | "Failed to setup RTC battery charging: %d\n", ret); | ||
| 244 | return ret; | ||
| 245 | } | ||
| 246 | |||
| 247 | ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG, | ||
| 248 | DA9052_ALARM_Y_TICK_ON, 0); | ||
| 249 | if (ret != 0) | ||
| 250 | rtc_err(rtc, "Failed to disable TICKS: %d\n", ret); | ||
| 251 | |||
| 242 | ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM", | 252 | ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM", |
| 243 | da9052_rtc_irq, rtc); | 253 | da9052_rtc_irq, rtc); |
| 244 | if (ret != 0) { | 254 | if (ret != 0) { |
| 245 | rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); | 255 | rtc_err(rtc, "irq registration failed: %d\n", ret); |
| 246 | return ret; | 256 | return ret; |
| 247 | } | 257 | } |
| 248 | 258 | ||
| @@ -261,7 +271,7 @@ static struct platform_driver da9052_rtc_driver = { | |||
| 261 | 271 | ||
| 262 | module_platform_driver(da9052_rtc_driver); | 272 | module_platform_driver(da9052_rtc_driver); |
| 263 | 273 | ||
| 264 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | 274 | MODULE_AUTHOR("Anthony Olech <Anthony.Olech@diasemi.com>"); |
| 265 | MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC"); | 275 | MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC"); |
| 266 | MODULE_LICENSE("GPL"); | 276 | MODULE_LICENSE("GPL"); |
| 267 | MODULE_ALIAS("platform:da9052-rtc"); | 277 | MODULE_ALIAS("platform:da9052-rtc"); |
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c new file mode 100644 index 000000000000..595393098b09 --- /dev/null +++ b/drivers/rtc/rtc-da9063.c | |||
| @@ -0,0 +1,333 @@ | |||
| 1 | /* rtc-da9063.c - Real time clock device driver for DA9063 | ||
| 2 | * Copyright (C) 2013-14 Dialog Semiconductor Ltd. | ||
| 3 | * | ||
| 4 | * This library is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU Library General Public | ||
| 6 | * License as published by the Free Software Foundation; either | ||
| 7 | * version 2 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This library is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * Library General Public License for more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/rtc.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/regmap.h> | ||
| 24 | #include <linux/mfd/da9063/registers.h> | ||
| 25 | #include <linux/mfd/da9063/core.h> | ||
| 26 | |||
| 27 | #define YEARS_TO_DA9063(year) ((year) - 100) | ||
| 28 | #define MONTHS_TO_DA9063(month) ((month) + 1) | ||
| 29 | #define YEARS_FROM_DA9063(year) ((year) + 100) | ||
| 30 | #define MONTHS_FROM_DA9063(month) ((month) - 1) | ||
| 31 | |||
| 32 | #define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1) | ||
| 33 | #define RTC_SEC 0 | ||
| 34 | #define RTC_MIN 1 | ||
| 35 | #define RTC_HOUR 2 | ||
| 36 | #define RTC_DAY 3 | ||
| 37 | #define RTC_MONTH 4 | ||
| 38 | #define RTC_YEAR 5 | ||
| 39 | |||
| 40 | struct da9063_rtc { | ||
| 41 | struct rtc_device *rtc_dev; | ||
| 42 | struct da9063 *hw; | ||
| 43 | struct rtc_time alarm_time; | ||
| 44 | bool rtc_sync; | ||
| 45 | }; | ||
| 46 | |||
| 47 | static void da9063_data_to_tm(u8 *data, struct rtc_time *tm) | ||
| 48 | { | ||
| 49 | tm->tm_sec = data[RTC_SEC] & DA9063_COUNT_SEC_MASK; | ||
| 50 | tm->tm_min = data[RTC_MIN] & DA9063_COUNT_MIN_MASK; | ||
| 51 | tm->tm_hour = data[RTC_HOUR] & DA9063_COUNT_HOUR_MASK; | ||
| 52 | tm->tm_mday = data[RTC_DAY] & DA9063_COUNT_DAY_MASK; | ||
| 53 | tm->tm_mon = MONTHS_FROM_DA9063(data[RTC_MONTH] & | ||
| 54 | DA9063_COUNT_MONTH_MASK); | ||
| 55 | tm->tm_year = YEARS_FROM_DA9063(data[RTC_YEAR] & | ||
| 56 | DA9063_COUNT_YEAR_MASK); | ||
| 57 | } | ||
| 58 | |||
| 59 | static void da9063_tm_to_data(struct rtc_time *tm, u8 *data) | ||
| 60 | { | ||
| 61 | data[RTC_SEC] &= ~DA9063_COUNT_SEC_MASK; | ||
| 62 | data[RTC_SEC] |= tm->tm_sec & DA9063_COUNT_SEC_MASK; | ||
| 63 | |||
| 64 | data[RTC_MIN] &= ~DA9063_COUNT_MIN_MASK; | ||
| 65 | data[RTC_MIN] |= tm->tm_min & DA9063_COUNT_MIN_MASK; | ||
| 66 | |||
| 67 | data[RTC_HOUR] &= ~DA9063_COUNT_HOUR_MASK; | ||
| 68 | data[RTC_HOUR] |= tm->tm_hour & DA9063_COUNT_HOUR_MASK; | ||
| 69 | |||
| 70 | data[RTC_DAY] &= ~DA9063_COUNT_DAY_MASK; | ||
| 71 | data[RTC_DAY] |= tm->tm_mday & DA9063_COUNT_DAY_MASK; | ||
| 72 | |||
| 73 | data[RTC_MONTH] &= ~DA9063_COUNT_MONTH_MASK; | ||
| 74 | data[RTC_MONTH] |= MONTHS_TO_DA9063(tm->tm_mon) & | ||
| 75 | DA9063_COUNT_MONTH_MASK; | ||
| 76 | |||
| 77 | data[RTC_YEAR] &= ~DA9063_COUNT_YEAR_MASK; | ||
| 78 | data[RTC_YEAR] |= YEARS_TO_DA9063(tm->tm_year) & | ||
| 79 | DA9063_COUNT_YEAR_MASK; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int da9063_rtc_stop_alarm(struct device *dev) | ||
| 83 | { | ||
| 84 | struct da9063_rtc *rtc = dev_get_drvdata(dev); | ||
| 85 | |||
| 86 | return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y, | ||
| 87 | DA9063_ALARM_ON, 0); | ||
| 88 | } | ||
| 89 | |||
| 90 | static int da9063_rtc_start_alarm(struct device *dev) | ||
| 91 | { | ||
| 92 | struct da9063_rtc *rtc = dev_get_drvdata(dev); | ||
| 93 | |||
| 94 | return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y, | ||
| 95 | DA9063_ALARM_ON, DA9063_ALARM_ON); | ||
| 96 | } | ||
| 97 | |||
| 98 | static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 99 | { | ||
| 100 | struct da9063_rtc *rtc = dev_get_drvdata(dev); | ||
| 101 | unsigned long tm_secs; | ||
| 102 | unsigned long al_secs; | ||
| 103 | u8 data[RTC_DATA_LEN]; | ||
| 104 | int ret; | ||
| 105 | |||
| 106 | ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_COUNT_S, | ||
| 107 | data, RTC_DATA_LEN); | ||
| 108 | if (ret < 0) { | ||
| 109 | dev_err(dev, "Failed to read RTC time data: %d\n", ret); | ||
| 110 | return ret; | ||
| 111 | } | ||
| 112 | |||
| 113 | if (!(data[RTC_SEC] & DA9063_RTC_READ)) { | ||
| 114 | dev_dbg(dev, "RTC not yet ready to be read by the host\n"); | ||
| 115 | return -EINVAL; | ||
| 116 | } | ||
| 117 | |||
| 118 | da9063_data_to_tm(data, tm); | ||
| 119 | |||
| 120 | rtc_tm_to_time(tm, &tm_secs); | ||
| 121 | rtc_tm_to_time(&rtc->alarm_time, &al_secs); | ||
| 122 | |||
| 123 | /* handle the rtc synchronisation delay */ | ||
| 124 | if (rtc->rtc_sync == true && al_secs - tm_secs == 1) | ||
| 125 | memcpy(tm, &rtc->alarm_time, sizeof(struct rtc_time)); | ||
| 126 | else | ||
| 127 | rtc->rtc_sync = false; | ||
| 128 | |||
| 129 | return rtc_valid_tm(tm); | ||
| 130 | } | ||
| 131 | |||
| 132 | static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 133 | { | ||
| 134 | struct da9063_rtc *rtc = dev_get_drvdata(dev); | ||
| 135 | u8 data[RTC_DATA_LEN]; | ||
| 136 | int ret; | ||
| 137 | |||
| 138 | da9063_tm_to_data(tm, data); | ||
| 139 | ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_COUNT_S, | ||
| 140 | data, RTC_DATA_LEN); | ||
| 141 | if (ret < 0) | ||
| 142 | dev_err(dev, "Failed to set RTC time data: %d\n", ret); | ||
| 143 | |||
| 144 | return ret; | ||
| 145 | } | ||
| 146 | |||
| 147 | static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 148 | { | ||
| 149 | struct da9063_rtc *rtc = dev_get_drvdata(dev); | ||
| 150 | u8 data[RTC_DATA_LEN]; | ||
| 151 | int ret; | ||
| 152 | unsigned int val; | ||
| 153 | |||
| 154 | ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_ALARM_S, | ||
| 155 | &data[RTC_SEC], RTC_DATA_LEN); | ||
| 156 | if (ret < 0) | ||
| 157 | return ret; | ||
| 158 | |||
| 159 | da9063_data_to_tm(data, &alrm->time); | ||
| 160 | |||
| 161 | alrm->enabled = !!(data[RTC_YEAR] & DA9063_ALARM_ON); | ||
| 162 | |||
| 163 | ret = regmap_read(rtc->hw->regmap, DA9063_REG_EVENT_A, &val); | ||
| 164 | if (ret < 0) | ||
| 165 | return ret; | ||
| 166 | |||
| 167 | if (val & (DA9063_E_ALARM)) | ||
| 168 | alrm->pending = 1; | ||
| 169 | else | ||
| 170 | alrm->pending = 0; | ||
| 171 | |||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 176 | { | ||
| 177 | struct da9063_rtc *rtc = dev_get_drvdata(dev); | ||
| 178 | u8 data[RTC_DATA_LEN]; | ||
| 179 | int ret; | ||
| 180 | |||
| 181 | da9063_tm_to_data(&alrm->time, data); | ||
| 182 | |||
| 183 | ret = da9063_rtc_stop_alarm(dev); | ||
| 184 | if (ret < 0) { | ||
| 185 | dev_err(dev, "Failed to stop alarm: %d\n", ret); | ||
| 186 | return ret; | ||
| 187 | } | ||
| 188 | |||
| 189 | ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_ALARM_S, | ||
| 190 | data, RTC_DATA_LEN); | ||
| 191 | if (ret < 0) { | ||
| 192 | dev_err(dev, "Failed to write alarm: %d\n", ret); | ||
| 193 | return ret; | ||
| 194 | } | ||
| 195 | |||
| 196 | rtc->alarm_time = alrm->time; | ||
| 197 | |||
| 198 | if (alrm->enabled) { | ||
| 199 | ret = da9063_rtc_start_alarm(dev); | ||
| 200 | if (ret < 0) { | ||
| 201 | dev_err(dev, "Failed to start alarm: %d\n", ret); | ||
| 202 | return ret; | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | return ret; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int da9063_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
| 210 | { | ||
| 211 | if (enabled) | ||
| 212 | return da9063_rtc_start_alarm(dev); | ||
| 213 | else | ||
| 214 | return da9063_rtc_stop_alarm(dev); | ||
| 215 | } | ||
| 216 | |||
| 217 | static irqreturn_t da9063_alarm_event(int irq, void *data) | ||
| 218 | { | ||
| 219 | struct da9063_rtc *rtc = data; | ||
| 220 | |||
| 221 | regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y, | ||
| 222 | DA9063_ALARM_ON, 0); | ||
| 223 | |||
| 224 | rtc->rtc_sync = true; | ||
| 225 | rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
| 226 | |||
| 227 | return IRQ_HANDLED; | ||
| 228 | } | ||
| 229 | |||
| 230 | static const struct rtc_class_ops da9063_rtc_ops = { | ||
| 231 | .read_time = da9063_rtc_read_time, | ||
| 232 | .set_time = da9063_rtc_set_time, | ||
| 233 | .read_alarm = da9063_rtc_read_alarm, | ||
| 234 | .set_alarm = da9063_rtc_set_alarm, | ||
| 235 | .alarm_irq_enable = da9063_rtc_alarm_irq_enable, | ||
| 236 | }; | ||
| 237 | |||
| 238 | static int da9063_rtc_probe(struct platform_device *pdev) | ||
| 239 | { | ||
| 240 | struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); | ||
| 241 | struct da9063_rtc *rtc; | ||
| 242 | int irq_alarm; | ||
| 243 | u8 data[RTC_DATA_LEN]; | ||
| 244 | int ret; | ||
| 245 | |||
| 246 | ret = regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_E, | ||
| 247 | DA9063_RTC_EN, DA9063_RTC_EN); | ||
| 248 | if (ret < 0) { | ||
| 249 | dev_err(&pdev->dev, "Failed to enable RTC\n"); | ||
| 250 | goto err; | ||
| 251 | } | ||
| 252 | |||
| 253 | ret = regmap_update_bits(da9063->regmap, DA9063_REG_EN_32K, | ||
| 254 | DA9063_CRYSTAL, DA9063_CRYSTAL); | ||
| 255 | if (ret < 0) { | ||
| 256 | dev_err(&pdev->dev, "Failed to run 32kHz oscillator\n"); | ||
| 257 | goto err; | ||
| 258 | } | ||
| 259 | |||
| 260 | ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S, | ||
| 261 | DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM, | ||
| 262 | 0); | ||
| 263 | if (ret < 0) { | ||
| 264 | dev_err(&pdev->dev, "Failed to access RTC alarm register\n"); | ||
| 265 | goto err; | ||
| 266 | } | ||
| 267 | |||
| 268 | ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S, | ||
| 269 | DA9063_ALARM_STATUS_ALARM, | ||
| 270 | DA9063_ALARM_STATUS_ALARM); | ||
| 271 | if (ret < 0) { | ||
| 272 | dev_err(&pdev->dev, "Failed to access RTC alarm register\n"); | ||
| 273 | goto err; | ||
| 274 | } | ||
| 275 | |||
| 276 | ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_Y, | ||
| 277 | DA9063_TICK_ON, 0); | ||
| 278 | if (ret < 0) { | ||
| 279 | dev_err(&pdev->dev, "Failed to disable TICKs\n"); | ||
| 280 | goto err; | ||
| 281 | } | ||
| 282 | |||
| 283 | ret = regmap_bulk_read(da9063->regmap, DA9063_REG_ALARM_S, | ||
| 284 | data, RTC_DATA_LEN); | ||
| 285 | if (ret < 0) { | ||
| 286 | dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n", | ||
| 287 | ret); | ||
| 288 | goto err; | ||
| 289 | } | ||
| 290 | |||
| 291 | rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); | ||
| 292 | if (!rtc) | ||
| 293 | return -ENOMEM; | ||
| 294 | |||
| 295 | platform_set_drvdata(pdev, rtc); | ||
| 296 | |||
| 297 | irq_alarm = platform_get_irq_byname(pdev, "ALARM"); | ||
| 298 | ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL, | ||
| 299 | da9063_alarm_event, | ||
| 300 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 301 | "ALARM", rtc); | ||
| 302 | if (ret) { | ||
| 303 | dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n", | ||
| 304 | irq_alarm, ret); | ||
| 305 | goto err; | ||
| 306 | } | ||
| 307 | |||
| 308 | rtc->hw = da9063; | ||
| 309 | rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC, | ||
| 310 | &da9063_rtc_ops, THIS_MODULE); | ||
| 311 | if (IS_ERR(rtc->rtc_dev)) | ||
| 312 | return PTR_ERR(rtc->rtc_dev); | ||
| 313 | |||
| 314 | da9063_data_to_tm(data, &rtc->alarm_time); | ||
| 315 | rtc->rtc_sync = false; | ||
| 316 | err: | ||
| 317 | return ret; | ||
| 318 | } | ||
| 319 | |||
| 320 | static struct platform_driver da9063_rtc_driver = { | ||
| 321 | .probe = da9063_rtc_probe, | ||
| 322 | .driver = { | ||
| 323 | .name = DA9063_DRVNAME_RTC, | ||
| 324 | .owner = THIS_MODULE, | ||
| 325 | }, | ||
| 326 | }; | ||
| 327 | |||
| 328 | module_platform_driver(da9063_rtc_driver); | ||
| 329 | |||
| 330 | MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); | ||
| 331 | MODULE_DESCRIPTION("Real time clock device driver for Dialog DA9063"); | ||
| 332 | MODULE_LICENSE("GPL v2"); | ||
| 333 | MODULE_ALIAS("platform:" DA9063_DRVNAME_RTC); | ||
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c new file mode 100644 index 000000000000..c3719189dd96 --- /dev/null +++ b/drivers/rtc/rtc-ds1343.c | |||
| @@ -0,0 +1,689 @@ | |||
| 1 | /* rtc-ds1343.c | ||
| 2 | * | ||
| 3 | * Driver for Dallas Semiconductor DS1343 Low Current, SPI Compatible | ||
| 4 | * Real Time Clock | ||
| 5 | * | ||
| 6 | * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/spi/spi.h> | ||
| 19 | #include <linux/regmap.h> | ||
| 20 | #include <linux/rtc.h> | ||
| 21 | #include <linux/bcd.h> | ||
| 22 | #include <linux/pm.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | |||
| 25 | #define DS1343_DRV_VERSION "01.00" | ||
| 26 | #define DALLAS_MAXIM_DS1343 0 | ||
| 27 | #define DALLAS_MAXIM_DS1344 1 | ||
| 28 | |||
| 29 | /* RTC DS1343 Registers */ | ||
| 30 | #define DS1343_SECONDS_REG 0x00 | ||
| 31 | #define DS1343_MINUTES_REG 0x01 | ||
| 32 | #define DS1343_HOURS_REG 0x02 | ||
| 33 | #define DS1343_DAY_REG 0x03 | ||
| 34 | #define DS1343_DATE_REG 0x04 | ||
| 35 | #define DS1343_MONTH_REG 0x05 | ||
| 36 | #define DS1343_YEAR_REG 0x06 | ||
| 37 | #define DS1343_ALM0_SEC_REG 0x07 | ||
| 38 | #define DS1343_ALM0_MIN_REG 0x08 | ||
| 39 | #define DS1343_ALM0_HOUR_REG 0x09 | ||
| 40 | #define DS1343_ALM0_DAY_REG 0x0A | ||
| 41 | #define DS1343_ALM1_SEC_REG 0x0B | ||
| 42 | #define DS1343_ALM1_MIN_REG 0x0C | ||
| 43 | #define DS1343_ALM1_HOUR_REG 0x0D | ||
| 44 | #define DS1343_ALM1_DAY_REG 0x0E | ||
| 45 | #define DS1343_CONTROL_REG 0x0F | ||
| 46 | #define DS1343_STATUS_REG 0x10 | ||
| 47 | #define DS1343_TRICKLE_REG 0x11 | ||
| 48 | |||
| 49 | /* DS1343 Control Registers bits */ | ||
| 50 | #define DS1343_EOSC 0x80 | ||
| 51 | #define DS1343_DOSF 0x20 | ||
| 52 | #define DS1343_EGFIL 0x10 | ||
| 53 | #define DS1343_SQW 0x08 | ||
| 54 | #define DS1343_INTCN 0x04 | ||
| 55 | #define DS1343_A1IE 0x02 | ||
| 56 | #define DS1343_A0IE 0x01 | ||
| 57 | |||
| 58 | /* DS1343 Status Registers bits */ | ||
| 59 | #define DS1343_OSF 0x80 | ||
| 60 | #define DS1343_IRQF1 0x02 | ||
| 61 | #define DS1343_IRQF0 0x01 | ||
| 62 | |||
| 63 | /* DS1343 Trickle Charger Registers bits */ | ||
| 64 | #define DS1343_TRICKLE_MAGIC 0xa0 | ||
| 65 | #define DS1343_TRICKLE_DS1 0x08 | ||
| 66 | #define DS1343_TRICKLE_1K 0x01 | ||
| 67 | #define DS1343_TRICKLE_2K 0x02 | ||
| 68 | #define DS1343_TRICKLE_4K 0x03 | ||
| 69 | |||
| 70 | static const struct spi_device_id ds1343_id[] = { | ||
| 71 | { "ds1343", DALLAS_MAXIM_DS1343 }, | ||
| 72 | { "ds1344", DALLAS_MAXIM_DS1344 }, | ||
| 73 | { } | ||
| 74 | }; | ||
| 75 | MODULE_DEVICE_TABLE(spi, ds1343_id); | ||
| 76 | |||
| 77 | struct ds1343_priv { | ||
| 78 | struct spi_device *spi; | ||
| 79 | struct rtc_device *rtc; | ||
| 80 | struct regmap *map; | ||
| 81 | struct mutex mutex; | ||
| 82 | unsigned int irqen; | ||
| 83 | int irq; | ||
| 84 | int alarm_sec; | ||
| 85 | int alarm_min; | ||
| 86 | int alarm_hour; | ||
| 87 | int alarm_mday; | ||
| 88 | }; | ||
| 89 | |||
| 90 | static int ds1343_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
| 91 | { | ||
| 92 | switch (cmd) { | ||
| 93 | #ifdef RTC_SET_CHARGE | ||
| 94 | case RTC_SET_CHARGE: | ||
| 95 | { | ||
| 96 | int val; | ||
| 97 | |||
| 98 | if (copy_from_user(&val, (int __user *)arg, sizeof(int))) | ||
| 99 | return -EFAULT; | ||
| 100 | |||
| 101 | return regmap_write(priv->map, DS1343_TRICKLE_REG, val); | ||
| 102 | } | ||
| 103 | break; | ||
| 104 | #endif | ||
| 105 | } | ||
| 106 | |||
| 107 | return -ENOIOCTLCMD; | ||
| 108 | } | ||
| 109 | |||
| 110 | static ssize_t ds1343_show_glitchfilter(struct device *dev, | ||
| 111 | struct device_attribute *attr, char *buf) | ||
| 112 | { | ||
| 113 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 114 | int glitch_filt_status, data; | ||
| 115 | |||
| 116 | regmap_read(priv->map, DS1343_CONTROL_REG, &data); | ||
| 117 | |||
| 118 | glitch_filt_status = !!(data & DS1343_EGFIL); | ||
| 119 | |||
| 120 | if (glitch_filt_status) | ||
| 121 | return sprintf(buf, "enabled\n"); | ||
| 122 | else | ||
| 123 | return sprintf(buf, "disabled\n"); | ||
| 124 | } | ||
| 125 | |||
| 126 | static ssize_t ds1343_store_glitchfilter(struct device *dev, | ||
| 127 | struct device_attribute *attr, | ||
| 128 | const char *buf, size_t count) | ||
| 129 | { | ||
| 130 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 131 | int data; | ||
| 132 | |||
| 133 | regmap_read(priv->map, DS1343_CONTROL_REG, &data); | ||
| 134 | |||
| 135 | if (strncmp(buf, "enabled", 7) == 0) | ||
| 136 | data |= DS1343_EGFIL; | ||
| 137 | |||
| 138 | else if (strncmp(buf, "disabled", 8) == 0) | ||
| 139 | data &= ~(DS1343_EGFIL); | ||
| 140 | |||
| 141 | else | ||
| 142 | return -EINVAL; | ||
| 143 | |||
| 144 | regmap_write(priv->map, DS1343_CONTROL_REG, data); | ||
| 145 | |||
| 146 | return count; | ||
| 147 | } | ||
| 148 | |||
| 149 | static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter, | ||
| 150 | ds1343_store_glitchfilter); | ||
| 151 | |||
| 152 | static ssize_t ds1343_show_alarmstatus(struct device *dev, | ||
| 153 | struct device_attribute *attr, char *buf) | ||
| 154 | { | ||
| 155 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 156 | int alarmstatus, data; | ||
| 157 | |||
| 158 | regmap_read(priv->map, DS1343_CONTROL_REG, &data); | ||
| 159 | |||
| 160 | alarmstatus = !!(data & DS1343_A0IE); | ||
| 161 | |||
| 162 | if (alarmstatus) | ||
| 163 | return sprintf(buf, "enabled\n"); | ||
| 164 | else | ||
| 165 | return sprintf(buf, "disabled\n"); | ||
| 166 | } | ||
| 167 | |||
| 168 | static DEVICE_ATTR(alarm_status, S_IRUGO, ds1343_show_alarmstatus, NULL); | ||
| 169 | |||
| 170 | static ssize_t ds1343_show_alarmmode(struct device *dev, | ||
| 171 | struct device_attribute *attr, char *buf) | ||
| 172 | { | ||
| 173 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 174 | int alarm_mode, data; | ||
| 175 | char *alarm_str; | ||
| 176 | |||
| 177 | regmap_read(priv->map, DS1343_ALM0_SEC_REG, &data); | ||
| 178 | alarm_mode = (data & 0x80) >> 4; | ||
| 179 | |||
| 180 | regmap_read(priv->map, DS1343_ALM0_MIN_REG, &data); | ||
| 181 | alarm_mode |= (data & 0x80) >> 5; | ||
| 182 | |||
| 183 | regmap_read(priv->map, DS1343_ALM0_HOUR_REG, &data); | ||
| 184 | alarm_mode |= (data & 0x80) >> 6; | ||
| 185 | |||
| 186 | regmap_read(priv->map, DS1343_ALM0_DAY_REG, &data); | ||
| 187 | alarm_mode |= (data & 0x80) >> 7; | ||
| 188 | |||
| 189 | switch (alarm_mode) { | ||
| 190 | case 15: | ||
| 191 | alarm_str = "each second"; | ||
| 192 | break; | ||
| 193 | |||
| 194 | case 7: | ||
| 195 | alarm_str = "seconds match"; | ||
| 196 | break; | ||
| 197 | |||
| 198 | case 3: | ||
| 199 | alarm_str = "minutes and seconds match"; | ||
| 200 | break; | ||
| 201 | |||
| 202 | case 1: | ||
| 203 | alarm_str = "hours, minutes and seconds match"; | ||
| 204 | break; | ||
| 205 | |||
| 206 | case 0: | ||
| 207 | alarm_str = "day, hours, minutes and seconds match"; | ||
| 208 | break; | ||
| 209 | |||
| 210 | default: | ||
| 211 | alarm_str = "invalid"; | ||
| 212 | break; | ||
| 213 | } | ||
| 214 | |||
| 215 | return sprintf(buf, "%s\n", alarm_str); | ||
| 216 | } | ||
| 217 | |||
| 218 | static DEVICE_ATTR(alarm_mode, S_IRUGO, ds1343_show_alarmmode, NULL); | ||
| 219 | |||
| 220 | static ssize_t ds1343_show_tricklecharger(struct device *dev, | ||
| 221 | struct device_attribute *attr, char *buf) | ||
| 222 | { | ||
| 223 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 224 | int data; | ||
| 225 | char *diodes = "disabled", *resistors = " "; | ||
| 226 | |||
| 227 | regmap_read(priv->map, DS1343_TRICKLE_REG, &data); | ||
| 228 | |||
| 229 | if ((data & 0xf0) == DS1343_TRICKLE_MAGIC) { | ||
| 230 | switch (data & 0x0c) { | ||
| 231 | case DS1343_TRICKLE_DS1: | ||
| 232 | diodes = "one diode,"; | ||
| 233 | break; | ||
| 234 | |||
| 235 | default: | ||
| 236 | diodes = "no diode,"; | ||
| 237 | break; | ||
| 238 | } | ||
| 239 | |||
| 240 | switch (data & 0x03) { | ||
| 241 | case DS1343_TRICKLE_1K: | ||
| 242 | resistors = "1k Ohm"; | ||
| 243 | break; | ||
| 244 | |||
| 245 | case DS1343_TRICKLE_2K: | ||
| 246 | resistors = "2k Ohm"; | ||
| 247 | break; | ||
| 248 | |||
| 249 | case DS1343_TRICKLE_4K: | ||
| 250 | resistors = "4k Ohm"; | ||
| 251 | break; | ||
| 252 | |||
| 253 | default: | ||
| 254 | diodes = "disabled"; | ||
| 255 | break; | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | return sprintf(buf, "%s %s\n", diodes, resistors); | ||
| 260 | } | ||
| 261 | |||
| 262 | static DEVICE_ATTR(trickle_charger, S_IRUGO, ds1343_show_tricklecharger, NULL); | ||
| 263 | |||
| 264 | static int ds1343_sysfs_register(struct device *dev) | ||
| 265 | { | ||
| 266 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 267 | int err; | ||
| 268 | |||
| 269 | err = device_create_file(dev, &dev_attr_glitch_filter); | ||
| 270 | if (err) | ||
| 271 | return err; | ||
| 272 | |||
| 273 | err = device_create_file(dev, &dev_attr_trickle_charger); | ||
| 274 | if (err) | ||
| 275 | goto error1; | ||
| 276 | |||
| 277 | if (priv->irq <= 0) | ||
| 278 | return err; | ||
| 279 | |||
| 280 | err = device_create_file(dev, &dev_attr_alarm_mode); | ||
| 281 | if (err) | ||
| 282 | goto error2; | ||
| 283 | |||
| 284 | err = device_create_file(dev, &dev_attr_alarm_status); | ||
| 285 | if (!err) | ||
| 286 | return err; | ||
| 287 | |||
| 288 | device_remove_file(dev, &dev_attr_alarm_mode); | ||
| 289 | |||
| 290 | error2: | ||
| 291 | device_remove_file(dev, &dev_attr_trickle_charger); | ||
| 292 | |||
| 293 | error1: | ||
| 294 | device_remove_file(dev, &dev_attr_glitch_filter); | ||
| 295 | |||
| 296 | return err; | ||
| 297 | } | ||
| 298 | |||
| 299 | static void ds1343_sysfs_unregister(struct device *dev) | ||
| 300 | { | ||
| 301 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 302 | |||
| 303 | device_remove_file(dev, &dev_attr_glitch_filter); | ||
| 304 | device_remove_file(dev, &dev_attr_trickle_charger); | ||
| 305 | |||
| 306 | if (priv->irq <= 0) | ||
| 307 | return; | ||
| 308 | |||
| 309 | device_remove_file(dev, &dev_attr_alarm_status); | ||
| 310 | device_remove_file(dev, &dev_attr_alarm_mode); | ||
| 311 | } | ||
| 312 | |||
| 313 | static int ds1343_read_time(struct device *dev, struct rtc_time *dt) | ||
| 314 | { | ||
| 315 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 316 | unsigned char buf[7]; | ||
| 317 | int res; | ||
| 318 | |||
| 319 | res = regmap_bulk_read(priv->map, DS1343_SECONDS_REG, buf, 7); | ||
| 320 | if (res) | ||
| 321 | return res; | ||
| 322 | |||
| 323 | dt->tm_sec = bcd2bin(buf[0]); | ||
| 324 | dt->tm_min = bcd2bin(buf[1]); | ||
| 325 | dt->tm_hour = bcd2bin(buf[2] & 0x3F); | ||
| 326 | dt->tm_wday = bcd2bin(buf[3]) - 1; | ||
| 327 | dt->tm_mday = bcd2bin(buf[4]); | ||
| 328 | dt->tm_mon = bcd2bin(buf[5] & 0x1F) - 1; | ||
| 329 | dt->tm_year = bcd2bin(buf[6]) + 100; /* year offset from 1900 */ | ||
| 330 | |||
| 331 | return rtc_valid_tm(dt); | ||
| 332 | } | ||
| 333 | |||
| 334 | static int ds1343_set_time(struct device *dev, struct rtc_time *dt) | ||
| 335 | { | ||
| 336 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 337 | int res; | ||
| 338 | |||
| 339 | res = regmap_write(priv->map, DS1343_SECONDS_REG, | ||
| 340 | bin2bcd(dt->tm_sec)); | ||
| 341 | if (res) | ||
| 342 | return res; | ||
| 343 | |||
| 344 | res = regmap_write(priv->map, DS1343_MINUTES_REG, | ||
| 345 | bin2bcd(dt->tm_min)); | ||
| 346 | if (res) | ||
| 347 | return res; | ||
| 348 | |||
| 349 | res = regmap_write(priv->map, DS1343_HOURS_REG, | ||
| 350 | bin2bcd(dt->tm_hour) & 0x3F); | ||
| 351 | if (res) | ||
| 352 | return res; | ||
| 353 | |||
| 354 | res = regmap_write(priv->map, DS1343_DAY_REG, | ||
| 355 | bin2bcd(dt->tm_wday + 1)); | ||
| 356 | if (res) | ||
| 357 | return res; | ||
| 358 | |||
| 359 | res = regmap_write(priv->map, DS1343_DATE_REG, | ||
| 360 | bin2bcd(dt->tm_mday)); | ||
| 361 | if (res) | ||
| 362 | return res; | ||
| 363 | |||
| 364 | res = regmap_write(priv->map, DS1343_MONTH_REG, | ||
| 365 | bin2bcd(dt->tm_mon + 1)); | ||
| 366 | if (res) | ||
| 367 | return res; | ||
| 368 | |||
| 369 | dt->tm_year %= 100; | ||
| 370 | |||
| 371 | res = regmap_write(priv->map, DS1343_YEAR_REG, | ||
| 372 | bin2bcd(dt->tm_year)); | ||
| 373 | if (res) | ||
| 374 | return res; | ||
| 375 | |||
| 376 | return 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | static int ds1343_update_alarm(struct device *dev) | ||
| 380 | { | ||
| 381 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 382 | unsigned int control, stat; | ||
| 383 | unsigned char buf[4]; | ||
| 384 | int res = 0; | ||
| 385 | |||
| 386 | res = regmap_read(priv->map, DS1343_CONTROL_REG, &control); | ||
| 387 | if (res) | ||
| 388 | return res; | ||
| 389 | |||
| 390 | res = regmap_read(priv->map, DS1343_STATUS_REG, &stat); | ||
| 391 | if (res) | ||
| 392 | return res; | ||
| 393 | |||
| 394 | control &= ~(DS1343_A0IE); | ||
| 395 | stat &= ~(DS1343_IRQF0); | ||
| 396 | |||
| 397 | res = regmap_write(priv->map, DS1343_CONTROL_REG, control); | ||
| 398 | if (res) | ||
| 399 | return res; | ||
| 400 | |||
| 401 | res = regmap_write(priv->map, DS1343_STATUS_REG, stat); | ||
| 402 | if (res) | ||
| 403 | return res; | ||
| 404 | |||
| 405 | buf[0] = priv->alarm_sec < 0 || (priv->irqen & RTC_UF) ? | ||
| 406 | 0x80 : bin2bcd(priv->alarm_sec) & 0x7F; | ||
| 407 | buf[1] = priv->alarm_min < 0 || (priv->irqen & RTC_UF) ? | ||
| 408 | 0x80 : bin2bcd(priv->alarm_min) & 0x7F; | ||
| 409 | buf[2] = priv->alarm_hour < 0 || (priv->irqen & RTC_UF) ? | ||
| 410 | 0x80 : bin2bcd(priv->alarm_hour) & 0x3F; | ||
| 411 | buf[3] = priv->alarm_mday < 0 || (priv->irqen & RTC_UF) ? | ||
| 412 | 0x80 : bin2bcd(priv->alarm_mday) & 0x7F; | ||
| 413 | |||
| 414 | res = regmap_bulk_write(priv->map, DS1343_ALM0_SEC_REG, buf, 4); | ||
| 415 | if (res) | ||
| 416 | return res; | ||
| 417 | |||
| 418 | if (priv->irqen) { | ||
| 419 | control |= DS1343_A0IE; | ||
| 420 | res = regmap_write(priv->map, DS1343_CONTROL_REG, control); | ||
| 421 | } | ||
| 422 | |||
| 423 | return res; | ||
| 424 | } | ||
| 425 | |||
| 426 | static int ds1343_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 427 | { | ||
| 428 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 429 | int res = 0; | ||
| 430 | unsigned int stat; | ||
| 431 | |||
| 432 | if (priv->irq <= 0) | ||
| 433 | return -EINVAL; | ||
| 434 | |||
| 435 | mutex_lock(&priv->mutex); | ||
| 436 | |||
| 437 | res = regmap_read(priv->map, DS1343_STATUS_REG, &stat); | ||
| 438 | if (res) | ||
| 439 | goto out; | ||
| 440 | |||
| 441 | alarm->enabled = !!(priv->irqen & RTC_AF); | ||
| 442 | alarm->pending = !!(stat & DS1343_IRQF0); | ||
| 443 | |||
| 444 | alarm->time.tm_sec = priv->alarm_sec < 0 ? 0 : priv->alarm_sec; | ||
| 445 | alarm->time.tm_min = priv->alarm_min < 0 ? 0 : priv->alarm_min; | ||
| 446 | alarm->time.tm_hour = priv->alarm_hour < 0 ? 0 : priv->alarm_hour; | ||
| 447 | alarm->time.tm_mday = priv->alarm_mday < 0 ? 0 : priv->alarm_mday; | ||
| 448 | |||
| 449 | alarm->time.tm_mon = -1; | ||
| 450 | alarm->time.tm_year = -1; | ||
| 451 | alarm->time.tm_wday = -1; | ||
| 452 | alarm->time.tm_yday = -1; | ||
| 453 | alarm->time.tm_isdst = -1; | ||
| 454 | |||
| 455 | out: | ||
| 456 | mutex_unlock(&priv->mutex); | ||
| 457 | return res; | ||
| 458 | } | ||
| 459 | |||
| 460 | static int ds1343_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 461 | { | ||
| 462 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 463 | int res = 0; | ||
| 464 | |||
| 465 | if (priv->irq <= 0) | ||
| 466 | return -EINVAL; | ||
| 467 | |||
| 468 | mutex_lock(&priv->mutex); | ||
| 469 | |||
| 470 | priv->alarm_sec = alarm->time.tm_sec; | ||
| 471 | priv->alarm_min = alarm->time.tm_min; | ||
| 472 | priv->alarm_hour = alarm->time.tm_hour; | ||
| 473 | priv->alarm_mday = alarm->time.tm_mday; | ||
| 474 | |||
| 475 | if (alarm->enabled) | ||
| 476 | priv->irqen |= RTC_AF; | ||
| 477 | |||
| 478 | res = ds1343_update_alarm(dev); | ||
| 479 | |||
| 480 | mutex_unlock(&priv->mutex); | ||
| 481 | |||
| 482 | return res; | ||
| 483 | } | ||
| 484 | |||
| 485 | static int ds1343_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
| 486 | { | ||
| 487 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 488 | int res = 0; | ||
| 489 | |||
| 490 | if (priv->irq <= 0) | ||
| 491 | return -EINVAL; | ||
| 492 | |||
| 493 | mutex_lock(&priv->mutex); | ||
| 494 | |||
| 495 | if (enabled) | ||
| 496 | priv->irqen |= RTC_AF; | ||
| 497 | else | ||
| 498 | priv->irqen &= ~RTC_AF; | ||
| 499 | |||
| 500 | res = ds1343_update_alarm(dev); | ||
| 501 | |||
| 502 | mutex_unlock(&priv->mutex); | ||
| 503 | |||
| 504 | return res; | ||
| 505 | } | ||
| 506 | |||
| 507 | static irqreturn_t ds1343_thread(int irq, void *dev_id) | ||
| 508 | { | ||
| 509 | struct ds1343_priv *priv = dev_id; | ||
| 510 | unsigned int stat, control; | ||
| 511 | int res = 0; | ||
| 512 | |||
| 513 | mutex_lock(&priv->mutex); | ||
| 514 | |||
| 515 | res = regmap_read(priv->map, DS1343_STATUS_REG, &stat); | ||
| 516 | if (res) | ||
| 517 | goto out; | ||
| 518 | |||
| 519 | if (stat & DS1343_IRQF0) { | ||
| 520 | stat &= ~DS1343_IRQF0; | ||
| 521 | regmap_write(priv->map, DS1343_STATUS_REG, stat); | ||
| 522 | |||
| 523 | res = regmap_read(priv->map, DS1343_CONTROL_REG, &control); | ||
| 524 | if (res) | ||
| 525 | goto out; | ||
| 526 | |||
| 527 | control &= ~DS1343_A0IE; | ||
| 528 | regmap_write(priv->map, DS1343_CONTROL_REG, control); | ||
| 529 | |||
| 530 | rtc_update_irq(priv->rtc, 1, RTC_AF | RTC_IRQF); | ||
| 531 | } | ||
| 532 | |||
| 533 | out: | ||
| 534 | mutex_unlock(&priv->mutex); | ||
| 535 | return IRQ_HANDLED; | ||
| 536 | } | ||
| 537 | |||
| 538 | static const struct rtc_class_ops ds1343_rtc_ops = { | ||
| 539 | .ioctl = ds1343_ioctl, | ||
| 540 | .read_time = ds1343_read_time, | ||
| 541 | .set_time = ds1343_set_time, | ||
| 542 | .read_alarm = ds1343_read_alarm, | ||
| 543 | .set_alarm = ds1343_set_alarm, | ||
| 544 | .alarm_irq_enable = ds1343_alarm_irq_enable, | ||
| 545 | }; | ||
| 546 | |||
| 547 | static int ds1343_probe(struct spi_device *spi) | ||
| 548 | { | ||
| 549 | struct ds1343_priv *priv; | ||
| 550 | struct regmap_config config; | ||
| 551 | unsigned int data; | ||
| 552 | int res; | ||
| 553 | |||
| 554 | memset(&config, 0, sizeof(config)); | ||
| 555 | config.reg_bits = 8; | ||
| 556 | config.val_bits = 8; | ||
| 557 | config.write_flag_mask = 0x80; | ||
| 558 | |||
| 559 | priv = devm_kzalloc(&spi->dev, sizeof(struct ds1343_priv), GFP_KERNEL); | ||
| 560 | if (!priv) | ||
| 561 | return -ENOMEM; | ||
| 562 | |||
| 563 | priv->spi = spi; | ||
| 564 | mutex_init(&priv->mutex); | ||
| 565 | |||
| 566 | /* RTC DS1347 works in spi mode 3 and | ||
| 567 | * its chip select is active high | ||
| 568 | */ | ||
| 569 | spi->mode = SPI_MODE_3 | SPI_CS_HIGH; | ||
| 570 | spi->bits_per_word = 8; | ||
| 571 | res = spi_setup(spi); | ||
| 572 | if (res) | ||
| 573 | return res; | ||
| 574 | |||
| 575 | spi_set_drvdata(spi, priv); | ||
| 576 | |||
| 577 | priv->map = devm_regmap_init_spi(spi, &config); | ||
| 578 | |||
| 579 | if (IS_ERR(priv->map)) { | ||
| 580 | dev_err(&spi->dev, "spi regmap init failed for rtc ds1343\n"); | ||
| 581 | return PTR_ERR(priv->map); | ||
| 582 | } | ||
| 583 | |||
| 584 | res = regmap_read(priv->map, DS1343_SECONDS_REG, &data); | ||
| 585 | if (res) | ||
| 586 | return res; | ||
| 587 | |||
| 588 | regmap_read(priv->map, DS1343_CONTROL_REG, &data); | ||
| 589 | data |= DS1343_INTCN; | ||
| 590 | data &= ~(DS1343_EOSC | DS1343_A1IE | DS1343_A0IE); | ||
| 591 | regmap_write(priv->map, DS1343_CONTROL_REG, data); | ||
| 592 | |||
| 593 | regmap_read(priv->map, DS1343_STATUS_REG, &data); | ||
| 594 | data &= ~(DS1343_OSF | DS1343_IRQF1 | DS1343_IRQF0); | ||
| 595 | regmap_write(priv->map, DS1343_STATUS_REG, data); | ||
| 596 | |||
| 597 | priv->rtc = devm_rtc_device_register(&spi->dev, "ds1343", | ||
| 598 | &ds1343_rtc_ops, THIS_MODULE); | ||
| 599 | if (IS_ERR(priv->rtc)) { | ||
| 600 | dev_err(&spi->dev, "unable to register rtc ds1343\n"); | ||
| 601 | return PTR_ERR(priv->rtc); | ||
| 602 | } | ||
| 603 | |||
| 604 | priv->irq = spi->irq; | ||
| 605 | |||
| 606 | if (priv->irq >= 0) { | ||
| 607 | res = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, | ||
| 608 | ds1343_thread, | ||
| 609 | IRQF_NO_SUSPEND | IRQF_ONESHOT, | ||
| 610 | "ds1343", priv); | ||
| 611 | if (res) { | ||
| 612 | priv->irq = -1; | ||
| 613 | dev_err(&spi->dev, | ||
| 614 | "unable to request irq for rtc ds1343\n"); | ||
| 615 | } else { | ||
| 616 | device_set_wakeup_capable(&spi->dev, 1); | ||
| 617 | } | ||
| 618 | } | ||
| 619 | |||
| 620 | res = ds1343_sysfs_register(&spi->dev); | ||
| 621 | if (res) | ||
| 622 | dev_err(&spi->dev, | ||
| 623 | "unable to create sysfs entries for rtc ds1343\n"); | ||
| 624 | |||
| 625 | return 0; | ||
| 626 | } | ||
| 627 | |||
| 628 | static int ds1343_remove(struct spi_device *spi) | ||
| 629 | { | ||
| 630 | struct ds1343_priv *priv = spi_get_drvdata(spi); | ||
| 631 | |||
| 632 | if (spi->irq) { | ||
| 633 | mutex_lock(&priv->mutex); | ||
| 634 | priv->irqen &= ~RTC_AF; | ||
| 635 | mutex_unlock(&priv->mutex); | ||
| 636 | |||
| 637 | devm_free_irq(&spi->dev, spi->irq, priv); | ||
| 638 | } | ||
| 639 | |||
| 640 | spi_set_drvdata(spi, NULL); | ||
| 641 | |||
| 642 | ds1343_sysfs_unregister(&spi->dev); | ||
| 643 | |||
| 644 | return 0; | ||
| 645 | } | ||
| 646 | |||
| 647 | #ifdef CONFIG_PM_SLEEP | ||
| 648 | |||
| 649 | static int ds1343_suspend(struct device *dev) | ||
| 650 | { | ||
| 651 | struct spi_device *spi = to_spi_device(dev); | ||
| 652 | |||
| 653 | if (spi->irq >= 0 && device_may_wakeup(dev)) | ||
| 654 | enable_irq_wake(spi->irq); | ||
| 655 | |||
| 656 | return 0; | ||
| 657 | } | ||
| 658 | |||
| 659 | static int ds1343_resume(struct device *dev) | ||
| 660 | { | ||
| 661 | struct spi_device *spi = to_spi_device(dev); | ||
| 662 | |||
| 663 | if (spi->irq >= 0 && device_may_wakeup(dev)) | ||
| 664 | disable_irq_wake(spi->irq); | ||
| 665 | |||
| 666 | return 0; | ||
| 667 | } | ||
| 668 | |||
| 669 | #endif | ||
| 670 | |||
| 671 | static SIMPLE_DEV_PM_OPS(ds1343_pm, ds1343_suspend, ds1343_resume); | ||
| 672 | |||
| 673 | static struct spi_driver ds1343_driver = { | ||
| 674 | .driver = { | ||
| 675 | .name = "ds1343", | ||
| 676 | .owner = THIS_MODULE, | ||
| 677 | .pm = &ds1343_pm, | ||
| 678 | }, | ||
| 679 | .probe = ds1343_probe, | ||
| 680 | .remove = ds1343_remove, | ||
| 681 | .id_table = ds1343_id, | ||
| 682 | }; | ||
| 683 | |||
| 684 | module_spi_driver(ds1343_driver); | ||
| 685 | |||
| 686 | MODULE_DESCRIPTION("DS1343 RTC SPI Driver"); | ||
| 687 | MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>"); | ||
| 688 | MODULE_LICENSE("GPL v2"); | ||
| 689 | MODULE_VERSION(DS1343_DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 942103dac30f..c6b2191a4128 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
| @@ -219,7 +219,7 @@ static int ds1742_rtc_remove(struct platform_device *pdev) | |||
| 219 | return 0; | 219 | return 0; |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | static struct of_device_id __maybe_unused ds1742_rtc_of_match[] = { | 222 | static const struct of_device_id __maybe_unused ds1742_rtc_of_match[] = { |
| 223 | { .compatible = "maxim,ds1742", }, | 223 | { .compatible = "maxim,ds1742", }, |
| 224 | { } | 224 | { } |
| 225 | }; | 225 | }; |
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index 797aa0252ba9..c4c38431012e 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c | |||
| @@ -35,7 +35,7 @@ static inline int | |||
| 35 | compute_yday(efi_time_t *eft) | 35 | compute_yday(efi_time_t *eft) |
| 36 | { | 36 | { |
| 37 | /* efi_time_t.month is in the [1-12] so, we need -1 */ | 37 | /* efi_time_t.month is in the [1-12] so, we need -1 */ |
| 38 | return rtc_year_days(eft->day - 1, eft->month - 1, eft->year); | 38 | return rtc_year_days(eft->day, eft->month - 1, eft->year); |
| 39 | } | 39 | } |
| 40 | /* | 40 | /* |
| 41 | * returns day of the week [0-6] 0=Sunday | 41 | * returns day of the week [0-6] 0=Sunday |
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index e5f13c4310fe..b936bb4096b5 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c | |||
| @@ -418,6 +418,9 @@ static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563) | |||
| 418 | init.num_parents = 0; | 418 | init.num_parents = 0; |
| 419 | hym8563->clkout_hw.init = &init; | 419 | hym8563->clkout_hw.init = &init; |
| 420 | 420 | ||
| 421 | /* optional override of the clockname */ | ||
| 422 | of_property_read_string(node, "clock-output-names", &init.name); | ||
| 423 | |||
| 421 | /* register the clock */ | 424 | /* register the clock */ |
| 422 | clk = clk_register(&client->dev, &hym8563->clkout_hw); | 425 | clk = clk_register(&client->dev, &hym8563->clkout_hw); |
| 423 | 426 | ||
| @@ -585,7 +588,7 @@ static const struct i2c_device_id hym8563_id[] = { | |||
| 585 | }; | 588 | }; |
| 586 | MODULE_DEVICE_TABLE(i2c, hym8563_id); | 589 | MODULE_DEVICE_TABLE(i2c, hym8563_id); |
| 587 | 590 | ||
| 588 | static struct of_device_id hym8563_dt_idtable[] = { | 591 | static const struct of_device_id hym8563_dt_idtable[] = { |
| 589 | { .compatible = "haoyu,hym8563" }, | 592 | { .compatible = "haoyu,hym8563" }, |
| 590 | {}, | 593 | {}, |
| 591 | }; | 594 | }; |
diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c index 41bd76aaff76..455b601d731d 100644 --- a/drivers/rtc/rtc-isl12057.c +++ b/drivers/rtc/rtc-isl12057.c | |||
| @@ -278,7 +278,7 @@ static int isl12057_probe(struct i2c_client *client, | |||
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | #ifdef CONFIG_OF | 280 | #ifdef CONFIG_OF |
| 281 | static struct of_device_id isl12057_dt_match[] = { | 281 | static const struct of_device_id isl12057_dt_match[] = { |
| 282 | { .compatible = "isl,isl12057" }, | 282 | { .compatible = "isl,isl12057" }, |
| 283 | { }, | 283 | { }, |
| 284 | }; | 284 | }; |
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index a5248aa1abf1..7ff7427c2e6a 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
| @@ -66,8 +66,6 @@ | |||
| 66 | #define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */ | 66 | #define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */ |
| 67 | #define M41T80_FEATURE_SQ_ALT (1 << 4) /* RSx bits are in reg 4 */ | 67 | #define M41T80_FEATURE_SQ_ALT (1 << 4) /* RSx bits are in reg 4 */ |
| 68 | 68 | ||
| 69 | #define DRV_VERSION "0.05" | ||
| 70 | |||
| 71 | static DEFINE_MUTEX(m41t80_rtc_mutex); | 69 | static DEFINE_MUTEX(m41t80_rtc_mutex); |
| 72 | static const struct i2c_device_id m41t80_id[] = { | 70 | static const struct i2c_device_id m41t80_id[] = { |
| 73 | { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT }, | 71 | { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT }, |
| @@ -80,6 +78,7 @@ static const struct i2c_device_id m41t80_id[] = { | |||
| 80 | { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, | 78 | { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
| 81 | { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, | 79 | { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
| 82 | { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, | 80 | { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
| 81 | { "rv4162", M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT }, | ||
| 83 | { } | 82 | { } |
| 84 | }; | 83 | }; |
| 85 | MODULE_DEVICE_TABLE(i2c, m41t80_id); | 84 | MODULE_DEVICE_TABLE(i2c, m41t80_id); |
| @@ -232,7 +231,7 @@ static ssize_t m41t80_sysfs_show_flags(struct device *dev, | |||
| 232 | 231 | ||
| 233 | val = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); | 232 | val = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); |
| 234 | if (val < 0) | 233 | if (val < 0) |
| 235 | return -EIO; | 234 | return val; |
| 236 | return sprintf(buf, "%#x\n", val); | 235 | return sprintf(buf, "%#x\n", val); |
| 237 | } | 236 | } |
| 238 | static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL); | 237 | static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL); |
| @@ -252,7 +251,7 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev, | |||
| 252 | reg_sqw = M41T80_REG_WDAY; | 251 | reg_sqw = M41T80_REG_WDAY; |
| 253 | val = i2c_smbus_read_byte_data(client, reg_sqw); | 252 | val = i2c_smbus_read_byte_data(client, reg_sqw); |
| 254 | if (val < 0) | 253 | if (val < 0) |
| 255 | return -EIO; | 254 | return val; |
| 256 | val = (val >> 4) & 0xf; | 255 | val = (val >> 4) & 0xf; |
| 257 | switch (val) { | 256 | switch (val) { |
| 258 | case 0: | 257 | case 0: |
| @@ -271,7 +270,7 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev, | |||
| 271 | { | 270 | { |
| 272 | struct i2c_client *client = to_i2c_client(dev); | 271 | struct i2c_client *client = to_i2c_client(dev); |
| 273 | struct m41t80_data *clientdata = i2c_get_clientdata(client); | 272 | struct m41t80_data *clientdata = i2c_get_clientdata(client); |
| 274 | int almon, sqw, reg_sqw; | 273 | int almon, sqw, reg_sqw, rc; |
| 275 | int val = simple_strtoul(buf, NULL, 0); | 274 | int val = simple_strtoul(buf, NULL, 0); |
| 276 | 275 | ||
| 277 | if (!(clientdata->features & M41T80_FEATURE_SQ)) | 276 | if (!(clientdata->features & M41T80_FEATURE_SQ)) |
| @@ -291,21 +290,30 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev, | |||
| 291 | /* disable SQW, set SQW frequency & re-enable */ | 290 | /* disable SQW, set SQW frequency & re-enable */ |
| 292 | almon = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); | 291 | almon = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); |
| 293 | if (almon < 0) | 292 | if (almon < 0) |
| 294 | return -EIO; | 293 | return almon; |
| 295 | reg_sqw = M41T80_REG_SQW; | 294 | reg_sqw = M41T80_REG_SQW; |
| 296 | if (clientdata->features & M41T80_FEATURE_SQ_ALT) | 295 | if (clientdata->features & M41T80_FEATURE_SQ_ALT) |
| 297 | reg_sqw = M41T80_REG_WDAY; | 296 | reg_sqw = M41T80_REG_WDAY; |
| 298 | sqw = i2c_smbus_read_byte_data(client, reg_sqw); | 297 | sqw = i2c_smbus_read_byte_data(client, reg_sqw); |
| 299 | if (sqw < 0) | 298 | if (sqw < 0) |
| 300 | return -EIO; | 299 | return sqw; |
| 301 | sqw = (sqw & 0x0f) | (val << 4); | 300 | sqw = (sqw & 0x0f) | (val << 4); |
| 302 | if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, | 301 | |
| 303 | almon & ~M41T80_ALMON_SQWE) < 0 || | 302 | rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, |
| 304 | i2c_smbus_write_byte_data(client, reg_sqw, sqw) < 0) | 303 | almon & ~M41T80_ALMON_SQWE); |
| 305 | return -EIO; | 304 | if (rc < 0) |
| 306 | if (val && i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, | 305 | return rc; |
| 307 | almon | M41T80_ALMON_SQWE) < 0) | 306 | |
| 308 | return -EIO; | 307 | if (val) { |
| 308 | rc = i2c_smbus_write_byte_data(client, reg_sqw, sqw); | ||
| 309 | if (rc < 0) | ||
| 310 | return rc; | ||
| 311 | |||
| 312 | rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, | ||
| 313 | almon | M41T80_ALMON_SQWE); | ||
| 314 | if (rc <0) | ||
| 315 | return rc; | ||
| 316 | } | ||
| 309 | return count; | 317 | return count; |
| 310 | } | 318 | } |
| 311 | static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR, | 319 | static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR, |
| @@ -629,40 +637,28 @@ static int m41t80_probe(struct i2c_client *client, | |||
| 629 | struct m41t80_data *clientdata = NULL; | 637 | struct m41t80_data *clientdata = NULL; |
| 630 | 638 | ||
| 631 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | 639 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
| 632 | | I2C_FUNC_SMBUS_BYTE_DATA)) { | 640 | | I2C_FUNC_SMBUS_BYTE_DATA)) |
| 633 | rc = -ENODEV; | 641 | return -ENODEV; |
| 634 | goto exit; | ||
| 635 | } | ||
| 636 | |||
| 637 | dev_info(&client->dev, | ||
| 638 | "chip found, driver version " DRV_VERSION "\n"); | ||
| 639 | 642 | ||
| 640 | clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata), | 643 | clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata), |
| 641 | GFP_KERNEL); | 644 | GFP_KERNEL); |
| 642 | if (!clientdata) { | 645 | if (!clientdata) |
| 643 | rc = -ENOMEM; | 646 | return -ENOMEM; |
| 644 | goto exit; | ||
| 645 | } | ||
| 646 | 647 | ||
| 647 | clientdata->features = id->driver_data; | 648 | clientdata->features = id->driver_data; |
| 648 | i2c_set_clientdata(client, clientdata); | 649 | i2c_set_clientdata(client, clientdata); |
| 649 | 650 | ||
| 650 | rtc = devm_rtc_device_register(&client->dev, client->name, | 651 | rtc = devm_rtc_device_register(&client->dev, client->name, |
| 651 | &m41t80_rtc_ops, THIS_MODULE); | 652 | &m41t80_rtc_ops, THIS_MODULE); |
| 652 | if (IS_ERR(rtc)) { | 653 | if (IS_ERR(rtc)) |
| 653 | rc = PTR_ERR(rtc); | 654 | return PTR_ERR(rtc); |
| 654 | rtc = NULL; | ||
| 655 | goto exit; | ||
| 656 | } | ||
| 657 | 655 | ||
| 658 | clientdata->rtc = rtc; | 656 | clientdata->rtc = rtc; |
| 659 | 657 | ||
| 660 | /* Make sure HT (Halt Update) bit is cleared */ | 658 | /* Make sure HT (Halt Update) bit is cleared */ |
| 661 | rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR); | 659 | rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR); |
| 662 | if (rc < 0) | ||
| 663 | goto ht_err; | ||
| 664 | 660 | ||
| 665 | if (rc & M41T80_ALHOUR_HT) { | 661 | if (rc >= 0 && rc & M41T80_ALHOUR_HT) { |
| 666 | if (clientdata->features & M41T80_FEATURE_HT) { | 662 | if (clientdata->features & M41T80_FEATURE_HT) { |
| 667 | m41t80_get_datetime(client, &tm); | 663 | m41t80_get_datetime(client, &tm); |
| 668 | dev_info(&client->dev, "HT bit was set!\n"); | 664 | dev_info(&client->dev, "HT bit was set!\n"); |
| @@ -673,53 +669,44 @@ static int m41t80_probe(struct i2c_client *client, | |||
| 673 | tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, | 669 | tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, |
| 674 | tm.tm_min, tm.tm_sec); | 670 | tm.tm_min, tm.tm_sec); |
| 675 | } | 671 | } |
| 676 | if (i2c_smbus_write_byte_data(client, | 672 | rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_HOUR, |
| 677 | M41T80_REG_ALARM_HOUR, | 673 | rc & ~M41T80_ALHOUR_HT); |
| 678 | rc & ~M41T80_ALHOUR_HT) < 0) | 674 | } |
| 679 | goto ht_err; | 675 | |
| 676 | if (rc < 0) { | ||
| 677 | dev_err(&client->dev, "Can't clear HT bit\n"); | ||
| 678 | return rc; | ||
| 680 | } | 679 | } |
| 681 | 680 | ||
| 682 | /* Make sure ST (stop) bit is cleared */ | 681 | /* Make sure ST (stop) bit is cleared */ |
| 683 | rc = i2c_smbus_read_byte_data(client, M41T80_REG_SEC); | 682 | rc = i2c_smbus_read_byte_data(client, M41T80_REG_SEC); |
| 684 | if (rc < 0) | ||
| 685 | goto st_err; | ||
| 686 | 683 | ||
| 687 | if (rc & M41T80_SEC_ST) { | 684 | if (rc >= 0 && rc & M41T80_SEC_ST) |
| 688 | if (i2c_smbus_write_byte_data(client, M41T80_REG_SEC, | 685 | rc = i2c_smbus_write_byte_data(client, M41T80_REG_SEC, |
| 689 | rc & ~M41T80_SEC_ST) < 0) | 686 | rc & ~M41T80_SEC_ST); |
| 690 | goto st_err; | 687 | if (rc < 0) { |
| 688 | dev_err(&client->dev, "Can't clear ST bit\n"); | ||
| 689 | return rc; | ||
| 691 | } | 690 | } |
| 692 | 691 | ||
| 693 | rc = m41t80_sysfs_register(&client->dev); | 692 | rc = m41t80_sysfs_register(&client->dev); |
| 694 | if (rc) | 693 | if (rc) |
| 695 | goto exit; | 694 | return rc; |
| 696 | 695 | ||
| 697 | #ifdef CONFIG_RTC_DRV_M41T80_WDT | 696 | #ifdef CONFIG_RTC_DRV_M41T80_WDT |
| 698 | if (clientdata->features & M41T80_FEATURE_HT) { | 697 | if (clientdata->features & M41T80_FEATURE_HT) { |
| 699 | save_client = client; | 698 | save_client = client; |
| 700 | rc = misc_register(&wdt_dev); | 699 | rc = misc_register(&wdt_dev); |
| 701 | if (rc) | 700 | if (rc) |
| 702 | goto exit; | 701 | return rc; |
| 703 | rc = register_reboot_notifier(&wdt_notifier); | 702 | rc = register_reboot_notifier(&wdt_notifier); |
| 704 | if (rc) { | 703 | if (rc) { |
| 705 | misc_deregister(&wdt_dev); | 704 | misc_deregister(&wdt_dev); |
| 706 | goto exit; | 705 | return rc; |
| 707 | } | 706 | } |
| 708 | } | 707 | } |
| 709 | #endif | 708 | #endif |
| 710 | return 0; | 709 | return 0; |
| 711 | |||
| 712 | st_err: | ||
| 713 | rc = -EIO; | ||
| 714 | dev_err(&client->dev, "Can't clear ST bit\n"); | ||
| 715 | goto exit; | ||
| 716 | ht_err: | ||
| 717 | rc = -EIO; | ||
| 718 | dev_err(&client->dev, "Can't clear HT bit\n"); | ||
| 719 | goto exit; | ||
| 720 | |||
| 721 | exit: | ||
| 722 | return rc; | ||
| 723 | } | 710 | } |
| 724 | 711 | ||
| 725 | static int m41t80_remove(struct i2c_client *client) | 712 | static int m41t80_remove(struct i2c_client *client) |
| @@ -750,4 +737,3 @@ module_i2c_driver(m41t80_driver); | |||
| 750 | MODULE_AUTHOR("Alexander Bigga <ab@mycable.de>"); | 737 | MODULE_AUTHOR("Alexander Bigga <ab@mycable.de>"); |
| 751 | MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver"); | 738 | MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver"); |
| 752 | MODULE_LICENSE("GPL"); | 739 | MODULE_LICENSE("GPL"); |
| 753 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c new file mode 100644 index 000000000000..34295bf00416 --- /dev/null +++ b/drivers/rtc/rtc-mcp795.c | |||
| @@ -0,0 +1,199 @@ | |||
| 1 | /* | ||
| 2 | * SPI Driver for Microchip MCP795 RTC | ||
| 3 | * | ||
| 4 | * Copyright (C) Josef Gajdusek <atx@atx.name> | ||
| 5 | * | ||
| 6 | * based on other Linux RTC drivers | ||
| 7 | * | ||
| 8 | * Device datasheet: | ||
| 9 | * http://ww1.microchip.com/downloads/en/DeviceDoc/22280A.pdf | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | * | ||
| 15 | * */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/device.h> | ||
| 20 | #include <linux/printk.h> | ||
| 21 | #include <linux/spi/spi.h> | ||
| 22 | #include <linux/rtc.h> | ||
| 23 | |||
| 24 | /* MCP795 Instructions, see datasheet table 3-1 */ | ||
| 25 | #define MCP795_EEREAD 0x03 | ||
| 26 | #define MCP795_EEWRITE 0x02 | ||
| 27 | #define MCP795_EEWRDI 0x04 | ||
| 28 | #define MCP795_EEWREN 0x06 | ||
| 29 | #define MCP795_SRREAD 0x05 | ||
| 30 | #define MCP795_SRWRITE 0x01 | ||
| 31 | #define MCP795_READ 0x13 | ||
| 32 | #define MCP795_WRITE 0x12 | ||
| 33 | #define MCP795_UNLOCK 0x14 | ||
| 34 | #define MCP795_IDWRITE 0x32 | ||
| 35 | #define MCP795_IDREAD 0x33 | ||
| 36 | #define MCP795_CLRWDT 0x44 | ||
| 37 | #define MCP795_CLRRAM 0x54 | ||
| 38 | |||
| 39 | #define MCP795_ST_BIT 0x80 | ||
| 40 | #define MCP795_24_BIT 0x40 | ||
| 41 | |||
| 42 | static int mcp795_rtcc_read(struct device *dev, u8 addr, u8 *buf, u8 count) | ||
| 43 | { | ||
| 44 | struct spi_device *spi = to_spi_device(dev); | ||
| 45 | int ret; | ||
| 46 | u8 tx[2]; | ||
| 47 | |||
| 48 | tx[0] = MCP795_READ; | ||
| 49 | tx[1] = addr; | ||
| 50 | ret = spi_write_then_read(spi, tx, sizeof(tx), buf, count); | ||
| 51 | |||
| 52 | if (ret) | ||
| 53 | dev_err(dev, "Failed reading %d bytes from address %x.\n", | ||
| 54 | count, addr); | ||
| 55 | |||
| 56 | return ret; | ||
| 57 | } | ||
| 58 | |||
| 59 | static int mcp795_rtcc_write(struct device *dev, u8 addr, u8 *data, u8 count) | ||
| 60 | { | ||
| 61 | struct spi_device *spi = to_spi_device(dev); | ||
| 62 | int ret; | ||
| 63 | u8 tx[2 + count]; | ||
| 64 | |||
| 65 | tx[0] = MCP795_WRITE; | ||
| 66 | tx[1] = addr; | ||
| 67 | memcpy(&tx[2], data, count); | ||
| 68 | |||
| 69 | ret = spi_write(spi, tx, 2 + count); | ||
| 70 | |||
| 71 | if (ret) | ||
| 72 | dev_err(dev, "Failed to write %d bytes to address %x.\n", | ||
| 73 | count, addr); | ||
| 74 | |||
| 75 | return ret; | ||
| 76 | } | ||
| 77 | |||
| 78 | static int mcp795_rtcc_set_bits(struct device *dev, u8 addr, u8 mask, u8 state) | ||
| 79 | { | ||
| 80 | int ret; | ||
| 81 | u8 tmp; | ||
| 82 | |||
| 83 | ret = mcp795_rtcc_read(dev, addr, &tmp, 1); | ||
| 84 | if (ret) | ||
| 85 | return ret; | ||
| 86 | |||
| 87 | if ((tmp & mask) != state) { | ||
| 88 | tmp = (tmp & ~mask) | state; | ||
| 89 | ret = mcp795_rtcc_write(dev, addr, &tmp, 1); | ||
| 90 | } | ||
| 91 | |||
| 92 | return ret; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int mcp795_set_time(struct device *dev, struct rtc_time *tim) | ||
| 96 | { | ||
| 97 | int ret; | ||
| 98 | u8 data[7]; | ||
| 99 | |||
| 100 | /* Read first, so we can leave config bits untouched */ | ||
| 101 | ret = mcp795_rtcc_read(dev, 0x01, data, sizeof(data)); | ||
| 102 | |||
| 103 | if (ret) | ||
| 104 | return ret; | ||
| 105 | |||
| 106 | data[0] = (data[0] & 0x80) | ((tim->tm_sec / 10) << 4) | (tim->tm_sec % 10); | ||
| 107 | data[1] = (data[1] & 0x80) | ((tim->tm_min / 10) << 4) | (tim->tm_min % 10); | ||
| 108 | data[2] = ((tim->tm_hour / 10) << 4) | (tim->tm_hour % 10); | ||
| 109 | data[4] = ((tim->tm_mday / 10) << 4) | ((tim->tm_mday) % 10); | ||
| 110 | data[5] = (data[5] & 0x10) | (tim->tm_mon / 10) | (tim->tm_mon % 10); | ||
| 111 | |||
| 112 | if (tim->tm_year > 100) | ||
| 113 | tim->tm_year -= 100; | ||
| 114 | |||
| 115 | data[6] = ((tim->tm_year / 10) << 4) | (tim->tm_year % 10); | ||
| 116 | |||
| 117 | ret = mcp795_rtcc_write(dev, 0x01, data, sizeof(data)); | ||
| 118 | |||
| 119 | if (ret) | ||
| 120 | return ret; | ||
| 121 | |||
| 122 | dev_dbg(dev, "Set mcp795: %04d-%02d-%02d %02d:%02d:%02d\n", | ||
| 123 | tim->tm_year + 1900, tim->tm_mon, tim->tm_mday, | ||
| 124 | tim->tm_hour, tim->tm_min, tim->tm_sec); | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int mcp795_read_time(struct device *dev, struct rtc_time *tim) | ||
| 130 | { | ||
| 131 | int ret; | ||
| 132 | u8 data[7]; | ||
| 133 | |||
| 134 | ret = mcp795_rtcc_read(dev, 0x01, data, sizeof(data)); | ||
| 135 | |||
| 136 | if (ret) | ||
| 137 | return ret; | ||
| 138 | |||
| 139 | tim->tm_sec = ((data[0] & 0x70) >> 4) * 10 + (data[0] & 0x0f); | ||
| 140 | tim->tm_min = ((data[1] & 0x70) >> 4) * 10 + (data[1] & 0x0f); | ||
| 141 | tim->tm_hour = ((data[2] & 0x30) >> 4) * 10 + (data[2] & 0x0f); | ||
| 142 | tim->tm_mday = ((data[4] & 0x30) >> 4) * 10 + (data[4] & 0x0f); | ||
| 143 | tim->tm_mon = ((data[5] & 0x10) >> 4) * 10 + (data[5] & 0x0f); | ||
| 144 | tim->tm_year = ((data[6] & 0xf0) >> 4) * 10 + (data[6] & 0x0f) + 100; /* Assume we are in 20xx */ | ||
| 145 | |||
| 146 | dev_dbg(dev, "Read from mcp795: %04d-%02d-%02d %02d:%02d:%02d\n", | ||
| 147 | tim->tm_year + 1900, tim->tm_mon, tim->tm_mday, | ||
| 148 | tim->tm_hour, tim->tm_min, tim->tm_sec); | ||
| 149 | |||
| 150 | return rtc_valid_tm(tim); | ||
| 151 | } | ||
| 152 | |||
| 153 | static struct rtc_class_ops mcp795_rtc_ops = { | ||
| 154 | .read_time = mcp795_read_time, | ||
| 155 | .set_time = mcp795_set_time | ||
| 156 | }; | ||
| 157 | |||
| 158 | static int mcp795_probe(struct spi_device *spi) | ||
| 159 | { | ||
| 160 | struct rtc_device *rtc; | ||
| 161 | int ret; | ||
| 162 | |||
| 163 | spi->mode = SPI_MODE_0; | ||
| 164 | spi->bits_per_word = 8; | ||
| 165 | ret = spi_setup(spi); | ||
| 166 | if (ret) { | ||
| 167 | dev_err(&spi->dev, "Unable to setup SPI\n"); | ||
| 168 | return ret; | ||
| 169 | } | ||
| 170 | |||
| 171 | /* Start the oscillator */ | ||
| 172 | mcp795_rtcc_set_bits(&spi->dev, 0x01, MCP795_ST_BIT, MCP795_ST_BIT); | ||
| 173 | /* Clear the 12 hour mode flag*/ | ||
| 174 | mcp795_rtcc_set_bits(&spi->dev, 0x03, MCP795_24_BIT, 0); | ||
| 175 | |||
| 176 | rtc = devm_rtc_device_register(&spi->dev, "rtc-mcp795", | ||
| 177 | &mcp795_rtc_ops, THIS_MODULE); | ||
| 178 | if (IS_ERR(rtc)) | ||
| 179 | return PTR_ERR(rtc); | ||
| 180 | |||
| 181 | spi_set_drvdata(spi, rtc); | ||
| 182 | |||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | |||
| 186 | static struct spi_driver mcp795_driver = { | ||
| 187 | .driver = { | ||
| 188 | .name = "rtc-mcp795", | ||
| 189 | .owner = THIS_MODULE, | ||
| 190 | }, | ||
| 191 | .probe = mcp795_probe, | ||
| 192 | }; | ||
| 193 | |||
| 194 | module_spi_driver(mcp795_driver); | ||
| 195 | |||
| 196 | MODULE_DESCRIPTION("MCP795 RTC SPI Driver"); | ||
| 197 | MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>"); | ||
| 198 | MODULE_LICENSE("GPL"); | ||
| 199 | MODULE_ALIAS("spi:mcp795"); | ||
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index d15a999363fc..6aaec2fc7c0d 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c | |||
| @@ -319,7 +319,7 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) | |||
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | #ifdef CONFIG_OF | 321 | #ifdef CONFIG_OF |
| 322 | static struct of_device_id rtc_mv_of_match_table[] = { | 322 | static const struct of_device_id rtc_mv_of_match_table[] = { |
| 323 | { .compatible = "marvell,orion-rtc", }, | 323 | { .compatible = "marvell,orion-rtc", }, |
| 324 | {} | 324 | {} |
| 325 | }; | 325 | }; |
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 26de5f8c2ae4..21142e6574a9 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
| @@ -73,43 +73,52 @@ | |||
| 73 | #define OMAP_RTC_IRQWAKEEN 0x7c | 73 | #define OMAP_RTC_IRQWAKEEN 0x7c |
| 74 | 74 | ||
| 75 | /* OMAP_RTC_CTRL_REG bit fields: */ | 75 | /* OMAP_RTC_CTRL_REG bit fields: */ |
| 76 | #define OMAP_RTC_CTRL_SPLIT (1<<7) | 76 | #define OMAP_RTC_CTRL_SPLIT BIT(7) |
| 77 | #define OMAP_RTC_CTRL_DISABLE (1<<6) | 77 | #define OMAP_RTC_CTRL_DISABLE BIT(6) |
| 78 | #define OMAP_RTC_CTRL_SET_32_COUNTER (1<<5) | 78 | #define OMAP_RTC_CTRL_SET_32_COUNTER BIT(5) |
| 79 | #define OMAP_RTC_CTRL_TEST (1<<4) | 79 | #define OMAP_RTC_CTRL_TEST BIT(4) |
| 80 | #define OMAP_RTC_CTRL_MODE_12_24 (1<<3) | 80 | #define OMAP_RTC_CTRL_MODE_12_24 BIT(3) |
| 81 | #define OMAP_RTC_CTRL_AUTO_COMP (1<<2) | 81 | #define OMAP_RTC_CTRL_AUTO_COMP BIT(2) |
| 82 | #define OMAP_RTC_CTRL_ROUND_30S (1<<1) | 82 | #define OMAP_RTC_CTRL_ROUND_30S BIT(1) |
| 83 | #define OMAP_RTC_CTRL_STOP (1<<0) | 83 | #define OMAP_RTC_CTRL_STOP BIT(0) |
| 84 | 84 | ||
| 85 | /* OMAP_RTC_STATUS_REG bit fields: */ | 85 | /* OMAP_RTC_STATUS_REG bit fields: */ |
| 86 | #define OMAP_RTC_STATUS_POWER_UP (1<<7) | 86 | #define OMAP_RTC_STATUS_POWER_UP BIT(7) |
| 87 | #define OMAP_RTC_STATUS_ALARM (1<<6) | 87 | #define OMAP_RTC_STATUS_ALARM BIT(6) |
| 88 | #define OMAP_RTC_STATUS_1D_EVENT (1<<5) | 88 | #define OMAP_RTC_STATUS_1D_EVENT BIT(5) |
| 89 | #define OMAP_RTC_STATUS_1H_EVENT (1<<4) | 89 | #define OMAP_RTC_STATUS_1H_EVENT BIT(4) |
| 90 | #define OMAP_RTC_STATUS_1M_EVENT (1<<3) | 90 | #define OMAP_RTC_STATUS_1M_EVENT BIT(3) |
| 91 | #define OMAP_RTC_STATUS_1S_EVENT (1<<2) | 91 | #define OMAP_RTC_STATUS_1S_EVENT BIT(2) |
| 92 | #define OMAP_RTC_STATUS_RUN (1<<1) | 92 | #define OMAP_RTC_STATUS_RUN BIT(1) |
| 93 | #define OMAP_RTC_STATUS_BUSY (1<<0) | 93 | #define OMAP_RTC_STATUS_BUSY BIT(0) |
| 94 | 94 | ||
| 95 | /* OMAP_RTC_INTERRUPTS_REG bit fields: */ | 95 | /* OMAP_RTC_INTERRUPTS_REG bit fields: */ |
| 96 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) | 96 | #define OMAP_RTC_INTERRUPTS_IT_ALARM BIT(3) |
| 97 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) | 97 | #define OMAP_RTC_INTERRUPTS_IT_TIMER BIT(2) |
| 98 | |||
| 99 | /* OMAP_RTC_OSC_REG bit fields: */ | ||
| 100 | #define OMAP_RTC_OSC_32KCLK_EN BIT(6) | ||
| 98 | 101 | ||
| 99 | /* OMAP_RTC_IRQWAKEEN bit fields: */ | 102 | /* OMAP_RTC_IRQWAKEEN bit fields: */ |
| 100 | #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN (1<<1) | 103 | #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN BIT(1) |
| 101 | 104 | ||
| 102 | /* OMAP_RTC_KICKER values */ | 105 | /* OMAP_RTC_KICKER values */ |
| 103 | #define KICK0_VALUE 0x83e70b13 | 106 | #define KICK0_VALUE 0x83e70b13 |
| 104 | #define KICK1_VALUE 0x95a4f1e0 | 107 | #define KICK1_VALUE 0x95a4f1e0 |
| 105 | 108 | ||
| 106 | #define OMAP_RTC_HAS_KICKER 0x1 | 109 | #define OMAP_RTC_HAS_KICKER BIT(0) |
| 107 | 110 | ||
| 108 | /* | 111 | /* |
| 109 | * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup | 112 | * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup |
| 110 | * generation for event Alarm. | 113 | * generation for event Alarm. |
| 111 | */ | 114 | */ |
| 112 | #define OMAP_RTC_HAS_IRQWAKEEN 0x2 | 115 | #define OMAP_RTC_HAS_IRQWAKEEN BIT(1) |
| 116 | |||
| 117 | /* | ||
| 118 | * Some RTC IP revisions (like those in AM335x and DRA7x) need | ||
| 119 | * the 32KHz clock to be explicitly enabled. | ||
| 120 | */ | ||
| 121 | #define OMAP_RTC_HAS_32KCLK_EN BIT(2) | ||
| 113 | 122 | ||
| 114 | static void __iomem *rtc_base; | 123 | static void __iomem *rtc_base; |
| 115 | 124 | ||
| @@ -162,17 +171,28 @@ static irqreturn_t rtc_irq(int irq, void *rtc) | |||
| 162 | 171 | ||
| 163 | static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 172 | static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
| 164 | { | 173 | { |
| 165 | u8 reg; | 174 | u8 reg, irqwake_reg = 0; |
| 175 | struct platform_device *pdev = to_platform_device(dev); | ||
| 176 | const struct platform_device_id *id_entry = | ||
| 177 | platform_get_device_id(pdev); | ||
| 166 | 178 | ||
| 167 | local_irq_disable(); | 179 | local_irq_disable(); |
| 168 | rtc_wait_not_busy(); | 180 | rtc_wait_not_busy(); |
| 169 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); | 181 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); |
| 170 | if (enabled) | 182 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) |
| 183 | irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN); | ||
| 184 | |||
| 185 | if (enabled) { | ||
| 171 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; | 186 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; |
| 172 | else | 187 | irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; |
| 188 | } else { | ||
| 173 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; | 189 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; |
| 190 | irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; | ||
| 191 | } | ||
| 174 | rtc_wait_not_busy(); | 192 | rtc_wait_not_busy(); |
| 175 | rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); | 193 | rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); |
| 194 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) | ||
| 195 | rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN); | ||
| 176 | local_irq_enable(); | 196 | local_irq_enable(); |
| 177 | 197 | ||
| 178 | return 0; | 198 | return 0; |
| @@ -272,7 +292,10 @@ static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
| 272 | 292 | ||
| 273 | static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | 293 | static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) |
| 274 | { | 294 | { |
| 275 | u8 reg; | 295 | u8 reg, irqwake_reg = 0; |
| 296 | struct platform_device *pdev = to_platform_device(dev); | ||
| 297 | const struct platform_device_id *id_entry = | ||
| 298 | platform_get_device_id(pdev); | ||
| 276 | 299 | ||
| 277 | if (tm2bcd(&alm->time) < 0) | 300 | if (tm2bcd(&alm->time) < 0) |
| 278 | return -EINVAL; | 301 | return -EINVAL; |
| @@ -288,11 +311,19 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
| 288 | rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG); | 311 | rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG); |
| 289 | 312 | ||
| 290 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); | 313 | reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); |
| 291 | if (alm->enabled) | 314 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) |
| 315 | irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN); | ||
| 316 | |||
| 317 | if (alm->enabled) { | ||
| 292 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; | 318 | reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; |
| 293 | else | 319 | irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; |
| 320 | } else { | ||
| 294 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; | 321 | reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; |
| 322 | irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; | ||
| 323 | } | ||
| 295 | rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); | 324 | rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); |
| 325 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) | ||
| 326 | rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN); | ||
| 296 | 327 | ||
| 297 | local_irq_enable(); | 328 | local_irq_enable(); |
| 298 | 329 | ||
| @@ -319,7 +350,8 @@ static struct platform_device_id omap_rtc_devtype[] = { | |||
| 319 | }, | 350 | }, |
| 320 | [OMAP_RTC_DATA_AM3352_IDX] = { | 351 | [OMAP_RTC_DATA_AM3352_IDX] = { |
| 321 | .name = "am3352-rtc", | 352 | .name = "am3352-rtc", |
| 322 | .driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN, | 353 | .driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN | |
| 354 | OMAP_RTC_HAS_32KCLK_EN, | ||
| 323 | }, | 355 | }, |
| 324 | [OMAP_RTC_DATA_DA830_IDX] = { | 356 | [OMAP_RTC_DATA_DA830_IDX] = { |
| 325 | .name = "da830-rtc", | 357 | .name = "da830-rtc", |
| @@ -352,6 +384,12 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
| 352 | if (of_id) | 384 | if (of_id) |
| 353 | pdev->id_entry = of_id->data; | 385 | pdev->id_entry = of_id->data; |
| 354 | 386 | ||
| 387 | id_entry = platform_get_device_id(pdev); | ||
| 388 | if (!id_entry) { | ||
| 389 | dev_err(&pdev->dev, "no matching device entry\n"); | ||
| 390 | return -ENODEV; | ||
| 391 | } | ||
| 392 | |||
| 355 | omap_rtc_timer = platform_get_irq(pdev, 0); | 393 | omap_rtc_timer = platform_get_irq(pdev, 0); |
| 356 | if (omap_rtc_timer <= 0) { | 394 | if (omap_rtc_timer <= 0) { |
| 357 | pr_debug("%s: no update irq?\n", pdev->name); | 395 | pr_debug("%s: no update irq?\n", pdev->name); |
| @@ -373,8 +411,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
| 373 | pm_runtime_enable(&pdev->dev); | 411 | pm_runtime_enable(&pdev->dev); |
| 374 | pm_runtime_get_sync(&pdev->dev); | 412 | pm_runtime_get_sync(&pdev->dev); |
| 375 | 413 | ||
| 376 | id_entry = platform_get_device_id(pdev); | 414 | if (id_entry->driver_data & OMAP_RTC_HAS_KICKER) { |
| 377 | if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) { | ||
| 378 | rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); | 415 | rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); |
| 379 | rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG); | 416 | rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG); |
| 380 | } | 417 | } |
| @@ -393,6 +430,10 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
| 393 | */ | 430 | */ |
| 394 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 431 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
| 395 | 432 | ||
| 433 | /* enable RTC functional clock */ | ||
| 434 | if (id_entry->driver_data & OMAP_RTC_HAS_32KCLK_EN) | ||
| 435 | rtc_writel(OMAP_RTC_OSC_32KCLK_EN, OMAP_RTC_OSC_REG); | ||
| 436 | |||
| 396 | /* clear old status */ | 437 | /* clear old status */ |
| 397 | reg = rtc_read(OMAP_RTC_STATUS_REG); | 438 | reg = rtc_read(OMAP_RTC_STATUS_REG); |
| 398 | if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) { | 439 | if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) { |
| @@ -452,7 +493,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
| 452 | return 0; | 493 | return 0; |
| 453 | 494 | ||
| 454 | fail0: | 495 | fail0: |
| 455 | if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) | 496 | if (id_entry->driver_data & OMAP_RTC_HAS_KICKER) |
| 456 | rtc_writel(0, OMAP_RTC_KICK0_REG); | 497 | rtc_writel(0, OMAP_RTC_KICK0_REG); |
| 457 | pm_runtime_put_sync(&pdev->dev); | 498 | pm_runtime_put_sync(&pdev->dev); |
| 458 | pm_runtime_disable(&pdev->dev); | 499 | pm_runtime_disable(&pdev->dev); |
| @@ -469,7 +510,7 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
| 469 | /* leave rtc running, but disable irqs */ | 510 | /* leave rtc running, but disable irqs */ |
| 470 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 511 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
| 471 | 512 | ||
| 472 | if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) | 513 | if (id_entry->driver_data & OMAP_RTC_HAS_KICKER) |
| 473 | rtc_writel(0, OMAP_RTC_KICK0_REG); | 514 | rtc_writel(0, OMAP_RTC_KICK0_REG); |
| 474 | 515 | ||
| 475 | /* Disable the clock/module */ | 516 | /* Disable the clock/module */ |
| @@ -484,28 +525,16 @@ static u8 irqstat; | |||
| 484 | 525 | ||
| 485 | static int omap_rtc_suspend(struct device *dev) | 526 | static int omap_rtc_suspend(struct device *dev) |
| 486 | { | 527 | { |
| 487 | u8 irqwake_stat; | ||
| 488 | struct platform_device *pdev = to_platform_device(dev); | ||
| 489 | const struct platform_device_id *id_entry = | ||
| 490 | platform_get_device_id(pdev); | ||
| 491 | |||
| 492 | irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); | 528 | irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); |
| 493 | 529 | ||
| 494 | /* FIXME the RTC alarm is not currently acting as a wakeup event | 530 | /* FIXME the RTC alarm is not currently acting as a wakeup event |
| 495 | * source on some platforms, and in fact this enable() call is just | 531 | * source on some platforms, and in fact this enable() call is just |
| 496 | * saving a flag that's never used... | 532 | * saving a flag that's never used... |
| 497 | */ | 533 | */ |
| 498 | if (device_may_wakeup(dev)) { | 534 | if (device_may_wakeup(dev)) |
| 499 | enable_irq_wake(omap_rtc_alarm); | 535 | enable_irq_wake(omap_rtc_alarm); |
| 500 | 536 | else | |
| 501 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) { | ||
| 502 | irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN); | ||
| 503 | irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; | ||
| 504 | rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN); | ||
| 505 | } | ||
| 506 | } else { | ||
| 507 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 537 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
| 508 | } | ||
| 509 | 538 | ||
| 510 | /* Disable the clock/module */ | 539 | /* Disable the clock/module */ |
| 511 | pm_runtime_put_sync(dev); | 540 | pm_runtime_put_sync(dev); |
| @@ -515,25 +544,14 @@ static int omap_rtc_suspend(struct device *dev) | |||
| 515 | 544 | ||
| 516 | static int omap_rtc_resume(struct device *dev) | 545 | static int omap_rtc_resume(struct device *dev) |
| 517 | { | 546 | { |
| 518 | u8 irqwake_stat; | ||
| 519 | struct platform_device *pdev = to_platform_device(dev); | ||
| 520 | const struct platform_device_id *id_entry = | ||
| 521 | platform_get_device_id(pdev); | ||
| 522 | |||
| 523 | /* Enable the clock/module so that we can access the registers */ | 547 | /* Enable the clock/module so that we can access the registers */ |
| 524 | pm_runtime_get_sync(dev); | 548 | pm_runtime_get_sync(dev); |
| 525 | 549 | ||
| 526 | if (device_may_wakeup(dev)) { | 550 | if (device_may_wakeup(dev)) |
| 527 | disable_irq_wake(omap_rtc_alarm); | 551 | disable_irq_wake(omap_rtc_alarm); |
| 528 | 552 | else | |
| 529 | if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) { | ||
| 530 | irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN); | ||
| 531 | irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; | ||
| 532 | rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN); | ||
| 533 | } | ||
| 534 | } else { | ||
| 535 | rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG); | 553 | rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG); |
| 536 | } | 554 | |
| 537 | return 0; | 555 | return 0; |
| 538 | } | 556 | } |
| 539 | #endif | 557 | #endif |
diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c index c360d62fb3f6..4dfe2d793fa3 100644 --- a/drivers/rtc/rtc-palmas.c +++ b/drivers/rtc/rtc-palmas.c | |||
| @@ -352,7 +352,7 @@ static SIMPLE_DEV_PM_OPS(palmas_rtc_pm_ops, palmas_rtc_suspend, | |||
| 352 | palmas_rtc_resume); | 352 | palmas_rtc_resume); |
| 353 | 353 | ||
| 354 | #ifdef CONFIG_OF | 354 | #ifdef CONFIG_OF |
| 355 | static struct of_device_id of_palmas_rtc_match[] = { | 355 | static const struct of_device_id of_palmas_rtc_match[] = { |
| 356 | { .compatible = "ti,palmas-rtc"}, | 356 | { .compatible = "ti,palmas-rtc"}, |
| 357 | { }, | 357 | { }, |
| 358 | }; | 358 | }; |
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index cccbf9d89729..4561f375327d 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
| @@ -389,7 +389,7 @@ static int __exit pxa_rtc_remove(struct platform_device *pdev) | |||
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | #ifdef CONFIG_OF | 391 | #ifdef CONFIG_OF |
| 392 | static struct of_device_id pxa_rtc_dt_ids[] = { | 392 | static const struct of_device_id pxa_rtc_dt_ids[] = { |
| 393 | { .compatible = "marvell,pxa-rtc" }, | 393 | { .compatible = "marvell,pxa-rtc" }, |
| 394 | {} | 394 | {} |
| 395 | }; | 395 | }; |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 0f7adeb1944a..b6e1ca08c2c0 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
| @@ -338,7 +338,7 @@ static SIMPLE_DEV_PM_OPS(sa1100_rtc_pm_ops, sa1100_rtc_suspend, | |||
| 338 | sa1100_rtc_resume); | 338 | sa1100_rtc_resume); |
| 339 | 339 | ||
| 340 | #ifdef CONFIG_OF | 340 | #ifdef CONFIG_OF |
| 341 | static struct of_device_id sa1100_rtc_dt_ids[] = { | 341 | static const struct of_device_id sa1100_rtc_dt_ids[] = { |
| 342 | { .compatible = "mrvl,sa1100-rtc", }, | 342 | { .compatible = "mrvl,sa1100-rtc", }, |
| 343 | { .compatible = "mrvl,mmp-rtc", }, | 343 | { .compatible = "mrvl,mmp-rtc", }, |
| 344 | {} | 344 | {} |
diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c new file mode 100644 index 000000000000..14129cc85bdb --- /dev/null +++ b/drivers/rtc/rtc-xgene.c | |||
| @@ -0,0 +1,278 @@ | |||
| 1 | /* | ||
| 2 | * APM X-Gene SoC Real Time Clock Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2014, Applied Micro Circuits Corporation | ||
| 5 | * Author: Rameshwar Prasad Sahu <rsahu@apm.com> | ||
| 6 | * Loc Ho <lho@apm.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/of.h> | ||
| 26 | #include <linux/platform_device.h> | ||
| 27 | #include <linux/io.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | #include <linux/clk.h> | ||
| 30 | #include <linux/delay.h> | ||
| 31 | #include <linux/rtc.h> | ||
| 32 | |||
| 33 | /* RTC CSR Registers */ | ||
| 34 | #define RTC_CCVR 0x00 | ||
| 35 | #define RTC_CMR 0x04 | ||
| 36 | #define RTC_CLR 0x08 | ||
| 37 | #define RTC_CCR 0x0C | ||
| 38 | #define RTC_CCR_IE BIT(0) | ||
| 39 | #define RTC_CCR_MASK BIT(1) | ||
| 40 | #define RTC_CCR_EN BIT(2) | ||
| 41 | #define RTC_CCR_WEN BIT(3) | ||
| 42 | #define RTC_STAT 0x10 | ||
| 43 | #define RTC_STAT_BIT BIT(0) | ||
| 44 | #define RTC_RSTAT 0x14 | ||
| 45 | #define RTC_EOI 0x18 | ||
| 46 | #define RTC_VER 0x1C | ||
| 47 | |||
| 48 | struct xgene_rtc_dev { | ||
| 49 | struct rtc_device *rtc; | ||
| 50 | struct device *dev; | ||
| 51 | unsigned long alarm_time; | ||
| 52 | void __iomem *csr_base; | ||
| 53 | struct clk *clk; | ||
| 54 | unsigned int irq_wake; | ||
| 55 | }; | ||
| 56 | |||
| 57 | static int xgene_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 58 | { | ||
| 59 | struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); | ||
| 60 | |||
| 61 | rtc_time_to_tm(readl(pdata->csr_base + RTC_CCVR), tm); | ||
| 62 | return rtc_valid_tm(tm); | ||
| 63 | } | ||
| 64 | |||
| 65 | static int xgene_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
| 66 | { | ||
| 67 | struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); | ||
| 68 | |||
| 69 | /* | ||
| 70 | * NOTE: After the following write, the RTC_CCVR is only reflected | ||
| 71 | * after the update cycle of 1 seconds. | ||
| 72 | */ | ||
| 73 | writel((u32) secs, pdata->csr_base + RTC_CLR); | ||
| 74 | readl(pdata->csr_base + RTC_CLR); /* Force a barrier */ | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int xgene_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 80 | { | ||
| 81 | struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); | ||
| 82 | |||
| 83 | rtc_time_to_tm(pdata->alarm_time, &alrm->time); | ||
| 84 | alrm->enabled = readl(pdata->csr_base + RTC_CCR) & RTC_CCR_IE; | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int xgene_rtc_alarm_irq_enable(struct device *dev, u32 enabled) | ||
| 90 | { | ||
| 91 | struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); | ||
| 92 | u32 ccr; | ||
| 93 | |||
| 94 | ccr = readl(pdata->csr_base + RTC_CCR); | ||
| 95 | if (enabled) { | ||
| 96 | ccr &= ~RTC_CCR_MASK; | ||
| 97 | ccr |= RTC_CCR_IE; | ||
| 98 | } else { | ||
| 99 | ccr &= ~RTC_CCR_IE; | ||
| 100 | ccr |= RTC_CCR_MASK; | ||
| 101 | } | ||
| 102 | writel(ccr, pdata->csr_base + RTC_CCR); | ||
| 103 | |||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | static int xgene_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 108 | { | ||
| 109 | struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); | ||
| 110 | unsigned long rtc_time; | ||
| 111 | unsigned long alarm_time; | ||
| 112 | |||
| 113 | rtc_time = readl(pdata->csr_base + RTC_CCVR); | ||
| 114 | rtc_tm_to_time(&alrm->time, &alarm_time); | ||
| 115 | |||
| 116 | pdata->alarm_time = alarm_time; | ||
| 117 | writel((u32) pdata->alarm_time, pdata->csr_base + RTC_CMR); | ||
| 118 | |||
| 119 | xgene_rtc_alarm_irq_enable(dev, alrm->enabled); | ||
| 120 | |||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | static const struct rtc_class_ops xgene_rtc_ops = { | ||
| 125 | .read_time = xgene_rtc_read_time, | ||
| 126 | .set_mmss = xgene_rtc_set_mmss, | ||
| 127 | .read_alarm = xgene_rtc_read_alarm, | ||
| 128 | .set_alarm = xgene_rtc_set_alarm, | ||
| 129 | .alarm_irq_enable = xgene_rtc_alarm_irq_enable, | ||
| 130 | }; | ||
| 131 | |||
| 132 | static irqreturn_t xgene_rtc_interrupt(int irq, void *id) | ||
| 133 | { | ||
| 134 | struct xgene_rtc_dev *pdata = (struct xgene_rtc_dev *) id; | ||
| 135 | |||
| 136 | /* Check if interrupt asserted */ | ||
| 137 | if (!(readl(pdata->csr_base + RTC_STAT) & RTC_STAT_BIT)) | ||
| 138 | return IRQ_NONE; | ||
| 139 | |||
| 140 | /* Clear interrupt */ | ||
| 141 | readl(pdata->csr_base + RTC_EOI); | ||
| 142 | |||
| 143 | rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); | ||
| 144 | |||
| 145 | return IRQ_HANDLED; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int xgene_rtc_probe(struct platform_device *pdev) | ||
| 149 | { | ||
| 150 | struct xgene_rtc_dev *pdata; | ||
| 151 | struct resource *res; | ||
| 152 | int ret; | ||
| 153 | int irq; | ||
| 154 | |||
| 155 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
| 156 | if (!pdata) | ||
| 157 | return -ENOMEM; | ||
| 158 | platform_set_drvdata(pdev, pdata); | ||
| 159 | pdata->dev = &pdev->dev; | ||
| 160 | |||
| 161 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 162 | pdata->csr_base = devm_ioremap_resource(&pdev->dev, res); | ||
| 163 | if (IS_ERR(pdata->csr_base)) | ||
| 164 | return PTR_ERR(pdata->csr_base); | ||
| 165 | |||
| 166 | irq = platform_get_irq(pdev, 0); | ||
| 167 | if (irq < 0) { | ||
| 168 | dev_err(&pdev->dev, "No IRQ resource\n"); | ||
| 169 | return irq; | ||
| 170 | } | ||
| 171 | ret = devm_request_irq(&pdev->dev, irq, xgene_rtc_interrupt, 0, | ||
| 172 | dev_name(&pdev->dev), pdata); | ||
| 173 | if (ret) { | ||
| 174 | dev_err(&pdev->dev, "Could not request IRQ\n"); | ||
| 175 | return ret; | ||
| 176 | } | ||
| 177 | |||
| 178 | pdata->clk = devm_clk_get(&pdev->dev, NULL); | ||
| 179 | if (IS_ERR(pdata->clk)) { | ||
| 180 | dev_err(&pdev->dev, "Couldn't get the clock for RTC\n"); | ||
| 181 | return -ENODEV; | ||
| 182 | } | ||
| 183 | clk_prepare_enable(pdata->clk); | ||
| 184 | |||
| 185 | /* Turn on the clock and the crystal */ | ||
| 186 | writel(RTC_CCR_EN, pdata->csr_base + RTC_CCR); | ||
| 187 | |||
| 188 | device_init_wakeup(&pdev->dev, 1); | ||
| 189 | |||
| 190 | pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, | ||
| 191 | &xgene_rtc_ops, THIS_MODULE); | ||
| 192 | if (IS_ERR(pdata->rtc)) { | ||
| 193 | clk_disable_unprepare(pdata->clk); | ||
| 194 | return PTR_ERR(pdata->rtc); | ||
| 195 | } | ||
| 196 | |||
| 197 | /* HW does not support update faster than 1 seconds */ | ||
| 198 | pdata->rtc->uie_unsupported = 1; | ||
| 199 | |||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | static int xgene_rtc_remove(struct platform_device *pdev) | ||
| 204 | { | ||
| 205 | struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); | ||
| 206 | |||
| 207 | xgene_rtc_alarm_irq_enable(&pdev->dev, 0); | ||
| 208 | device_init_wakeup(&pdev->dev, 0); | ||
| 209 | clk_disable_unprepare(pdata->clk); | ||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | #ifdef CONFIG_PM_SLEEP | ||
| 214 | static int xgene_rtc_suspend(struct device *dev) | ||
| 215 | { | ||
| 216 | struct platform_device *pdev = to_platform_device(dev); | ||
| 217 | struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); | ||
| 218 | int irq; | ||
| 219 | |||
| 220 | irq = platform_get_irq(pdev, 0); | ||
| 221 | if (device_may_wakeup(&pdev->dev)) { | ||
| 222 | if (!enable_irq_wake(irq)) | ||
| 223 | pdata->irq_wake = 1; | ||
| 224 | } else { | ||
| 225 | xgene_rtc_alarm_irq_enable(dev, 0); | ||
| 226 | clk_disable(pdata->clk); | ||
| 227 | } | ||
| 228 | |||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int xgene_rtc_resume(struct device *dev) | ||
| 233 | { | ||
| 234 | struct platform_device *pdev = to_platform_device(dev); | ||
| 235 | struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); | ||
| 236 | int irq; | ||
| 237 | |||
| 238 | irq = platform_get_irq(pdev, 0); | ||
| 239 | if (device_may_wakeup(&pdev->dev)) { | ||
| 240 | if (pdata->irq_wake) { | ||
| 241 | disable_irq_wake(irq); | ||
| 242 | pdata->irq_wake = 0; | ||
| 243 | } | ||
| 244 | } else { | ||
| 245 | clk_enable(pdata->clk); | ||
| 246 | xgene_rtc_alarm_irq_enable(dev, 1); | ||
| 247 | } | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | #endif | ||
| 252 | |||
| 253 | static SIMPLE_DEV_PM_OPS(xgene_rtc_pm_ops, xgene_rtc_suspend, xgene_rtc_resume); | ||
| 254 | |||
| 255 | #ifdef CONFIG_OF | ||
| 256 | static const struct of_device_id xgene_rtc_of_match[] = { | ||
| 257 | {.compatible = "apm,xgene-rtc" }, | ||
| 258 | { } | ||
| 259 | }; | ||
| 260 | MODULE_DEVICE_TABLE(of, xgene_rtc_of_match); | ||
| 261 | #endif | ||
| 262 | |||
| 263 | static struct platform_driver xgene_rtc_driver = { | ||
| 264 | .probe = xgene_rtc_probe, | ||
| 265 | .remove = xgene_rtc_remove, | ||
| 266 | .driver = { | ||
| 267 | .owner = THIS_MODULE, | ||
| 268 | .name = "xgene-rtc", | ||
| 269 | .pm = &xgene_rtc_pm_ops, | ||
| 270 | .of_match_table = of_match_ptr(xgene_rtc_of_match), | ||
| 271 | }, | ||
| 272 | }; | ||
| 273 | |||
| 274 | module_platform_driver(xgene_rtc_driver); | ||
| 275 | |||
| 276 | MODULE_DESCRIPTION("APM X-Gene SoC RTC driver"); | ||
| 277 | MODULE_AUTHOR("Rameshwar Sahu <rsahu@apm.com>"); | ||
| 278 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c index 2b6b93f7d8ef..546f16299ef9 100644 --- a/drivers/scsi/scsi_sysctl.c +++ b/drivers/scsi/scsi_sysctl.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include "scsi_priv.h" | 12 | #include "scsi_priv.h" |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | static ctl_table scsi_table[] = { | 15 | static struct ctl_table scsi_table[] = { |
| 16 | { .procname = "logging_level", | 16 | { .procname = "logging_level", |
| 17 | .data = &scsi_logging_level, | 17 | .data = &scsi_logging_level, |
| 18 | .maxlen = sizeof(scsi_logging_level), | 18 | .maxlen = sizeof(scsi_logging_level), |
| @@ -21,14 +21,14 @@ static ctl_table scsi_table[] = { | |||
| 21 | { } | 21 | { } |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | static ctl_table scsi_dir_table[] = { | 24 | static struct ctl_table scsi_dir_table[] = { |
| 25 | { .procname = "scsi", | 25 | { .procname = "scsi", |
| 26 | .mode = 0555, | 26 | .mode = 0555, |
| 27 | .child = scsi_table }, | 27 | .child = scsi_table }, |
| 28 | { } | 28 | { } |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static ctl_table scsi_root_table[] = { | 31 | static struct ctl_table scsi_root_table[] = { |
| 32 | { .procname = "dev", | 32 | { .procname = "dev", |
| 33 | .mode = 0555, | 33 | .mode = 0555, |
| 34 | .child = scsi_dir_table }, | 34 | .child = scsi_dir_table }, |
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index b767a64e49d9..454b65898e2c 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #include <linux/jiffies.h> | 46 | #include <linux/jiffies.h> |
| 47 | #include <linux/syscalls.h> | 47 | #include <linux/syscalls.h> |
| 48 | #include <linux/of.h> | 48 | #include <linux/of.h> |
| 49 | #include <linux/rcupdate.h> | ||
| 49 | 50 | ||
| 50 | #include <asm/ptrace.h> | 51 | #include <asm/ptrace.h> |
| 51 | #include <asm/irq_regs.h> | 52 | #include <asm/irq_regs.h> |
| @@ -510,9 +511,9 @@ void __handle_sysrq(int key, bool check_mask) | |||
| 510 | struct sysrq_key_op *op_p; | 511 | struct sysrq_key_op *op_p; |
| 511 | int orig_log_level; | 512 | int orig_log_level; |
| 512 | int i; | 513 | int i; |
| 513 | unsigned long flags; | ||
| 514 | 514 | ||
| 515 | spin_lock_irqsave(&sysrq_key_table_lock, flags); | 515 | rcu_sysrq_start(); |
| 516 | rcu_read_lock(); | ||
| 516 | /* | 517 | /* |
| 517 | * Raise the apparent loglevel to maximum so that the sysrq header | 518 | * Raise the apparent loglevel to maximum so that the sysrq header |
| 518 | * is shown to provide the user with positive feedback. We do not | 519 | * is shown to provide the user with positive feedback. We do not |
| @@ -554,7 +555,8 @@ void __handle_sysrq(int key, bool check_mask) | |||
| 554 | printk("\n"); | 555 | printk("\n"); |
| 555 | console_loglevel = orig_log_level; | 556 | console_loglevel = orig_log_level; |
| 556 | } | 557 | } |
| 557 | spin_unlock_irqrestore(&sysrq_key_table_lock, flags); | 558 | rcu_read_unlock(); |
| 559 | rcu_sysrq_end(); | ||
| 558 | } | 560 | } |
| 559 | 561 | ||
| 560 | void handle_sysrq(int key) | 562 | void handle_sysrq(int key) |
| @@ -1043,16 +1045,23 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, | |||
| 1043 | struct sysrq_key_op *remove_op_p) | 1045 | struct sysrq_key_op *remove_op_p) |
| 1044 | { | 1046 | { |
| 1045 | int retval; | 1047 | int retval; |
| 1046 | unsigned long flags; | ||
| 1047 | 1048 | ||
| 1048 | spin_lock_irqsave(&sysrq_key_table_lock, flags); | 1049 | spin_lock(&sysrq_key_table_lock); |
| 1049 | if (__sysrq_get_key_op(key) == remove_op_p) { | 1050 | if (__sysrq_get_key_op(key) == remove_op_p) { |
| 1050 | __sysrq_put_key_op(key, insert_op_p); | 1051 | __sysrq_put_key_op(key, insert_op_p); |
| 1051 | retval = 0; | 1052 | retval = 0; |
| 1052 | } else { | 1053 | } else { |
| 1053 | retval = -1; | 1054 | retval = -1; |
| 1054 | } | 1055 | } |
| 1055 | spin_unlock_irqrestore(&sysrq_key_table_lock, flags); | 1056 | spin_unlock(&sysrq_key_table_lock); |
| 1057 | |||
| 1058 | /* | ||
| 1059 | * A concurrent __handle_sysrq either got the old op or the new op. | ||
| 1060 | * Wait for it to go away before returning, so the code for an old | ||
| 1061 | * op is not freed (eg. on module unload) while it is in use. | ||
| 1062 | */ | ||
| 1063 | synchronize_rcu(); | ||
| 1064 | |||
| 1056 | return retval; | 1065 | return retval; |
| 1057 | } | 1066 | } |
| 1058 | 1067 | ||
