rtc-rzn1.c (10565B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Renesas RZ/N1 Real Time Clock interface for Linux 4 * 5 * Copyright: 6 * - 2014 Renesas Electronics Europe Limited 7 * - 2022 Schneider Electric 8 * 9 * Authors: 10 * - Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com> 11 * - Miquel Raynal <miquel.raynal@bootlin.com> 12 */ 13 14#include <linux/bcd.h> 15#include <linux/init.h> 16#include <linux/iopoll.h> 17#include <linux/module.h> 18#include <linux/of_device.h> 19#include <linux/platform_device.h> 20#include <linux/pm_runtime.h> 21#include <linux/rtc.h> 22 23#define RZN1_RTC_CTL0 0x00 24#define RZN1_RTC_CTL0_SLSB_SUBU 0 25#define RZN1_RTC_CTL0_SLSB_SCMP BIT(4) 26#define RZN1_RTC_CTL0_AMPM BIT(5) 27#define RZN1_RTC_CTL0_CE BIT(7) 28 29#define RZN1_RTC_CTL1 0x04 30#define RZN1_RTC_CTL1_ALME BIT(4) 31 32#define RZN1_RTC_CTL2 0x08 33#define RZN1_RTC_CTL2_WAIT BIT(0) 34#define RZN1_RTC_CTL2_WST BIT(1) 35#define RZN1_RTC_CTL2_WUST BIT(5) 36#define RZN1_RTC_CTL2_STOPPED (RZN1_RTC_CTL2_WAIT | RZN1_RTC_CTL2_WST) 37 38#define RZN1_RTC_SEC 0x14 39#define RZN1_RTC_MIN 0x18 40#define RZN1_RTC_HOUR 0x1c 41#define RZN1_RTC_WEEK 0x20 42#define RZN1_RTC_DAY 0x24 43#define RZN1_RTC_MONTH 0x28 44#define RZN1_RTC_YEAR 0x2c 45 46#define RZN1_RTC_SUBU 0x38 47#define RZN1_RTC_SUBU_DEV BIT(7) 48#define RZN1_RTC_SUBU_DECR BIT(6) 49 50#define RZN1_RTC_ALM 0x40 51#define RZN1_RTC_ALH 0x44 52#define RZN1_RTC_ALW 0x48 53 54#define RZN1_RTC_SECC 0x4c 55#define RZN1_RTC_MINC 0x50 56#define RZN1_RTC_HOURC 0x54 57#define RZN1_RTC_WEEKC 0x58 58#define RZN1_RTC_DAYC 0x5c 59#define RZN1_RTC_MONTHC 0x60 60#define RZN1_RTC_YEARC 0x64 61 62struct rzn1_rtc { 63 struct rtc_device *rtcdev; 64 void __iomem *base; 65}; 66 67static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm) 68{ 69 tm->tm_sec = readl(rtc->base + RZN1_RTC_SECC); 70 tm->tm_min = readl(rtc->base + RZN1_RTC_MINC); 71 tm->tm_hour = readl(rtc->base + RZN1_RTC_HOURC); 72 tm->tm_wday = readl(rtc->base + RZN1_RTC_WEEKC); 73 tm->tm_mday = readl(rtc->base + RZN1_RTC_DAYC); 74 tm->tm_mon = readl(rtc->base + RZN1_RTC_MONTHC); 75 tm->tm_year = readl(rtc->base + RZN1_RTC_YEARC); 76} 77 78static unsigned int rzn1_rtc_tm_to_wday(struct rtc_time *tm) 79{ 80 time64_t time; 81 unsigned int days; 82 u32 secs; 83 84 time = rtc_tm_to_time64(tm); 85 days = div_s64_rem(time, 86400, &secs); 86 87 /* day of the week, 1970-01-01 was a Thursday */ 88 return (days + 4) % 7; 89} 90 91static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm) 92{ 93 struct rzn1_rtc *rtc = dev_get_drvdata(dev); 94 u32 val, secs; 95 96 /* 97 * The RTC was not started or is stopped and thus does not carry the 98 * proper time/date. 99 */ 100 val = readl(rtc->base + RZN1_RTC_CTL2); 101 if (val & RZN1_RTC_CTL2_STOPPED) 102 return -EINVAL; 103 104 rzn1_rtc_get_time_snapshot(rtc, tm); 105 secs = readl(rtc->base + RZN1_RTC_SECC); 106 if (tm->tm_sec != secs) 107 rzn1_rtc_get_time_snapshot(rtc, tm); 108 109 tm->tm_sec = bcd2bin(tm->tm_sec); 110 tm->tm_min = bcd2bin(tm->tm_min); 111 tm->tm_hour = bcd2bin(tm->tm_hour); 112 tm->tm_wday = bcd2bin(tm->tm_wday); 113 tm->tm_mday = bcd2bin(tm->tm_mday); 114 tm->tm_mon = bcd2bin(tm->tm_mon); 115 tm->tm_year = bcd2bin(tm->tm_year); 116 117 return 0; 118} 119 120static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm) 121{ 122 struct rzn1_rtc *rtc = dev_get_drvdata(dev); 123 u32 val; 124 int ret; 125 126 tm->tm_sec = bin2bcd(tm->tm_sec); 127 tm->tm_min = bin2bcd(tm->tm_min); 128 tm->tm_hour = bin2bcd(tm->tm_hour); 129 tm->tm_wday = bin2bcd(rzn1_rtc_tm_to_wday(tm)); 130 tm->tm_mday = bin2bcd(tm->tm_mday); 131 tm->tm_mon = bin2bcd(tm->tm_mon); 132 tm->tm_year = bin2bcd(tm->tm_year); 133 134 val = readl(rtc->base + RZN1_RTC_CTL2); 135 if (!(val & RZN1_RTC_CTL2_STOPPED)) { 136 /* Hold the counter if it was counting up */ 137 writel(RZN1_RTC_CTL2_WAIT, rtc->base + RZN1_RTC_CTL2); 138 139 /* Wait for the counter to stop: two 32k clock cycles */ 140 usleep_range(61, 100); 141 ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, val, 142 val & RZN1_RTC_CTL2_WST, 0, 100); 143 if (ret) 144 return ret; 145 } 146 147 writel(tm->tm_sec, rtc->base + RZN1_RTC_SEC); 148 writel(tm->tm_min, rtc->base + RZN1_RTC_MIN); 149 writel(tm->tm_hour, rtc->base + RZN1_RTC_HOUR); 150 writel(tm->tm_wday, rtc->base + RZN1_RTC_WEEK); 151 writel(tm->tm_mday, rtc->base + RZN1_RTC_DAY); 152 writel(tm->tm_mon, rtc->base + RZN1_RTC_MONTH); 153 writel(tm->tm_year, rtc->base + RZN1_RTC_YEAR); 154 writel(0, rtc->base + RZN1_RTC_CTL2); 155 156 return 0; 157} 158 159static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id) 160{ 161 struct rzn1_rtc *rtc = dev_id; 162 163 rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF); 164 165 return IRQ_HANDLED; 166} 167 168static int rzn1_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) 169{ 170 struct rzn1_rtc *rtc = dev_get_drvdata(dev); 171 u32 ctl1 = readl(rtc->base + RZN1_RTC_CTL1); 172 173 if (enable) 174 ctl1 |= RZN1_RTC_CTL1_ALME; 175 else 176 ctl1 &= ~RZN1_RTC_CTL1_ALME; 177 178 writel(ctl1, rtc->base + RZN1_RTC_CTL1); 179 180 return 0; 181} 182 183static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 184{ 185 struct rzn1_rtc *rtc = dev_get_drvdata(dev); 186 struct rtc_time *tm = &alrm->time; 187 unsigned int min, hour, wday, delta_days; 188 time64_t alarm; 189 u32 ctl1; 190 int ret; 191 192 ret = rzn1_rtc_read_time(dev, tm); 193 if (ret) 194 return ret; 195 196 min = readl(rtc->base + RZN1_RTC_ALM); 197 hour = readl(rtc->base + RZN1_RTC_ALH); 198 wday = readl(rtc->base + RZN1_RTC_ALW); 199 200 tm->tm_sec = 0; 201 tm->tm_min = bcd2bin(min); 202 tm->tm_hour = bcd2bin(hour); 203 delta_days = ((fls(wday) - 1) - tm->tm_wday + 7) % 7; 204 tm->tm_wday = fls(wday) - 1; 205 206 if (delta_days) { 207 alarm = rtc_tm_to_time64(tm) + (delta_days * 86400); 208 rtc_time64_to_tm(alarm, tm); 209 } 210 211 ctl1 = readl(rtc->base + RZN1_RTC_CTL1); 212 alrm->enabled = !!(ctl1 & RZN1_RTC_CTL1_ALME); 213 214 return 0; 215} 216 217static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 218{ 219 struct rzn1_rtc *rtc = dev_get_drvdata(dev); 220 struct rtc_time *tm = &alrm->time, tm_now; 221 unsigned long alarm, farest; 222 unsigned int days_ahead, wday; 223 int ret; 224 225 ret = rzn1_rtc_read_time(dev, &tm_now); 226 if (ret) 227 return ret; 228 229 /* We cannot set alarms more than one week ahead */ 230 farest = rtc_tm_to_time64(&tm_now) + (7 * 86400); 231 alarm = rtc_tm_to_time64(tm); 232 if (time_after(alarm, farest)) 233 return -ERANGE; 234 235 /* Convert alarm day into week day */ 236 days_ahead = tm->tm_mday - tm_now.tm_mday; 237 wday = (tm_now.tm_wday + days_ahead) % 7; 238 239 writel(bin2bcd(tm->tm_min), rtc->base + RZN1_RTC_ALM); 240 writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH); 241 writel(BIT(wday), rtc->base + RZN1_RTC_ALW); 242 243 rzn1_rtc_alarm_irq_enable(dev, alrm->enabled); 244 245 return 0; 246} 247 248static int rzn1_rtc_read_offset(struct device *dev, long *offset) 249{ 250 struct rzn1_rtc *rtc = dev_get_drvdata(dev); 251 unsigned int ppb_per_step; 252 bool subtract; 253 u32 val; 254 255 val = readl(rtc->base + RZN1_RTC_SUBU); 256 ppb_per_step = val & RZN1_RTC_SUBU_DEV ? 1017 : 3051; 257 subtract = val & RZN1_RTC_SUBU_DECR; 258 val &= 0x3F; 259 260 if (!val) 261 *offset = 0; 262 else if (subtract) 263 *offset = -(((~val) & 0x3F) + 1) * ppb_per_step; 264 else 265 *offset = (val - 1) * ppb_per_step; 266 267 return 0; 268} 269 270static int rzn1_rtc_set_offset(struct device *dev, long offset) 271{ 272 struct rzn1_rtc *rtc = dev_get_drvdata(dev); 273 int stepsh, stepsl, steps; 274 u32 subu = 0, ctl2; 275 int ret; 276 277 /* 278 * Check which resolution mode (every 20 or 60s) can be used. 279 * Between 2 and 124 clock pulses can be added or substracted. 280 * 281 * In 20s mode, the minimum resolution is 2 / (32768 * 20) which is 282 * close to 3051 ppb. In 60s mode, the resolution is closer to 1017. 283 */ 284 stepsh = DIV_ROUND_CLOSEST(offset, 1017); 285 stepsl = DIV_ROUND_CLOSEST(offset, 3051); 286 287 if (stepsh >= -0x3E && stepsh <= 0x3E) { 288 /* 1017 ppb per step */ 289 steps = stepsh; 290 subu |= RZN1_RTC_SUBU_DEV; 291 } else if (stepsl >= -0x3E && stepsl <= 0x3E) { 292 /* 3051 ppb per step */ 293 steps = stepsl; 294 } else { 295 return -ERANGE; 296 } 297 298 if (!steps) 299 return 0; 300 301 if (steps > 0) { 302 subu |= steps + 1; 303 } else { 304 subu |= RZN1_RTC_SUBU_DECR; 305 subu |= (~(-steps - 1)) & 0x3F; 306 } 307 308 ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, ctl2, 309 !(ctl2 & RZN1_RTC_CTL2_WUST), 100, 2000000); 310 if (ret) 311 return ret; 312 313 writel(subu, rtc->base + RZN1_RTC_SUBU); 314 315 return 0; 316} 317 318static const struct rtc_class_ops rzn1_rtc_ops = { 319 .read_time = rzn1_rtc_read_time, 320 .set_time = rzn1_rtc_set_time, 321 .read_alarm = rzn1_rtc_read_alarm, 322 .set_alarm = rzn1_rtc_set_alarm, 323 .alarm_irq_enable = rzn1_rtc_alarm_irq_enable, 324 .read_offset = rzn1_rtc_read_offset, 325 .set_offset = rzn1_rtc_set_offset, 326}; 327 328static int rzn1_rtc_probe(struct platform_device *pdev) 329{ 330 struct rzn1_rtc *rtc; 331 int alarm_irq; 332 int ret; 333 334 rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); 335 if (!rtc) 336 return -ENOMEM; 337 338 platform_set_drvdata(pdev, rtc); 339 340 rtc->base = devm_platform_ioremap_resource(pdev, 0); 341 if (IS_ERR(rtc->base)) 342 return dev_err_probe(&pdev->dev, PTR_ERR(rtc->base), "Missing reg\n"); 343 344 alarm_irq = platform_get_irq(pdev, 0); 345 if (alarm_irq < 0) 346 return alarm_irq; 347 348 rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev); 349 if (IS_ERR(rtc->rtcdev)) 350 return PTR_ERR(rtc->rtcdev); 351 352 rtc->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000; 353 rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099; 354 rtc->rtcdev->ops = &rzn1_rtc_ops; 355 set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features); 356 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features); 357 358 devm_pm_runtime_enable(&pdev->dev); 359 ret = pm_runtime_resume_and_get(&pdev->dev); 360 if (ret < 0) 361 return ret; 362 363 /* 364 * Ensure the clock counter is enabled. 365 * Set 24-hour mode and possible oscillator offset compensation in SUBU mode. 366 */ 367 writel(RZN1_RTC_CTL0_CE | RZN1_RTC_CTL0_AMPM | RZN1_RTC_CTL0_SLSB_SUBU, 368 rtc->base + RZN1_RTC_CTL0); 369 370 /* Disable all interrupts */ 371 writel(0, rtc->base + RZN1_RTC_CTL1); 372 373 ret = devm_request_irq(&pdev->dev, alarm_irq, rzn1_rtc_alarm_irq, 0, 374 dev_name(&pdev->dev), rtc); 375 if (ret) { 376 dev_err(&pdev->dev, "RTC timer interrupt not available\n"); 377 goto dis_runtime_pm; 378 } 379 380 ret = devm_rtc_register_device(rtc->rtcdev); 381 if (ret) 382 goto dis_runtime_pm; 383 384 return 0; 385 386dis_runtime_pm: 387 pm_runtime_put(&pdev->dev); 388 389 return ret; 390} 391 392static int rzn1_rtc_remove(struct platform_device *pdev) 393{ 394 pm_runtime_put(&pdev->dev); 395 396 return 0; 397} 398 399static const struct of_device_id rzn1_rtc_of_match[] = { 400 { .compatible = "renesas,rzn1-rtc" }, 401 {}, 402}; 403MODULE_DEVICE_TABLE(of, rzn1_rtc_of_match); 404 405static struct platform_driver rzn1_rtc_driver = { 406 .probe = rzn1_rtc_probe, 407 .remove = rzn1_rtc_remove, 408 .driver = { 409 .name = "rzn1-rtc", 410 .of_match_table = rzn1_rtc_of_match, 411 }, 412}; 413module_platform_driver(rzn1_rtc_driver); 414 415MODULE_AUTHOR("Michel Pollet <Michel.Pollet@bp.renesas.com"); 416MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com"); 417MODULE_DESCRIPTION("RZ/N1 RTC driver"); 418MODULE_LICENSE("GPL");