364 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Real Time Clock driver for Freescale MC13XXX PMIC4 *5 * (C) 2009 Sascha Hauer, Pengutronix6 * (C) 2009 Uwe Kleine-Koenig, Pengutronix7 */8 9#include <linux/mfd/mc13xxx.h>10#include <linux/platform_device.h>11#include <linux/kernel.h>12#include <linux/module.h>13#include <linux/mod_devicetable.h>14#include <linux/slab.h>15#include <linux/rtc.h>16 17#define DRIVER_NAME "mc13xxx-rtc"18 19#define MC13XXX_RTCTOD 2020#define MC13XXX_RTCTODA 2121#define MC13XXX_RTCDAY 2222#define MC13XXX_RTCDAYA 2323 24#define SEC_PER_DAY (24 * 60 * 60)25 26struct mc13xxx_rtc {27 struct rtc_device *rtc;28 struct mc13xxx *mc13xxx;29 int valid;30};31 32static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev,33 unsigned int enabled, int irq)34{35 struct mc13xxx_rtc *priv = dev_get_drvdata(dev);36 int (*func)(struct mc13xxx *mc13xxx, int irq);37 38 if (!priv->valid)39 return -ENODATA;40 41 func = enabled ? mc13xxx_irq_unmask : mc13xxx_irq_mask;42 return func(priv->mc13xxx, irq);43}44 45static int mc13xxx_rtc_alarm_irq_enable(struct device *dev,46 unsigned int enabled)47{48 struct mc13xxx_rtc *priv = dev_get_drvdata(dev);49 int ret;50 51 mc13xxx_lock(priv->mc13xxx);52 53 ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, MC13XXX_IRQ_TODA);54 55 mc13xxx_unlock(priv->mc13xxx);56 57 return ret;58}59 60static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)61{62 struct mc13xxx_rtc *priv = dev_get_drvdata(dev);63 unsigned int seconds, days1, days2;64 65 if (!priv->valid)66 return -ENODATA;67 68 do {69 int ret;70 71 ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1);72 if (ret)73 return ret;74 75 ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds);76 if (ret)77 return ret;78 79 ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2);80 if (ret)81 return ret;82 } while (days1 != days2);83 84 rtc_time64_to_tm((time64_t)days1 * SEC_PER_DAY + seconds, tm);85 86 return 0;87}88 89static int mc13xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)90{91 struct mc13xxx_rtc *priv = dev_get_drvdata(dev);92 unsigned int seconds, days;93 unsigned int alarmseconds;94 int ret;95 96 days = div_s64_rem(rtc_tm_to_time64(tm), SEC_PER_DAY, &seconds);97 98 mc13xxx_lock(priv->mc13xxx);99 100 /*101 * temporarily invalidate alarm to prevent triggering it when the day is102 * already updated while the time isn't yet.103 */104 ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds);105 if (unlikely(ret))106 goto out;107 108 if (alarmseconds < SEC_PER_DAY) {109 ret = mc13xxx_reg_write(priv->mc13xxx,110 MC13XXX_RTCTODA, 0x1ffff);111 if (unlikely(ret))112 goto out;113 }114 115 /*116 * write seconds=0 to prevent a day switch between writing days117 * and seconds below118 */119 ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0);120 if (unlikely(ret))121 goto out;122 123 ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days);124 if (unlikely(ret))125 goto out;126 127 ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds);128 if (unlikely(ret))129 goto out;130 131 /* restore alarm */132 if (alarmseconds < SEC_PER_DAY) {133 ret = mc13xxx_reg_write(priv->mc13xxx,134 MC13XXX_RTCTODA, alarmseconds);135 if (unlikely(ret))136 goto out;137 }138 139 if (!priv->valid) {140 ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST);141 if (unlikely(ret))142 goto out;143 144 ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST);145 }146 147out:148 priv->valid = !ret;149 150 mc13xxx_unlock(priv->mc13xxx);151 152 return ret;153}154 155static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)156{157 struct mc13xxx_rtc *priv = dev_get_drvdata(dev);158 unsigned int seconds, days;159 time64_t s1970;160 int enabled, pending;161 int ret;162 163 mc13xxx_lock(priv->mc13xxx);164 165 ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds);166 if (unlikely(ret))167 goto out;168 if (seconds >= SEC_PER_DAY) {169 ret = -ENODATA;170 goto out;171 }172 173 ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days);174 if (unlikely(ret))175 goto out;176 177 ret = mc13xxx_irq_status(priv->mc13xxx, MC13XXX_IRQ_TODA,178 &enabled, &pending);179 180out:181 mc13xxx_unlock(priv->mc13xxx);182 183 if (ret)184 return ret;185 186 alarm->enabled = enabled;187 alarm->pending = pending;188 189 s1970 = (time64_t)days * SEC_PER_DAY + seconds;190 191 rtc_time64_to_tm(s1970, &alarm->time);192 dev_dbg(dev, "%s: %lld\n", __func__, (long long)s1970);193 194 return 0;195}196 197static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)198{199 struct mc13xxx_rtc *priv = dev_get_drvdata(dev);200 time64_t s1970;201 u32 seconds, days;202 int ret;203 204 mc13xxx_lock(priv->mc13xxx);205 206 /* disable alarm to prevent false triggering */207 ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff);208 if (unlikely(ret))209 goto out;210 211 ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA);212 if (unlikely(ret))213 goto out;214 215 s1970 = rtc_tm_to_time64(&alarm->time);216 217 dev_dbg(dev, "%s: %s %lld\n", __func__, alarm->enabled ? "on" : "off",218 (long long)s1970);219 220 ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled,221 MC13XXX_IRQ_TODA);222 if (unlikely(ret))223 goto out;224 225 days = div_s64_rem(s1970, SEC_PER_DAY, &seconds);226 227 ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days);228 if (unlikely(ret))229 goto out;230 231 ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds);232 233out:234 mc13xxx_unlock(priv->mc13xxx);235 236 return ret;237}238 239static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev)240{241 struct mc13xxx_rtc *priv = dev;242 struct mc13xxx *mc13xxx = priv->mc13xxx;243 244 rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF);245 246 mc13xxx_irq_ack(mc13xxx, irq);247 248 return IRQ_HANDLED;249}250 251static const struct rtc_class_ops mc13xxx_rtc_ops = {252 .read_time = mc13xxx_rtc_read_time,253 .set_time = mc13xxx_rtc_set_time,254 .read_alarm = mc13xxx_rtc_read_alarm,255 .set_alarm = mc13xxx_rtc_set_alarm,256 .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable,257};258 259static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev)260{261 struct mc13xxx_rtc *priv = dev;262 struct mc13xxx *mc13xxx = priv->mc13xxx;263 264 priv->valid = 0;265 266 mc13xxx_irq_mask(mc13xxx, irq);267 268 return IRQ_HANDLED;269}270 271static int __init mc13xxx_rtc_probe(struct platform_device *pdev)272{273 int ret;274 struct mc13xxx_rtc *priv;275 struct mc13xxx *mc13xxx;276 277 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);278 if (!priv)279 return -ENOMEM;280 281 mc13xxx = dev_get_drvdata(pdev->dev.parent);282 priv->mc13xxx = mc13xxx;283 priv->valid = 1;284 285 priv->rtc = devm_rtc_allocate_device(&pdev->dev);286 if (IS_ERR(priv->rtc))287 return PTR_ERR(priv->rtc);288 platform_set_drvdata(pdev, priv);289 290 priv->rtc->ops = &mc13xxx_rtc_ops;291 /* 15bit days + hours, minutes, seconds */292 priv->rtc->range_max = (timeu64_t)(1 << 15) * SEC_PER_DAY - 1;293 294 mc13xxx_lock(mc13xxx);295 296 mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_RTCRST);297 298 ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST,299 mc13xxx_rtc_reset_handler, DRIVER_NAME, priv);300 if (ret)301 goto err_irq_request;302 303 ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA,304 mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv);305 if (ret)306 goto err_irq_request;307 308 mc13xxx_unlock(mc13xxx);309 310 ret = devm_rtc_register_device(priv->rtc);311 if (ret) {312 mc13xxx_lock(mc13xxx);313 goto err_irq_request;314 }315 316 return 0;317 318err_irq_request:319 mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);320 mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);321 322 mc13xxx_unlock(mc13xxx);323 324 return ret;325}326 327static void mc13xxx_rtc_remove(struct platform_device *pdev)328{329 struct mc13xxx_rtc *priv = platform_get_drvdata(pdev);330 331 mc13xxx_lock(priv->mc13xxx);332 333 mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TODA, priv);334 mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_RTCRST, priv);335 336 mc13xxx_unlock(priv->mc13xxx);337}338 339static const struct platform_device_id mc13xxx_rtc_idtable[] = {340 {341 .name = "mc13783-rtc",342 }, {343 .name = "mc13892-rtc",344 }, {345 .name = "mc34708-rtc",346 },347 { /* sentinel */ }348};349MODULE_DEVICE_TABLE(platform, mc13xxx_rtc_idtable);350 351static struct platform_driver mc13xxx_rtc_driver = {352 .id_table = mc13xxx_rtc_idtable,353 .remove_new = mc13xxx_rtc_remove,354 .driver = {355 .name = DRIVER_NAME,356 },357};358 359module_platform_driver_probe(mc13xxx_rtc_driver, &mc13xxx_rtc_probe);360 361MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");362MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC");363MODULE_LICENSE("GPL v2");364