diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-efi.c | 1 | ||||
-rw-r--r-- | drivers/rtc/rtc-pl031.c | 3 | ||||
-rw-r--r-- | drivers/rtc/rtc-r9701.c | 22 | ||||
-rw-r--r-- | drivers/rtc/rtc-s3c.c | 31 | ||||
-rw-r--r-- | drivers/rtc/rtc-twl.c | 43 |
5 files changed, 83 insertions, 17 deletions
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index 550292304b0f..c9f890b088da 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c @@ -213,7 +213,6 @@ static struct platform_driver efi_rtc_driver = { .name = "rtc-efi", .owner = THIS_MODULE, }, - .probe = efi_rtc_probe, .remove = __exit_p(efi_rtc_remove), }; diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 692de7360e94..684ef4bbfce4 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -339,8 +339,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); /* Enable the clockwatch on ST Variants */ - if ((ldata->hw_designer == AMBA_VENDOR_ST) && - (ldata->hw_revision > 1)) + if (ldata->hw_designer == AMBA_VENDOR_ST) writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, ldata->base + RTC_CR); diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index 7f8e6c247935..33b6ba0afa0d 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -122,6 +122,7 @@ static const struct rtc_class_ops r9701_rtc_ops = { static int __devinit r9701_probe(struct spi_device *spi) { struct rtc_device *rtc; + struct rtc_time dt; unsigned char tmp; int res; @@ -132,6 +133,27 @@ static int __devinit r9701_probe(struct spi_device *spi) return -ENODEV; } + /* + * The device seems to be present. Now check if the registers + * contain invalid values. If so, try to write a default date: + * 2000/1/1 00:00:00 + */ + r9701_get_datetime(&spi->dev, &dt); + if (rtc_valid_tm(&dt)) { + dev_info(&spi->dev, "trying to repair invalid date/time\n"); + dt.tm_sec = 0; + dt.tm_min = 0; + dt.tm_hour = 0; + dt.tm_mday = 1; + dt.tm_mon = 0; + dt.tm_year = 100; + + if (r9701_set_datetime(&spi->dev, &dt)) { + dev_err(&spi->dev, "cannot repair RTC register\n"); + return -ENODEV; + } + } + rtc = rtc_device_register("r9701", &spi->dev, &r9701_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 9ccea134a996..3f3a29752369 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -40,6 +40,10 @@ enum s3c_cpu_type { TYPE_S3C64XX, }; +struct s3c_rtc_drv_data { + int cpu_type; +}; + /* I have yet to find an S3C implementation with more than one * of these rtc blocks in */ @@ -446,10 +450,12 @@ static const struct of_device_id s3c_rtc_dt_match[]; static inline int s3c_rtc_get_driver_data(struct platform_device *pdev) { #ifdef CONFIG_OF + struct s3c_rtc_drv_data *data; if (pdev->dev.of_node) { const struct of_device_id *match; match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node); - return match->data; + data = (struct s3c_rtc_drv_data *) match->data; + return data->cpu_type; } #endif return platform_get_device_id(pdev)->driver_data; @@ -664,20 +670,27 @@ static int s3c_rtc_resume(struct platform_device *pdev) #define s3c_rtc_resume NULL #endif +static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = { + [TYPE_S3C2410] = { TYPE_S3C2410 }, + [TYPE_S3C2416] = { TYPE_S3C2416 }, + [TYPE_S3C2443] = { TYPE_S3C2443 }, + [TYPE_S3C64XX] = { TYPE_S3C64XX }, +}; + #ifdef CONFIG_OF static const struct of_device_id s3c_rtc_dt_match[] = { { - .compatible = "samsung,s3c2410-rtc" - .data = TYPE_S3C2410, + .compatible = "samsung,s3c2410-rtc", + .data = &s3c_rtc_drv_data_array[TYPE_S3C2410], }, { - .compatible = "samsung,s3c2416-rtc" - .data = TYPE_S3C2416, + .compatible = "samsung,s3c2416-rtc", + .data = &s3c_rtc_drv_data_array[TYPE_S3C2416], }, { - .compatible = "samsung,s3c2443-rtc" - .data = TYPE_S3C2443, + .compatible = "samsung,s3c2443-rtc", + .data = &s3c_rtc_drv_data_array[TYPE_S3C2443], }, { - .compatible = "samsung,s3c6410-rtc" - .data = TYPE_S3C64XX, + .compatible = "samsung,s3c6410-rtc", + .data = &s3c_rtc_drv_data_array[TYPE_S3C64XX], }, {}, }; diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 4c2c6df2a9ef..258abeabf624 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -112,6 +112,7 @@ static const u8 twl6030_rtc_reg_map[] = { #define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 #define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 #define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 +#define BIT_RTC_CTRL_REG_RTC_V_OPT 0x80 /* RTC_STATUS_REG bitfields */ #define BIT_RTC_STATUS_REG_RUN_M 0x02 @@ -235,25 +236,57 @@ static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) unsigned char rtc_data[ALL_TIME_REGS + 1]; int ret; u8 save_control; + u8 rtc_control; ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); - if (ret < 0) + if (ret < 0) { + dev_err(dev, "%s: reading CTRL_REG, error %d\n", __func__, ret); return ret; + } + /* for twl6030/32 make sure BIT_RTC_CTRL_REG_GET_TIME_M is clear */ + if (twl_class_is_6030()) { + if (save_control & BIT_RTC_CTRL_REG_GET_TIME_M) { + save_control &= ~BIT_RTC_CTRL_REG_GET_TIME_M; + ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + if (ret < 0) { + dev_err(dev, "%s clr GET_TIME, error %d\n", + __func__, ret); + return ret; + } + } + } - save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; + /* Copy RTC counting registers to static registers or latches */ + rtc_control = save_control | BIT_RTC_CTRL_REG_GET_TIME_M; - ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); - if (ret < 0) + /* for twl6030/32 enable read access to static shadowed registers */ + if (twl_class_is_6030()) + rtc_control |= BIT_RTC_CTRL_REG_RTC_V_OPT; + + ret = twl_rtc_write_u8(rtc_control, REG_RTC_CTRL_REG); + if (ret < 0) { + dev_err(dev, "%s: writing CTRL_REG, error %d\n", __func__, ret); return ret; + } ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); if (ret < 0) { - dev_err(dev, "rtc_read_time error %d\n", ret); + dev_err(dev, "%s: reading data, error %d\n", __func__, ret); return ret; } + /* for twl6030 restore original state of rtc control register */ + if (twl_class_is_6030()) { + ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + if (ret < 0) { + dev_err(dev, "%s: restore CTRL_REG, error %d\n", + __func__, ret); + return ret; + } + } + tm->tm_sec = bcd2bin(rtc_data[0]); tm->tm_min = bcd2bin(rtc_data[1]); tm->tm_hour = bcd2bin(rtc_data[2]); |