diff options
Diffstat (limited to 'drivers/rtc/rtc-max77686.c')
-rw-r--r-- | drivers/rtc/rtc-max77686.c | 140 |
1 files changed, 31 insertions, 109 deletions
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index d20a7f0786e..cf73e969c8c 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -32,15 +32,6 @@ #define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) #define RTC_RBUDR_SHIFT 4 #define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT) -/* WTSR and SMPL Register */ -#define WTSRT_SHIFT 0 -#define SMPLT_SHIFT 2 -#define WTSR_EN_SHIFT 6 -#define SMPL_EN_SHIFT 7 -#define WTSRT_MASK (3 << WTSRT_SHIFT) -#define SMPLT_MASK (3 << SMPLT_SHIFT) -#define WTSR_EN_MASK (1 << WTSR_EN_SHIFT) -#define SMPL_EN_MASK (1 << SMPL_EN_SHIFT) /* RTC Hour register */ #define HOUR_PM_SHIFT 6 #define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) @@ -49,7 +40,6 @@ #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) #define MAX77686_RTC_UPDATE_DELAY 16 -#undef MAX77686_RTC_WTSR_SMPL enum { RTC_SEC = 0, @@ -80,16 +70,6 @@ enum MAX77686_RTC_OP { MAX77686_RTC_READ, }; -static inline int max77686_rtc_calculate_wday(u8 shifted) -{ - int counter = -1; - while (shifted) { - shifted >>= 1; - counter++; - } - return counter; -} - static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, int rtc_24hr_mode) { @@ -103,7 +83,8 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, tm->tm_hour += 12; } - tm->tm_wday = max77686_rtc_calculate_wday(data[RTC_WEEKDAY] & 0x7f); + /* Only a single bit is set in data[], so fls() would be equivalent */ + tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1; tm->tm_mday = data[RTC_DATE] & 0x1f; tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; @@ -412,64 +393,6 @@ static const struct rtc_class_ops max77686_rtc_ops = { .alarm_irq_enable = max77686_rtc_alarm_irq_enable, }; -#ifdef MAX77686_RTC_WTSR_SMPL -static void max77686_rtc_enable_wtsr(struct max77686_rtc_info *info, bool enable) -{ - int ret; - unsigned int val, mask; - - if (enable) - val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT); - else - val = 0; - - mask = WTSR_EN_MASK | WTSRT_MASK; - - dev_info(info->dev, "%s: %s WTSR\n", __func__, - enable ? "enable" : "disable"); - - ret = regmap_update_bits(info->max77686->rtc_regmap, - MAX77686_WTSR_SMPL_CNTL, mask, val); - if (ret < 0) { - dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n", - __func__, ret); - return; - } - - max77686_rtc_update(info, MAX77686_RTC_WRITE); -} - -static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable) -{ - int ret; - unsigned int val, mask; - - if (enable) - val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT); - else - val = 0; - - mask = SMPL_EN_MASK | SMPLT_MASK; - - dev_info(info->dev, "%s: %s SMPL\n", __func__, - enable ? "enable" : "disable"); - - ret = regmap_update_bits(info->max77686->rtc_regmap, - MAX77686_WTSR_SMPL_CNTL, mask, val); - if (ret < 0) { - dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n", - __func__, ret); - return; - } - - max77686_rtc_update(info, MAX77686_RTC_WRITE); - - val = 0; - regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); - dev_info(info->dev, "%s: WTSR_SMPL(0x%02x)\n", __func__, val); -} -#endif /* MAX77686_RTC_WTSR_SMPL */ - static int max77686_rtc_init_reg(struct max77686_rtc_info *info) { u8 data[2]; @@ -519,19 +442,12 @@ static int max77686_rtc_probe(struct platform_device *pdev) goto err_rtc; } -#ifdef MAX77686_RTC_WTSR_SMPL - max77686_rtc_enable_wtsr(info, true); - max77686_rtc_enable_smpl(info, true); -#endif - device_init_wakeup(&pdev->dev, 1); info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc", &max77686_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { - dev_info(&pdev->dev, "%s: fail\n", __func__); - ret = PTR_ERR(info->rtc_dev); dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); if (ret == 0) @@ -539,6 +455,12 @@ static int max77686_rtc_probe(struct platform_device *pdev) goto err_rtc; } + if (!max77686->rtc_irq_data) { + ret = -EINVAL; + dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__); + goto err_rtc; + } + info->virq = regmap_irq_get_virq(max77686->rtc_irq_data, MAX77686_RTCIRQ_RTCA1); if (!info->virq) { @@ -556,33 +478,33 @@ err_rtc: return ret; } -static void max77686_rtc_shutdown(struct platform_device *pdev) +#ifdef CONFIG_PM_SLEEP +static int max77686_rtc_suspend(struct device *dev) { -#ifdef MAX77686_RTC_WTSR_SMPL - struct max77686_rtc_info *info = platform_get_drvdata(pdev); - int i; - u8 val = 0; - - for (i = 0; i < 3; i++) { - max77686_rtc_enable_wtsr(info, false); - regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); - dev_info(info->dev, "%s: WTSR_SMPL reg(0x%02x)\n", __func__, - val); - if (val & WTSR_EN_MASK) { - dev_emerg(info->dev, "%s: fail to disable WTSR\n", - __func__); - } else { - dev_info(info->dev, "%s: success to disable WTSR\n", - __func__); - break; - } + if (device_may_wakeup(dev)) { + struct max77686_rtc_info *info = dev_get_drvdata(dev); + + return enable_irq_wake(info->virq); } - /* Disable SMPL when power off */ - max77686_rtc_enable_smpl(info, false); -#endif /* MAX77686_RTC_WTSR_SMPL */ + return 0; } +static int max77686_rtc_resume(struct device *dev) +{ + if (device_may_wakeup(dev)) { + struct max77686_rtc_info *info = dev_get_drvdata(dev); + + return disable_irq_wake(info->virq); + } + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops, + max77686_rtc_suspend, max77686_rtc_resume); + static const struct platform_device_id rtc_id[] = { { "max77686-rtc", 0 }, {}, @@ -592,9 +514,9 @@ static struct platform_driver max77686_rtc_driver = { .driver = { .name = "max77686-rtc", .owner = THIS_MODULE, + .pm = &max77686_rtc_pm_ops, }, .probe = max77686_rtc_probe, - .shutdown = max77686_rtc_shutdown, .id_table = rtc_id, }; |