diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/rtc-da9063.c | 19 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1307.c | 44 | ||||
| -rw-r--r-- | drivers/rtc/rtc-rk808.c | 48 |
3 files changed, 61 insertions, 50 deletions
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c index 284b587da65c..d6c853bbfa9f 100644 --- a/drivers/rtc/rtc-da9063.c +++ b/drivers/rtc/rtc-da9063.c | |||
| @@ -483,24 +483,23 @@ static int da9063_rtc_probe(struct platform_device *pdev) | |||
| 483 | 483 | ||
| 484 | platform_set_drvdata(pdev, rtc); | 484 | platform_set_drvdata(pdev, rtc); |
| 485 | 485 | ||
| 486 | rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC, | ||
| 487 | &da9063_rtc_ops, THIS_MODULE); | ||
| 488 | if (IS_ERR(rtc->rtc_dev)) | ||
| 489 | return PTR_ERR(rtc->rtc_dev); | ||
| 490 | |||
| 491 | da9063_data_to_tm(data, &rtc->alarm_time, rtc); | ||
| 492 | rtc->rtc_sync = false; | ||
| 493 | |||
| 486 | irq_alarm = platform_get_irq_byname(pdev, "ALARM"); | 494 | irq_alarm = platform_get_irq_byname(pdev, "ALARM"); |
| 487 | ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL, | 495 | ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL, |
| 488 | da9063_alarm_event, | 496 | da9063_alarm_event, |
| 489 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 497 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
| 490 | "ALARM", rtc); | 498 | "ALARM", rtc); |
| 491 | if (ret) { | 499 | if (ret) |
| 492 | dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n", | 500 | dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n", |
| 493 | irq_alarm, ret); | 501 | irq_alarm, ret); |
| 494 | return ret; | ||
| 495 | } | ||
| 496 | |||
| 497 | rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC, | ||
| 498 | &da9063_rtc_ops, THIS_MODULE); | ||
| 499 | if (IS_ERR(rtc->rtc_dev)) | ||
| 500 | return PTR_ERR(rtc->rtc_dev); | ||
| 501 | 502 | ||
| 502 | da9063_data_to_tm(data, &rtc->alarm_time, rtc); | ||
| 503 | rtc->rtc_sync = false; | ||
| 504 | return ret; | 503 | return ret; |
| 505 | } | 504 | } |
| 506 | 505 | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 188006c55ce0..aa705bb4748c 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
| @@ -15,9 +15,6 @@ | |||
| 15 | #include <linux/i2c.h> | 15 | #include <linux/i2c.h> |
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/of_device.h> | ||
| 19 | #include <linux/of_irq.h> | ||
| 20 | #include <linux/pm_wakeirq.h> | ||
| 21 | #include <linux/rtc/ds1307.h> | 18 | #include <linux/rtc/ds1307.h> |
| 22 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
| 23 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| @@ -117,7 +114,6 @@ struct ds1307 { | |||
| 117 | #define HAS_ALARM 1 /* bit 1 == irq claimed */ | 114 | #define HAS_ALARM 1 /* bit 1 == irq claimed */ |
| 118 | struct i2c_client *client; | 115 | struct i2c_client *client; |
| 119 | struct rtc_device *rtc; | 116 | struct rtc_device *rtc; |
| 120 | int wakeirq; | ||
| 121 | s32 (*read_block_data)(const struct i2c_client *client, u8 command, | 117 | s32 (*read_block_data)(const struct i2c_client *client, u8 command, |
| 122 | u8 length, u8 *values); | 118 | u8 length, u8 *values); |
| 123 | s32 (*write_block_data)(const struct i2c_client *client, u8 command, | 119 | s32 (*write_block_data)(const struct i2c_client *client, u8 command, |
| @@ -1138,7 +1134,10 @@ read_rtc: | |||
| 1138 | bin2bcd(tmp)); | 1134 | bin2bcd(tmp)); |
| 1139 | } | 1135 | } |
| 1140 | 1136 | ||
| 1141 | device_set_wakeup_capable(&client->dev, want_irq); | 1137 | if (want_irq) { |
| 1138 | device_set_wakeup_capable(&client->dev, true); | ||
| 1139 | set_bit(HAS_ALARM, &ds1307->flags); | ||
| 1140 | } | ||
| 1142 | ds1307->rtc = devm_rtc_device_register(&client->dev, client->name, | 1141 | ds1307->rtc = devm_rtc_device_register(&client->dev, client->name, |
| 1143 | rtc_ops, THIS_MODULE); | 1142 | rtc_ops, THIS_MODULE); |
| 1144 | if (IS_ERR(ds1307->rtc)) { | 1143 | if (IS_ERR(ds1307->rtc)) { |
| @@ -1146,43 +1145,19 @@ read_rtc: | |||
| 1146 | } | 1145 | } |
| 1147 | 1146 | ||
| 1148 | if (want_irq) { | 1147 | if (want_irq) { |
| 1149 | struct device_node *node = client->dev.of_node; | ||
| 1150 | |||
| 1151 | err = devm_request_threaded_irq(&client->dev, | 1148 | err = devm_request_threaded_irq(&client->dev, |
| 1152 | client->irq, NULL, irq_handler, | 1149 | client->irq, NULL, irq_handler, |
| 1153 | IRQF_SHARED | IRQF_ONESHOT, | 1150 | IRQF_SHARED | IRQF_ONESHOT, |
| 1154 | ds1307->rtc->name, client); | 1151 | ds1307->rtc->name, client); |
| 1155 | if (err) { | 1152 | if (err) { |
| 1156 | client->irq = 0; | 1153 | client->irq = 0; |
| 1154 | device_set_wakeup_capable(&client->dev, false); | ||
| 1155 | clear_bit(HAS_ALARM, &ds1307->flags); | ||
| 1157 | dev_err(&client->dev, "unable to request IRQ!\n"); | 1156 | dev_err(&client->dev, "unable to request IRQ!\n"); |
| 1158 | goto no_irq; | 1157 | } else |
| 1159 | } | 1158 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); |
| 1160 | |||
| 1161 | set_bit(HAS_ALARM, &ds1307->flags); | ||
| 1162 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); | ||
| 1163 | |||
| 1164 | /* Currently supported by OF code only! */ | ||
| 1165 | if (!node) | ||
| 1166 | goto no_irq; | ||
| 1167 | |||
| 1168 | err = of_irq_get(node, 1); | ||
| 1169 | if (err <= 0) { | ||
| 1170 | if (err == -EPROBE_DEFER) | ||
| 1171 | goto exit; | ||
| 1172 | goto no_irq; | ||
| 1173 | } | ||
| 1174 | ds1307->wakeirq = err; | ||
| 1175 | |||
| 1176 | err = dev_pm_set_dedicated_wake_irq(&client->dev, | ||
| 1177 | ds1307->wakeirq); | ||
| 1178 | if (err) { | ||
| 1179 | dev_err(&client->dev, "unable to setup wakeIRQ %d!\n", | ||
| 1180 | err); | ||
| 1181 | goto exit; | ||
| 1182 | } | ||
| 1183 | } | 1159 | } |
| 1184 | 1160 | ||
| 1185 | no_irq: | ||
| 1186 | if (chip->nvram_size) { | 1161 | if (chip->nvram_size) { |
| 1187 | 1162 | ||
| 1188 | ds1307->nvram = devm_kzalloc(&client->dev, | 1163 | ds1307->nvram = devm_kzalloc(&client->dev, |
| @@ -1226,9 +1201,6 @@ static int ds1307_remove(struct i2c_client *client) | |||
| 1226 | { | 1201 | { |
| 1227 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | 1202 | struct ds1307 *ds1307 = i2c_get_clientdata(client); |
| 1228 | 1203 | ||
| 1229 | if (ds1307->wakeirq) | ||
| 1230 | dev_pm_clear_wake_irq(&client->dev); | ||
| 1231 | |||
| 1232 | if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) | 1204 | if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) |
| 1233 | sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram); | 1205 | sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram); |
| 1234 | 1206 | ||
diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c index 91ca0bc1b484..35c9aada07c8 100644 --- a/drivers/rtc/rtc-rk808.c +++ b/drivers/rtc/rtc-rk808.c | |||
| @@ -56,6 +56,42 @@ struct rk808_rtc { | |||
| 56 | int irq; | 56 | int irq; |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | /* | ||
| 60 | * The Rockchip calendar used by the RK808 counts November with 31 days. We use | ||
| 61 | * these translation functions to convert its dates to/from the Gregorian | ||
| 62 | * calendar used by the rest of the world. We arbitrarily define Jan 1st, 2016 | ||
| 63 | * as the day when both calendars were in sync, and treat all other dates | ||
| 64 | * relative to that. | ||
| 65 | * NOTE: Other system software (e.g. firmware) that reads the same hardware must | ||
| 66 | * implement this exact same conversion algorithm, with the same anchor date. | ||
| 67 | */ | ||
| 68 | static time64_t nov2dec_transitions(struct rtc_time *tm) | ||
| 69 | { | ||
| 70 | return (tm->tm_year + 1900) - 2016 + (tm->tm_mon + 1 > 11 ? 1 : 0); | ||
| 71 | } | ||
| 72 | |||
| 73 | static void rockchip_to_gregorian(struct rtc_time *tm) | ||
| 74 | { | ||
| 75 | /* If it's Nov 31st, rtc_tm_to_time64() will count that like Dec 1st */ | ||
| 76 | time64_t time = rtc_tm_to_time64(tm); | ||
| 77 | rtc_time64_to_tm(time + nov2dec_transitions(tm) * 86400, tm); | ||
| 78 | } | ||
| 79 | |||
| 80 | static void gregorian_to_rockchip(struct rtc_time *tm) | ||
| 81 | { | ||
| 82 | time64_t extra_days = nov2dec_transitions(tm); | ||
| 83 | time64_t time = rtc_tm_to_time64(tm); | ||
| 84 | rtc_time64_to_tm(time - extra_days * 86400, tm); | ||
| 85 | |||
| 86 | /* Compensate if we went back over Nov 31st (will work up to 2381) */ | ||
| 87 | if (nov2dec_transitions(tm) < extra_days) { | ||
| 88 | if (tm->tm_mon + 1 == 11) | ||
| 89 | tm->tm_mday++; /* This may result in 31! */ | ||
| 90 | else | ||
| 91 | rtc_time64_to_tm(time - (extra_days - 1) * 86400, tm); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 59 | /* Read current time and date in RTC */ | 95 | /* Read current time and date in RTC */ |
| 60 | static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) | 96 | static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) |
| 61 | { | 97 | { |
| @@ -101,9 +137,10 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) | |||
| 101 | tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1; | 137 | tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1; |
| 102 | tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100; | 138 | tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100; |
| 103 | tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK); | 139 | tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK); |
| 140 | rockchip_to_gregorian(tm); | ||
| 104 | dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", | 141 | dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", |
| 105 | 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, | 142 | 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, |
| 106 | tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec); | 143 | tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec); |
| 107 | 144 | ||
| 108 | return ret; | 145 | return ret; |
| 109 | } | 146 | } |
| @@ -116,6 +153,10 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 116 | u8 rtc_data[NUM_TIME_REGS]; | 153 | u8 rtc_data[NUM_TIME_REGS]; |
| 117 | int ret; | 154 | int ret; |
| 118 | 155 | ||
| 156 | dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", | ||
| 157 | 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, | ||
| 158 | tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
| 159 | gregorian_to_rockchip(tm); | ||
| 119 | rtc_data[0] = bin2bcd(tm->tm_sec); | 160 | rtc_data[0] = bin2bcd(tm->tm_sec); |
| 120 | rtc_data[1] = bin2bcd(tm->tm_min); | 161 | rtc_data[1] = bin2bcd(tm->tm_min); |
| 121 | rtc_data[2] = bin2bcd(tm->tm_hour); | 162 | rtc_data[2] = bin2bcd(tm->tm_hour); |
| @@ -123,9 +164,6 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 123 | rtc_data[4] = bin2bcd(tm->tm_mon + 1); | 164 | rtc_data[4] = bin2bcd(tm->tm_mon + 1); |
| 124 | rtc_data[5] = bin2bcd(tm->tm_year - 100); | 165 | rtc_data[5] = bin2bcd(tm->tm_year - 100); |
| 125 | rtc_data[6] = bin2bcd(tm->tm_wday); | 166 | rtc_data[6] = bin2bcd(tm->tm_wday); |
| 126 | dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", | ||
| 127 | 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, | ||
| 128 | tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec); | ||
| 129 | 167 | ||
| 130 | /* Stop RTC while updating the RTC registers */ | 168 | /* Stop RTC while updating the RTC registers */ |
| 131 | ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, | 169 | ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, |
| @@ -170,6 +208,7 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 170 | alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK); | 208 | alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK); |
| 171 | alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1; | 209 | alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1; |
| 172 | alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100; | 210 | alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100; |
| 211 | rockchip_to_gregorian(&alrm->time); | ||
| 173 | 212 | ||
| 174 | ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg); | 213 | ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg); |
| 175 | if (ret) { | 214 | if (ret) { |
| @@ -227,6 +266,7 @@ static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 227 | alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour, | 266 | alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour, |
| 228 | alrm->time.tm_min, alrm->time.tm_sec); | 267 | alrm->time.tm_min, alrm->time.tm_sec); |
| 229 | 268 | ||
| 269 | gregorian_to_rockchip(&alrm->time); | ||
| 230 | alrm_data[0] = bin2bcd(alrm->time.tm_sec); | 270 | alrm_data[0] = bin2bcd(alrm->time.tm_sec); |
| 231 | alrm_data[1] = bin2bcd(alrm->time.tm_min); | 271 | alrm_data[1] = bin2bcd(alrm->time.tm_min); |
| 232 | alrm_data[2] = bin2bcd(alrm->time.tm_hour); | 272 | alrm_data[2] = bin2bcd(alrm->time.tm_hour); |
