linux/drivers/rtc/rtc-bd70528.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2//
   3// Copyright (C) 2018 ROHM Semiconductors
   4//
   5// RTC driver for ROHM BD70528 PMIC
   6
   7#include <linux/bcd.h>
   8#include <linux/mfd/rohm-bd70528.h>
   9#include <linux/mfd/rohm-bd71828.h>
  10#include <linux/module.h>
  11#include <linux/of.h>
  12#include <linux/platform_device.h>
  13#include <linux/regmap.h>
  14#include <linux/rtc.h>
  15
  16/*
  17 * We read regs RTC_SEC => RTC_YEAR
  18 * this struct is ordered according to chip registers.
  19 * Keep it u8 only (or packed) to avoid padding issues.
  20 */
  21struct bd70528_rtc_day {
  22        u8 sec;
  23        u8 min;
  24        u8 hour;
  25} __packed;
  26
  27struct bd70528_rtc_data {
  28        struct bd70528_rtc_day time;
  29        u8 week;
  30        u8 day;
  31        u8 month;
  32        u8 year;
  33} __packed;
  34
  35struct bd70528_rtc_wake {
  36        struct bd70528_rtc_day time;
  37        u8 ctrl;
  38} __packed;
  39
  40struct bd71828_rtc_alm {
  41        struct bd70528_rtc_data alm0;
  42        struct bd70528_rtc_data alm1;
  43        u8 alm_mask;
  44        u8 alm1_mask;
  45} __packed;
  46
  47struct bd70528_rtc_alm {
  48        struct bd70528_rtc_data data;
  49        u8 alm_mask;
  50        u8 alm_repeat;
  51} __packed;
  52
  53struct bd70528_rtc {
  54        struct rohm_regmap_dev *parent;
  55        struct device *dev;
  56        u8 reg_time_start;
  57        bool has_rtc_timers;
  58};
  59
  60static int bd70528_set_wake(struct rohm_regmap_dev *bd70528,
  61                            int enable, int *old_state)
  62{
  63        int ret;
  64        unsigned int ctrl_reg;
  65
  66        ret = regmap_read(bd70528->regmap, BD70528_REG_WAKE_EN, &ctrl_reg);
  67        if (ret)
  68                return ret;
  69
  70        if (old_state) {
  71                if (ctrl_reg & BD70528_MASK_WAKE_EN)
  72                        *old_state |= BD70528_WAKE_STATE_BIT;
  73                else
  74                        *old_state &= ~BD70528_WAKE_STATE_BIT;
  75
  76                if (!enable == !(*old_state & BD70528_WAKE_STATE_BIT))
  77                        return 0;
  78        }
  79
  80        if (enable)
  81                ctrl_reg |= BD70528_MASK_WAKE_EN;
  82        else
  83                ctrl_reg &= ~BD70528_MASK_WAKE_EN;
  84
  85        return regmap_write(bd70528->regmap, BD70528_REG_WAKE_EN,
  86                            ctrl_reg);
  87}
  88
  89static int bd70528_set_elapsed_tmr(struct rohm_regmap_dev *bd70528,
  90                                   int enable, int *old_state)
  91{
  92        int ret;
  93        unsigned int ctrl_reg;
  94
  95        /*
  96         * TBD
  97         * What is the purpose of elapsed timer ?
  98         * Is the timeout registers counting down, or is the disable - re-enable
  99         * going to restart the elapsed-time counting? If counting is restarted
 100         * the timeout should be decreased by the amount of time that has
 101         * elapsed since starting the timer. Maybe we should store the monotonic
 102         * clock value when timer is started so that if RTC is set while timer
 103         * is armed we could do the compensation. This is a hack if RTC/system
 104         * clk are drifting. OTOH, RTC controlled via I2C is in any case
 105         * inaccurate...
 106         */
 107        ret = regmap_read(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN,
 108                          &ctrl_reg);
 109        if (ret)
 110                return ret;
 111
 112        if (old_state) {
 113                if (ctrl_reg & BD70528_MASK_ELAPSED_TIMER_EN)
 114                        *old_state |= BD70528_ELAPSED_STATE_BIT;
 115                else
 116                        *old_state &= ~BD70528_ELAPSED_STATE_BIT;
 117
 118                if ((!enable) == (!(*old_state & BD70528_ELAPSED_STATE_BIT)))
 119                        return 0;
 120        }
 121
 122        if (enable)
 123                ctrl_reg |= BD70528_MASK_ELAPSED_TIMER_EN;
 124        else
 125                ctrl_reg &= ~BD70528_MASK_ELAPSED_TIMER_EN;
 126
 127        return regmap_write(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN,
 128                            ctrl_reg);
 129}
 130
 131static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state,
 132                                        int *old_state)
 133{
 134        int ret;
 135
 136        ret = bd70528_wdt_set(r->parent, new_state & BD70528_WDT_STATE_BIT,
 137                              old_state);
 138        if (ret) {
 139                dev_err(r->dev,
 140                        "Failed to disable WDG for RTC setting (%d)\n", ret);
 141                return ret;
 142        }
 143        ret = bd70528_set_elapsed_tmr(r->parent,
 144                                      new_state & BD70528_ELAPSED_STATE_BIT,
 145                                      old_state);
 146        if (ret) {
 147                dev_err(r->dev,
 148                        "Failed to disable 'elapsed timer' for RTC setting\n");
 149                return ret;
 150        }
 151        ret = bd70528_set_wake(r->parent, new_state & BD70528_WAKE_STATE_BIT,
 152                               old_state);
 153        if (ret) {
 154                dev_err(r->dev,
 155                        "Failed to disable 'wake timer' for RTC setting\n");
 156                return ret;
 157        }
 158
 159        return ret;
 160}
 161
 162static int bd70528_re_enable_rtc_based_timers(struct bd70528_rtc *r,
 163                                              int old_state)
 164{
 165        if (!r->has_rtc_timers)
 166                return 0;
 167
 168        return bd70528_set_rtc_based_timers(r, old_state, NULL);
 169}
 170
 171static int bd70528_disable_rtc_based_timers(struct bd70528_rtc *r,
 172                                            int *old_state)
 173{
 174        if (!r->has_rtc_timers)
 175                return 0;
 176
 177        return bd70528_set_rtc_based_timers(r, 0, old_state);
 178}
 179
 180static inline void tmday2rtc(struct rtc_time *t, struct bd70528_rtc_day *d)
 181{
 182        d->sec &= ~BD70528_MASK_RTC_SEC;
 183        d->min &= ~BD70528_MASK_RTC_MINUTE;
 184        d->hour &= ~BD70528_MASK_RTC_HOUR;
 185        d->sec |= bin2bcd(t->tm_sec);
 186        d->min |= bin2bcd(t->tm_min);
 187        d->hour |= bin2bcd(t->tm_hour);
 188}
 189
 190static inline void tm2rtc(struct rtc_time *t, struct bd70528_rtc_data *r)
 191{
 192        r->day &= ~BD70528_MASK_RTC_DAY;
 193        r->week &= ~BD70528_MASK_RTC_WEEK;
 194        r->month &= ~BD70528_MASK_RTC_MONTH;
 195        /*
 196         * PM and 24H bits are not used by Wake - thus we clear them
 197         * here and not in tmday2rtc() which is also used by wake.
 198         */
 199        r->time.hour &= ~(BD70528_MASK_RTC_HOUR_PM | BD70528_MASK_RTC_HOUR_24H);
 200
 201        tmday2rtc(t, &r->time);
 202        /*
 203         * We do always set time in 24H mode.
 204         */
 205        r->time.hour |= BD70528_MASK_RTC_HOUR_24H;
 206        r->day |= bin2bcd(t->tm_mday);
 207        r->week |= bin2bcd(t->tm_wday);
 208        r->month |= bin2bcd(t->tm_mon + 1);
 209        r->year = bin2bcd(t->tm_year - 100);
 210}
 211
 212static inline void rtc2tm(struct bd70528_rtc_data *r, struct rtc_time *t)
 213{
 214        t->tm_sec = bcd2bin(r->time.sec & BD70528_MASK_RTC_SEC);
 215        t->tm_min = bcd2bin(r->time.min & BD70528_MASK_RTC_MINUTE);
 216        t->tm_hour = bcd2bin(r->time.hour & BD70528_MASK_RTC_HOUR);
 217        /*
 218         * If RTC is in 12H mode, then bit BD70528_MASK_RTC_HOUR_PM
 219         * is not BCD value but tells whether it is AM or PM
 220         */
 221        if (!(r->time.hour & BD70528_MASK_RTC_HOUR_24H)) {
 222                t->tm_hour %= 12;
 223                if (r->time.hour & BD70528_MASK_RTC_HOUR_PM)
 224                        t->tm_hour += 12;
 225        }
 226        t->tm_mday = bcd2bin(r->day & BD70528_MASK_RTC_DAY);
 227        t->tm_mon = bcd2bin(r->month & BD70528_MASK_RTC_MONTH) - 1;
 228        t->tm_year = 100 + bcd2bin(r->year & BD70528_MASK_RTC_YEAR);
 229        t->tm_wday = bcd2bin(r->week & BD70528_MASK_RTC_WEEK);
 230}
 231
 232static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)
 233{
 234        int ret;
 235        struct bd71828_rtc_alm alm;
 236        struct bd70528_rtc *r = dev_get_drvdata(dev);
 237        struct rohm_regmap_dev *parent = r->parent;
 238
 239        ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START,
 240                               &alm, sizeof(alm));
 241        if (ret) {
 242                dev_err(dev, "Failed to read alarm regs\n");
 243                return ret;
 244        }
 245
 246        tm2rtc(&a->time, &alm.alm0);
 247
 248        if (!a->enabled)
 249                alm.alm_mask &= ~BD70528_MASK_ALM_EN;
 250        else
 251                alm.alm_mask |= BD70528_MASK_ALM_EN;
 252
 253        ret = regmap_bulk_write(parent->regmap, BD71828_REG_RTC_ALM_START,
 254                                &alm, sizeof(alm));
 255        if (ret)
 256                dev_err(dev, "Failed to set alarm time\n");
 257
 258        return ret;
 259
 260}
 261
 262static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
 263{
 264        struct bd70528_rtc_wake wake;
 265        struct bd70528_rtc_alm alm;
 266        int ret;
 267        struct bd70528_rtc *r = dev_get_drvdata(dev);
 268        struct rohm_regmap_dev *parent = r->parent;
 269
 270        ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_WAKE_START,
 271                               &wake, sizeof(wake));
 272        if (ret) {
 273                dev_err(dev, "Failed to read wake regs\n");
 274                return ret;
 275        }
 276
 277        ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START,
 278                               &alm, sizeof(alm));
 279        if (ret) {
 280                dev_err(dev, "Failed to read alarm regs\n");
 281                return ret;
 282        }
 283
 284        tm2rtc(&a->time, &alm.data);
 285        tmday2rtc(&a->time, &wake.time);
 286
 287        if (a->enabled) {
 288                alm.alm_mask &= ~BD70528_MASK_ALM_EN;
 289                wake.ctrl |= BD70528_MASK_WAKE_EN;
 290        } else {
 291                alm.alm_mask |= BD70528_MASK_ALM_EN;
 292                wake.ctrl &= ~BD70528_MASK_WAKE_EN;
 293        }
 294
 295        ret = regmap_bulk_write(parent->regmap,
 296                                BD70528_REG_RTC_WAKE_START, &wake,
 297                                sizeof(wake));
 298        if (ret) {
 299                dev_err(dev, "Failed to set wake time\n");
 300                return ret;
 301        }
 302        ret = regmap_bulk_write(parent->regmap, BD70528_REG_RTC_ALM_START,
 303                                &alm, sizeof(alm));
 304        if (ret)
 305                dev_err(dev, "Failed to set alarm time\n");
 306
 307        return ret;
 308}
 309
 310static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)
 311{
 312        int ret;
 313        struct bd71828_rtc_alm alm;
 314        struct bd70528_rtc *r = dev_get_drvdata(dev);
 315        struct rohm_regmap_dev *parent = r->parent;
 316
 317        ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START,
 318                               &alm, sizeof(alm));
 319        if (ret) {
 320                dev_err(dev, "Failed to read alarm regs\n");
 321                return ret;
 322        }
 323
 324        rtc2tm(&alm.alm0, &a->time);
 325        a->time.tm_mday = -1;
 326        a->time.tm_mon = -1;
 327        a->time.tm_year = -1;
 328        a->enabled = !!(alm.alm_mask & BD70528_MASK_ALM_EN);
 329        a->pending = 0;
 330
 331        return 0;
 332}
 333
 334static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a)
 335{
 336        struct bd70528_rtc_alm alm;
 337        int ret;
 338        struct bd70528_rtc *r = dev_get_drvdata(dev);
 339        struct rohm_regmap_dev *parent = r->parent;
 340
 341        ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START,
 342                               &alm, sizeof(alm));
 343        if (ret) {
 344                dev_err(dev, "Failed to read alarm regs\n");
 345                return ret;
 346        }
 347
 348        rtc2tm(&alm.data, &a->time);
 349        a->time.tm_mday = -1;
 350        a->time.tm_mon = -1;
 351        a->time.tm_year = -1;
 352        a->enabled = !(alm.alm_mask & BD70528_MASK_ALM_EN);
 353        a->pending = 0;
 354
 355        return 0;
 356}
 357
 358static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
 359{
 360        int ret, tmpret, old_states;
 361        struct bd70528_rtc_data rtc_data;
 362        struct bd70528_rtc *r = dev_get_drvdata(dev);
 363        struct rohm_regmap_dev *parent = r->parent;
 364
 365        ret = bd70528_disable_rtc_based_timers(r, &old_states);
 366        if (ret)
 367                return ret;
 368
 369        tmpret = regmap_bulk_read(parent->regmap,
 370                                  r->reg_time_start, &rtc_data,
 371                                  sizeof(rtc_data));
 372        if (tmpret) {
 373                dev_err(dev, "Failed to read RTC time registers\n");
 374                goto renable_out;
 375        }
 376        tm2rtc(t, &rtc_data);
 377
 378        tmpret = regmap_bulk_write(parent->regmap,
 379                                   r->reg_time_start, &rtc_data,
 380                                   sizeof(rtc_data));
 381        if (tmpret) {
 382                dev_err(dev, "Failed to set RTC time\n");
 383                goto renable_out;
 384        }
 385
 386renable_out:
 387        ret = bd70528_re_enable_rtc_based_timers(r, old_states);
 388        if (tmpret)
 389                ret = tmpret;
 390
 391        return ret;
 392}
 393
 394static int bd71828_set_time(struct device *dev, struct rtc_time *t)
 395{
 396        return bd70528_set_time_locked(dev, t);
 397}
 398
 399static int bd70528_set_time(struct device *dev, struct rtc_time *t)
 400{
 401        int ret;
 402        struct bd70528_rtc *r = dev_get_drvdata(dev);
 403
 404        bd70528_wdt_lock(r->parent);
 405        ret = bd70528_set_time_locked(dev, t);
 406        bd70528_wdt_unlock(r->parent);
 407        return ret;
 408}
 409
 410static int bd70528_get_time(struct device *dev, struct rtc_time *t)
 411{
 412        struct bd70528_rtc *r = dev_get_drvdata(dev);
 413        struct rohm_regmap_dev *parent = r->parent;
 414        struct bd70528_rtc_data rtc_data;
 415        int ret;
 416
 417        /* read the RTC date and time registers all at once */
 418        ret = regmap_bulk_read(parent->regmap,
 419                               r->reg_time_start, &rtc_data,
 420                               sizeof(rtc_data));
 421        if (ret) {
 422                dev_err(dev, "Failed to read RTC time (err %d)\n", ret);
 423                return ret;
 424        }
 425
 426        rtc2tm(&rtc_data, t);
 427
 428        return 0;
 429}
 430
 431static int bd70528_alm_enable(struct device *dev, unsigned int enabled)
 432{
 433        int ret;
 434        unsigned int enableval = BD70528_MASK_ALM_EN;
 435        struct bd70528_rtc *r = dev_get_drvdata(dev);
 436
 437        if (enabled)
 438                enableval = 0;
 439
 440        bd70528_wdt_lock(r->parent);
 441        ret = bd70528_set_wake(r->parent, enabled, NULL);
 442        if (ret) {
 443                dev_err(dev, "Failed to change wake state\n");
 444                goto out_unlock;
 445        }
 446        ret = regmap_update_bits(r->parent->regmap, BD70528_REG_RTC_ALM_MASK,
 447                                 BD70528_MASK_ALM_EN, enableval);
 448        if (ret)
 449                dev_err(dev, "Failed to change alarm state\n");
 450
 451out_unlock:
 452        bd70528_wdt_unlock(r->parent);
 453        return ret;
 454}
 455
 456static int bd71828_alm_enable(struct device *dev, unsigned int enabled)
 457{
 458        int ret;
 459        struct bd70528_rtc *r = dev_get_drvdata(dev);
 460        unsigned int enableval = BD70528_MASK_ALM_EN;
 461
 462        if (!enabled)
 463                enableval = 0;
 464
 465        ret = regmap_update_bits(r->parent->regmap, BD71828_REG_RTC_ALM0_MASK,
 466                                 BD70528_MASK_ALM_EN, enableval);
 467        if (ret)
 468                dev_err(dev, "Failed to change alarm state\n");
 469
 470        return ret;
 471}
 472
 473static const struct rtc_class_ops bd70528_rtc_ops = {
 474        .read_time              = bd70528_get_time,
 475        .set_time               = bd70528_set_time,
 476        .read_alarm             = bd70528_read_alarm,
 477        .set_alarm              = bd70528_set_alarm,
 478        .alarm_irq_enable       = bd70528_alm_enable,
 479};
 480
 481static const struct rtc_class_ops bd71828_rtc_ops = {
 482        .read_time              = bd70528_get_time,
 483        .set_time               = bd71828_set_time,
 484        .read_alarm             = bd71828_read_alarm,
 485        .set_alarm              = bd71828_set_alarm,
 486        .alarm_irq_enable       = bd71828_alm_enable,
 487};
 488
 489static irqreturn_t alm_hndlr(int irq, void *data)
 490{
 491        struct rtc_device *rtc = data;
 492
 493        rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF | RTC_PF);
 494        return IRQ_HANDLED;
 495}
 496
 497static int bd70528_probe(struct platform_device *pdev)
 498{
 499        struct bd70528_rtc *bd_rtc;
 500        const struct rtc_class_ops *rtc_ops;
 501        struct rohm_regmap_dev *parent;
 502        const char *irq_name;
 503        int ret;
 504        struct rtc_device *rtc;
 505        int irq;
 506        unsigned int hr;
 507        bool enable_main_irq = false;
 508        u8 hour_reg;
 509        enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
 510
 511        parent = dev_get_drvdata(pdev->dev.parent);
 512        if (!parent) {
 513                dev_err(&pdev->dev, "No MFD driver data\n");
 514                return -EINVAL;
 515        }
 516        bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL);
 517        if (!bd_rtc)
 518                return -ENOMEM;
 519
 520        bd_rtc->parent = parent;
 521        bd_rtc->dev = &pdev->dev;
 522
 523        switch (chip) {
 524        case ROHM_CHIP_TYPE_BD70528:
 525                irq_name = "bd70528-rtc-alm";
 526                bd_rtc->has_rtc_timers = true;
 527                bd_rtc->reg_time_start = BD70528_REG_RTC_START;
 528                hour_reg = BD70528_REG_RTC_HOUR;
 529                enable_main_irq = true;
 530                rtc_ops = &bd70528_rtc_ops;
 531                break;
 532        case ROHM_CHIP_TYPE_BD71828:
 533                irq_name = "bd71828-rtc-alm-0";
 534                bd_rtc->reg_time_start = BD71828_REG_RTC_START;
 535                hour_reg = BD71828_REG_RTC_HOUR;
 536                rtc_ops = &bd71828_rtc_ops;
 537                break;
 538        default:
 539                dev_err(&pdev->dev, "Unknown chip\n");
 540                return -ENOENT;
 541        }
 542
 543        irq = platform_get_irq_byname(pdev, irq_name);
 544
 545        if (irq < 0)
 546                return irq;
 547
 548        platform_set_drvdata(pdev, bd_rtc);
 549
 550        ret = regmap_read(parent->regmap, hour_reg, &hr);
 551
 552        if (ret) {
 553                dev_err(&pdev->dev, "Failed to reag RTC clock\n");
 554                return ret;
 555        }
 556
 557        if (!(hr & BD70528_MASK_RTC_HOUR_24H)) {
 558                struct rtc_time t;
 559
 560                ret = rtc_ops->read_time(&pdev->dev, &t);
 561
 562                if (!ret)
 563                        ret = rtc_ops->set_time(&pdev->dev, &t);
 564
 565                if (ret) {
 566                        dev_err(&pdev->dev,
 567                                "Setting 24H clock for RTC failed\n");
 568                        return ret;
 569                }
 570        }
 571
 572        device_set_wakeup_capable(&pdev->dev, true);
 573        device_wakeup_enable(&pdev->dev);
 574
 575        rtc = devm_rtc_allocate_device(&pdev->dev);
 576        if (IS_ERR(rtc)) {
 577                dev_err(&pdev->dev, "RTC device creation failed\n");
 578                return PTR_ERR(rtc);
 579        }
 580
 581        rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
 582        rtc->range_max = RTC_TIMESTAMP_END_2099;
 583        rtc->ops = rtc_ops;
 584
 585        /* Request alarm IRQ prior to registerig the RTC */
 586        ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, &alm_hndlr,
 587                                        IRQF_ONESHOT, "bd70528-rtc", rtc);
 588        if (ret)
 589                return ret;
 590
 591        /*
 592         *  BD70528 irq controller is not touching the main mask register.
 593         *  So enable the RTC block interrupts at main level. We can just
 594         *  leave them enabled as irq-controller should disable irqs
 595         *  from sub-registers when IRQ is disabled or freed.
 596         */
 597        if (enable_main_irq) {
 598                ret = regmap_update_bits(parent->regmap,
 599                                 BD70528_REG_INT_MAIN_MASK,
 600                                 BD70528_INT_RTC_MASK, 0);
 601                if (ret) {
 602                        dev_err(&pdev->dev, "Failed to enable RTC interrupts\n");
 603                        return ret;
 604                }
 605        }
 606
 607        return rtc_register_device(rtc);
 608}
 609
 610static const struct platform_device_id bd718x7_rtc_id[] = {
 611        { "bd70528-rtc", ROHM_CHIP_TYPE_BD70528 },
 612        { "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 },
 613        { },
 614};
 615MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id);
 616
 617static struct platform_driver bd70528_rtc = {
 618        .driver = {
 619                .name = "bd70528-rtc"
 620        },
 621        .probe = bd70528_probe,
 622        .id_table = bd718x7_rtc_id,
 623};
 624
 625module_platform_driver(bd70528_rtc);
 626
 627MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
 628MODULE_DESCRIPTION("ROHM BD70528 and BD71828 PMIC RTC driver");
 629MODULE_LICENSE("GPL");
 630MODULE_ALIAS("platform:bd70528-rtc");
 631