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

rtc: rtc-ab-b5ze-s3: add sub-minute alarm support

Abracon AB-RTCMC-32.768kHz-B5ZE-S3 alarm is only accurate to the minute.
For that reason, UIE mode is currently not supported by the driver. But
the device provides a watchdog timer which can be coupled with the alarm
mechanism to extend support and provide sub-minute alarm capability.

This patch implements that extension. More precisely, it makes use of the
watchdog timer for alarms which are less that four minutes in the future
(with second accuracy) and use standard alarm mechanism for other alarms
(with minute accuracy).

Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Peter Huewe <peter.huewe@infineon.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Thierry Reding <treding@nvidia.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robherring2@gmail.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Landley <rob@landley.net>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Kumar Gala <galak@codeaurora.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Arnaud Ebalard and committed by
Linus Torvalds
c8a1d8a5 0b2f6228

+263 -30
+263 -30
drivers/rtc/rtc-ab-b5ze-s3.c
··· 133 133 int irq; 134 134 135 135 bool battery_low; 136 + bool timer_alarm; /* current alarm is via timer A */ 136 137 }; 137 138 138 139 /* ··· 188 187 enable ? ABB5ZES3_REG_CTRL1_AIE : 0); 189 188 if (ret) 190 189 dev_err(dev, "%s: writing alarm INT failed (%d)\n", 190 + __func__, ret); 191 + 192 + return ret; 193 + } 194 + 195 + /* Enable or disable timer (watchdog timer A interrupt generation) */ 196 + static int _abb5zes3_rtc_update_timer(struct device *dev, bool enable) 197 + { 198 + struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 199 + int ret; 200 + 201 + ret = regmap_update_bits(data->regmap, ABB5ZES3_REG_CTRL2, 202 + ABB5ZES3_REG_CTRL2_WTAIE, 203 + enable ? ABB5ZES3_REG_CTRL2_WTAIE : 0); 204 + if (ret) 205 + dev_err(dev, "%s: writing timer INT failed (%d)\n", 191 206 __func__, ret); 192 207 193 208 return ret; ··· 294 277 return ret; 295 278 } 296 279 297 - static int abb5zes3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) 280 + /* 281 + * Set provided TAQ and Timer A registers (TIMA_CLK and TIMA) based on 282 + * given number of seconds. 283 + */ 284 + static inline void sec_to_timer_a(u8 secs, u8 *taq, u8 *timer_a) 285 + { 286 + *taq = ABB5ZES3_REG_TIMA_CLK_TAQ1; /* 1Hz */ 287 + *timer_a = secs; 288 + } 289 + 290 + /* 291 + * Return current number of seconds in Timer A. As we only use 292 + * timer A with a 1Hz freq, this is what we expect to have. 293 + */ 294 + static inline int sec_from_timer_a(u8 *secs, u8 taq, u8 timer_a) 295 + { 296 + if (taq != ABB5ZES3_REG_TIMA_CLK_TAQ1) /* 1Hz */ 297 + return -EINVAL; 298 + 299 + *secs = timer_a; 300 + 301 + return 0; 302 + } 303 + 304 + /* 305 + * Read alarm currently configured via a watchdog timer using timer A. This 306 + * is done by reading current RTC time and adding remaining timer time. 307 + */ 308 + static int _abb5zes3_rtc_read_timer(struct device *dev, 309 + struct rtc_wkalrm *alarm) 310 + { 311 + struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 312 + struct rtc_time rtc_tm, *alarm_tm = &alarm->time; 313 + u8 regs[ABB5ZES3_TIMA_SEC_LEN + 1]; 314 + unsigned long rtc_secs; 315 + unsigned int reg; 316 + u8 timer_secs; 317 + int ret; 318 + 319 + /* 320 + * Instead of doing two separate calls, because they are consecutive, 321 + * we grab both clockout register and Timer A section. The latter is 322 + * used to decide if timer A is enabled (as a watchdog timer). 323 + */ 324 + ret = regmap_bulk_read(data->regmap, ABB5ZES3_REG_TIM_CLK, regs, 325 + ABB5ZES3_TIMA_SEC_LEN + 1); 326 + if (ret) { 327 + dev_err(dev, "%s: reading Timer A section failed (%d)\n", 328 + __func__, ret); 329 + goto err; 330 + } 331 + 332 + /* get current time ... */ 333 + ret = _abb5zes3_rtc_read_time(dev, &rtc_tm); 334 + if (ret) 335 + goto err; 336 + 337 + /* ... convert to seconds ... */ 338 + ret = rtc_tm_to_time(&rtc_tm, &rtc_secs); 339 + if (ret) 340 + goto err; 341 + 342 + /* ... add remaining timer A time ... */ 343 + ret = sec_from_timer_a(&timer_secs, regs[1], regs[2]); 344 + if (ret) 345 + goto err; 346 + 347 + /* ... and convert back. */ 348 + rtc_time_to_tm(rtc_secs + timer_secs, alarm_tm); 349 + 350 + ret = regmap_read(data->regmap, ABB5ZES3_REG_CTRL2, &reg); 351 + if (ret) { 352 + dev_err(dev, "%s: reading ctrl reg failed (%d)\n", 353 + __func__, ret); 354 + goto err; 355 + } 356 + 357 + alarm->enabled = !!(reg & ABB5ZES3_REG_CTRL2_WTAIE); 358 + 359 + err: 360 + return ret; 361 + } 362 + 363 + /* Read alarm currently configured via a RTC alarm registers. */ 364 + static int _abb5zes3_rtc_read_alarm(struct device *dev, 365 + struct rtc_wkalrm *alarm) 298 366 { 299 367 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 300 368 struct rtc_time rtc_tm, *alarm_tm = &alarm->time; ··· 388 286 unsigned int reg; 389 287 int ret; 390 288 391 - mutex_lock(&data->lock); 392 289 ret = regmap_bulk_read(data->regmap, ABB5ZES3_REG_ALRM_MN, regs, 393 290 ABB5ZES3_ALRM_SEC_LEN); 394 291 if (ret) { ··· 441 340 alarm->enabled = !!(reg & ABB5ZES3_REG_CTRL1_AIE); 442 341 443 342 err: 343 + return ret; 344 + } 345 + 346 + /* 347 + * As the Alarm mechanism supported by the chip is only accurate to the 348 + * minute, we use the watchdog timer mechanism provided by timer A 349 + * (up to 256 seconds w/ a second accuracy) for low alarm values (below 350 + * 4 minutes). Otherwise, we use the common alarm mechanism provided 351 + * by the chip. In order for that to work, we keep track of currently 352 + * configured timer type via 'timer_alarm' flag in our private data 353 + * structure. 354 + */ 355 + static int abb5zes3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) 356 + { 357 + struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 358 + int ret; 359 + 360 + mutex_lock(&data->lock); 361 + if (data->timer_alarm) 362 + ret = _abb5zes3_rtc_read_timer(dev, alarm); 363 + else 364 + ret = _abb5zes3_rtc_read_alarm(dev, alarm); 444 365 mutex_unlock(&data->lock); 445 366 446 367 return ret; 447 368 } 448 369 449 - /* ALARM is only accurate to the minute (not the second) */ 450 - static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) 370 + /* 371 + * Set alarm using chip alarm mechanism. It is only accurate to the 372 + * minute (not the second). The function expects alarm interrupt to 373 + * be disabled. 374 + */ 375 + static int _abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) 451 376 { 452 377 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 453 378 struct rtc_time *alarm_tm = &alarm->time; ··· 482 355 struct rtc_time rtc_tm; 483 356 int ret, enable = 1; 484 357 485 - mutex_lock(&data->lock); 486 358 ret = _abb5zes3_rtc_read_time(dev, &rtc_tm); 487 359 if (ret) 488 360 goto err; ··· 523 397 } 524 398 } 525 399 526 - /* Disable the alarm before modifying it */ 527 - ret = _abb5zes3_rtc_update_alarm(dev, 0); 528 - if (ret < 0) { 529 - dev_err(dev, "%s: unable to disable the alarm (%d)\n", 530 - __func__, ret); 531 - goto err; 532 - } 533 - 534 - /* Program alarm registers */ 535 - regs[0] = bin2bcd(alarm_tm->tm_min) & 0x7f; /* minute */ 536 - regs[1] = bin2bcd(alarm_tm->tm_hour) & 0x3f; /* hour */ 537 - regs[2] = bin2bcd(alarm_tm->tm_mday) & 0x3f; /* day of the month */ 400 + /* 401 + * Program all alarm registers but DW one. For each register, setting 402 + * MSB to 0 enables associated alarm. 403 + */ 404 + regs[0] = bin2bcd(alarm_tm->tm_min) & 0x7f; 405 + regs[1] = bin2bcd(alarm_tm->tm_hour) & 0x3f; 406 + regs[2] = bin2bcd(alarm_tm->tm_mday) & 0x3f; 538 407 regs[3] = ABB5ZES3_REG_ALRM_DW_AE; /* do not match day of the week */ 539 408 540 409 ret = regmap_bulk_write(data->regmap, ABB5ZES3_REG_ALRM_MN, regs, ··· 540 419 goto err; 541 420 } 542 421 543 - /* Enable or disable alarm */ 422 + /* Record currently configured alarm is not a timer */ 423 + data->timer_alarm = 0; 424 + 425 + /* Enable or disable alarm interrupt generation */ 544 426 ret = _abb5zes3_rtc_update_alarm(dev, enable); 545 427 546 428 err: 547 - mutex_unlock(&data->lock); 548 - 549 429 return ret; 550 430 } 551 431 432 + /* 433 + * Set alarm using timer watchdog (via timer A) mechanism. The function expects 434 + * timer A interrupt to be disabled. 435 + */ 436 + static int _abb5zes3_rtc_set_timer(struct device *dev, struct rtc_wkalrm *alarm, 437 + u8 secs) 438 + { 439 + struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 440 + u8 regs[ABB5ZES3_TIMA_SEC_LEN]; 441 + u8 mask = ABB5ZES3_REG_TIM_CLK_TAC0 | ABB5ZES3_REG_TIM_CLK_TAC1; 442 + int ret = 0; 443 + 444 + /* Program given number of seconds to Timer A registers */ 445 + sec_to_timer_a(secs, &regs[0], &regs[1]); 446 + ret = regmap_bulk_write(data->regmap, ABB5ZES3_REG_TIMA_CLK, regs, 447 + ABB5ZES3_TIMA_SEC_LEN); 448 + if (ret < 0) { 449 + dev_err(dev, "%s: writing timer section failed\n", __func__); 450 + goto err; 451 + } 452 + 453 + /* Configure Timer A as a watchdog timer */ 454 + ret = regmap_update_bits(data->regmap, ABB5ZES3_REG_TIM_CLK, 455 + mask, ABB5ZES3_REG_TIM_CLK_TAC1); 456 + if (ret) 457 + dev_err(dev, "%s: failed to update timer\n", __func__); 458 + 459 + /* Record currently configured alarm is a timer */ 460 + data->timer_alarm = 1; 461 + 462 + /* Enable or disable timer interrupt generation */ 463 + ret = _abb5zes3_rtc_update_timer(dev, alarm->enabled); 464 + 465 + err: 466 + return ret; 467 + } 468 + 469 + /* 470 + * The chip has an alarm which is only accurate to the minute. In order to 471 + * handle alarms below that limit, we use the watchdog timer function of 472 + * timer A. More precisely, the timer method is used for alarms below 240 473 + * seconds. 474 + */ 475 + static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) 476 + { 477 + struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 478 + struct rtc_time *alarm_tm = &alarm->time; 479 + unsigned long rtc_secs, alarm_secs; 480 + struct rtc_time rtc_tm; 481 + int ret; 482 + 483 + mutex_lock(&data->lock); 484 + ret = _abb5zes3_rtc_read_time(dev, &rtc_tm); 485 + if (ret) 486 + goto err; 487 + 488 + ret = rtc_tm_to_time(&rtc_tm, &rtc_secs); 489 + if (ret) 490 + goto err; 491 + 492 + ret = rtc_tm_to_time(alarm_tm, &alarm_secs); 493 + if (ret) 494 + goto err; 495 + 496 + /* Let's first disable both the alarm and the timer interrupts */ 497 + ret = _abb5zes3_rtc_update_alarm(dev, false); 498 + if (ret < 0) { 499 + dev_err(dev, "%s: unable to disable alarm (%d)\n", __func__, 500 + ret); 501 + goto err; 502 + } 503 + ret = _abb5zes3_rtc_update_timer(dev, false); 504 + if (ret < 0) { 505 + dev_err(dev, "%s: unable to disable timer (%d)\n", __func__, 506 + ret); 507 + goto err; 508 + } 509 + 510 + data->timer_alarm = 0; 511 + 512 + /* 513 + * Let's now configure the alarm; if we are expected to ring in 514 + * more than 240s, then we setup an alarm. Otherwise, a timer. 515 + */ 516 + if ((alarm_secs > rtc_secs) && ((alarm_secs - rtc_secs) <= 240)) 517 + ret = _abb5zes3_rtc_set_timer(dev, alarm, 518 + alarm_secs - rtc_secs); 519 + else 520 + ret = _abb5zes3_rtc_set_alarm(dev, alarm); 521 + 522 + err: 523 + mutex_unlock(&data->lock); 524 + 525 + if (ret) 526 + dev_err(dev, "%s: unable to configure alarm (%d)\n", __func__, 527 + ret); 528 + 529 + return ret; 530 + } 552 531 553 532 /* Enable or disable battery low irq generation */ 554 533 static inline int _abb5zes3_rtc_battery_low_irq_enable(struct regmap *regmap, ··· 667 446 static int abb5zes3_rtc_check_setup(struct device *dev) 668 447 { 669 448 struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); 670 - struct regmap *regmap = data->regmap; 449 + struct regmap *regmap = data->regmap; 671 450 unsigned int reg; 672 451 int ret; 673 452 u8 mask; ··· 800 579 801 580 if (rtc_data->irq) { 802 581 mutex_lock(&rtc_data->lock); 803 - ret = _abb5zes3_rtc_update_alarm(dev, enable); 582 + if (rtc_data->timer_alarm) 583 + ret = _abb5zes3_rtc_update_timer(dev, enable); 584 + else 585 + ret = _abb5zes3_rtc_update_alarm(dev, enable); 804 586 mutex_unlock(&rtc_data->lock); 805 587 } 806 588 ··· 849 625 /* Acknowledge and disable the alarm */ 850 626 _abb5zes3_rtc_clear_alarm(dev); 851 627 _abb5zes3_rtc_update_alarm(dev, 0); 628 + 629 + handled = IRQ_HANDLED; 630 + } 631 + 632 + /* Check watchdog Timer A flag */ 633 + if (regs[ABB5ZES3_REG_CTRL2] & ABB5ZES3_REG_CTRL2_WTAF) { 634 + dev_dbg(dev, "RTC timer!\n"); 635 + 636 + rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); 637 + 638 + /* 639 + * Acknowledge and disable the alarm. Note: WTAF 640 + * flag had been cleared when reading CTRL2 641 + */ 642 + _abb5zes3_rtc_update_timer(dev, 0); 643 + 644 + rtc_data->timer_alarm = 0; 852 645 853 646 handled = IRQ_HANDLED; 854 647 } ··· 952 711 __func__, ret); 953 712 goto err; 954 713 } 955 - 956 - /* 957 - * AB-B5Z5E only supports a coarse granularity alarm (one minute 958 - * resolution up to one month) so we cannot support UIE mode 959 - * using the device's alarm. Note it should be feasible to support 960 - * such a feature using one of the two timers the device provides. 961 - */ 962 - data->rtc->uie_unsupported = 1; 963 714 964 715 /* Enable battery low detection interrupt if battery not already low */ 965 716 if (!data->battery_low && data->irq) {