341 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Real Time Clock driver for Marvell 88PM80x PMIC4 *5 * Copyright (c) 2012 Marvell International Ltd.6 * Wenzeng Chen<wzch@marvell.com>7 * Qiao Zhou <zhouqiao@marvell.com>8 */9 10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/slab.h>13#include <linux/regmap.h>14#include <linux/mfd/core.h>15#include <linux/mfd/88pm80x.h>16#include <linux/rtc.h>17 18#define PM800_RTC_COUNTER1 (0xD1)19#define PM800_RTC_COUNTER2 (0xD2)20#define PM800_RTC_COUNTER3 (0xD3)21#define PM800_RTC_COUNTER4 (0xD4)22#define PM800_RTC_EXPIRE1_1 (0xD5)23#define PM800_RTC_EXPIRE1_2 (0xD6)24#define PM800_RTC_EXPIRE1_3 (0xD7)25#define PM800_RTC_EXPIRE1_4 (0xD8)26#define PM800_RTC_TRIM1 (0xD9)27#define PM800_RTC_TRIM2 (0xDA)28#define PM800_RTC_TRIM3 (0xDB)29#define PM800_RTC_TRIM4 (0xDC)30#define PM800_RTC_EXPIRE2_1 (0xDD)31#define PM800_RTC_EXPIRE2_2 (0xDE)32#define PM800_RTC_EXPIRE2_3 (0xDF)33#define PM800_RTC_EXPIRE2_4 (0xE0)34 35#define PM800_POWER_DOWN_LOG1 (0xE5)36#define PM800_POWER_DOWN_LOG2 (0xE6)37 38struct pm80x_rtc_info {39 struct pm80x_chip *chip;40 struct regmap *map;41 struct rtc_device *rtc_dev;42 struct device *dev;43 44 int irq;45};46 47static irqreturn_t rtc_update_handler(int irq, void *data)48{49 struct pm80x_rtc_info *info = (struct pm80x_rtc_info *)data;50 int mask;51 52 mask = PM800_ALARM | PM800_ALARM_WAKEUP;53 regmap_update_bits(info->map, PM800_RTC_CONTROL, mask | PM800_ALARM1_EN,54 mask);55 rtc_update_irq(info->rtc_dev, 1, RTC_AF);56 return IRQ_HANDLED;57}58 59static int pm80x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)60{61 struct pm80x_rtc_info *info = dev_get_drvdata(dev);62 63 if (enabled)64 regmap_update_bits(info->map, PM800_RTC_CONTROL,65 PM800_ALARM1_EN, PM800_ALARM1_EN);66 else67 regmap_update_bits(info->map, PM800_RTC_CONTROL,68 PM800_ALARM1_EN, 0);69 return 0;70}71 72/*73 * Calculate the next alarm time given the requested alarm time mask74 * and the current time.75 */76static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,77 struct rtc_time *alrm)78{79 unsigned long next_time;80 unsigned long now_time;81 82 next->tm_year = now->tm_year;83 next->tm_mon = now->tm_mon;84 next->tm_mday = now->tm_mday;85 next->tm_hour = alrm->tm_hour;86 next->tm_min = alrm->tm_min;87 next->tm_sec = alrm->tm_sec;88 89 now_time = rtc_tm_to_time64(now);90 next_time = rtc_tm_to_time64(next);91 92 if (next_time < now_time) {93 /* Advance one day */94 next_time += 60 * 60 * 24;95 rtc_time64_to_tm(next_time, next);96 }97}98 99static int pm80x_rtc_read_time(struct device *dev, struct rtc_time *tm)100{101 struct pm80x_rtc_info *info = dev_get_drvdata(dev);102 unsigned char buf[4];103 unsigned long ticks, base, data;104 regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4);105 base = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |106 (buf[1] << 8) | buf[0];107 dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]);108 109 /* load 32-bit read-only counter */110 regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4);111 data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |112 (buf[1] << 8) | buf[0];113 ticks = base + data;114 dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",115 base, data, ticks);116 rtc_time64_to_tm(ticks, tm);117 return 0;118}119 120static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm)121{122 struct pm80x_rtc_info *info = dev_get_drvdata(dev);123 unsigned char buf[4];124 unsigned long ticks, base, data;125 126 ticks = rtc_tm_to_time64(tm);127 128 /* load 32-bit read-only counter */129 regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4);130 data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |131 (buf[1] << 8) | buf[0];132 base = ticks - data;133 dev_dbg(info->dev, "set base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",134 base, data, ticks);135 buf[0] = base & 0xFF;136 buf[1] = (base >> 8) & 0xFF;137 buf[2] = (base >> 16) & 0xFF;138 buf[3] = (base >> 24) & 0xFF;139 regmap_raw_write(info->map, PM800_RTC_EXPIRE2_1, buf, 4);140 141 return 0;142}143 144static int pm80x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)145{146 struct pm80x_rtc_info *info = dev_get_drvdata(dev);147 unsigned char buf[4];148 unsigned long ticks, base, data;149 int ret;150 151 regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4);152 base = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |153 (buf[1] << 8) | buf[0];154 dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]);155 156 regmap_raw_read(info->map, PM800_RTC_EXPIRE1_1, buf, 4);157 data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |158 (buf[1] << 8) | buf[0];159 ticks = base + data;160 dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",161 base, data, ticks);162 163 rtc_time64_to_tm(ticks, &alrm->time);164 regmap_read(info->map, PM800_RTC_CONTROL, &ret);165 alrm->enabled = (ret & PM800_ALARM1_EN) ? 1 : 0;166 alrm->pending = (ret & (PM800_ALARM | PM800_ALARM_WAKEUP)) ? 1 : 0;167 return 0;168}169 170static int pm80x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)171{172 struct pm80x_rtc_info *info = dev_get_drvdata(dev);173 struct rtc_time now_tm, alarm_tm;174 unsigned long ticks, base, data;175 unsigned char buf[4];176 int mask;177 178 regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_ALARM1_EN, 0);179 180 regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4);181 base = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |182 (buf[1] << 8) | buf[0];183 dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]);184 185 /* load 32-bit read-only counter */186 regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4);187 data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |188 (buf[1] << 8) | buf[0];189 ticks = base + data;190 dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",191 base, data, ticks);192 193 rtc_time64_to_tm(ticks, &now_tm);194 dev_dbg(info->dev, "%s, now time : %lu\n", __func__, ticks);195 rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);196 /* get new ticks for alarm in 24 hours */197 ticks = rtc_tm_to_time64(&alarm_tm);198 dev_dbg(info->dev, "%s, alarm time: %lu\n", __func__, ticks);199 data = ticks - base;200 201 buf[0] = data & 0xff;202 buf[1] = (data >> 8) & 0xff;203 buf[2] = (data >> 16) & 0xff;204 buf[3] = (data >> 24) & 0xff;205 regmap_raw_write(info->map, PM800_RTC_EXPIRE1_1, buf, 4);206 if (alrm->enabled) {207 mask = PM800_ALARM | PM800_ALARM_WAKEUP | PM800_ALARM1_EN;208 regmap_update_bits(info->map, PM800_RTC_CONTROL, mask, mask);209 } else {210 mask = PM800_ALARM | PM800_ALARM_WAKEUP | PM800_ALARM1_EN;211 regmap_update_bits(info->map, PM800_RTC_CONTROL, mask,212 PM800_ALARM | PM800_ALARM_WAKEUP);213 }214 return 0;215}216 217static const struct rtc_class_ops pm80x_rtc_ops = {218 .read_time = pm80x_rtc_read_time,219 .set_time = pm80x_rtc_set_time,220 .read_alarm = pm80x_rtc_read_alarm,221 .set_alarm = pm80x_rtc_set_alarm,222 .alarm_irq_enable = pm80x_rtc_alarm_irq_enable,223};224 225#ifdef CONFIG_PM_SLEEP226static int pm80x_rtc_suspend(struct device *dev)227{228 return pm80x_dev_suspend(dev);229}230 231static int pm80x_rtc_resume(struct device *dev)232{233 return pm80x_dev_resume(dev);234}235#endif236 237static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume);238 239static int pm80x_rtc_probe(struct platform_device *pdev)240{241 struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);242 struct pm80x_rtc_pdata *pdata = dev_get_platdata(&pdev->dev);243 struct pm80x_rtc_info *info;244 struct device_node *node = pdev->dev.of_node;245 int ret;246 247 if (!pdata && !node) {248 dev_err(&pdev->dev,249 "pm80x-rtc requires platform data or of_node\n");250 return -EINVAL;251 }252 253 if (!pdata) {254 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);255 if (!pdata) {256 dev_err(&pdev->dev, "failed to allocate memory\n");257 return -ENOMEM;258 }259 }260 261 info =262 devm_kzalloc(&pdev->dev, sizeof(struct pm80x_rtc_info), GFP_KERNEL);263 if (!info)264 return -ENOMEM;265 info->irq = platform_get_irq(pdev, 0);266 if (info->irq < 0) {267 ret = -EINVAL;268 goto out;269 }270 271 info->chip = chip;272 info->map = chip->regmap;273 if (!info->map) {274 dev_err(&pdev->dev, "no regmap!\n");275 ret = -EINVAL;276 goto out;277 }278 279 info->dev = &pdev->dev;280 dev_set_drvdata(&pdev->dev, info);281 282 info->rtc_dev = devm_rtc_allocate_device(&pdev->dev);283 if (IS_ERR(info->rtc_dev))284 return PTR_ERR(info->rtc_dev);285 286 ret = pm80x_request_irq(chip, info->irq, rtc_update_handler,287 IRQF_ONESHOT, "rtc", info);288 if (ret < 0) {289 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",290 info->irq, ret);291 goto out;292 }293 294 info->rtc_dev->ops = &pm80x_rtc_ops;295 info->rtc_dev->range_max = U32_MAX;296 297 ret = devm_rtc_register_device(info->rtc_dev);298 if (ret)299 goto out_rtc;300 301 /*302 * enable internal XO instead of internal 3.25MHz clock since it can303 * free running in PMIC power-down state.304 */305 regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_RTC1_USE_XO,306 PM800_RTC1_USE_XO);307 308 /* remember whether this power up is caused by PMIC RTC or not */309 info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;310 311 device_init_wakeup(&pdev->dev, 1);312 313 return 0;314out_rtc:315 pm80x_free_irq(chip, info->irq, info);316out:317 return ret;318}319 320static void pm80x_rtc_remove(struct platform_device *pdev)321{322 struct pm80x_rtc_info *info = platform_get_drvdata(pdev);323 pm80x_free_irq(info->chip, info->irq, info);324}325 326static struct platform_driver pm80x_rtc_driver = {327 .driver = {328 .name = "88pm80x-rtc",329 .pm = &pm80x_rtc_pm_ops,330 },331 .probe = pm80x_rtc_probe,332 .remove_new = pm80x_rtc_remove,333};334 335module_platform_driver(pm80x_rtc_driver);336 337MODULE_LICENSE("GPL");338MODULE_DESCRIPTION("Marvell 88PM80x RTC driver");339MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>");340MODULE_ALIAS("platform:88pm80x-rtc");341