Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtc: mediatek: Add MT6397 RTC driver

Add Mediatek MT6397 RTC driver

Signed-off-by: Tianping Fang <tianping.fang@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>

authored by

Tianping Fang and committed by
Alexandre Belloni
fc297911 a5d7ea09

+405
+10
drivers/rtc/Kconfig
··· 1530 1530 This driver can also be built as a module. If so, the module 1531 1531 will be called rtc-moxart 1532 1532 1533 + config RTC_DRV_MT6397 1534 + tristate "Mediatek Real Time Clock driver" 1535 + depends on MFD_MT6397 || COMPILE_TEST 1536 + help 1537 + This selects the Mediatek(R) RTC driver. RTC is part of Mediatek 1538 + MT6397 PMIC. You should enable MT6397 PMIC MFD before select 1539 + Mediatek(R) RTC driver. 1540 + 1541 + If you want to use Mediatek(R) RTC interface, select Y or M here. 1542 + 1533 1543 config RTC_DRV_XGENE 1534 1544 tristate "APM X-Gene RTC" 1535 1545 depends on HAS_IOMEM
+1
drivers/rtc/Makefile
··· 155 155 obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o 156 156 obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o 157 157 obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o 158 + obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o
+394
drivers/rtc/rtc-mt6397.c
··· 1 + /* 2 + * Copyright (c) 2014-2015 MediaTek Inc. 3 + * Author: Tianping.Fang <tianping.fang@mediatek.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + */ 14 + 15 + #include <linux/delay.h> 16 + #include <linux/init.h> 17 + #include <linux/module.h> 18 + #include <linux/regmap.h> 19 + #include <linux/rtc.h> 20 + #include <linux/irqdomain.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/of_address.h> 23 + #include <linux/of_irq.h> 24 + #include <linux/io.h> 25 + #include <linux/mfd/mt6397/core.h> 26 + 27 + #define RTC_BBPU 0x0000 28 + #define RTC_BBPU_CBUSY BIT(6) 29 + 30 + #define RTC_WRTGR 0x003c 31 + 32 + #define RTC_IRQ_STA 0x0002 33 + #define RTC_IRQ_STA_AL BIT(0) 34 + #define RTC_IRQ_STA_LP BIT(3) 35 + 36 + #define RTC_IRQ_EN 0x0004 37 + #define RTC_IRQ_EN_AL BIT(0) 38 + #define RTC_IRQ_EN_ONESHOT BIT(2) 39 + #define RTC_IRQ_EN_LP BIT(3) 40 + #define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL) 41 + 42 + #define RTC_AL_MASK 0x0008 43 + #define RTC_AL_MASK_DOW BIT(4) 44 + 45 + #define RTC_TC_SEC 0x000a 46 + /* Min, Hour, Dom... register offset to RTC_TC_SEC */ 47 + #define RTC_OFFSET_SEC 0 48 + #define RTC_OFFSET_MIN 1 49 + #define RTC_OFFSET_HOUR 2 50 + #define RTC_OFFSET_DOM 3 51 + #define RTC_OFFSET_DOW 4 52 + #define RTC_OFFSET_MTH 5 53 + #define RTC_OFFSET_YEAR 6 54 + #define RTC_OFFSET_COUNT 7 55 + 56 + #define RTC_AL_SEC 0x0018 57 + 58 + #define RTC_PDN2 0x002e 59 + #define RTC_PDN2_PWRON_ALARM BIT(4) 60 + 61 + #define RTC_MIN_YEAR 1968 62 + #define RTC_BASE_YEAR 1900 63 + #define RTC_NUM_YEARS 128 64 + #define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR) 65 + 66 + struct mt6397_rtc { 67 + struct device *dev; 68 + struct rtc_device *rtc_dev; 69 + struct mutex lock; 70 + struct regmap *regmap; 71 + int irq; 72 + u32 addr_base; 73 + }; 74 + 75 + static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc) 76 + { 77 + unsigned long timeout = jiffies + HZ; 78 + int ret; 79 + u32 data; 80 + 81 + ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_WRTGR, 1); 82 + if (ret < 0) 83 + return ret; 84 + 85 + while (1) { 86 + ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_BBPU, 87 + &data); 88 + if (ret < 0) 89 + break; 90 + if (!(data & RTC_BBPU_CBUSY)) 91 + break; 92 + if (time_after(jiffies, timeout)) { 93 + ret = -ETIMEDOUT; 94 + break; 95 + } 96 + cpu_relax(); 97 + } 98 + 99 + return ret; 100 + } 101 + 102 + static irqreturn_t mtk_rtc_irq_handler_thread(int irq, void *data) 103 + { 104 + struct mt6397_rtc *rtc = data; 105 + u32 irqsta, irqen; 106 + int ret; 107 + 108 + ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_STA, &irqsta); 109 + if ((ret >= 0) && (irqsta & RTC_IRQ_STA_AL)) { 110 + rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); 111 + irqen = irqsta & ~RTC_IRQ_EN_AL; 112 + mutex_lock(&rtc->lock); 113 + if (regmap_write(rtc->regmap, rtc->addr_base + RTC_IRQ_EN, 114 + irqen) < 0) 115 + mtk_rtc_write_trigger(rtc); 116 + mutex_unlock(&rtc->lock); 117 + 118 + return IRQ_HANDLED; 119 + } 120 + 121 + return IRQ_NONE; 122 + } 123 + 124 + static int __mtk_rtc_read_time(struct mt6397_rtc *rtc, 125 + struct rtc_time *tm, int *sec) 126 + { 127 + int ret; 128 + u16 data[RTC_OFFSET_COUNT]; 129 + 130 + mutex_lock(&rtc->lock); 131 + ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC, 132 + data, RTC_OFFSET_COUNT); 133 + if (ret < 0) 134 + goto exit; 135 + 136 + tm->tm_sec = data[RTC_OFFSET_SEC]; 137 + tm->tm_min = data[RTC_OFFSET_MIN]; 138 + tm->tm_hour = data[RTC_OFFSET_HOUR]; 139 + tm->tm_mday = data[RTC_OFFSET_DOM]; 140 + tm->tm_mon = data[RTC_OFFSET_MTH]; 141 + tm->tm_year = data[RTC_OFFSET_YEAR]; 142 + 143 + ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC, sec); 144 + exit: 145 + mutex_unlock(&rtc->lock); 146 + return ret; 147 + } 148 + 149 + static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm) 150 + { 151 + time64_t time; 152 + struct mt6397_rtc *rtc = dev_get_drvdata(dev); 153 + int sec, ret; 154 + 155 + do { 156 + ret = __mtk_rtc_read_time(rtc, tm, &sec); 157 + if (ret < 0) 158 + goto exit; 159 + } while (sec < tm->tm_sec); 160 + 161 + /* HW register use 7 bits to store year data, minus 162 + * RTC_MIN_YEAR_OFFSET before write year data to register, and plus 163 + * RTC_MIN_YEAR_OFFSET back after read year from register 164 + */ 165 + tm->tm_year += RTC_MIN_YEAR_OFFSET; 166 + 167 + /* HW register start mon from one, but tm_mon start from zero. */ 168 + tm->tm_mon--; 169 + time = rtc_tm_to_time64(tm); 170 + 171 + /* rtc_tm_to_time64 covert Gregorian date to seconds since 172 + * 01-01-1970 00:00:00, and this date is Thursday. 173 + */ 174 + tm->tm_wday = (time / 86400 + 4) % 7; 175 + 176 + exit: 177 + return ret; 178 + } 179 + 180 + static int mtk_rtc_set_time(struct device *dev, struct rtc_time *tm) 181 + { 182 + struct mt6397_rtc *rtc = dev_get_drvdata(dev); 183 + int ret; 184 + u16 data[RTC_OFFSET_COUNT]; 185 + 186 + tm->tm_year -= RTC_MIN_YEAR_OFFSET; 187 + tm->tm_mon++; 188 + 189 + data[RTC_OFFSET_SEC] = tm->tm_sec; 190 + data[RTC_OFFSET_MIN] = tm->tm_min; 191 + data[RTC_OFFSET_HOUR] = tm->tm_hour; 192 + data[RTC_OFFSET_DOM] = tm->tm_mday; 193 + data[RTC_OFFSET_MTH] = tm->tm_mon; 194 + data[RTC_OFFSET_YEAR] = tm->tm_year; 195 + 196 + mutex_lock(&rtc->lock); 197 + ret = regmap_bulk_write(rtc->regmap, rtc->addr_base + RTC_TC_SEC, 198 + data, RTC_OFFSET_COUNT); 199 + if (ret < 0) 200 + goto exit; 201 + 202 + /* Time register write to hardware after call trigger function */ 203 + ret = mtk_rtc_write_trigger(rtc); 204 + 205 + exit: 206 + mutex_unlock(&rtc->lock); 207 + return ret; 208 + } 209 + 210 + static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 211 + { 212 + struct rtc_time *tm = &alm->time; 213 + struct mt6397_rtc *rtc = dev_get_drvdata(dev); 214 + u32 irqen, pdn2; 215 + int ret; 216 + u16 data[RTC_OFFSET_COUNT]; 217 + 218 + mutex_lock(&rtc->lock); 219 + ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_EN, &irqen); 220 + if (ret < 0) 221 + goto err_exit; 222 + ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_PDN2, &pdn2); 223 + if (ret < 0) 224 + goto err_exit; 225 + 226 + ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_AL_SEC, 227 + data, RTC_OFFSET_COUNT); 228 + if (ret < 0) 229 + goto err_exit; 230 + 231 + alm->enabled = !!(irqen & RTC_IRQ_EN_AL); 232 + alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM); 233 + mutex_unlock(&rtc->lock); 234 + 235 + tm->tm_sec = data[RTC_OFFSET_SEC]; 236 + tm->tm_min = data[RTC_OFFSET_MIN]; 237 + tm->tm_hour = data[RTC_OFFSET_HOUR]; 238 + tm->tm_mday = data[RTC_OFFSET_DOM]; 239 + tm->tm_mon = data[RTC_OFFSET_MTH]; 240 + tm->tm_year = data[RTC_OFFSET_YEAR]; 241 + 242 + tm->tm_year += RTC_MIN_YEAR_OFFSET; 243 + tm->tm_mon--; 244 + 245 + return 0; 246 + err_exit: 247 + mutex_unlock(&rtc->lock); 248 + return ret; 249 + } 250 + 251 + static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 252 + { 253 + struct rtc_time *tm = &alm->time; 254 + struct mt6397_rtc *rtc = dev_get_drvdata(dev); 255 + int ret; 256 + u16 data[RTC_OFFSET_COUNT]; 257 + 258 + tm->tm_year -= RTC_MIN_YEAR_OFFSET; 259 + tm->tm_mon++; 260 + 261 + data[RTC_OFFSET_SEC] = tm->tm_sec; 262 + data[RTC_OFFSET_MIN] = tm->tm_min; 263 + data[RTC_OFFSET_HOUR] = tm->tm_hour; 264 + data[RTC_OFFSET_DOM] = tm->tm_mday; 265 + data[RTC_OFFSET_MTH] = tm->tm_mon; 266 + data[RTC_OFFSET_YEAR] = tm->tm_year; 267 + 268 + mutex_lock(&rtc->lock); 269 + if (alm->enabled) { 270 + ret = regmap_bulk_write(rtc->regmap, 271 + rtc->addr_base + RTC_AL_SEC, 272 + data, RTC_OFFSET_COUNT); 273 + if (ret < 0) 274 + goto exit; 275 + ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_AL_MASK, 276 + RTC_AL_MASK_DOW); 277 + if (ret < 0) 278 + goto exit; 279 + ret = regmap_update_bits(rtc->regmap, 280 + rtc->addr_base + RTC_IRQ_EN, 281 + RTC_IRQ_EN_ONESHOT_AL, 282 + RTC_IRQ_EN_ONESHOT_AL); 283 + if (ret < 0) 284 + goto exit; 285 + } else { 286 + ret = regmap_update_bits(rtc->regmap, 287 + rtc->addr_base + RTC_IRQ_EN, 288 + RTC_IRQ_EN_ONESHOT_AL, 0); 289 + if (ret < 0) 290 + goto exit; 291 + } 292 + 293 + /* All alarm time register write to hardware after calling 294 + * mtk_rtc_write_trigger. This can avoid race condition if alarm 295 + * occur happen during writing alarm time register. 296 + */ 297 + ret = mtk_rtc_write_trigger(rtc); 298 + exit: 299 + mutex_unlock(&rtc->lock); 300 + return ret; 301 + } 302 + 303 + static struct rtc_class_ops mtk_rtc_ops = { 304 + .read_time = mtk_rtc_read_time, 305 + .set_time = mtk_rtc_set_time, 306 + .read_alarm = mtk_rtc_read_alarm, 307 + .set_alarm = mtk_rtc_set_alarm, 308 + }; 309 + 310 + static int mtk_rtc_probe(struct platform_device *pdev) 311 + { 312 + struct resource *res; 313 + struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent); 314 + struct mt6397_rtc *rtc; 315 + int ret; 316 + 317 + rtc = devm_kzalloc(&pdev->dev, sizeof(struct mt6397_rtc), GFP_KERNEL); 318 + if (!rtc) 319 + return -ENOMEM; 320 + 321 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 322 + rtc->addr_base = res->start; 323 + 324 + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 325 + rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start); 326 + if (rtc->irq <= 0) 327 + return -EINVAL; 328 + 329 + rtc->regmap = mt6397_chip->regmap; 330 + rtc->dev = &pdev->dev; 331 + mutex_init(&rtc->lock); 332 + 333 + platform_set_drvdata(pdev, rtc); 334 + 335 + ret = request_threaded_irq(rtc->irq, NULL, 336 + mtk_rtc_irq_handler_thread, 337 + IRQF_ONESHOT | IRQF_TRIGGER_HIGH, 338 + "mt6397-rtc", rtc); 339 + if (ret) { 340 + dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", 341 + rtc->irq, ret); 342 + goto out_dispose_irq; 343 + } 344 + 345 + rtc->rtc_dev = rtc_device_register("mt6397-rtc", &pdev->dev, 346 + &mtk_rtc_ops, THIS_MODULE); 347 + if (IS_ERR(rtc->rtc_dev)) { 348 + dev_err(&pdev->dev, "register rtc device failed\n"); 349 + ret = PTR_ERR(rtc->rtc_dev); 350 + goto out_free_irq; 351 + } 352 + 353 + device_init_wakeup(&pdev->dev, 1); 354 + 355 + return 0; 356 + 357 + out_free_irq: 358 + free_irq(rtc->irq, rtc->rtc_dev); 359 + out_dispose_irq: 360 + irq_dispose_mapping(rtc->irq); 361 + return ret; 362 + } 363 + 364 + static int mtk_rtc_remove(struct platform_device *pdev) 365 + { 366 + struct mt6397_rtc *rtc = platform_get_drvdata(pdev); 367 + 368 + rtc_device_unregister(rtc->rtc_dev); 369 + free_irq(rtc->irq, rtc->rtc_dev); 370 + irq_dispose_mapping(rtc->irq); 371 + 372 + return 0; 373 + } 374 + 375 + static const struct of_device_id mt6397_rtc_of_match[] = { 376 + { .compatible = "mediatek,mt6397-rtc", }, 377 + { } 378 + }; 379 + 380 + static struct platform_driver mtk_rtc_driver = { 381 + .driver = { 382 + .name = "mt6397-rtc", 383 + .of_match_table = mt6397_rtc_of_match, 384 + }, 385 + .probe = mtk_rtc_probe, 386 + .remove = mtk_rtc_remove, 387 + }; 388 + 389 + module_platform_driver(mtk_rtc_driver); 390 + 391 + MODULE_LICENSE("GPL v2"); 392 + MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>"); 393 + MODULE_DESCRIPTION("RTC Driver for MediaTek MT6397 PMIC"); 394 + MODULE_ALIAS("platform:mt6397-rtc");