diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 29 | ||||
| -rw-r--r-- | drivers/rtc/Makefile | 5 | ||||
| -rw-r--r-- | drivers/rtc/class.c | 16 | ||||
| -rw-r--r-- | drivers/rtc/interface.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-au1xxx.c | 18 | ||||
| -rw-r--r-- | drivers/rtc/rtc-da9063.c | 54 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1343.c | 75 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1742.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-efi-platform.c | 31 | ||||
| -rw-r--r-- | drivers/rtc/rtc-efi.c | 32 | ||||
| -rw-r--r-- | drivers/rtc/rtc-isl12022.c | 12 | ||||
| -rw-r--r-- | drivers/rtc/rtc-max77686.c | 27 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf85063.c | 204 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf8563.c | 231 | ||||
| -rw-r--r-- | drivers/rtc/rtc-tps65910.c | 4 |
15 files changed, 644 insertions, 98 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 0754f5c7cb3b..a168e96142b9 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -373,6 +373,14 @@ config RTC_DRV_PCF8563 | |||
| 373 | This driver can also be built as a module. If so, the module | 373 | This driver can also be built as a module. If so, the module |
| 374 | will be called rtc-pcf8563. | 374 | will be called rtc-pcf8563. |
| 375 | 375 | ||
| 376 | config RTC_DRV_PCF85063 | ||
| 377 | tristate "nxp PCF85063" | ||
| 378 | help | ||
| 379 | If you say yes here you get support for the PCF85063 RTC chip | ||
| 380 | |||
| 381 | This driver can also be built as a module. If so, the module | ||
| 382 | will be called rtc-pcf85063. | ||
| 383 | |||
| 376 | config RTC_DRV_PCF8583 | 384 | config RTC_DRV_PCF8583 |
| 377 | tristate "Philips PCF8583" | 385 | tristate "Philips PCF8583" |
| 378 | help | 386 | help |
| @@ -760,6 +768,15 @@ config RTC_DRV_DS1742 | |||
| 760 | This driver can also be built as a module. If so, the module | 768 | This driver can also be built as a module. If so, the module |
| 761 | will be called rtc-ds1742. | 769 | will be called rtc-ds1742. |
| 762 | 770 | ||
| 771 | config RTC_DRV_DS2404 | ||
| 772 | tristate "Maxim/Dallas DS2404" | ||
| 773 | help | ||
| 774 | If you say yes here you get support for the | ||
| 775 | Dallas DS2404 RTC chip. | ||
| 776 | |||
| 777 | This driver can also be built as a module. If so, the module | ||
| 778 | will be called rtc-ds2404. | ||
| 779 | |||
| 763 | config RTC_DRV_DA9052 | 780 | config RTC_DRV_DA9052 |
| 764 | tristate "Dialog DA9052/DA9053 RTC" | 781 | tristate "Dialog DA9052/DA9053 RTC" |
| 765 | depends on PMIC_DA9052 | 782 | depends on PMIC_DA9052 |
| @@ -789,7 +806,7 @@ config RTC_DRV_DA9063 | |||
| 789 | 806 | ||
| 790 | config RTC_DRV_EFI | 807 | config RTC_DRV_EFI |
| 791 | tristate "EFI RTC" | 808 | tristate "EFI RTC" |
| 792 | depends on IA64 | 809 | depends on EFI |
| 793 | help | 810 | help |
| 794 | If you say yes here you will get support for the EFI | 811 | If you say yes here you will get support for the EFI |
| 795 | Real Time Clock. | 812 | Real Time Clock. |
| @@ -873,15 +890,6 @@ config RTC_DRV_V3020 | |||
| 873 | This driver can also be built as a module. If so, the module | 890 | This driver can also be built as a module. If so, the module |
| 874 | will be called rtc-v3020. | 891 | will be called rtc-v3020. |
| 875 | 892 | ||
| 876 | config RTC_DRV_DS2404 | ||
| 877 | tristate "Dallas DS2404" | ||
| 878 | help | ||
| 879 | If you say yes here you get support for the | ||
| 880 | Dallas DS2404 RTC chip. | ||
| 881 | |||
| 882 | This driver can also be built as a module. If so, the module | ||
| 883 | will be called rtc-ds2404. | ||
| 884 | |||
| 885 | config RTC_DRV_WM831X | 893 | config RTC_DRV_WM831X |
| 886 | tristate "Wolfson Microelectronics WM831x RTC" | 894 | tristate "Wolfson Microelectronics WM831x RTC" |
| 887 | depends on MFD_WM831X | 895 | depends on MFD_WM831X |
| @@ -1349,6 +1357,7 @@ config RTC_DRV_SIRFSOC | |||
| 1349 | 1357 | ||
| 1350 | config RTC_DRV_MOXART | 1358 | config RTC_DRV_MOXART |
| 1351 | tristate "MOXA ART RTC" | 1359 | tristate "MOXA ART RTC" |
| 1360 | depends on ARCH_MOXART || COMPILE_TEST | ||
| 1352 | help | 1361 | help |
| 1353 | If you say yes here you get support for the MOXA ART | 1362 | If you say yes here you get support for the MOXA ART |
| 1354 | RTC module. | 1363 | RTC module. |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 70347d041d10..56f061c7c815 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -10,6 +10,10 @@ obj-$(CONFIG_RTC_SYSTOHC) += systohc.o | |||
| 10 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o | 10 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o |
| 11 | rtc-core-y := class.o interface.o | 11 | rtc-core-y := class.o interface.o |
| 12 | 12 | ||
| 13 | ifdef CONFIG_RTC_DRV_EFI | ||
| 14 | rtc-core-y += rtc-efi-platform.o | ||
| 15 | endif | ||
| 16 | |||
| 13 | rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o | 17 | rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o |
| 14 | rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o | 18 | rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o |
| 15 | rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | 19 | rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o |
| @@ -93,6 +97,7 @@ obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o | |||
| 93 | obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o | 97 | obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o |
| 94 | obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o | 98 | obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o |
| 95 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 99 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
| 100 | obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o | ||
| 96 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o | 101 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
| 97 | obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o | 102 | obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o |
| 98 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o | 103 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 589351ef75d0..38e26be705be 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -53,6 +53,7 @@ static int rtc_suspend(struct device *dev) | |||
| 53 | struct rtc_device *rtc = to_rtc_device(dev); | 53 | struct rtc_device *rtc = to_rtc_device(dev); |
| 54 | struct rtc_time tm; | 54 | struct rtc_time tm; |
| 55 | struct timespec delta, delta_delta; | 55 | struct timespec delta, delta_delta; |
| 56 | int err; | ||
| 56 | 57 | ||
| 57 | if (has_persistent_clock()) | 58 | if (has_persistent_clock()) |
| 58 | return 0; | 59 | return 0; |
| @@ -61,7 +62,12 @@ static int rtc_suspend(struct device *dev) | |||
| 61 | return 0; | 62 | return 0; |
| 62 | 63 | ||
| 63 | /* snapshot the current RTC and system time at suspend*/ | 64 | /* snapshot the current RTC and system time at suspend*/ |
| 64 | rtc_read_time(rtc, &tm); | 65 | err = rtc_read_time(rtc, &tm); |
| 66 | if (err < 0) { | ||
| 67 | pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev)); | ||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 65 | getnstimeofday(&old_system); | 71 | getnstimeofday(&old_system); |
| 66 | rtc_tm_to_time(&tm, &old_rtc.tv_sec); | 72 | rtc_tm_to_time(&tm, &old_rtc.tv_sec); |
| 67 | 73 | ||
| @@ -94,6 +100,7 @@ static int rtc_resume(struct device *dev) | |||
| 94 | struct rtc_time tm; | 100 | struct rtc_time tm; |
| 95 | struct timespec new_system, new_rtc; | 101 | struct timespec new_system, new_rtc; |
| 96 | struct timespec sleep_time; | 102 | struct timespec sleep_time; |
| 103 | int err; | ||
| 97 | 104 | ||
| 98 | if (has_persistent_clock()) | 105 | if (has_persistent_clock()) |
| 99 | return 0; | 106 | return 0; |
| @@ -104,7 +111,12 @@ static int rtc_resume(struct device *dev) | |||
| 104 | 111 | ||
| 105 | /* snapshot the current rtc and system time at resume */ | 112 | /* snapshot the current rtc and system time at resume */ |
| 106 | getnstimeofday(&new_system); | 113 | getnstimeofday(&new_system); |
| 107 | rtc_read_time(rtc, &tm); | 114 | err = rtc_read_time(rtc, &tm); |
| 115 | if (err < 0) { | ||
| 116 | pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev)); | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 108 | if (rtc_valid_tm(&tm) != 0) { | 120 | if (rtc_valid_tm(&tm) != 0) { |
| 109 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); | 121 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); |
| 110 | return 0; | 122 | return 0; |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 5813fa52c3d4..5b2717f5dafa 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
| @@ -348,6 +348,8 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
| 348 | 348 | ||
| 349 | /* Make sure we're not setting alarms in the past */ | 349 | /* Make sure we're not setting alarms in the past */ |
| 350 | err = __rtc_read_time(rtc, &tm); | 350 | err = __rtc_read_time(rtc, &tm); |
| 351 | if (err) | ||
| 352 | return err; | ||
| 351 | rtc_tm_to_time(&tm, &now); | 353 | rtc_tm_to_time(&tm, &now); |
| 352 | if (scheduled <= now) | 354 | if (scheduled <= now) |
| 353 | return -ETIME; | 355 | return -ETIME; |
diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c index ed526a192ce0..fd25e2374d4e 100644 --- a/drivers/rtc/rtc-au1xxx.c +++ b/drivers/rtc/rtc-au1xxx.c | |||
| @@ -32,7 +32,7 @@ static int au1xtoy_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 32 | { | 32 | { |
| 33 | unsigned long t; | 33 | unsigned long t; |
| 34 | 34 | ||
| 35 | t = au_readl(SYS_TOYREAD); | 35 | t = alchemy_rdsys(AU1000_SYS_TOYREAD); |
| 36 | 36 | ||
| 37 | rtc_time_to_tm(t, tm); | 37 | rtc_time_to_tm(t, tm); |
| 38 | 38 | ||
| @@ -45,13 +45,12 @@ static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 45 | 45 | ||
| 46 | rtc_tm_to_time(tm, &t); | 46 | rtc_tm_to_time(tm, &t); |
| 47 | 47 | ||
| 48 | au_writel(t, SYS_TOYWRITE); | 48 | alchemy_wrsys(t, AU1000_SYS_TOYWRITE); |
| 49 | au_sync(); | ||
| 50 | 49 | ||
| 51 | /* wait for the pending register write to succeed. This can | 50 | /* wait for the pending register write to succeed. This can |
| 52 | * take up to 6 seconds... | 51 | * take up to 6 seconds... |
| 53 | */ | 52 | */ |
| 54 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S) | 53 | while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S) |
| 55 | msleep(1); | 54 | msleep(1); |
| 56 | 55 | ||
| 57 | return 0; | 56 | return 0; |
| @@ -68,7 +67,7 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev) | |||
| 68 | unsigned long t; | 67 | unsigned long t; |
| 69 | int ret; | 68 | int ret; |
| 70 | 69 | ||
| 71 | t = au_readl(SYS_COUNTER_CNTRL); | 70 | t = alchemy_rdsys(AU1000_SYS_CNTRCTRL); |
| 72 | if (!(t & CNTR_OK)) { | 71 | if (!(t & CNTR_OK)) { |
| 73 | dev_err(&pdev->dev, "counters not working; aborting.\n"); | 72 | dev_err(&pdev->dev, "counters not working; aborting.\n"); |
| 74 | ret = -ENODEV; | 73 | ret = -ENODEV; |
| @@ -78,10 +77,10 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev) | |||
| 78 | ret = -ETIMEDOUT; | 77 | ret = -ETIMEDOUT; |
| 79 | 78 | ||
| 80 | /* set counter0 tickrate to 1Hz if necessary */ | 79 | /* set counter0 tickrate to 1Hz if necessary */ |
| 81 | if (au_readl(SYS_TOYTRIM) != 32767) { | 80 | if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767) { |
| 82 | /* wait until hardware gives access to TRIM register */ | 81 | /* wait until hardware gives access to TRIM register */ |
| 83 | t = 0x00100000; | 82 | t = 0x00100000; |
| 84 | while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S) && --t) | 83 | while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T0S) && --t) |
| 85 | msleep(1); | 84 | msleep(1); |
| 86 | 85 | ||
| 87 | if (!t) { | 86 | if (!t) { |
| @@ -93,12 +92,11 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev) | |||
| 93 | } | 92 | } |
| 94 | 93 | ||
| 95 | /* set 1Hz TOY tick rate */ | 94 | /* set 1Hz TOY tick rate */ |
| 96 | au_writel(32767, SYS_TOYTRIM); | 95 | alchemy_wrsys(32767, AU1000_SYS_TOYTRIM); |
| 97 | au_sync(); | ||
| 98 | } | 96 | } |
| 99 | 97 | ||
| 100 | /* wait until the hardware allows writes to the counter reg */ | 98 | /* wait until the hardware allows writes to the counter reg */ |
| 101 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S) | 99 | while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S) |
| 102 | msleep(1); | 100 | msleep(1); |
| 103 | 101 | ||
| 104 | rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx", | 102 | rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx", |
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c index 595393098b09..731ed1a97f59 100644 --- a/drivers/rtc/rtc-da9063.c +++ b/drivers/rtc/rtc-da9063.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #define YEARS_FROM_DA9063(year) ((year) + 100) | 29 | #define YEARS_FROM_DA9063(year) ((year) + 100) |
| 30 | #define MONTHS_FROM_DA9063(month) ((month) - 1) | 30 | #define MONTHS_FROM_DA9063(month) ((month) - 1) |
| 31 | 31 | ||
| 32 | #define RTC_ALARM_DATA_LEN (DA9063_AD_REG_ALARM_Y - DA9063_AD_REG_ALARM_MI + 1) | ||
| 33 | |||
| 32 | #define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1) | 34 | #define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1) |
| 33 | #define RTC_SEC 0 | 35 | #define RTC_SEC 0 |
| 34 | #define RTC_MIN 1 | 36 | #define RTC_MIN 1 |
| @@ -42,6 +44,10 @@ struct da9063_rtc { | |||
| 42 | struct da9063 *hw; | 44 | struct da9063 *hw; |
| 43 | struct rtc_time alarm_time; | 45 | struct rtc_time alarm_time; |
| 44 | bool rtc_sync; | 46 | bool rtc_sync; |
| 47 | int alarm_year; | ||
| 48 | int alarm_start; | ||
| 49 | int alarm_len; | ||
| 50 | int data_start; | ||
| 45 | }; | 51 | }; |
| 46 | 52 | ||
| 47 | static void da9063_data_to_tm(u8 *data, struct rtc_time *tm) | 53 | static void da9063_data_to_tm(u8 *data, struct rtc_time *tm) |
| @@ -83,7 +89,7 @@ static int da9063_rtc_stop_alarm(struct device *dev) | |||
| 83 | { | 89 | { |
| 84 | struct da9063_rtc *rtc = dev_get_drvdata(dev); | 90 | struct da9063_rtc *rtc = dev_get_drvdata(dev); |
| 85 | 91 | ||
| 86 | return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y, | 92 | return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year, |
| 87 | DA9063_ALARM_ON, 0); | 93 | DA9063_ALARM_ON, 0); |
| 88 | } | 94 | } |
| 89 | 95 | ||
| @@ -91,7 +97,7 @@ static int da9063_rtc_start_alarm(struct device *dev) | |||
| 91 | { | 97 | { |
| 92 | struct da9063_rtc *rtc = dev_get_drvdata(dev); | 98 | struct da9063_rtc *rtc = dev_get_drvdata(dev); |
| 93 | 99 | ||
| 94 | return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y, | 100 | return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year, |
| 95 | DA9063_ALARM_ON, DA9063_ALARM_ON); | 101 | DA9063_ALARM_ON, DA9063_ALARM_ON); |
| 96 | } | 102 | } |
| 97 | 103 | ||
| @@ -151,8 +157,9 @@ static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 151 | int ret; | 157 | int ret; |
| 152 | unsigned int val; | 158 | unsigned int val; |
| 153 | 159 | ||
| 154 | ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_ALARM_S, | 160 | data[RTC_SEC] = 0; |
| 155 | &data[RTC_SEC], RTC_DATA_LEN); | 161 | ret = regmap_bulk_read(rtc->hw->regmap, rtc->alarm_start, |
| 162 | &data[rtc->data_start], rtc->alarm_len); | ||
| 156 | if (ret < 0) | 163 | if (ret < 0) |
| 157 | return ret; | 164 | return ret; |
| 158 | 165 | ||
| @@ -186,14 +193,14 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 186 | return ret; | 193 | return ret; |
| 187 | } | 194 | } |
| 188 | 195 | ||
| 189 | ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_ALARM_S, | 196 | ret = regmap_bulk_write(rtc->hw->regmap, rtc->alarm_start, |
| 190 | data, RTC_DATA_LEN); | 197 | &data[rtc->data_start], rtc->alarm_len); |
| 191 | if (ret < 0) { | 198 | if (ret < 0) { |
| 192 | dev_err(dev, "Failed to write alarm: %d\n", ret); | 199 | dev_err(dev, "Failed to write alarm: %d\n", ret); |
| 193 | return ret; | 200 | return ret; |
| 194 | } | 201 | } |
| 195 | 202 | ||
| 196 | rtc->alarm_time = alrm->time; | 203 | da9063_data_to_tm(data, &rtc->alarm_time); |
| 197 | 204 | ||
| 198 | if (alrm->enabled) { | 205 | if (alrm->enabled) { |
| 199 | ret = da9063_rtc_start_alarm(dev); | 206 | ret = da9063_rtc_start_alarm(dev); |
| @@ -218,7 +225,7 @@ static irqreturn_t da9063_alarm_event(int irq, void *data) | |||
| 218 | { | 225 | { |
| 219 | struct da9063_rtc *rtc = data; | 226 | struct da9063_rtc *rtc = data; |
| 220 | 227 | ||
| 221 | regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y, | 228 | regmap_update_bits(rtc->hw->regmap, rtc->alarm_year, |
| 222 | DA9063_ALARM_ON, 0); | 229 | DA9063_ALARM_ON, 0); |
| 223 | 230 | ||
| 224 | rtc->rtc_sync = true; | 231 | rtc->rtc_sync = true; |
| @@ -257,7 +264,23 @@ static int da9063_rtc_probe(struct platform_device *pdev) | |||
| 257 | goto err; | 264 | goto err; |
| 258 | } | 265 | } |
| 259 | 266 | ||
| 260 | ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S, | 267 | rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); |
| 268 | if (!rtc) | ||
| 269 | return -ENOMEM; | ||
| 270 | |||
| 271 | if (da9063->variant_code == PMIC_DA9063_AD) { | ||
| 272 | rtc->alarm_year = DA9063_AD_REG_ALARM_Y; | ||
| 273 | rtc->alarm_start = DA9063_AD_REG_ALARM_MI; | ||
| 274 | rtc->alarm_len = RTC_ALARM_DATA_LEN; | ||
| 275 | rtc->data_start = RTC_MIN; | ||
| 276 | } else { | ||
| 277 | rtc->alarm_year = DA9063_BB_REG_ALARM_Y; | ||
| 278 | rtc->alarm_start = DA9063_BB_REG_ALARM_S; | ||
| 279 | rtc->alarm_len = RTC_DATA_LEN; | ||
| 280 | rtc->data_start = RTC_SEC; | ||
| 281 | } | ||
| 282 | |||
| 283 | ret = regmap_update_bits(da9063->regmap, rtc->alarm_start, | ||
| 261 | DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM, | 284 | DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM, |
| 262 | 0); | 285 | 0); |
| 263 | if (ret < 0) { | 286 | if (ret < 0) { |
| @@ -265,7 +288,7 @@ static int da9063_rtc_probe(struct platform_device *pdev) | |||
| 265 | goto err; | 288 | goto err; |
| 266 | } | 289 | } |
| 267 | 290 | ||
| 268 | ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S, | 291 | ret = regmap_update_bits(da9063->regmap, rtc->alarm_start, |
| 269 | DA9063_ALARM_STATUS_ALARM, | 292 | DA9063_ALARM_STATUS_ALARM, |
| 270 | DA9063_ALARM_STATUS_ALARM); | 293 | DA9063_ALARM_STATUS_ALARM); |
| 271 | if (ret < 0) { | 294 | if (ret < 0) { |
| @@ -273,25 +296,22 @@ static int da9063_rtc_probe(struct platform_device *pdev) | |||
| 273 | goto err; | 296 | goto err; |
| 274 | } | 297 | } |
| 275 | 298 | ||
| 276 | ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_Y, | 299 | ret = regmap_update_bits(da9063->regmap, rtc->alarm_year, |
| 277 | DA9063_TICK_ON, 0); | 300 | DA9063_TICK_ON, 0); |
| 278 | if (ret < 0) { | 301 | if (ret < 0) { |
| 279 | dev_err(&pdev->dev, "Failed to disable TICKs\n"); | 302 | dev_err(&pdev->dev, "Failed to disable TICKs\n"); |
| 280 | goto err; | 303 | goto err; |
| 281 | } | 304 | } |
| 282 | 305 | ||
| 283 | ret = regmap_bulk_read(da9063->regmap, DA9063_REG_ALARM_S, | 306 | data[RTC_SEC] = 0; |
| 284 | data, RTC_DATA_LEN); | 307 | ret = regmap_bulk_read(da9063->regmap, rtc->alarm_start, |
| 308 | &data[rtc->data_start], rtc->alarm_len); | ||
| 285 | if (ret < 0) { | 309 | if (ret < 0) { |
| 286 | dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n", | 310 | dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n", |
| 287 | ret); | 311 | ret); |
| 288 | goto err; | 312 | goto err; |
| 289 | } | 313 | } |
| 290 | 314 | ||
| 291 | rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); | ||
| 292 | if (!rtc) | ||
| 293 | return -ENOMEM; | ||
| 294 | |||
| 295 | platform_set_drvdata(pdev, rtc); | 315 | platform_set_drvdata(pdev, rtc); |
| 296 | 316 | ||
| 297 | irq_alarm = platform_get_irq_byname(pdev, "ALARM"); | 317 | irq_alarm = platform_get_irq_byname(pdev, "ALARM"); |
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index c3719189dd96..ae9f997223b1 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | * Real Time Clock | 4 | * Real Time Clock |
| 5 | * | 5 | * |
| 6 | * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com> | 6 | * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com> |
| 7 | * Ankur Srivastava <sankurece@gmail.com> : DS1343 Nvram Support | ||
| 7 | * | 8 | * |
| 8 | * This program is free software; you can redistribute it and/or modify | 9 | * 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 | * it under the terms of the GNU General Public License version 2 as |
| @@ -45,6 +46,9 @@ | |||
| 45 | #define DS1343_CONTROL_REG 0x0F | 46 | #define DS1343_CONTROL_REG 0x0F |
| 46 | #define DS1343_STATUS_REG 0x10 | 47 | #define DS1343_STATUS_REG 0x10 |
| 47 | #define DS1343_TRICKLE_REG 0x11 | 48 | #define DS1343_TRICKLE_REG 0x11 |
| 49 | #define DS1343_NVRAM 0x20 | ||
| 50 | |||
| 51 | #define DS1343_NVRAM_LEN 96 | ||
| 48 | 52 | ||
| 49 | /* DS1343 Control Registers bits */ | 53 | /* DS1343 Control Registers bits */ |
| 50 | #define DS1343_EOSC 0x80 | 54 | #define DS1343_EOSC 0x80 |
| @@ -149,6 +153,64 @@ static ssize_t ds1343_store_glitchfilter(struct device *dev, | |||
| 149 | static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter, | 153 | static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter, |
| 150 | ds1343_store_glitchfilter); | 154 | ds1343_store_glitchfilter); |
| 151 | 155 | ||
| 156 | static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj, | ||
| 157 | struct bin_attribute *attr, | ||
| 158 | char *buf, loff_t off, size_t count) | ||
| 159 | { | ||
| 160 | int ret; | ||
| 161 | unsigned char address; | ||
| 162 | struct device *dev = kobj_to_dev(kobj); | ||
| 163 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 164 | |||
| 165 | if (unlikely(!count)) | ||
| 166 | return count; | ||
| 167 | |||
| 168 | if ((count + off) > DS1343_NVRAM_LEN) | ||
| 169 | count = DS1343_NVRAM_LEN - off; | ||
| 170 | |||
| 171 | address = DS1343_NVRAM + off; | ||
| 172 | |||
| 173 | ret = regmap_bulk_write(priv->map, address, buf, count); | ||
| 174 | if (ret < 0) | ||
| 175 | dev_err(&priv->spi->dev, "Error in nvram write %d", ret); | ||
| 176 | |||
| 177 | return (ret < 0) ? ret : count; | ||
| 178 | } | ||
| 179 | |||
| 180 | |||
| 181 | static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj, | ||
| 182 | struct bin_attribute *attr, | ||
| 183 | char *buf, loff_t off, size_t count) | ||
| 184 | { | ||
| 185 | int ret; | ||
| 186 | unsigned char address; | ||
| 187 | struct device *dev = kobj_to_dev(kobj); | ||
| 188 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 189 | |||
| 190 | if (unlikely(!count)) | ||
| 191 | return count; | ||
| 192 | |||
| 193 | if ((count + off) > DS1343_NVRAM_LEN) | ||
| 194 | count = DS1343_NVRAM_LEN - off; | ||
| 195 | |||
| 196 | address = DS1343_NVRAM + off; | ||
| 197 | |||
| 198 | ret = regmap_bulk_read(priv->map, address, buf, count); | ||
| 199 | if (ret < 0) | ||
| 200 | dev_err(&priv->spi->dev, "Error in nvram read %d\n", ret); | ||
| 201 | |||
| 202 | return (ret < 0) ? ret : count; | ||
| 203 | } | ||
| 204 | |||
| 205 | |||
| 206 | static struct bin_attribute nvram_attr = { | ||
| 207 | .attr.name = "nvram", | ||
| 208 | .attr.mode = S_IRUGO | S_IWUSR, | ||
| 209 | .read = ds1343_nvram_read, | ||
| 210 | .write = ds1343_nvram_write, | ||
| 211 | .size = DS1343_NVRAM_LEN, | ||
| 212 | }; | ||
| 213 | |||
| 152 | static ssize_t ds1343_show_alarmstatus(struct device *dev, | 214 | static ssize_t ds1343_show_alarmstatus(struct device *dev, |
| 153 | struct device_attribute *attr, char *buf) | 215 | struct device_attribute *attr, char *buf) |
| 154 | { | 216 | { |
| @@ -274,12 +336,16 @@ static int ds1343_sysfs_register(struct device *dev) | |||
| 274 | if (err) | 336 | if (err) |
| 275 | goto error1; | 337 | goto error1; |
| 276 | 338 | ||
| 339 | err = device_create_bin_file(dev, &nvram_attr); | ||
| 340 | if (err) | ||
| 341 | goto error2; | ||
| 342 | |||
| 277 | if (priv->irq <= 0) | 343 | if (priv->irq <= 0) |
| 278 | return err; | 344 | return err; |
| 279 | 345 | ||
| 280 | err = device_create_file(dev, &dev_attr_alarm_mode); | 346 | err = device_create_file(dev, &dev_attr_alarm_mode); |
| 281 | if (err) | 347 | if (err) |
| 282 | goto error2; | 348 | goto error3; |
| 283 | 349 | ||
| 284 | err = device_create_file(dev, &dev_attr_alarm_status); | 350 | err = device_create_file(dev, &dev_attr_alarm_status); |
| 285 | if (!err) | 351 | if (!err) |
| @@ -287,6 +353,9 @@ static int ds1343_sysfs_register(struct device *dev) | |||
| 287 | 353 | ||
| 288 | device_remove_file(dev, &dev_attr_alarm_mode); | 354 | device_remove_file(dev, &dev_attr_alarm_mode); |
| 289 | 355 | ||
| 356 | error3: | ||
| 357 | device_remove_bin_file(dev, &nvram_attr); | ||
| 358 | |||
| 290 | error2: | 359 | error2: |
| 291 | device_remove_file(dev, &dev_attr_trickle_charger); | 360 | device_remove_file(dev, &dev_attr_trickle_charger); |
| 292 | 361 | ||
| @@ -302,6 +371,7 @@ static void ds1343_sysfs_unregister(struct device *dev) | |||
| 302 | 371 | ||
| 303 | device_remove_file(dev, &dev_attr_glitch_filter); | 372 | device_remove_file(dev, &dev_attr_glitch_filter); |
| 304 | device_remove_file(dev, &dev_attr_trickle_charger); | 373 | device_remove_file(dev, &dev_attr_trickle_charger); |
| 374 | device_remove_bin_file(dev, &nvram_attr); | ||
| 305 | 375 | ||
| 306 | if (priv->irq <= 0) | 376 | if (priv->irq <= 0) |
| 307 | return; | 377 | return; |
| @@ -684,6 +754,7 @@ static struct spi_driver ds1343_driver = { | |||
| 684 | module_spi_driver(ds1343_driver); | 754 | module_spi_driver(ds1343_driver); |
| 685 | 755 | ||
| 686 | MODULE_DESCRIPTION("DS1343 RTC SPI Driver"); | 756 | MODULE_DESCRIPTION("DS1343 RTC SPI Driver"); |
| 687 | MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>"); | 757 | MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>," |
| 758 | "Ankur Srivastava <sankurece@gmail.com>"); | ||
| 688 | MODULE_LICENSE("GPL v2"); | 759 | MODULE_LICENSE("GPL v2"); |
| 689 | MODULE_VERSION(DS1343_DRV_VERSION); | 760 | MODULE_VERSION(DS1343_DRV_VERSION); |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index c6b2191a4128..9822715db8ba 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
| @@ -231,7 +231,7 @@ static struct platform_driver ds1742_rtc_driver = { | |||
| 231 | .driver = { | 231 | .driver = { |
| 232 | .name = "rtc-ds1742", | 232 | .name = "rtc-ds1742", |
| 233 | .owner = THIS_MODULE, | 233 | .owner = THIS_MODULE, |
| 234 | .of_match_table = ds1742_rtc_of_match, | 234 | .of_match_table = of_match_ptr(ds1742_rtc_of_match), |
| 235 | }, | 235 | }, |
| 236 | }; | 236 | }; |
| 237 | 237 | ||
diff --git a/drivers/rtc/rtc-efi-platform.c b/drivers/rtc/rtc-efi-platform.c new file mode 100644 index 000000000000..b40fbe332af4 --- /dev/null +++ b/drivers/rtc/rtc-efi-platform.c | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | /* | ||
| 2 | * Moved from arch/ia64/kernel/time.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 1998-2003 Hewlett-Packard Co | ||
| 5 | * Stephane Eranian <eranian@hpl.hp.com> | ||
| 6 | * David Mosberger <davidm@hpl.hp.com> | ||
| 7 | * Copyright (C) 1999 Don Dugger <don.dugger@intel.com> | ||
| 8 | * Copyright (C) 1999-2000 VA Linux Systems | ||
| 9 | * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com> | ||
| 10 | */ | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/efi.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | |||
| 17 | static struct platform_device rtc_efi_dev = { | ||
| 18 | .name = "rtc-efi", | ||
| 19 | .id = -1, | ||
| 20 | }; | ||
| 21 | |||
| 22 | static int __init rtc_init(void) | ||
| 23 | { | ||
| 24 | if (efi_enabled(EFI_RUNTIME_SERVICES)) | ||
| 25 | if (platform_device_register(&rtc_efi_dev) < 0) | ||
| 26 | pr_err("unable to register rtc device...\n"); | ||
| 27 | |||
| 28 | /* not necessarily an error */ | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | module_init(rtc_init); | ||
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index c4c38431012e..8225b89de810 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/stringify.h> | ||
| 20 | #include <linux/time.h> | 21 | #include <linux/time.h> |
| 21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
| 22 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
| @@ -48,8 +49,8 @@ compute_wday(efi_time_t *eft) | |||
| 48 | int y; | 49 | int y; |
| 49 | int ndays = 0; | 50 | int ndays = 0; |
| 50 | 51 | ||
| 51 | if (eft->year < 1998) { | 52 | if (eft->year < EFI_RTC_EPOCH) { |
| 52 | pr_err("EFI year < 1998, invalid date\n"); | 53 | pr_err("EFI year < " __stringify(EFI_RTC_EPOCH) ", invalid date\n"); |
| 53 | return -1; | 54 | return -1; |
| 54 | } | 55 | } |
| 55 | 56 | ||
| @@ -78,19 +79,36 @@ convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft) | |||
| 78 | eft->timezone = EFI_UNSPECIFIED_TIMEZONE; | 79 | eft->timezone = EFI_UNSPECIFIED_TIMEZONE; |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | static void | 82 | static bool |
| 82 | convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) | 83 | convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) |
| 83 | { | 84 | { |
| 84 | memset(wtime, 0, sizeof(*wtime)); | 85 | memset(wtime, 0, sizeof(*wtime)); |
| 86 | |||
| 87 | if (eft->second >= 60) | ||
| 88 | return false; | ||
| 85 | wtime->tm_sec = eft->second; | 89 | wtime->tm_sec = eft->second; |
| 90 | |||
| 91 | if (eft->minute >= 60) | ||
| 92 | return false; | ||
| 86 | wtime->tm_min = eft->minute; | 93 | wtime->tm_min = eft->minute; |
| 94 | |||
| 95 | if (eft->hour >= 24) | ||
| 96 | return false; | ||
| 87 | wtime->tm_hour = eft->hour; | 97 | wtime->tm_hour = eft->hour; |
| 98 | |||
| 99 | if (!eft->day || eft->day > 31) | ||
| 100 | return false; | ||
| 88 | wtime->tm_mday = eft->day; | 101 | wtime->tm_mday = eft->day; |
| 102 | |||
| 103 | if (!eft->month || eft->month > 12) | ||
| 104 | return false; | ||
| 89 | wtime->tm_mon = eft->month - 1; | 105 | wtime->tm_mon = eft->month - 1; |
| 90 | wtime->tm_year = eft->year - 1900; | 106 | wtime->tm_year = eft->year - 1900; |
| 91 | 107 | ||
| 92 | /* day of the week [0-6], Sunday=0 */ | 108 | /* day of the week [0-6], Sunday=0 */ |
| 93 | wtime->tm_wday = compute_wday(eft); | 109 | wtime->tm_wday = compute_wday(eft); |
| 110 | if (wtime->tm_wday < 0) | ||
| 111 | return false; | ||
| 94 | 112 | ||
| 95 | /* day in the year [1-365]*/ | 113 | /* day in the year [1-365]*/ |
| 96 | wtime->tm_yday = compute_yday(eft); | 114 | wtime->tm_yday = compute_yday(eft); |
| @@ -106,6 +124,8 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) | |||
| 106 | default: | 124 | default: |
| 107 | wtime->tm_isdst = -1; | 125 | wtime->tm_isdst = -1; |
| 108 | } | 126 | } |
| 127 | |||
| 128 | return true; | ||
| 109 | } | 129 | } |
| 110 | 130 | ||
| 111 | static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | 131 | static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) |
| @@ -122,7 +142,8 @@ static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
| 122 | if (status != EFI_SUCCESS) | 142 | if (status != EFI_SUCCESS) |
| 123 | return -EINVAL; | 143 | return -EINVAL; |
| 124 | 144 | ||
| 125 | convert_from_efi_time(&eft, &wkalrm->time); | 145 | if (!convert_from_efi_time(&eft, &wkalrm->time)) |
| 146 | return -EIO; | ||
| 126 | 147 | ||
| 127 | return rtc_valid_tm(&wkalrm->time); | 148 | return rtc_valid_tm(&wkalrm->time); |
| 128 | } | 149 | } |
| @@ -163,7 +184,8 @@ static int efi_read_time(struct device *dev, struct rtc_time *tm) | |||
| 163 | return -EINVAL; | 184 | return -EINVAL; |
| 164 | } | 185 | } |
| 165 | 186 | ||
| 166 | convert_from_efi_time(&eft, tm); | 187 | if (!convert_from_efi_time(&eft, tm)) |
| 188 | return -EIO; | ||
| 167 | 189 | ||
| 168 | return rtc_valid_tm(tm); | 190 | return rtc_valid_tm(tm); |
| 169 | } | 191 | } |
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 03b891129428..aa55f081c505 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/of_device.h> | ||
| 20 | 22 | ||
| 21 | #define DRV_VERSION "0.1" | 23 | #define DRV_VERSION "0.1" |
| 22 | 24 | ||
| @@ -271,6 +273,13 @@ static int isl12022_probe(struct i2c_client *client, | |||
| 271 | return PTR_ERR_OR_ZERO(isl12022->rtc); | 273 | return PTR_ERR_OR_ZERO(isl12022->rtc); |
| 272 | } | 274 | } |
| 273 | 275 | ||
| 276 | #ifdef CONFIG_OF | ||
| 277 | static struct of_device_id isl12022_dt_match[] = { | ||
| 278 | { .compatible = "isl,isl12022" }, | ||
| 279 | { }, | ||
| 280 | }; | ||
| 281 | #endif | ||
| 282 | |||
| 274 | static const struct i2c_device_id isl12022_id[] = { | 283 | static const struct i2c_device_id isl12022_id[] = { |
| 275 | { "isl12022", 0 }, | 284 | { "isl12022", 0 }, |
| 276 | { } | 285 | { } |
| @@ -280,6 +289,9 @@ MODULE_DEVICE_TABLE(i2c, isl12022_id); | |||
| 280 | static struct i2c_driver isl12022_driver = { | 289 | static struct i2c_driver isl12022_driver = { |
| 281 | .driver = { | 290 | .driver = { |
| 282 | .name = "rtc-isl12022", | 291 | .name = "rtc-isl12022", |
| 292 | #ifdef CONFIG_OF | ||
| 293 | .of_match_table = of_match_ptr(isl12022_dt_match), | ||
| 294 | #endif | ||
| 283 | }, | 295 | }, |
| 284 | .probe = isl12022_probe, | 296 | .probe = isl12022_probe, |
| 285 | .id_table = isl12022_id, | 297 | .id_table = isl12022_id, |
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 9efe118a28ba..d20a7f0786eb 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c | |||
| @@ -492,16 +492,11 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) | |||
| 492 | return ret; | 492 | return ret; |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | static struct regmap_config max77686_rtc_regmap_config = { | ||
| 496 | .reg_bits = 8, | ||
| 497 | .val_bits = 8, | ||
| 498 | }; | ||
| 499 | |||
| 500 | static int max77686_rtc_probe(struct platform_device *pdev) | 495 | static int max77686_rtc_probe(struct platform_device *pdev) |
| 501 | { | 496 | { |
| 502 | struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent); | 497 | struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent); |
| 503 | struct max77686_rtc_info *info; | 498 | struct max77686_rtc_info *info; |
| 504 | int ret, virq; | 499 | int ret; |
| 505 | 500 | ||
| 506 | dev_info(&pdev->dev, "%s\n", __func__); | 501 | dev_info(&pdev->dev, "%s\n", __func__); |
| 507 | 502 | ||
| @@ -514,14 +509,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) | |||
| 514 | info->dev = &pdev->dev; | 509 | info->dev = &pdev->dev; |
| 515 | info->max77686 = max77686; | 510 | info->max77686 = max77686; |
| 516 | info->rtc = max77686->rtc; | 511 | info->rtc = max77686->rtc; |
| 517 | info->max77686->rtc_regmap = devm_regmap_init_i2c(info->max77686->rtc, | 512 | |
| 518 | &max77686_rtc_regmap_config); | ||
| 519 | if (IS_ERR(info->max77686->rtc_regmap)) { | ||
| 520 | ret = PTR_ERR(info->max77686->rtc_regmap); | ||
| 521 | dev_err(info->max77686->dev, "Failed to allocate register map: %d\n", | ||
| 522 | ret); | ||
| 523 | return ret; | ||
| 524 | } | ||
| 525 | platform_set_drvdata(pdev, info); | 513 | platform_set_drvdata(pdev, info); |
| 526 | 514 | ||
| 527 | ret = max77686_rtc_init_reg(info); | 515 | ret = max77686_rtc_init_reg(info); |
| @@ -550,15 +538,16 @@ static int max77686_rtc_probe(struct platform_device *pdev) | |||
| 550 | ret = -EINVAL; | 538 | ret = -EINVAL; |
| 551 | goto err_rtc; | 539 | goto err_rtc; |
| 552 | } | 540 | } |
| 553 | virq = irq_create_mapping(max77686->irq_domain, MAX77686_RTCIRQ_RTCA1); | 541 | |
| 554 | if (!virq) { | 542 | info->virq = regmap_irq_get_virq(max77686->rtc_irq_data, |
| 543 | MAX77686_RTCIRQ_RTCA1); | ||
| 544 | if (!info->virq) { | ||
| 555 | ret = -ENXIO; | 545 | ret = -ENXIO; |
| 556 | goto err_rtc; | 546 | goto err_rtc; |
| 557 | } | 547 | } |
| 558 | info->virq = virq; | ||
| 559 | 548 | ||
| 560 | ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, | 549 | ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL, |
| 561 | max77686_rtc_alarm_irq, 0, "rtc-alarm0", info); | 550 | max77686_rtc_alarm_irq, 0, "rtc-alarm1", info); |
| 562 | if (ret < 0) | 551 | if (ret < 0) |
| 563 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", | 552 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", |
| 564 | info->virq, ret); | 553 | info->virq, ret); |
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c new file mode 100644 index 000000000000..6a12bf62c504 --- /dev/null +++ b/drivers/rtc/rtc-pcf85063.c | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | /* | ||
| 2 | * An I2C driver for the PCF85063 RTC | ||
| 3 | * Copyright 2014 Rose Technology | ||
| 4 | * | ||
| 5 | * Author: Søren Andersen <san@rosetechnology.dk> | ||
| 6 | * Maintainers: http://www.nslu2-linux.org/ | ||
| 7 | * | ||
| 8 | * based on the other drivers in this same directory. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | #include <linux/i2c.h> | ||
| 15 | #include <linux/bcd.h> | ||
| 16 | #include <linux/rtc.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | |||
| 19 | #define DRV_VERSION "0.0.1" | ||
| 20 | |||
| 21 | #define PCF85063_REG_CTRL1 0x00 /* status */ | ||
| 22 | #define PCF85063_REG_CTRL2 0x01 | ||
| 23 | |||
| 24 | #define PCF85063_REG_SC 0x04 /* datetime */ | ||
| 25 | #define PCF85063_REG_MN 0x05 | ||
| 26 | #define PCF85063_REG_HR 0x06 | ||
| 27 | #define PCF85063_REG_DM 0x07 | ||
| 28 | #define PCF85063_REG_DW 0x08 | ||
| 29 | #define PCF85063_REG_MO 0x09 | ||
| 30 | #define PCF85063_REG_YR 0x0A | ||
| 31 | |||
| 32 | #define PCF85063_MO_C 0x80 /* century */ | ||
| 33 | |||
| 34 | static struct i2c_driver pcf85063_driver; | ||
| 35 | |||
| 36 | struct pcf85063 { | ||
| 37 | struct rtc_device *rtc; | ||
| 38 | int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */ | ||
| 39 | int voltage_low; /* indicates if a low_voltage was detected */ | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* | ||
| 43 | * In the routines that deal directly with the pcf85063 hardware, we use | ||
| 44 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
| 45 | */ | ||
| 46 | static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 47 | { | ||
| 48 | struct pcf85063 *pcf85063 = i2c_get_clientdata(client); | ||
| 49 | unsigned char buf[13] = { PCF85063_REG_CTRL1 }; | ||
| 50 | struct i2c_msg msgs[] = { | ||
| 51 | {/* setup read ptr */ | ||
| 52 | .addr = client->addr, | ||
| 53 | .len = 1, | ||
| 54 | .buf = buf | ||
| 55 | }, | ||
| 56 | {/* read status + date */ | ||
| 57 | .addr = client->addr, | ||
| 58 | .flags = I2C_M_RD, | ||
| 59 | .len = 13, | ||
| 60 | .buf = buf | ||
| 61 | }, | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* read registers */ | ||
| 65 | if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { | ||
| 66 | dev_err(&client->dev, "%s: read error\n", __func__); | ||
| 67 | return -EIO; | ||
| 68 | } | ||
| 69 | |||
| 70 | tm->tm_sec = bcd2bin(buf[PCF85063_REG_SC] & 0x7F); | ||
| 71 | tm->tm_min = bcd2bin(buf[PCF85063_REG_MN] & 0x7F); | ||
| 72 | tm->tm_hour = bcd2bin(buf[PCF85063_REG_HR] & 0x3F); /* rtc hr 0-23 */ | ||
| 73 | tm->tm_mday = bcd2bin(buf[PCF85063_REG_DM] & 0x3F); | ||
| 74 | tm->tm_wday = buf[PCF85063_REG_DW] & 0x07; | ||
| 75 | tm->tm_mon = bcd2bin(buf[PCF85063_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ | ||
| 76 | tm->tm_year = bcd2bin(buf[PCF85063_REG_YR]); | ||
| 77 | if (tm->tm_year < 70) | ||
| 78 | tm->tm_year += 100; /* assume we are in 1970...2069 */ | ||
| 79 | /* detect the polarity heuristically. see note above. */ | ||
| 80 | pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ? | ||
| 81 | (tm->tm_year >= 100) : (tm->tm_year < 100); | ||
| 82 | |||
| 83 | /* the clock can give out invalid datetime, but we cannot return | ||
| 84 | * -EINVAL otherwise hwclock will refuse to set the time on bootup. | ||
| 85 | */ | ||
| 86 | if (rtc_valid_tm(tm) < 0) | ||
| 87 | dev_err(&client->dev, "retrieved date/time is not valid.\n"); | ||
| 88 | |||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 93 | { | ||
| 94 | int i = 0, err = 0; | ||
| 95 | unsigned char buf[11]; | ||
| 96 | |||
| 97 | /* Control & status */ | ||
| 98 | buf[PCF85063_REG_CTRL1] = 0; | ||
| 99 | buf[PCF85063_REG_CTRL2] = 5; | ||
| 100 | |||
| 101 | /* hours, minutes and seconds */ | ||
| 102 | buf[PCF85063_REG_SC] = bin2bcd(tm->tm_sec) & 0x7F; | ||
| 103 | |||
| 104 | buf[PCF85063_REG_MN] = bin2bcd(tm->tm_min); | ||
| 105 | buf[PCF85063_REG_HR] = bin2bcd(tm->tm_hour); | ||
| 106 | |||
| 107 | /* Day of month, 1 - 31 */ | ||
| 108 | buf[PCF85063_REG_DM] = bin2bcd(tm->tm_mday); | ||
| 109 | |||
| 110 | /* Day, 0 - 6 */ | ||
| 111 | buf[PCF85063_REG_DW] = tm->tm_wday & 0x07; | ||
| 112 | |||
| 113 | /* month, 1 - 12 */ | ||
| 114 | buf[PCF85063_REG_MO] = bin2bcd(tm->tm_mon + 1); | ||
| 115 | |||
| 116 | /* year and century */ | ||
| 117 | buf[PCF85063_REG_YR] = bin2bcd(tm->tm_year % 100); | ||
| 118 | |||
| 119 | /* write register's data */ | ||
| 120 | for (i = 0; i < sizeof(buf); i++) { | ||
| 121 | unsigned char data[2] = { i, buf[i] }; | ||
| 122 | |||
| 123 | err = i2c_master_send(client, data, sizeof(data)); | ||
| 124 | if (err != sizeof(data)) { | ||
| 125 | dev_err(&client->dev, "%s: err=%d addr=%02x, data=%02x\n", | ||
| 126 | __func__, err, data[0], data[1]); | ||
| 127 | return -EIO; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 135 | { | ||
| 136 | return pcf85063_get_datetime(to_i2c_client(dev), tm); | ||
| 137 | } | ||
| 138 | |||
| 139 | static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 140 | { | ||
| 141 | return pcf85063_set_datetime(to_i2c_client(dev), tm); | ||
| 142 | } | ||
| 143 | |||
| 144 | static const struct rtc_class_ops pcf85063_rtc_ops = { | ||
| 145 | .read_time = pcf85063_rtc_read_time, | ||
| 146 | .set_time = pcf85063_rtc_set_time | ||
| 147 | }; | ||
| 148 | |||
| 149 | static int pcf85063_probe(struct i2c_client *client, | ||
| 150 | const struct i2c_device_id *id) | ||
| 151 | { | ||
| 152 | struct pcf85063 *pcf85063; | ||
| 153 | |||
| 154 | dev_dbg(&client->dev, "%s\n", __func__); | ||
| 155 | |||
| 156 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
| 157 | return -ENODEV; | ||
| 158 | |||
| 159 | pcf85063 = devm_kzalloc(&client->dev, sizeof(struct pcf85063), | ||
| 160 | GFP_KERNEL); | ||
| 161 | if (!pcf85063) | ||
| 162 | return -ENOMEM; | ||
| 163 | |||
| 164 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
| 165 | |||
| 166 | i2c_set_clientdata(client, pcf85063); | ||
| 167 | |||
| 168 | pcf85063->rtc = devm_rtc_device_register(&client->dev, | ||
| 169 | pcf85063_driver.driver.name, | ||
| 170 | &pcf85063_rtc_ops, THIS_MODULE); | ||
| 171 | |||
| 172 | return PTR_ERR_OR_ZERO(pcf85063->rtc); | ||
| 173 | } | ||
| 174 | |||
| 175 | static const struct i2c_device_id pcf85063_id[] = { | ||
| 176 | { "pcf85063", 0 }, | ||
| 177 | { } | ||
| 178 | }; | ||
| 179 | MODULE_DEVICE_TABLE(i2c, pcf85063_id); | ||
| 180 | |||
| 181 | #ifdef CONFIG_OF | ||
| 182 | static const struct of_device_id pcf85063_of_match[] = { | ||
| 183 | { .compatible = "nxp,pcf85063" }, | ||
| 184 | {} | ||
| 185 | }; | ||
| 186 | MODULE_DEVICE_TABLE(of, pcf85063_of_match); | ||
| 187 | #endif | ||
| 188 | |||
| 189 | static struct i2c_driver pcf85063_driver = { | ||
| 190 | .driver = { | ||
| 191 | .name = "rtc-pcf85063", | ||
| 192 | .owner = THIS_MODULE, | ||
| 193 | .of_match_table = of_match_ptr(pcf85063_of_match), | ||
| 194 | }, | ||
| 195 | .probe = pcf85063_probe, | ||
| 196 | .id_table = pcf85063_id, | ||
| 197 | }; | ||
| 198 | |||
| 199 | module_i2c_driver(pcf85063_driver); | ||
| 200 | |||
| 201 | MODULE_AUTHOR("Søren Andersen <san@rosetechnology.dk>"); | ||
| 202 | MODULE_DESCRIPTION("PCF85063 RTC driver"); | ||
| 203 | MODULE_LICENSE("GPL"); | ||
| 204 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 63b558c48196..5a197d9dc7e7 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | 26 | ||
| 27 | #define PCF8563_REG_ST1 0x00 /* status */ | 27 | #define PCF8563_REG_ST1 0x00 /* status */ |
| 28 | #define PCF8563_REG_ST2 0x01 | 28 | #define PCF8563_REG_ST2 0x01 |
| 29 | #define PCF8563_BIT_AIE (1 << 1) | ||
| 30 | #define PCF8563_BIT_AF (1 << 3) | ||
| 29 | 31 | ||
| 30 | #define PCF8563_REG_SC 0x02 /* datetime */ | 32 | #define PCF8563_REG_SC 0x02 /* datetime */ |
| 31 | #define PCF8563_REG_MN 0x03 | 33 | #define PCF8563_REG_MN 0x03 |
| @@ -36,9 +38,6 @@ | |||
| 36 | #define PCF8563_REG_YR 0x08 | 38 | #define PCF8563_REG_YR 0x08 |
| 37 | 39 | ||
| 38 | #define PCF8563_REG_AMN 0x09 /* alarm */ | 40 | #define PCF8563_REG_AMN 0x09 /* alarm */ |
| 39 | #define PCF8563_REG_AHR 0x0A | ||
| 40 | #define PCF8563_REG_ADM 0x0B | ||
| 41 | #define PCF8563_REG_ADW 0x0C | ||
| 42 | 41 | ||
| 43 | #define PCF8563_REG_CLKO 0x0D /* clock out */ | 42 | #define PCF8563_REG_CLKO 0x0D /* clock out */ |
| 44 | #define PCF8563_REG_TMRC 0x0E /* timer control */ | 43 | #define PCF8563_REG_TMRC 0x0E /* timer control */ |
| @@ -67,37 +66,133 @@ struct pcf8563 { | |||
| 67 | */ | 66 | */ |
| 68 | int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */ | 67 | int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */ |
| 69 | int voltage_low; /* incicates if a low_voltage was detected */ | 68 | int voltage_low; /* incicates if a low_voltage was detected */ |
| 69 | |||
| 70 | struct i2c_client *client; | ||
| 70 | }; | 71 | }; |
| 71 | 72 | ||
| 72 | /* | 73 | static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg, |
| 73 | * In the routines that deal directly with the pcf8563 hardware, we use | 74 | unsigned char length, unsigned char *buf) |
| 74 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
| 75 | */ | ||
| 76 | static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 77 | { | 75 | { |
| 78 | struct pcf8563 *pcf8563 = i2c_get_clientdata(client); | ||
| 79 | unsigned char buf[13] = { PCF8563_REG_ST1 }; | ||
| 80 | |||
| 81 | struct i2c_msg msgs[] = { | 76 | struct i2c_msg msgs[] = { |
| 82 | {/* setup read ptr */ | 77 | {/* setup read ptr */ |
| 83 | .addr = client->addr, | 78 | .addr = client->addr, |
| 84 | .len = 1, | 79 | .len = 1, |
| 85 | .buf = buf | 80 | .buf = ®, |
| 86 | }, | 81 | }, |
| 87 | {/* read status + date */ | 82 | { |
| 88 | .addr = client->addr, | 83 | .addr = client->addr, |
| 89 | .flags = I2C_M_RD, | 84 | .flags = I2C_M_RD, |
| 90 | .len = 13, | 85 | .len = length, |
| 91 | .buf = buf | 86 | .buf = buf |
| 92 | }, | 87 | }, |
| 93 | }; | 88 | }; |
| 94 | 89 | ||
| 95 | /* read registers */ | ||
| 96 | if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { | 90 | if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { |
| 97 | dev_err(&client->dev, "%s: read error\n", __func__); | 91 | dev_err(&client->dev, "%s: read error\n", __func__); |
| 98 | return -EIO; | 92 | return -EIO; |
| 99 | } | 93 | } |
| 100 | 94 | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int pcf8563_write_block_data(struct i2c_client *client, | ||
| 99 | unsigned char reg, unsigned char length, | ||
| 100 | unsigned char *buf) | ||
| 101 | { | ||
| 102 | int i, err; | ||
| 103 | |||
| 104 | for (i = 0; i < length; i++) { | ||
| 105 | unsigned char data[2] = { reg + i, buf[i] }; | ||
| 106 | |||
| 107 | err = i2c_master_send(client, data, sizeof(data)); | ||
| 108 | if (err != sizeof(data)) { | ||
| 109 | dev_err(&client->dev, | ||
| 110 | "%s: err=%d addr=%02x, data=%02x\n", | ||
| 111 | __func__, err, data[0], data[1]); | ||
| 112 | return -EIO; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | return 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on) | ||
| 120 | { | ||
| 121 | unsigned char buf[2]; | ||
| 122 | int err; | ||
| 123 | |||
| 124 | err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, buf + 1); | ||
| 125 | if (err < 0) | ||
| 126 | return err; | ||
| 127 | |||
| 128 | if (on) | ||
| 129 | buf[1] |= PCF8563_BIT_AIE; | ||
| 130 | else | ||
| 131 | buf[1] &= ~PCF8563_BIT_AIE; | ||
| 132 | |||
| 133 | buf[1] &= ~PCF8563_BIT_AF; | ||
| 134 | buf[0] = PCF8563_REG_ST2; | ||
| 135 | |||
| 136 | err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, buf + 1); | ||
| 137 | if (err < 0) { | ||
| 138 | dev_err(&client->dev, "%s: write error\n", __func__); | ||
| 139 | return -EIO; | ||
| 140 | } | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en, | ||
| 146 | unsigned char *pen) | ||
| 147 | { | ||
| 148 | unsigned char buf; | ||
| 149 | int err; | ||
| 150 | |||
| 151 | err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf); | ||
| 152 | if (err) | ||
| 153 | return err; | ||
| 154 | |||
| 155 | if (en) | ||
| 156 | *en = !!(buf & PCF8563_BIT_AIE); | ||
| 157 | if (pen) | ||
| 158 | *pen = !!(buf & PCF8563_BIT_AF); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | static irqreturn_t pcf8563_irq(int irq, void *dev_id) | ||
| 164 | { | ||
| 165 | struct pcf8563 *pcf8563 = i2c_get_clientdata(dev_id); | ||
| 166 | int err; | ||
| 167 | char pending; | ||
| 168 | |||
| 169 | err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending); | ||
| 170 | if (err < 0) | ||
| 171 | return err; | ||
| 172 | |||
| 173 | if (pending) { | ||
| 174 | rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF); | ||
| 175 | pcf8563_set_alarm_mode(pcf8563->client, 1); | ||
| 176 | return IRQ_HANDLED; | ||
| 177 | } | ||
| 178 | |||
| 179 | return IRQ_NONE; | ||
| 180 | } | ||
| 181 | |||
| 182 | /* | ||
| 183 | * In the routines that deal directly with the pcf8563 hardware, we use | ||
| 184 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
| 185 | */ | ||
| 186 | static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 187 | { | ||
| 188 | struct pcf8563 *pcf8563 = i2c_get_clientdata(client); | ||
| 189 | unsigned char buf[9]; | ||
| 190 | int err; | ||
| 191 | |||
| 192 | err = pcf8563_read_block_data(client, PCF8563_REG_ST1, 9, buf); | ||
| 193 | if (err) | ||
| 194 | return err; | ||
| 195 | |||
| 101 | if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) { | 196 | if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) { |
| 102 | pcf8563->voltage_low = 1; | 197 | pcf8563->voltage_low = 1; |
| 103 | dev_info(&client->dev, | 198 | dev_info(&client->dev, |
| @@ -144,7 +239,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
| 144 | static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | 239 | static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) |
| 145 | { | 240 | { |
| 146 | struct pcf8563 *pcf8563 = i2c_get_clientdata(client); | 241 | struct pcf8563 *pcf8563 = i2c_get_clientdata(client); |
| 147 | int i, err; | 242 | int err; |
| 148 | unsigned char buf[9]; | 243 | unsigned char buf[9]; |
| 149 | 244 | ||
| 150 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | 245 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " |
| @@ -170,19 +265,10 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
| 170 | 265 | ||
| 171 | buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; | 266 | buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; |
| 172 | 267 | ||
| 173 | /* write register's data */ | 268 | err = pcf8563_write_block_data(client, PCF8563_REG_SC, |
| 174 | for (i = 0; i < 7; i++) { | 269 | 9 - PCF8563_REG_SC, buf + PCF8563_REG_SC); |
| 175 | unsigned char data[2] = { PCF8563_REG_SC + i, | 270 | if (err) |
| 176 | buf[PCF8563_REG_SC + i] }; | 271 | return err; |
| 177 | |||
| 178 | err = i2c_master_send(client, data, sizeof(data)); | ||
| 179 | if (err != sizeof(data)) { | ||
| 180 | dev_err(&client->dev, | ||
| 181 | "%s: err=%d addr=%02x, data=%02x\n", | ||
| 182 | __func__, err, data[0], data[1]); | ||
| 183 | return -EIO; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | 272 | ||
| 187 | return 0; | 273 | return 0; |
| 188 | } | 274 | } |
| @@ -235,16 +321,83 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 235 | return pcf8563_set_datetime(to_i2c_client(dev), tm); | 321 | return pcf8563_set_datetime(to_i2c_client(dev), tm); |
| 236 | } | 322 | } |
| 237 | 323 | ||
| 324 | static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) | ||
| 325 | { | ||
| 326 | struct i2c_client *client = to_i2c_client(dev); | ||
| 327 | unsigned char buf[4]; | ||
| 328 | int err; | ||
| 329 | |||
| 330 | err = pcf8563_read_block_data(client, PCF8563_REG_AMN, 4, buf); | ||
| 331 | if (err) | ||
| 332 | return err; | ||
| 333 | |||
| 334 | dev_dbg(&client->dev, | ||
| 335 | "%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n", | ||
| 336 | __func__, buf[0], buf[1], buf[2], buf[3]); | ||
| 337 | |||
| 338 | tm->time.tm_min = bcd2bin(buf[0] & 0x7F); | ||
| 339 | tm->time.tm_hour = bcd2bin(buf[1] & 0x7F); | ||
| 340 | tm->time.tm_mday = bcd2bin(buf[2] & 0x1F); | ||
| 341 | tm->time.tm_wday = bcd2bin(buf[3] & 0x7); | ||
| 342 | tm->time.tm_mon = -1; | ||
| 343 | tm->time.tm_year = -1; | ||
| 344 | tm->time.tm_yday = -1; | ||
| 345 | tm->time.tm_isdst = -1; | ||
| 346 | |||
| 347 | err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending); | ||
| 348 | if (err < 0) | ||
| 349 | return err; | ||
| 350 | |||
| 351 | dev_dbg(&client->dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d," | ||
| 352 | " enabled=%d, pending=%d\n", __func__, tm->time.tm_min, | ||
| 353 | tm->time.tm_hour, tm->time.tm_mday, tm->time.tm_wday, | ||
| 354 | tm->enabled, tm->pending); | ||
| 355 | |||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | |||
| 359 | static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) | ||
| 360 | { | ||
| 361 | struct i2c_client *client = to_i2c_client(dev); | ||
| 362 | unsigned char buf[4]; | ||
| 363 | int err; | ||
| 364 | |||
| 365 | dev_dbg(dev, "%s, min=%d hour=%d wday=%d mday=%d " | ||
| 366 | "enabled=%d pending=%d\n", __func__, | ||
| 367 | tm->time.tm_min, tm->time.tm_hour, tm->time.tm_wday, | ||
| 368 | tm->time.tm_mday, tm->enabled, tm->pending); | ||
| 369 | |||
| 370 | buf[0] = bin2bcd(tm->time.tm_min); | ||
| 371 | buf[1] = bin2bcd(tm->time.tm_hour); | ||
| 372 | buf[2] = bin2bcd(tm->time.tm_mday); | ||
| 373 | buf[3] = tm->time.tm_wday & 0x07; | ||
| 374 | |||
| 375 | err = pcf8563_write_block_data(client, PCF8563_REG_AMN, 4, buf); | ||
| 376 | if (err) | ||
| 377 | return err; | ||
| 378 | |||
| 379 | return pcf8563_set_alarm_mode(client, 1); | ||
| 380 | } | ||
| 381 | |||
| 382 | static int pcf8563_irq_enable(struct device *dev, unsigned int enabled) | ||
| 383 | { | ||
| 384 | return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled); | ||
| 385 | } | ||
| 386 | |||
| 238 | static const struct rtc_class_ops pcf8563_rtc_ops = { | 387 | static const struct rtc_class_ops pcf8563_rtc_ops = { |
| 239 | .ioctl = pcf8563_rtc_ioctl, | 388 | .ioctl = pcf8563_rtc_ioctl, |
| 240 | .read_time = pcf8563_rtc_read_time, | 389 | .read_time = pcf8563_rtc_read_time, |
| 241 | .set_time = pcf8563_rtc_set_time, | 390 | .set_time = pcf8563_rtc_set_time, |
| 391 | .read_alarm = pcf8563_rtc_read_alarm, | ||
| 392 | .set_alarm = pcf8563_rtc_set_alarm, | ||
| 393 | .alarm_irq_enable = pcf8563_irq_enable, | ||
| 242 | }; | 394 | }; |
| 243 | 395 | ||
| 244 | static int pcf8563_probe(struct i2c_client *client, | 396 | static int pcf8563_probe(struct i2c_client *client, |
| 245 | const struct i2c_device_id *id) | 397 | const struct i2c_device_id *id) |
| 246 | { | 398 | { |
| 247 | struct pcf8563 *pcf8563; | 399 | struct pcf8563 *pcf8563; |
| 400 | int err; | ||
| 248 | 401 | ||
| 249 | dev_dbg(&client->dev, "%s\n", __func__); | 402 | dev_dbg(&client->dev, "%s\n", __func__); |
| 250 | 403 | ||
| @@ -259,12 +412,30 @@ static int pcf8563_probe(struct i2c_client *client, | |||
| 259 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 412 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
| 260 | 413 | ||
| 261 | i2c_set_clientdata(client, pcf8563); | 414 | i2c_set_clientdata(client, pcf8563); |
| 415 | pcf8563->client = client; | ||
| 416 | device_set_wakeup_capable(&client->dev, 1); | ||
| 262 | 417 | ||
| 263 | pcf8563->rtc = devm_rtc_device_register(&client->dev, | 418 | pcf8563->rtc = devm_rtc_device_register(&client->dev, |
| 264 | pcf8563_driver.driver.name, | 419 | pcf8563_driver.driver.name, |
| 265 | &pcf8563_rtc_ops, THIS_MODULE); | 420 | &pcf8563_rtc_ops, THIS_MODULE); |
| 266 | 421 | ||
| 267 | return PTR_ERR_OR_ZERO(pcf8563->rtc); | 422 | if (IS_ERR(pcf8563->rtc)) |
| 423 | return PTR_ERR(pcf8563->rtc); | ||
| 424 | |||
| 425 | if (client->irq > 0) { | ||
| 426 | err = devm_request_threaded_irq(&client->dev, client->irq, | ||
| 427 | NULL, pcf8563_irq, | ||
| 428 | IRQF_SHARED|IRQF_ONESHOT|IRQF_TRIGGER_FALLING, | ||
| 429 | pcf8563->rtc->name, client); | ||
| 430 | if (err) { | ||
| 431 | dev_err(&client->dev, "unable to request IRQ %d\n", | ||
| 432 | client->irq); | ||
| 433 | return err; | ||
| 434 | } | ||
| 435 | |||
| 436 | } | ||
| 437 | |||
| 438 | return 0; | ||
| 268 | } | 439 | } |
| 269 | 440 | ||
| 270 | static const struct i2c_device_id pcf8563_id[] = { | 441 | static const struct i2c_device_id pcf8563_id[] = { |
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 7af00208d637..2583349fbde5 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c | |||
| @@ -258,6 +258,8 @@ static int tps65910_rtc_probe(struct platform_device *pdev) | |||
| 258 | if (ret < 0) | 258 | if (ret < 0) |
| 259 | return ret; | 259 | return ret; |
| 260 | 260 | ||
| 261 | platform_set_drvdata(pdev, tps_rtc); | ||
| 262 | |||
| 261 | irq = platform_get_irq(pdev, 0); | 263 | irq = platform_get_irq(pdev, 0); |
| 262 | if (irq <= 0) { | 264 | if (irq <= 0) { |
| 263 | dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", | 265 | dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", |
| @@ -283,8 +285,6 @@ static int tps65910_rtc_probe(struct platform_device *pdev) | |||
| 283 | return ret; | 285 | return ret; |
| 284 | } | 286 | } |
| 285 | 287 | ||
| 286 | platform_set_drvdata(pdev, tps_rtc); | ||
| 287 | |||
| 288 | return 0; | 288 | return 0; |
| 289 | } | 289 | } |
| 290 | 290 | ||
