rtc-mt2712.c (11351B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2019 MediaTek Inc. 4 * Author: Ran Bi <ran.bi@mediatek.com> 5 */ 6 7#include <linux/delay.h> 8#include <linux/init.h> 9#include <linux/io.h> 10#include <linux/irqdomain.h> 11#include <linux/module.h> 12#include <linux/of_address.h> 13#include <linux/of_irq.h> 14#include <linux/platform_device.h> 15#include <linux/rtc.h> 16 17#define MT2712_BBPU 0x0000 18#define MT2712_BBPU_CLRPKY BIT(4) 19#define MT2712_BBPU_RELOAD BIT(5) 20#define MT2712_BBPU_CBUSY BIT(6) 21#define MT2712_BBPU_KEY (0x43 << 8) 22 23#define MT2712_IRQ_STA 0x0004 24#define MT2712_IRQ_STA_AL BIT(0) 25#define MT2712_IRQ_STA_TC BIT(1) 26 27#define MT2712_IRQ_EN 0x0008 28#define MT2712_IRQ_EN_AL BIT(0) 29#define MT2712_IRQ_EN_TC BIT(1) 30#define MT2712_IRQ_EN_ONESHOT BIT(2) 31 32#define MT2712_CII_EN 0x000c 33 34#define MT2712_AL_MASK 0x0010 35#define MT2712_AL_MASK_DOW BIT(4) 36 37#define MT2712_TC_SEC 0x0014 38#define MT2712_TC_MIN 0x0018 39#define MT2712_TC_HOU 0x001c 40#define MT2712_TC_DOM 0x0020 41#define MT2712_TC_DOW 0x0024 42#define MT2712_TC_MTH 0x0028 43#define MT2712_TC_YEA 0x002c 44 45#define MT2712_AL_SEC 0x0030 46#define MT2712_AL_MIN 0x0034 47#define MT2712_AL_HOU 0x0038 48#define MT2712_AL_DOM 0x003c 49#define MT2712_AL_DOW 0x0040 50#define MT2712_AL_MTH 0x0044 51#define MT2712_AL_YEA 0x0048 52 53#define MT2712_SEC_MASK 0x003f 54#define MT2712_MIN_MASK 0x003f 55#define MT2712_HOU_MASK 0x001f 56#define MT2712_DOM_MASK 0x001f 57#define MT2712_DOW_MASK 0x0007 58#define MT2712_MTH_MASK 0x000f 59#define MT2712_YEA_MASK 0x007f 60 61#define MT2712_POWERKEY1 0x004c 62#define MT2712_POWERKEY2 0x0050 63#define MT2712_POWERKEY1_KEY 0xa357 64#define MT2712_POWERKEY2_KEY 0x67d2 65 66#define MT2712_CON0 0x005c 67#define MT2712_CON1 0x0060 68 69#define MT2712_PROT 0x0070 70#define MT2712_PROT_UNLOCK1 0x9136 71#define MT2712_PROT_UNLOCK2 0x586a 72 73#define MT2712_WRTGR 0x0078 74 75#define MT2712_RTC_TIMESTAMP_END_2127 4985971199LL 76 77struct mt2712_rtc { 78 struct rtc_device *rtc; 79 void __iomem *base; 80 int irq; 81 u8 irq_wake_enabled; 82 u8 powerlost; 83}; 84 85static inline u32 mt2712_readl(struct mt2712_rtc *mt2712_rtc, u32 reg) 86{ 87 return readl(mt2712_rtc->base + reg); 88} 89 90static inline void mt2712_writel(struct mt2712_rtc *mt2712_rtc, 91 u32 reg, u32 val) 92{ 93 writel(val, mt2712_rtc->base + reg); 94} 95 96static void mt2712_rtc_write_trigger(struct mt2712_rtc *mt2712_rtc) 97{ 98 unsigned long timeout = jiffies + HZ / 10; 99 100 mt2712_writel(mt2712_rtc, MT2712_WRTGR, 1); 101 while (1) { 102 if (!(mt2712_readl(mt2712_rtc, MT2712_BBPU) 103 & MT2712_BBPU_CBUSY)) 104 break; 105 106 if (time_after(jiffies, timeout)) { 107 dev_err(&mt2712_rtc->rtc->dev, 108 "%s time out!\n", __func__); 109 break; 110 } 111 cpu_relax(); 112 } 113} 114 115static void mt2712_rtc_writeif_unlock(struct mt2712_rtc *mt2712_rtc) 116{ 117 mt2712_writel(mt2712_rtc, MT2712_PROT, MT2712_PROT_UNLOCK1); 118 mt2712_rtc_write_trigger(mt2712_rtc); 119 mt2712_writel(mt2712_rtc, MT2712_PROT, MT2712_PROT_UNLOCK2); 120 mt2712_rtc_write_trigger(mt2712_rtc); 121} 122 123static irqreturn_t rtc_irq_handler_thread(int irq, void *data) 124{ 125 struct mt2712_rtc *mt2712_rtc = data; 126 u16 irqsta; 127 128 /* Clear interrupt */ 129 irqsta = mt2712_readl(mt2712_rtc, MT2712_IRQ_STA); 130 if (irqsta & MT2712_IRQ_STA_AL) { 131 rtc_update_irq(mt2712_rtc->rtc, 1, RTC_IRQF | RTC_AF); 132 return IRQ_HANDLED; 133 } 134 135 return IRQ_NONE; 136} 137 138static void __mt2712_rtc_read_time(struct mt2712_rtc *mt2712_rtc, 139 struct rtc_time *tm, int *sec) 140{ 141 tm->tm_sec = mt2712_readl(mt2712_rtc, MT2712_TC_SEC) 142 & MT2712_SEC_MASK; 143 tm->tm_min = mt2712_readl(mt2712_rtc, MT2712_TC_MIN) 144 & MT2712_MIN_MASK; 145 tm->tm_hour = mt2712_readl(mt2712_rtc, MT2712_TC_HOU) 146 & MT2712_HOU_MASK; 147 tm->tm_mday = mt2712_readl(mt2712_rtc, MT2712_TC_DOM) 148 & MT2712_DOM_MASK; 149 tm->tm_mon = (mt2712_readl(mt2712_rtc, MT2712_TC_MTH) - 1) 150 & MT2712_MTH_MASK; 151 tm->tm_year = (mt2712_readl(mt2712_rtc, MT2712_TC_YEA) + 100) 152 & MT2712_YEA_MASK; 153 154 *sec = mt2712_readl(mt2712_rtc, MT2712_TC_SEC) & MT2712_SEC_MASK; 155} 156 157static int mt2712_rtc_read_time(struct device *dev, struct rtc_time *tm) 158{ 159 struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); 160 int sec; 161 162 if (mt2712_rtc->powerlost) 163 return -EINVAL; 164 165 do { 166 __mt2712_rtc_read_time(mt2712_rtc, tm, &sec); 167 } while (sec < tm->tm_sec); /* SEC has carried */ 168 169 return 0; 170} 171 172static int mt2712_rtc_set_time(struct device *dev, struct rtc_time *tm) 173{ 174 struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); 175 176 mt2712_writel(mt2712_rtc, MT2712_TC_SEC, tm->tm_sec & MT2712_SEC_MASK); 177 mt2712_writel(mt2712_rtc, MT2712_TC_MIN, tm->tm_min & MT2712_MIN_MASK); 178 mt2712_writel(mt2712_rtc, MT2712_TC_HOU, tm->tm_hour & MT2712_HOU_MASK); 179 mt2712_writel(mt2712_rtc, MT2712_TC_DOM, tm->tm_mday & MT2712_DOM_MASK); 180 mt2712_writel(mt2712_rtc, MT2712_TC_MTH, 181 (tm->tm_mon + 1) & MT2712_MTH_MASK); 182 mt2712_writel(mt2712_rtc, MT2712_TC_YEA, 183 (tm->tm_year - 100) & MT2712_YEA_MASK); 184 185 mt2712_rtc_write_trigger(mt2712_rtc); 186 187 if (mt2712_rtc->powerlost) 188 mt2712_rtc->powerlost = false; 189 190 return 0; 191} 192 193static int mt2712_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 194{ 195 struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); 196 struct rtc_time *tm = &alm->time; 197 u16 irqen; 198 199 irqen = mt2712_readl(mt2712_rtc, MT2712_IRQ_EN); 200 alm->enabled = !!(irqen & MT2712_IRQ_EN_AL); 201 202 tm->tm_sec = mt2712_readl(mt2712_rtc, MT2712_AL_SEC) & MT2712_SEC_MASK; 203 tm->tm_min = mt2712_readl(mt2712_rtc, MT2712_AL_MIN) & MT2712_MIN_MASK; 204 tm->tm_hour = mt2712_readl(mt2712_rtc, MT2712_AL_HOU) & MT2712_HOU_MASK; 205 tm->tm_mday = mt2712_readl(mt2712_rtc, MT2712_AL_DOM) & MT2712_DOM_MASK; 206 tm->tm_mon = (mt2712_readl(mt2712_rtc, MT2712_AL_MTH) - 1) 207 & MT2712_MTH_MASK; 208 tm->tm_year = (mt2712_readl(mt2712_rtc, MT2712_AL_YEA) + 100) 209 & MT2712_YEA_MASK; 210 211 return 0; 212} 213 214static int mt2712_rtc_alarm_irq_enable(struct device *dev, 215 unsigned int enabled) 216{ 217 struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); 218 u16 irqen; 219 220 irqen = mt2712_readl(mt2712_rtc, MT2712_IRQ_EN); 221 if (enabled) 222 irqen |= MT2712_IRQ_EN_AL; 223 else 224 irqen &= ~MT2712_IRQ_EN_AL; 225 mt2712_writel(mt2712_rtc, MT2712_IRQ_EN, irqen); 226 mt2712_rtc_write_trigger(mt2712_rtc); 227 228 return 0; 229} 230 231static int mt2712_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 232{ 233 struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); 234 struct rtc_time *tm = &alm->time; 235 236 dev_dbg(&mt2712_rtc->rtc->dev, "set al time: %ptR, alm en: %d\n", 237 tm, alm->enabled); 238 239 mt2712_writel(mt2712_rtc, MT2712_AL_SEC, 240 (mt2712_readl(mt2712_rtc, MT2712_AL_SEC) 241 & ~(MT2712_SEC_MASK)) | (tm->tm_sec & MT2712_SEC_MASK)); 242 mt2712_writel(mt2712_rtc, MT2712_AL_MIN, 243 (mt2712_readl(mt2712_rtc, MT2712_AL_MIN) 244 & ~(MT2712_MIN_MASK)) | (tm->tm_min & MT2712_MIN_MASK)); 245 mt2712_writel(mt2712_rtc, MT2712_AL_HOU, 246 (mt2712_readl(mt2712_rtc, MT2712_AL_HOU) 247 & ~(MT2712_HOU_MASK)) | (tm->tm_hour & MT2712_HOU_MASK)); 248 mt2712_writel(mt2712_rtc, MT2712_AL_DOM, 249 (mt2712_readl(mt2712_rtc, MT2712_AL_DOM) 250 & ~(MT2712_DOM_MASK)) | (tm->tm_mday & MT2712_DOM_MASK)); 251 mt2712_writel(mt2712_rtc, MT2712_AL_MTH, 252 (mt2712_readl(mt2712_rtc, MT2712_AL_MTH) 253 & ~(MT2712_MTH_MASK)) 254 | ((tm->tm_mon + 1) & MT2712_MTH_MASK)); 255 mt2712_writel(mt2712_rtc, MT2712_AL_YEA, 256 (mt2712_readl(mt2712_rtc, MT2712_AL_YEA) 257 & ~(MT2712_YEA_MASK)) 258 | ((tm->tm_year - 100) & MT2712_YEA_MASK)); 259 260 /* mask day of week */ 261 mt2712_writel(mt2712_rtc, MT2712_AL_MASK, MT2712_AL_MASK_DOW); 262 mt2712_rtc_write_trigger(mt2712_rtc); 263 264 mt2712_rtc_alarm_irq_enable(dev, alm->enabled); 265 266 return 0; 267} 268 269/* Init RTC register */ 270static void mt2712_rtc_hw_init(struct mt2712_rtc *mt2712_rtc) 271{ 272 u32 p1, p2; 273 274 mt2712_writel(mt2712_rtc, MT2712_BBPU, 275 MT2712_BBPU_KEY | MT2712_BBPU_RELOAD); 276 277 mt2712_writel(mt2712_rtc, MT2712_CII_EN, 0); 278 mt2712_writel(mt2712_rtc, MT2712_AL_MASK, 0); 279 /* necessary before set MT2712_POWERKEY */ 280 mt2712_writel(mt2712_rtc, MT2712_CON0, 0x4848); 281 mt2712_writel(mt2712_rtc, MT2712_CON1, 0x0048); 282 283 mt2712_rtc_write_trigger(mt2712_rtc); 284 285 p1 = mt2712_readl(mt2712_rtc, MT2712_POWERKEY1); 286 p2 = mt2712_readl(mt2712_rtc, MT2712_POWERKEY2); 287 if (p1 != MT2712_POWERKEY1_KEY || p2 != MT2712_POWERKEY2_KEY) { 288 mt2712_rtc->powerlost = true; 289 dev_dbg(&mt2712_rtc->rtc->dev, 290 "powerkey not set (lost power)\n"); 291 } else { 292 mt2712_rtc->powerlost = false; 293 } 294 295 /* RTC need POWERKEY1/2 match, then goto normal work mode */ 296 mt2712_writel(mt2712_rtc, MT2712_POWERKEY1, MT2712_POWERKEY1_KEY); 297 mt2712_writel(mt2712_rtc, MT2712_POWERKEY2, MT2712_POWERKEY2_KEY); 298 mt2712_rtc_write_trigger(mt2712_rtc); 299 300 mt2712_rtc_writeif_unlock(mt2712_rtc); 301} 302 303static const struct rtc_class_ops mt2712_rtc_ops = { 304 .read_time = mt2712_rtc_read_time, 305 .set_time = mt2712_rtc_set_time, 306 .read_alarm = mt2712_rtc_read_alarm, 307 .set_alarm = mt2712_rtc_set_alarm, 308 .alarm_irq_enable = mt2712_rtc_alarm_irq_enable, 309}; 310 311static int mt2712_rtc_probe(struct platform_device *pdev) 312{ 313 struct mt2712_rtc *mt2712_rtc; 314 int ret; 315 316 mt2712_rtc = devm_kzalloc(&pdev->dev, 317 sizeof(struct mt2712_rtc), GFP_KERNEL); 318 if (!mt2712_rtc) 319 return -ENOMEM; 320 321 mt2712_rtc->base = devm_platform_ioremap_resource(pdev, 0); 322 if (IS_ERR(mt2712_rtc->base)) 323 return PTR_ERR(mt2712_rtc->base); 324 325 /* rtc hw init */ 326 mt2712_rtc_hw_init(mt2712_rtc); 327 328 mt2712_rtc->irq = platform_get_irq(pdev, 0); 329 if (mt2712_rtc->irq < 0) 330 return mt2712_rtc->irq; 331 332 platform_set_drvdata(pdev, mt2712_rtc); 333 334 mt2712_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); 335 if (IS_ERR(mt2712_rtc->rtc)) 336 return PTR_ERR(mt2712_rtc->rtc); 337 338 ret = devm_request_threaded_irq(&pdev->dev, mt2712_rtc->irq, NULL, 339 rtc_irq_handler_thread, 340 IRQF_ONESHOT | IRQF_TRIGGER_LOW, 341 dev_name(&mt2712_rtc->rtc->dev), 342 mt2712_rtc); 343 if (ret) { 344 dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", 345 mt2712_rtc->irq, ret); 346 return ret; 347 } 348 349 device_init_wakeup(&pdev->dev, true); 350 351 mt2712_rtc->rtc->ops = &mt2712_rtc_ops; 352 mt2712_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; 353 mt2712_rtc->rtc->range_max = MT2712_RTC_TIMESTAMP_END_2127; 354 355 return devm_rtc_register_device(mt2712_rtc->rtc); 356} 357 358#ifdef CONFIG_PM_SLEEP 359static int mt2712_rtc_suspend(struct device *dev) 360{ 361 int wake_status = 0; 362 struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); 363 364 if (device_may_wakeup(dev)) { 365 wake_status = enable_irq_wake(mt2712_rtc->irq); 366 if (!wake_status) 367 mt2712_rtc->irq_wake_enabled = true; 368 } 369 370 return 0; 371} 372 373static int mt2712_rtc_resume(struct device *dev) 374{ 375 int wake_status = 0; 376 struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev); 377 378 if (device_may_wakeup(dev) && mt2712_rtc->irq_wake_enabled) { 379 wake_status = disable_irq_wake(mt2712_rtc->irq); 380 if (!wake_status) 381 mt2712_rtc->irq_wake_enabled = false; 382 } 383 384 return 0; 385} 386 387static SIMPLE_DEV_PM_OPS(mt2712_pm_ops, mt2712_rtc_suspend, 388 mt2712_rtc_resume); 389#endif 390 391static const struct of_device_id mt2712_rtc_of_match[] = { 392 { .compatible = "mediatek,mt2712-rtc", }, 393 { }, 394}; 395 396MODULE_DEVICE_TABLE(of, mt2712_rtc_of_match); 397 398static struct platform_driver mt2712_rtc_driver = { 399 .driver = { 400 .name = "mt2712-rtc", 401 .of_match_table = mt2712_rtc_of_match, 402#ifdef CONFIG_PM_SLEEP 403 .pm = &mt2712_pm_ops, 404#endif 405 }, 406 .probe = mt2712_rtc_probe, 407}; 408 409module_platform_driver(mt2712_rtc_driver); 410 411MODULE_DESCRIPTION("MediaTek MT2712 SoC based RTC Driver"); 412MODULE_AUTHOR("Ran Bi <ran.bi@mediatek.com>"); 413MODULE_LICENSE("GPL");