11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2fc297911STianping Fang /* 3fc297911STianping Fang * Copyright (c) 2014-2015 MediaTek Inc. 4fc297911STianping Fang * Author: Tianping.Fang <tianping.fang@mediatek.com> 5fc297911STianping Fang */ 6fc297911STianping Fang 7fc297911STianping Fang #include <linux/delay.h> 8fc297911STianping Fang #include <linux/init.h> 9fc297911STianping Fang #include <linux/module.h> 10fc297911STianping Fang #include <linux/regmap.h> 11fc297911STianping Fang #include <linux/rtc.h> 12fc297911STianping Fang #include <linux/irqdomain.h> 13fc297911STianping Fang #include <linux/platform_device.h> 14fc297911STianping Fang #include <linux/of_address.h> 15fc297911STianping Fang #include <linux/of_irq.h> 16fc297911STianping Fang #include <linux/io.h> 17fc297911STianping Fang #include <linux/mfd/mt6397/core.h> 18fc297911STianping Fang 19fc297911STianping Fang #define RTC_BBPU 0x0000 20fc297911STianping Fang #define RTC_BBPU_CBUSY BIT(6) 21fc297911STianping Fang 22fc297911STianping Fang #define RTC_WRTGR 0x003c 23fc297911STianping Fang 24fc297911STianping Fang #define RTC_IRQ_STA 0x0002 25fc297911STianping Fang #define RTC_IRQ_STA_AL BIT(0) 26fc297911STianping Fang #define RTC_IRQ_STA_LP BIT(3) 27fc297911STianping Fang 28fc297911STianping Fang #define RTC_IRQ_EN 0x0004 29fc297911STianping Fang #define RTC_IRQ_EN_AL BIT(0) 30fc297911STianping Fang #define RTC_IRQ_EN_ONESHOT BIT(2) 31fc297911STianping Fang #define RTC_IRQ_EN_LP BIT(3) 32fc297911STianping Fang #define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL) 33fc297911STianping Fang 34fc297911STianping Fang #define RTC_AL_MASK 0x0008 35fc297911STianping Fang #define RTC_AL_MASK_DOW BIT(4) 36fc297911STianping Fang 37fc297911STianping Fang #define RTC_TC_SEC 0x000a 38fc297911STianping Fang /* Min, Hour, Dom... register offset to RTC_TC_SEC */ 39fc297911STianping Fang #define RTC_OFFSET_SEC 0 40fc297911STianping Fang #define RTC_OFFSET_MIN 1 41fc297911STianping Fang #define RTC_OFFSET_HOUR 2 42fc297911STianping Fang #define RTC_OFFSET_DOM 3 43fc297911STianping Fang #define RTC_OFFSET_DOW 4 44fc297911STianping Fang #define RTC_OFFSET_MTH 5 45fc297911STianping Fang #define RTC_OFFSET_YEAR 6 46fc297911STianping Fang #define RTC_OFFSET_COUNT 7 47fc297911STianping Fang 48fc297911STianping Fang #define RTC_AL_SEC 0x0018 49fc297911STianping Fang 50fc297911STianping Fang #define RTC_PDN2 0x002e 51fc297911STianping Fang #define RTC_PDN2_PWRON_ALARM BIT(4) 52fc297911STianping Fang 53fc297911STianping Fang #define RTC_MIN_YEAR 1968 54fc297911STianping Fang #define RTC_BASE_YEAR 1900 55fc297911STianping Fang #define RTC_NUM_YEARS 128 56fc297911STianping Fang #define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR) 57fc297911STianping Fang 58fc297911STianping Fang struct mt6397_rtc { 59fc297911STianping Fang struct device *dev; 60fc297911STianping Fang struct rtc_device *rtc_dev; 61fc297911STianping Fang struct mutex lock; 62fc297911STianping Fang struct regmap *regmap; 63fc297911STianping Fang int irq; 64fc297911STianping Fang u32 addr_base; 65fc297911STianping Fang }; 66fc297911STianping Fang 67fc297911STianping Fang static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc) 68fc297911STianping Fang { 69fc297911STianping Fang unsigned long timeout = jiffies + HZ; 70fc297911STianping Fang int ret; 71fc297911STianping Fang u32 data; 72fc297911STianping Fang 73fc297911STianping Fang ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_WRTGR, 1); 74fc297911STianping Fang if (ret < 0) 75fc297911STianping Fang return ret; 76fc297911STianping Fang 77fc297911STianping Fang while (1) { 78fc297911STianping Fang ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_BBPU, 79fc297911STianping Fang &data); 80fc297911STianping Fang if (ret < 0) 81fc297911STianping Fang break; 82fc297911STianping Fang if (!(data & RTC_BBPU_CBUSY)) 83fc297911STianping Fang break; 84fc297911STianping Fang if (time_after(jiffies, timeout)) { 85fc297911STianping Fang ret = -ETIMEDOUT; 86fc297911STianping Fang break; 87fc297911STianping Fang } 88fc297911STianping Fang cpu_relax(); 89fc297911STianping Fang } 90fc297911STianping Fang 91fc297911STianping Fang return ret; 92fc297911STianping Fang } 93fc297911STianping Fang 94fc297911STianping Fang static irqreturn_t mtk_rtc_irq_handler_thread(int irq, void *data) 95fc297911STianping Fang { 96fc297911STianping Fang struct mt6397_rtc *rtc = data; 97fc297911STianping Fang u32 irqsta, irqen; 98fc297911STianping Fang int ret; 99fc297911STianping Fang 100fc297911STianping Fang ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_STA, &irqsta); 101fc297911STianping Fang if ((ret >= 0) && (irqsta & RTC_IRQ_STA_AL)) { 102fc297911STianping Fang rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); 103fc297911STianping Fang irqen = irqsta & ~RTC_IRQ_EN_AL; 104fc297911STianping Fang mutex_lock(&rtc->lock); 105fc297911STianping Fang if (regmap_write(rtc->regmap, rtc->addr_base + RTC_IRQ_EN, 106fc297911STianping Fang irqen) < 0) 107fc297911STianping Fang mtk_rtc_write_trigger(rtc); 108fc297911STianping Fang mutex_unlock(&rtc->lock); 109fc297911STianping Fang 110fc297911STianping Fang return IRQ_HANDLED; 111fc297911STianping Fang } 112fc297911STianping Fang 113fc297911STianping Fang return IRQ_NONE; 114fc297911STianping Fang } 115fc297911STianping Fang 116fc297911STianping Fang static int __mtk_rtc_read_time(struct mt6397_rtc *rtc, 117fc297911STianping Fang struct rtc_time *tm, int *sec) 118fc297911STianping Fang { 119fc297911STianping Fang int ret; 120fc297911STianping Fang u16 data[RTC_OFFSET_COUNT]; 121fc297911STianping Fang 122fc297911STianping Fang mutex_lock(&rtc->lock); 123fc297911STianping Fang ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC, 124fc297911STianping Fang data, RTC_OFFSET_COUNT); 125fc297911STianping Fang if (ret < 0) 126fc297911STianping Fang goto exit; 127fc297911STianping Fang 128fc297911STianping Fang tm->tm_sec = data[RTC_OFFSET_SEC]; 129fc297911STianping Fang tm->tm_min = data[RTC_OFFSET_MIN]; 130fc297911STianping Fang tm->tm_hour = data[RTC_OFFSET_HOUR]; 131fc297911STianping Fang tm->tm_mday = data[RTC_OFFSET_DOM]; 132fc297911STianping Fang tm->tm_mon = data[RTC_OFFSET_MTH]; 133fc297911STianping Fang tm->tm_year = data[RTC_OFFSET_YEAR]; 134fc297911STianping Fang 135fc297911STianping Fang ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC, sec); 136fc297911STianping Fang exit: 137fc297911STianping Fang mutex_unlock(&rtc->lock); 138fc297911STianping Fang return ret; 139fc297911STianping Fang } 140fc297911STianping Fang 141fc297911STianping Fang static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm) 142fc297911STianping Fang { 143fc297911STianping Fang time64_t time; 144fc297911STianping Fang struct mt6397_rtc *rtc = dev_get_drvdata(dev); 14593939967SAlexandre Belloni int days, sec, ret; 146fc297911STianping Fang 147fc297911STianping Fang do { 148fc297911STianping Fang ret = __mtk_rtc_read_time(rtc, tm, &sec); 149fc297911STianping Fang if (ret < 0) 150fc297911STianping Fang goto exit; 151fc297911STianping Fang } while (sec < tm->tm_sec); 152fc297911STianping Fang 153fc297911STianping Fang /* HW register use 7 bits to store year data, minus 154fc297911STianping Fang * RTC_MIN_YEAR_OFFSET before write year data to register, and plus 155fc297911STianping Fang * RTC_MIN_YEAR_OFFSET back after read year from register 156fc297911STianping Fang */ 157fc297911STianping Fang tm->tm_year += RTC_MIN_YEAR_OFFSET; 158fc297911STianping Fang 159fc297911STianping Fang /* HW register start mon from one, but tm_mon start from zero. */ 160fc297911STianping Fang tm->tm_mon--; 161fc297911STianping Fang time = rtc_tm_to_time64(tm); 162fc297911STianping Fang 163fc297911STianping Fang /* rtc_tm_to_time64 covert Gregorian date to seconds since 164fc297911STianping Fang * 01-01-1970 00:00:00, and this date is Thursday. 165fc297911STianping Fang */ 16693939967SAlexandre Belloni days = div_s64(time, 86400); 16793939967SAlexandre Belloni tm->tm_wday = (days + 4) % 7; 168fc297911STianping Fang 169fc297911STianping Fang exit: 170fc297911STianping Fang return ret; 171fc297911STianping Fang } 172fc297911STianping Fang 173fc297911STianping Fang static int mtk_rtc_set_time(struct device *dev, struct rtc_time *tm) 174fc297911STianping Fang { 175fc297911STianping Fang struct mt6397_rtc *rtc = dev_get_drvdata(dev); 176fc297911STianping Fang int ret; 177fc297911STianping Fang u16 data[RTC_OFFSET_COUNT]; 178fc297911STianping Fang 179fc297911STianping Fang tm->tm_year -= RTC_MIN_YEAR_OFFSET; 180fc297911STianping Fang tm->tm_mon++; 181fc297911STianping Fang 182fc297911STianping Fang data[RTC_OFFSET_SEC] = tm->tm_sec; 183fc297911STianping Fang data[RTC_OFFSET_MIN] = tm->tm_min; 184fc297911STianping Fang data[RTC_OFFSET_HOUR] = tm->tm_hour; 185fc297911STianping Fang data[RTC_OFFSET_DOM] = tm->tm_mday; 186fc297911STianping Fang data[RTC_OFFSET_MTH] = tm->tm_mon; 187fc297911STianping Fang data[RTC_OFFSET_YEAR] = tm->tm_year; 188fc297911STianping Fang 189fc297911STianping Fang mutex_lock(&rtc->lock); 190fc297911STianping Fang ret = regmap_bulk_write(rtc->regmap, rtc->addr_base + RTC_TC_SEC, 191fc297911STianping Fang data, RTC_OFFSET_COUNT); 192fc297911STianping Fang if (ret < 0) 193fc297911STianping Fang goto exit; 194fc297911STianping Fang 195fc297911STianping Fang /* Time register write to hardware after call trigger function */ 196fc297911STianping Fang ret = mtk_rtc_write_trigger(rtc); 197fc297911STianping Fang 198fc297911STianping Fang exit: 199fc297911STianping Fang mutex_unlock(&rtc->lock); 200fc297911STianping Fang return ret; 201fc297911STianping Fang } 202fc297911STianping Fang 203fc297911STianping Fang static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 204fc297911STianping Fang { 205fc297911STianping Fang struct rtc_time *tm = &alm->time; 206fc297911STianping Fang struct mt6397_rtc *rtc = dev_get_drvdata(dev); 207fc297911STianping Fang u32 irqen, pdn2; 208fc297911STianping Fang int ret; 209fc297911STianping Fang u16 data[RTC_OFFSET_COUNT]; 210fc297911STianping Fang 211fc297911STianping Fang mutex_lock(&rtc->lock); 212fc297911STianping Fang ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_EN, &irqen); 213fc297911STianping Fang if (ret < 0) 214fc297911STianping Fang goto err_exit; 215fc297911STianping Fang ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_PDN2, &pdn2); 216fc297911STianping Fang if (ret < 0) 217fc297911STianping Fang goto err_exit; 218fc297911STianping Fang 219fc297911STianping Fang ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_AL_SEC, 220fc297911STianping Fang data, RTC_OFFSET_COUNT); 221fc297911STianping Fang if (ret < 0) 222fc297911STianping Fang goto err_exit; 223fc297911STianping Fang 224fc297911STianping Fang alm->enabled = !!(irqen & RTC_IRQ_EN_AL); 225fc297911STianping Fang alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM); 226fc297911STianping Fang mutex_unlock(&rtc->lock); 227fc297911STianping Fang 228fc297911STianping Fang tm->tm_sec = data[RTC_OFFSET_SEC]; 229fc297911STianping Fang tm->tm_min = data[RTC_OFFSET_MIN]; 230fc297911STianping Fang tm->tm_hour = data[RTC_OFFSET_HOUR]; 231fc297911STianping Fang tm->tm_mday = data[RTC_OFFSET_DOM]; 232fc297911STianping Fang tm->tm_mon = data[RTC_OFFSET_MTH]; 233fc297911STianping Fang tm->tm_year = data[RTC_OFFSET_YEAR]; 234fc297911STianping Fang 235fc297911STianping Fang tm->tm_year += RTC_MIN_YEAR_OFFSET; 236fc297911STianping Fang tm->tm_mon--; 237fc297911STianping Fang 238fc297911STianping Fang return 0; 239fc297911STianping Fang err_exit: 240fc297911STianping Fang mutex_unlock(&rtc->lock); 241fc297911STianping Fang return ret; 242fc297911STianping Fang } 243fc297911STianping Fang 244fc297911STianping Fang static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 245fc297911STianping Fang { 246fc297911STianping Fang struct rtc_time *tm = &alm->time; 247fc297911STianping Fang struct mt6397_rtc *rtc = dev_get_drvdata(dev); 248fc297911STianping Fang int ret; 249fc297911STianping Fang u16 data[RTC_OFFSET_COUNT]; 250fc297911STianping Fang 251fc297911STianping Fang tm->tm_year -= RTC_MIN_YEAR_OFFSET; 252fc297911STianping Fang tm->tm_mon++; 253fc297911STianping Fang 254fc297911STianping Fang data[RTC_OFFSET_SEC] = tm->tm_sec; 255fc297911STianping Fang data[RTC_OFFSET_MIN] = tm->tm_min; 256fc297911STianping Fang data[RTC_OFFSET_HOUR] = tm->tm_hour; 257fc297911STianping Fang data[RTC_OFFSET_DOM] = tm->tm_mday; 258fc297911STianping Fang data[RTC_OFFSET_MTH] = tm->tm_mon; 259fc297911STianping Fang data[RTC_OFFSET_YEAR] = tm->tm_year; 260fc297911STianping Fang 261fc297911STianping Fang mutex_lock(&rtc->lock); 262fc297911STianping Fang if (alm->enabled) { 263fc297911STianping Fang ret = regmap_bulk_write(rtc->regmap, 264fc297911STianping Fang rtc->addr_base + RTC_AL_SEC, 265fc297911STianping Fang data, RTC_OFFSET_COUNT); 266fc297911STianping Fang if (ret < 0) 267fc297911STianping Fang goto exit; 268fc297911STianping Fang ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_AL_MASK, 269fc297911STianping Fang RTC_AL_MASK_DOW); 270fc297911STianping Fang if (ret < 0) 271fc297911STianping Fang goto exit; 272fc297911STianping Fang ret = regmap_update_bits(rtc->regmap, 273fc297911STianping Fang rtc->addr_base + RTC_IRQ_EN, 274fc297911STianping Fang RTC_IRQ_EN_ONESHOT_AL, 275fc297911STianping Fang RTC_IRQ_EN_ONESHOT_AL); 276fc297911STianping Fang if (ret < 0) 277fc297911STianping Fang goto exit; 278fc297911STianping Fang } else { 279fc297911STianping Fang ret = regmap_update_bits(rtc->regmap, 280fc297911STianping Fang rtc->addr_base + RTC_IRQ_EN, 281fc297911STianping Fang RTC_IRQ_EN_ONESHOT_AL, 0); 282fc297911STianping Fang if (ret < 0) 283fc297911STianping Fang goto exit; 284fc297911STianping Fang } 285fc297911STianping Fang 286fc297911STianping Fang /* All alarm time register write to hardware after calling 287fc297911STianping Fang * mtk_rtc_write_trigger. This can avoid race condition if alarm 288fc297911STianping Fang * occur happen during writing alarm time register. 289fc297911STianping Fang */ 290fc297911STianping Fang ret = mtk_rtc_write_trigger(rtc); 291fc297911STianping Fang exit: 292fc297911STianping Fang mutex_unlock(&rtc->lock); 293fc297911STianping Fang return ret; 294fc297911STianping Fang } 295fc297911STianping Fang 29634c7b3acSJulia Lawall static const struct rtc_class_ops mtk_rtc_ops = { 297fc297911STianping Fang .read_time = mtk_rtc_read_time, 298fc297911STianping Fang .set_time = mtk_rtc_set_time, 299fc297911STianping Fang .read_alarm = mtk_rtc_read_alarm, 300fc297911STianping Fang .set_alarm = mtk_rtc_set_alarm, 301fc297911STianping Fang }; 302fc297911STianping Fang 303fc297911STianping Fang static int mtk_rtc_probe(struct platform_device *pdev) 304fc297911STianping Fang { 305fc297911STianping Fang struct resource *res; 306fc297911STianping Fang struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent); 307fc297911STianping Fang struct mt6397_rtc *rtc; 308fc297911STianping Fang int ret; 309fc297911STianping Fang 310fc297911STianping Fang rtc = devm_kzalloc(&pdev->dev, sizeof(struct mt6397_rtc), GFP_KERNEL); 311fc297911STianping Fang if (!rtc) 312fc297911STianping Fang return -ENOMEM; 313fc297911STianping Fang 314fc297911STianping Fang res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 315fc297911STianping Fang rtc->addr_base = res->start; 316fc297911STianping Fang 317e695d3a0SChen Zhong rtc->irq = platform_get_irq(pdev, 0); 318e695d3a0SChen Zhong if (rtc->irq < 0) 319e695d3a0SChen Zhong return rtc->irq; 320fc297911STianping Fang 321fc297911STianping Fang rtc->regmap = mt6397_chip->regmap; 322fc297911STianping Fang rtc->dev = &pdev->dev; 323fc297911STianping Fang mutex_init(&rtc->lock); 324fc297911STianping Fang 325fc297911STianping Fang platform_set_drvdata(pdev, rtc); 326fc297911STianping Fang 327babab2f8SAlexandre Belloni rtc->rtc_dev = devm_rtc_allocate_device(rtc->dev); 328babab2f8SAlexandre Belloni if (IS_ERR(rtc->rtc_dev)) 329babab2f8SAlexandre Belloni return PTR_ERR(rtc->rtc_dev); 330babab2f8SAlexandre Belloni 331fc297911STianping Fang ret = request_threaded_irq(rtc->irq, NULL, 332fc297911STianping Fang mtk_rtc_irq_handler_thread, 333fc297911STianping Fang IRQF_ONESHOT | IRQF_TRIGGER_HIGH, 334fc297911STianping Fang "mt6397-rtc", rtc); 335fc297911STianping Fang if (ret) { 336fc297911STianping Fang dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", 337fc297911STianping Fang rtc->irq, ret); 33824db953eSPi-Hsun Shih return ret; 339fc297911STianping Fang } 340fc297911STianping Fang 341baeca449SWei-Ning Huang device_init_wakeup(&pdev->dev, 1); 342baeca449SWei-Ning Huang 343babab2f8SAlexandre Belloni rtc->rtc_dev->ops = &mtk_rtc_ops; 344babab2f8SAlexandre Belloni 345babab2f8SAlexandre Belloni ret = rtc_register_device(rtc->rtc_dev); 346babab2f8SAlexandre Belloni if (ret) { 347fc297911STianping Fang dev_err(&pdev->dev, "register rtc device failed\n"); 348fc297911STianping Fang goto out_free_irq; 349fc297911STianping Fang } 350fc297911STianping Fang 351fc297911STianping Fang return 0; 352fc297911STianping Fang 353fc297911STianping Fang out_free_irq: 35424db953eSPi-Hsun Shih free_irq(rtc->irq, rtc); 355fc297911STianping Fang return ret; 356fc297911STianping Fang } 357fc297911STianping Fang 358fc297911STianping Fang static int mtk_rtc_remove(struct platform_device *pdev) 359fc297911STianping Fang { 360fc297911STianping Fang struct mt6397_rtc *rtc = platform_get_drvdata(pdev); 361fc297911STianping Fang 36224db953eSPi-Hsun Shih free_irq(rtc->irq, rtc); 363fc297911STianping Fang 364fc297911STianping Fang return 0; 365fc297911STianping Fang } 366fc297911STianping Fang 367d7f9777dSHenry Chen #ifdef CONFIG_PM_SLEEP 368d7f9777dSHenry Chen static int mt6397_rtc_suspend(struct device *dev) 369d7f9777dSHenry Chen { 370d7f9777dSHenry Chen struct mt6397_rtc *rtc = dev_get_drvdata(dev); 371d7f9777dSHenry Chen 372d7f9777dSHenry Chen if (device_may_wakeup(dev)) 373d7f9777dSHenry Chen enable_irq_wake(rtc->irq); 374d7f9777dSHenry Chen 375d7f9777dSHenry Chen return 0; 376d7f9777dSHenry Chen } 377d7f9777dSHenry Chen 378d7f9777dSHenry Chen static int mt6397_rtc_resume(struct device *dev) 379d7f9777dSHenry Chen { 380d7f9777dSHenry Chen struct mt6397_rtc *rtc = dev_get_drvdata(dev); 381d7f9777dSHenry Chen 382d7f9777dSHenry Chen if (device_may_wakeup(dev)) 383d7f9777dSHenry Chen disable_irq_wake(rtc->irq); 384d7f9777dSHenry Chen 385d7f9777dSHenry Chen return 0; 386d7f9777dSHenry Chen } 387d7f9777dSHenry Chen #endif 388d7f9777dSHenry Chen 389d7f9777dSHenry Chen static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_rtc_suspend, 390d7f9777dSHenry Chen mt6397_rtc_resume); 391d7f9777dSHenry Chen 392fc297911STianping Fang static const struct of_device_id mt6397_rtc_of_match[] = { 393fc297911STianping Fang { .compatible = "mediatek,mt6397-rtc", }, 394fc297911STianping Fang { } 395fc297911STianping Fang }; 39673798d5cSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, mt6397_rtc_of_match); 397fc297911STianping Fang 398fc297911STianping Fang static struct platform_driver mtk_rtc_driver = { 399fc297911STianping Fang .driver = { 400fc297911STianping Fang .name = "mt6397-rtc", 401fc297911STianping Fang .of_match_table = mt6397_rtc_of_match, 402d7f9777dSHenry Chen .pm = &mt6397_pm_ops, 403fc297911STianping Fang }, 404fc297911STianping Fang .probe = mtk_rtc_probe, 405fc297911STianping Fang .remove = mtk_rtc_remove, 406fc297911STianping Fang }; 407fc297911STianping Fang 408fc297911STianping Fang module_platform_driver(mtk_rtc_driver); 409fc297911STianping Fang 410fc297911STianping Fang MODULE_LICENSE("GPL v2"); 411fc297911STianping Fang MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>"); 412fc297911STianping Fang MODULE_DESCRIPTION("RTC Driver for MediaTek MT6397 PMIC"); 413