410 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for MediaTek SoC based RTC4 *5 * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>6 */7 8#include <linux/clk.h>9#include <linux/interrupt.h>10#include <linux/io.h>11#include <linux/mod_devicetable.h>12#include <linux/module.h>13#include <linux/platform_device.h>14#include <linux/rtc.h>15 16#define MTK_RTC_DEV KBUILD_MODNAME17 18#define MTK_RTC_PWRCHK1 0x419#define RTC_PWRCHK1_MAGIC 0xc620 21#define MTK_RTC_PWRCHK2 0x822#define RTC_PWRCHK2_MAGIC 0x9a23 24#define MTK_RTC_KEY 0xc25#define RTC_KEY_MAGIC 0x5926 27#define MTK_RTC_PROT1 0x1028#define RTC_PROT1_MAGIC 0xa329 30#define MTK_RTC_PROT2 0x1431#define RTC_PROT2_MAGIC 0x5732 33#define MTK_RTC_PROT3 0x1834#define RTC_PROT3_MAGIC 0x6735 36#define MTK_RTC_PROT4 0x1c37#define RTC_PROT4_MAGIC 0xd238 39#define MTK_RTC_CTL 0x2040#define RTC_RC_STOP BIT(0)41 42#define MTK_RTC_DEBNCE 0x2c43#define RTC_DEBNCE_MASK GENMASK(2, 0)44 45#define MTK_RTC_INT 0x3046#define RTC_INT_AL_STA BIT(4)47 48/*49 * Ranges from 0x40 to 0x78 provide RTC time setup for year, month,50 * day of month, day of week, hour, minute and second.51 */52#define MTK_RTC_TREG(_t, _f) (0x40 + (0x4 * (_f)) + ((_t) * 0x20))53 54#define MTK_RTC_AL_CTL 0x7c55#define RTC_AL_EN BIT(0)56#define RTC_AL_ALL GENMASK(7, 0)57 58/*59 * The offset is used in the translation for the year between in struct60 * rtc_time and in hardware register MTK_RTC_TREG(x,MTK_YEA)61 */62#define MTK_RTC_TM_YR_OFFSET 10063 64/*65 * The lowest value for the valid tm_year. RTC hardware would take incorrectly66 * tm_year 100 as not a leap year and thus it is also required being excluded67 * from the valid options.68 */69#define MTK_RTC_TM_YR_L (MTK_RTC_TM_YR_OFFSET + 1)70 71/*72 * The most year the RTC can hold is 99 and the next to 99 in year register73 * would be wraparound to 0, for MT7622.74 */75#define MTK_RTC_HW_YR_LIMIT 9976 77/* The highest value for the valid tm_year */78#define MTK_RTC_TM_YR_H (MTK_RTC_TM_YR_OFFSET + MTK_RTC_HW_YR_LIMIT)79 80/* Simple macro helps to check whether the hardware supports the tm_year */81#define MTK_RTC_TM_YR_VALID(_y) ((_y) >= MTK_RTC_TM_YR_L && \82 (_y) <= MTK_RTC_TM_YR_H)83 84/* Types of the function the RTC provides are time counter and alarm. */85enum {86 MTK_TC,87 MTK_AL,88};89 90/* Indexes are used for the pointer to relevant registers in MTK_RTC_TREG */91enum {92 MTK_YEA,93 MTK_MON,94 MTK_DOM,95 MTK_DOW,96 MTK_HOU,97 MTK_MIN,98 MTK_SEC99};100 101struct mtk_rtc {102 struct rtc_device *rtc;103 void __iomem *base;104 int irq;105 struct clk *clk;106};107 108static void mtk_w32(struct mtk_rtc *rtc, u32 reg, u32 val)109{110 writel_relaxed(val, rtc->base + reg);111}112 113static u32 mtk_r32(struct mtk_rtc *rtc, u32 reg)114{115 return readl_relaxed(rtc->base + reg);116}117 118static void mtk_rmw(struct mtk_rtc *rtc, u32 reg, u32 mask, u32 set)119{120 u32 val;121 122 val = mtk_r32(rtc, reg);123 val &= ~mask;124 val |= set;125 mtk_w32(rtc, reg, val);126}127 128static void mtk_set(struct mtk_rtc *rtc, u32 reg, u32 val)129{130 mtk_rmw(rtc, reg, 0, val);131}132 133static void mtk_clr(struct mtk_rtc *rtc, u32 reg, u32 val)134{135 mtk_rmw(rtc, reg, val, 0);136}137 138static void mtk_rtc_hw_init(struct mtk_rtc *hw)139{140 /* The setup of the init sequence is for allowing RTC got to work */141 mtk_w32(hw, MTK_RTC_PWRCHK1, RTC_PWRCHK1_MAGIC);142 mtk_w32(hw, MTK_RTC_PWRCHK2, RTC_PWRCHK2_MAGIC);143 mtk_w32(hw, MTK_RTC_KEY, RTC_KEY_MAGIC);144 mtk_w32(hw, MTK_RTC_PROT1, RTC_PROT1_MAGIC);145 mtk_w32(hw, MTK_RTC_PROT2, RTC_PROT2_MAGIC);146 mtk_w32(hw, MTK_RTC_PROT3, RTC_PROT3_MAGIC);147 mtk_w32(hw, MTK_RTC_PROT4, RTC_PROT4_MAGIC);148 mtk_rmw(hw, MTK_RTC_DEBNCE, RTC_DEBNCE_MASK, 0);149 mtk_clr(hw, MTK_RTC_CTL, RTC_RC_STOP);150}151 152static void mtk_rtc_get_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm,153 int time_alarm)154{155 u32 year, mon, mday, wday, hour, min, sec;156 157 /*158 * Read again until the field of the second is not changed which159 * ensures all fields in the consistent state. Note that MTK_SEC must160 * be read first. In this way, it guarantees the others remain not161 * changed when the results for two MTK_SEC consecutive reads are same.162 */163 do {164 sec = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC));165 min = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MIN));166 hour = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_HOU));167 wday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOW));168 mday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOM));169 mon = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MON));170 year = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_YEA));171 } while (sec != mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC)));172 173 tm->tm_sec = sec;174 tm->tm_min = min;175 tm->tm_hour = hour;176 tm->tm_wday = wday;177 tm->tm_mday = mday;178 tm->tm_mon = mon - 1;179 180 /* Rebase to the absolute year which userspace queries */181 tm->tm_year = year + MTK_RTC_TM_YR_OFFSET;182}183 184static void mtk_rtc_set_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm,185 int time_alarm)186{187 u32 year;188 189 /* Rebase to the relative year which RTC hardware requires */190 year = tm->tm_year - MTK_RTC_TM_YR_OFFSET;191 192 mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_YEA), year);193 mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_MON), tm->tm_mon + 1);194 mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_DOW), tm->tm_wday);195 mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_DOM), tm->tm_mday);196 mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_HOU), tm->tm_hour);197 mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_MIN), tm->tm_min);198 mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC), tm->tm_sec);199}200 201static irqreturn_t mtk_rtc_alarmirq(int irq, void *id)202{203 struct mtk_rtc *hw = (struct mtk_rtc *)id;204 u32 irq_sta;205 206 irq_sta = mtk_r32(hw, MTK_RTC_INT);207 if (irq_sta & RTC_INT_AL_STA) {208 /* Stop alarm also implicitly disables the alarm interrupt */209 mtk_w32(hw, MTK_RTC_AL_CTL, 0);210 rtc_update_irq(hw->rtc, 1, RTC_IRQF | RTC_AF);211 212 /* Ack alarm interrupt status */213 mtk_w32(hw, MTK_RTC_INT, RTC_INT_AL_STA);214 return IRQ_HANDLED;215 }216 217 return IRQ_NONE;218}219 220static int mtk_rtc_gettime(struct device *dev, struct rtc_time *tm)221{222 struct mtk_rtc *hw = dev_get_drvdata(dev);223 224 mtk_rtc_get_alarm_or_time(hw, tm, MTK_TC);225 226 return 0;227}228 229static int mtk_rtc_settime(struct device *dev, struct rtc_time *tm)230{231 struct mtk_rtc *hw = dev_get_drvdata(dev);232 233 if (!MTK_RTC_TM_YR_VALID(tm->tm_year))234 return -EINVAL;235 236 /* Stop time counter before setting a new one*/237 mtk_set(hw, MTK_RTC_CTL, RTC_RC_STOP);238 239 mtk_rtc_set_alarm_or_time(hw, tm, MTK_TC);240 241 /* Restart the time counter */242 mtk_clr(hw, MTK_RTC_CTL, RTC_RC_STOP);243 244 return 0;245}246 247static int mtk_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)248{249 struct mtk_rtc *hw = dev_get_drvdata(dev);250 struct rtc_time *alrm_tm = &wkalrm->time;251 252 mtk_rtc_get_alarm_or_time(hw, alrm_tm, MTK_AL);253 254 wkalrm->enabled = !!(mtk_r32(hw, MTK_RTC_AL_CTL) & RTC_AL_EN);255 wkalrm->pending = !!(mtk_r32(hw, MTK_RTC_INT) & RTC_INT_AL_STA);256 257 return 0;258}259 260static int mtk_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)261{262 struct mtk_rtc *hw = dev_get_drvdata(dev);263 struct rtc_time *alrm_tm = &wkalrm->time;264 265 if (!MTK_RTC_TM_YR_VALID(alrm_tm->tm_year))266 return -EINVAL;267 268 /*269 * Stop the alarm also implicitly including disables interrupt before270 * setting a new one.271 */272 mtk_clr(hw, MTK_RTC_AL_CTL, RTC_AL_EN);273 274 /*275 * Avoid contention between mtk_rtc_setalarm and IRQ handler so that276 * disabling the interrupt and awaiting for pending IRQ handler to277 * complete.278 */279 synchronize_irq(hw->irq);280 281 mtk_rtc_set_alarm_or_time(hw, alrm_tm, MTK_AL);282 283 /* Restart the alarm with the new setup */284 mtk_w32(hw, MTK_RTC_AL_CTL, RTC_AL_ALL);285 286 return 0;287}288 289static const struct rtc_class_ops mtk_rtc_ops = {290 .read_time = mtk_rtc_gettime,291 .set_time = mtk_rtc_settime,292 .read_alarm = mtk_rtc_getalarm,293 .set_alarm = mtk_rtc_setalarm,294};295 296static const struct of_device_id mtk_rtc_match[] = {297 { .compatible = "mediatek,mt7622-rtc" },298 { .compatible = "mediatek,soc-rtc" },299 {},300};301MODULE_DEVICE_TABLE(of, mtk_rtc_match);302 303static int mtk_rtc_probe(struct platform_device *pdev)304{305 struct mtk_rtc *hw;306 int ret;307 308 hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);309 if (!hw)310 return -ENOMEM;311 312 platform_set_drvdata(pdev, hw);313 314 hw->base = devm_platform_ioremap_resource(pdev, 0);315 if (IS_ERR(hw->base))316 return PTR_ERR(hw->base);317 318 hw->clk = devm_clk_get(&pdev->dev, "rtc");319 if (IS_ERR(hw->clk)) {320 dev_err(&pdev->dev, "No clock\n");321 return PTR_ERR(hw->clk);322 }323 324 ret = clk_prepare_enable(hw->clk);325 if (ret)326 return ret;327 328 hw->irq = platform_get_irq(pdev, 0);329 if (hw->irq < 0) {330 ret = hw->irq;331 goto err;332 }333 334 ret = devm_request_irq(&pdev->dev, hw->irq, mtk_rtc_alarmirq,335 0, dev_name(&pdev->dev), hw);336 if (ret) {337 dev_err(&pdev->dev, "Can't request IRQ\n");338 goto err;339 }340 341 mtk_rtc_hw_init(hw);342 343 device_init_wakeup(&pdev->dev, true);344 345 hw->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,346 &mtk_rtc_ops, THIS_MODULE);347 if (IS_ERR(hw->rtc)) {348 ret = PTR_ERR(hw->rtc);349 dev_err(&pdev->dev, "Unable to register device\n");350 goto err;351 }352 353 return 0;354err:355 clk_disable_unprepare(hw->clk);356 357 return ret;358}359 360static void mtk_rtc_remove(struct platform_device *pdev)361{362 struct mtk_rtc *hw = platform_get_drvdata(pdev);363 364 clk_disable_unprepare(hw->clk);365}366 367#ifdef CONFIG_PM_SLEEP368static int mtk_rtc_suspend(struct device *dev)369{370 struct mtk_rtc *hw = dev_get_drvdata(dev);371 372 if (device_may_wakeup(dev))373 enable_irq_wake(hw->irq);374 375 return 0;376}377 378static int mtk_rtc_resume(struct device *dev)379{380 struct mtk_rtc *hw = dev_get_drvdata(dev);381 382 if (device_may_wakeup(dev))383 disable_irq_wake(hw->irq);384 385 return 0;386}387 388static SIMPLE_DEV_PM_OPS(mtk_rtc_pm_ops, mtk_rtc_suspend, mtk_rtc_resume);389 390#define MTK_RTC_PM_OPS (&mtk_rtc_pm_ops)391#else /* CONFIG_PM */392#define MTK_RTC_PM_OPS NULL393#endif /* CONFIG_PM */394 395static struct platform_driver mtk_rtc_driver = {396 .probe = mtk_rtc_probe,397 .remove_new = mtk_rtc_remove,398 .driver = {399 .name = MTK_RTC_DEV,400 .of_match_table = mtk_rtc_match,401 .pm = MTK_RTC_PM_OPS,402 },403};404 405module_platform_driver(mtk_rtc_driver);406 407MODULE_DESCRIPTION("MediaTek SoC based RTC Driver");408MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");409MODULE_LICENSE("GPL");410