linux/drivers/rtc/rtc-hym8563.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Haoyu HYM8563 RTC driver
   4 *
   5 * Copyright (C) 2013 MundoReader S.L.
   6 * Author: Heiko Stuebner <heiko@sntech.de>
   7 *
   8 * based on rtc-HYM8563
   9 * Copyright (C) 2010 ROCKCHIP, Inc.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/clk-provider.h>
  14#include <linux/i2c.h>
  15#include <linux/bcd.h>
  16#include <linux/rtc.h>
  17
  18#define HYM8563_CTL1            0x00
  19#define HYM8563_CTL1_TEST       BIT(7)
  20#define HYM8563_CTL1_STOP       BIT(5)
  21#define HYM8563_CTL1_TESTC      BIT(3)
  22
  23#define HYM8563_CTL2            0x01
  24#define HYM8563_CTL2_TI_TP      BIT(4)
  25#define HYM8563_CTL2_AF         BIT(3)
  26#define HYM8563_CTL2_TF         BIT(2)
  27#define HYM8563_CTL2_AIE        BIT(1)
  28#define HYM8563_CTL2_TIE        BIT(0)
  29
  30#define HYM8563_SEC             0x02
  31#define HYM8563_SEC_VL          BIT(7)
  32#define HYM8563_SEC_MASK        0x7f
  33
  34#define HYM8563_MIN             0x03
  35#define HYM8563_MIN_MASK        0x7f
  36
  37#define HYM8563_HOUR            0x04
  38#define HYM8563_HOUR_MASK       0x3f
  39
  40#define HYM8563_DAY             0x05
  41#define HYM8563_DAY_MASK        0x3f
  42
  43#define HYM8563_WEEKDAY         0x06
  44#define HYM8563_WEEKDAY_MASK    0x07
  45
  46#define HYM8563_MONTH           0x07
  47#define HYM8563_MONTH_CENTURY   BIT(7)
  48#define HYM8563_MONTH_MASK      0x1f
  49
  50#define HYM8563_YEAR            0x08
  51
  52#define HYM8563_ALM_MIN         0x09
  53#define HYM8563_ALM_HOUR        0x0a
  54#define HYM8563_ALM_DAY         0x0b
  55#define HYM8563_ALM_WEEK        0x0c
  56
  57/* Each alarm check can be disabled by setting this bit in the register */
  58#define HYM8563_ALM_BIT_DISABLE BIT(7)
  59
  60#define HYM8563_CLKOUT          0x0d
  61#define HYM8563_CLKOUT_ENABLE   BIT(7)
  62#define HYM8563_CLKOUT_32768    0
  63#define HYM8563_CLKOUT_1024     1
  64#define HYM8563_CLKOUT_32       2
  65#define HYM8563_CLKOUT_1        3
  66#define HYM8563_CLKOUT_MASK     3
  67
  68#define HYM8563_TMR_CTL         0x0e
  69#define HYM8563_TMR_CTL_ENABLE  BIT(7)
  70#define HYM8563_TMR_CTL_4096    0
  71#define HYM8563_TMR_CTL_64      1
  72#define HYM8563_TMR_CTL_1       2
  73#define HYM8563_TMR_CTL_1_60    3
  74#define HYM8563_TMR_CTL_MASK    3
  75
  76#define HYM8563_TMR_CNT         0x0f
  77
  78struct hym8563 {
  79        struct i2c_client       *client;
  80        struct rtc_device       *rtc;
  81#ifdef CONFIG_COMMON_CLK
  82        struct clk_hw           clkout_hw;
  83#endif
  84};
  85
  86/*
  87 * RTC handling
  88 */
  89
  90static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
  91{
  92        struct i2c_client *client = to_i2c_client(dev);
  93        u8 buf[7];
  94        int ret;
  95
  96        ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);
  97        if (ret < 0)
  98                return ret;
  99
 100        if (buf[0] & HYM8563_SEC_VL) {
 101                dev_warn(&client->dev,
 102                         "no valid clock/calendar values available\n");
 103                return -EINVAL;
 104        }
 105
 106        tm->tm_sec = bcd2bin(buf[0] & HYM8563_SEC_MASK);
 107        tm->tm_min = bcd2bin(buf[1] & HYM8563_MIN_MASK);
 108        tm->tm_hour = bcd2bin(buf[2] & HYM8563_HOUR_MASK);
 109        tm->tm_mday = bcd2bin(buf[3] & HYM8563_DAY_MASK);
 110        tm->tm_wday = bcd2bin(buf[4] & HYM8563_WEEKDAY_MASK); /* 0 = Sun */
 111        tm->tm_mon = bcd2bin(buf[5] & HYM8563_MONTH_MASK) - 1; /* 0 = Jan */
 112        tm->tm_year = bcd2bin(buf[6]) + 100;
 113
 114        return 0;
 115}
 116
 117static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
 118{
 119        struct i2c_client *client = to_i2c_client(dev);
 120        u8 buf[7];
 121        int ret;
 122
 123        /* Years >= 2100 are to far in the future, 19XX is to early */
 124        if (tm->tm_year < 100 || tm->tm_year >= 200)
 125                return -EINVAL;
 126
 127        buf[0] = bin2bcd(tm->tm_sec);
 128        buf[1] = bin2bcd(tm->tm_min);
 129        buf[2] = bin2bcd(tm->tm_hour);
 130        buf[3] = bin2bcd(tm->tm_mday);
 131        buf[4] = bin2bcd(tm->tm_wday);
 132        buf[5] = bin2bcd(tm->tm_mon + 1);
 133
 134        /*
 135         * While the HYM8563 has a century flag in the month register,
 136         * it does not seem to carry it over a subsequent write/read.
 137         * So we'll limit ourself to 100 years, starting at 2000 for now.
 138         */
 139        buf[6] = bin2bcd(tm->tm_year - 100);
 140
 141        /*
 142         * CTL1 only contains TEST-mode bits apart from stop,
 143         * so no need to read the value first
 144         */
 145        ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1,
 146                                                HYM8563_CTL1_STOP);
 147        if (ret < 0)
 148                return ret;
 149
 150        ret = i2c_smbus_write_i2c_block_data(client, HYM8563_SEC, 7, buf);
 151        if (ret < 0)
 152                return ret;
 153
 154        ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0);
 155        if (ret < 0)
 156                return ret;
 157
 158        return 0;
 159}
 160
 161static int hym8563_rtc_alarm_irq_enable(struct device *dev,
 162                                        unsigned int enabled)
 163{
 164        struct i2c_client *client = to_i2c_client(dev);
 165        int data;
 166
 167        data = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
 168        if (data < 0)
 169                return data;
 170
 171        if (enabled)
 172                data |= HYM8563_CTL2_AIE;
 173        else
 174                data &= ~HYM8563_CTL2_AIE;
 175
 176        return i2c_smbus_write_byte_data(client, HYM8563_CTL2, data);
 177};
 178
 179static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 180{
 181        struct i2c_client *client = to_i2c_client(dev);
 182        struct rtc_time *alm_tm = &alm->time;
 183        u8 buf[4];
 184        int ret;
 185
 186        ret = i2c_smbus_read_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf);
 187        if (ret < 0)
 188                return ret;
 189
 190        /* The alarm only has a minute accuracy */
 191        alm_tm->tm_sec = 0;
 192
 193        alm_tm->tm_min = (buf[0] & HYM8563_ALM_BIT_DISABLE) ?
 194                                        -1 :
 195                                        bcd2bin(buf[0] & HYM8563_MIN_MASK);
 196        alm_tm->tm_hour = (buf[1] & HYM8563_ALM_BIT_DISABLE) ?
 197                                        -1 :
 198                                        bcd2bin(buf[1] & HYM8563_HOUR_MASK);
 199        alm_tm->tm_mday = (buf[2] & HYM8563_ALM_BIT_DISABLE) ?
 200                                        -1 :
 201                                        bcd2bin(buf[2] & HYM8563_DAY_MASK);
 202        alm_tm->tm_wday = (buf[3] & HYM8563_ALM_BIT_DISABLE) ?
 203                                        -1 :
 204                                        bcd2bin(buf[3] & HYM8563_WEEKDAY_MASK);
 205
 206        ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
 207        if (ret < 0)
 208                return ret;
 209
 210        if (ret & HYM8563_CTL2_AIE)
 211                alm->enabled = 1;
 212
 213        return 0;
 214}
 215
 216static int hym8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 217{
 218        struct i2c_client *client = to_i2c_client(dev);
 219        struct rtc_time *alm_tm = &alm->time;
 220        u8 buf[4];
 221        int ret;
 222
 223        /*
 224         * The alarm has no seconds so deal with it
 225         */
 226        if (alm_tm->tm_sec) {
 227                alm_tm->tm_sec = 0;
 228                alm_tm->tm_min++;
 229                if (alm_tm->tm_min >= 60) {
 230                        alm_tm->tm_min = 0;
 231                        alm_tm->tm_hour++;
 232                        if (alm_tm->tm_hour >= 24) {
 233                                alm_tm->tm_hour = 0;
 234                                alm_tm->tm_mday++;
 235                                if (alm_tm->tm_mday > 31)
 236                                        alm_tm->tm_mday = 0;
 237                        }
 238                }
 239        }
 240
 241        ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
 242        if (ret < 0)
 243                return ret;
 244
 245        ret &= ~HYM8563_CTL2_AIE;
 246
 247        ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret);
 248        if (ret < 0)
 249                return ret;
 250
 251        buf[0] = (alm_tm->tm_min < 60 && alm_tm->tm_min >= 0) ?
 252                        bin2bcd(alm_tm->tm_min) : HYM8563_ALM_BIT_DISABLE;
 253
 254        buf[1] = (alm_tm->tm_hour < 24 && alm_tm->tm_hour >= 0) ?
 255                        bin2bcd(alm_tm->tm_hour) : HYM8563_ALM_BIT_DISABLE;
 256
 257        buf[2] = (alm_tm->tm_mday <= 31 && alm_tm->tm_mday >= 1) ?
 258                        bin2bcd(alm_tm->tm_mday) : HYM8563_ALM_BIT_DISABLE;
 259
 260        buf[3] = (alm_tm->tm_wday < 7 && alm_tm->tm_wday >= 0) ?
 261                        bin2bcd(alm_tm->tm_wday) : HYM8563_ALM_BIT_DISABLE;
 262
 263        ret = i2c_smbus_write_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf);
 264        if (ret < 0)
 265                return ret;
 266
 267        return hym8563_rtc_alarm_irq_enable(dev, alm->enabled);
 268}
 269
 270static const struct rtc_class_ops hym8563_rtc_ops = {
 271        .read_time              = hym8563_rtc_read_time,
 272        .set_time               = hym8563_rtc_set_time,
 273        .alarm_irq_enable       = hym8563_rtc_alarm_irq_enable,
 274        .read_alarm             = hym8563_rtc_read_alarm,
 275        .set_alarm              = hym8563_rtc_set_alarm,
 276};
 277
 278/*
 279 * Handling of the clkout
 280 */
 281
 282#ifdef CONFIG_COMMON_CLK
 283#define clkout_hw_to_hym8563(_hw) container_of(_hw, struct hym8563, clkout_hw)
 284
 285static int clkout_rates[] = {
 286        32768,
 287        1024,
 288        32,
 289        1,
 290};
 291
 292static unsigned long hym8563_clkout_recalc_rate(struct clk_hw *hw,
 293                                                unsigned long parent_rate)
 294{
 295        struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
 296        struct i2c_client *client = hym8563->client;
 297        int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
 298
 299        if (ret < 0)
 300                return 0;
 301
 302        ret &= HYM8563_CLKOUT_MASK;
 303        return clkout_rates[ret];
 304}
 305
 306static long hym8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
 307                                      unsigned long *prate)
 308{
 309        int i;
 310
 311        for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
 312                if (clkout_rates[i] <= rate)
 313                        return clkout_rates[i];
 314
 315        return 0;
 316}
 317
 318static int hym8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
 319                                   unsigned long parent_rate)
 320{
 321        struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
 322        struct i2c_client *client = hym8563->client;
 323        int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
 324        int i;
 325
 326        if (ret < 0)
 327                return ret;
 328
 329        for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
 330                if (clkout_rates[i] == rate) {
 331                        ret &= ~HYM8563_CLKOUT_MASK;
 332                        ret |= i;
 333                        return i2c_smbus_write_byte_data(client,
 334                                                         HYM8563_CLKOUT, ret);
 335                }
 336
 337        return -EINVAL;
 338}
 339
 340static int hym8563_clkout_control(struct clk_hw *hw, bool enable)
 341{
 342        struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
 343        struct i2c_client *client = hym8563->client;
 344        int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
 345
 346        if (ret < 0)
 347                return ret;
 348
 349        if (enable)
 350                ret |= HYM8563_CLKOUT_ENABLE;
 351        else
 352                ret &= ~HYM8563_CLKOUT_ENABLE;
 353
 354        return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret);
 355}
 356
 357static int hym8563_clkout_prepare(struct clk_hw *hw)
 358{
 359        return hym8563_clkout_control(hw, 1);
 360}
 361
 362static void hym8563_clkout_unprepare(struct clk_hw *hw)
 363{
 364        hym8563_clkout_control(hw, 0);
 365}
 366
 367static int hym8563_clkout_is_prepared(struct clk_hw *hw)
 368{
 369        struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
 370        struct i2c_client *client = hym8563->client;
 371        int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
 372
 373        if (ret < 0)
 374                return ret;
 375
 376        return !!(ret & HYM8563_CLKOUT_ENABLE);
 377}
 378
 379static const struct clk_ops hym8563_clkout_ops = {
 380        .prepare = hym8563_clkout_prepare,
 381        .unprepare = hym8563_clkout_unprepare,
 382        .is_prepared = hym8563_clkout_is_prepared,
 383        .recalc_rate = hym8563_clkout_recalc_rate,
 384        .round_rate = hym8563_clkout_round_rate,
 385        .set_rate = hym8563_clkout_set_rate,
 386};
 387
 388static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563)
 389{
 390        struct i2c_client *client = hym8563->client;
 391        struct device_node *node = client->dev.of_node;
 392        struct clk *clk;
 393        struct clk_init_data init;
 394        int ret;
 395
 396        ret = i2c_smbus_write_byte_data(client, HYM8563_CLKOUT,
 397                                                0);
 398        if (ret < 0)
 399                return ERR_PTR(ret);
 400
 401        init.name = "hym8563-clkout";
 402        init.ops = &hym8563_clkout_ops;
 403        init.flags = 0;
 404        init.parent_names = NULL;
 405        init.num_parents = 0;
 406        hym8563->clkout_hw.init = &init;
 407
 408        /* optional override of the clockname */
 409        of_property_read_string(node, "clock-output-names", &init.name);
 410
 411        /* register the clock */
 412        clk = clk_register(&client->dev, &hym8563->clkout_hw);
 413
 414        if (!IS_ERR(clk))
 415                of_clk_add_provider(node, of_clk_src_simple_get, clk);
 416
 417        return clk;
 418}
 419#endif
 420
 421/*
 422 * The alarm interrupt is implemented as a level-low interrupt in the
 423 * hym8563, while the timer interrupt uses a falling edge.
 424 * We don't use the timer at all, so the interrupt is requested to
 425 * use the level-low trigger.
 426 */
 427static irqreturn_t hym8563_irq(int irq, void *dev_id)
 428{
 429        struct hym8563 *hym8563 = (struct hym8563 *)dev_id;
 430        struct i2c_client *client = hym8563->client;
 431        struct mutex *lock = &hym8563->rtc->ops_lock;
 432        int data, ret;
 433
 434        mutex_lock(lock);
 435
 436        /* Clear the alarm flag */
 437
 438        data = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
 439        if (data < 0) {
 440                dev_err(&client->dev, "%s: error reading i2c data %d\n",
 441                        __func__, data);
 442                goto out;
 443        }
 444
 445        data &= ~HYM8563_CTL2_AF;
 446
 447        ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, data);
 448        if (ret < 0) {
 449                dev_err(&client->dev, "%s: error writing i2c data %d\n",
 450                        __func__, ret);
 451        }
 452
 453out:
 454        mutex_unlock(lock);
 455        return IRQ_HANDLED;
 456}
 457
 458static int hym8563_init_device(struct i2c_client *client)
 459{
 460        int ret;
 461
 462        /* Clear stop flag if present */
 463        ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0);
 464        if (ret < 0)
 465                return ret;
 466
 467        ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
 468        if (ret < 0)
 469                return ret;
 470
 471        /* Disable alarm and timer interrupts */
 472        ret &= ~HYM8563_CTL2_AIE;
 473        ret &= ~HYM8563_CTL2_TIE;
 474
 475        /* Clear any pending alarm and timer flags */
 476        if (ret & HYM8563_CTL2_AF)
 477                ret &= ~HYM8563_CTL2_AF;
 478
 479        if (ret & HYM8563_CTL2_TF)
 480                ret &= ~HYM8563_CTL2_TF;
 481
 482        ret &= ~HYM8563_CTL2_TI_TP;
 483
 484        return i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret);
 485}
 486
 487#ifdef CONFIG_PM_SLEEP
 488static int hym8563_suspend(struct device *dev)
 489{
 490        struct i2c_client *client = to_i2c_client(dev);
 491        int ret;
 492
 493        if (device_may_wakeup(dev)) {
 494                ret = enable_irq_wake(client->irq);
 495                if (ret) {
 496                        dev_err(dev, "enable_irq_wake failed, %d\n", ret);
 497                        return ret;
 498                }
 499        }
 500
 501        return 0;
 502}
 503
 504static int hym8563_resume(struct device *dev)
 505{
 506        struct i2c_client *client = to_i2c_client(dev);
 507
 508        if (device_may_wakeup(dev))
 509                disable_irq_wake(client->irq);
 510
 511        return 0;
 512}
 513#endif
 514
 515static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
 516
 517static int hym8563_probe(struct i2c_client *client,
 518                         const struct i2c_device_id *id)
 519{
 520        struct hym8563 *hym8563;
 521        int ret;
 522
 523        hym8563 = devm_kzalloc(&client->dev, sizeof(*hym8563), GFP_KERNEL);
 524        if (!hym8563)
 525                return -ENOMEM;
 526
 527        hym8563->client = client;
 528        i2c_set_clientdata(client, hym8563);
 529
 530        device_set_wakeup_capable(&client->dev, true);
 531
 532        ret = hym8563_init_device(client);
 533        if (ret) {
 534                dev_err(&client->dev, "could not init device, %d\n", ret);
 535                return ret;
 536        }
 537
 538        if (client->irq > 0) {
 539                ret = devm_request_threaded_irq(&client->dev, client->irq,
 540                                                NULL, hym8563_irq,
 541                                                IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 542                                                client->name, hym8563);
 543                if (ret < 0) {
 544                        dev_err(&client->dev, "irq %d request failed, %d\n",
 545                                client->irq, ret);
 546                        return ret;
 547                }
 548        }
 549
 550        /* check state of calendar information */
 551        ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);
 552        if (ret < 0)
 553                return ret;
 554
 555        dev_dbg(&client->dev, "rtc information is %s\n",
 556                (ret & HYM8563_SEC_VL) ? "invalid" : "valid");
 557
 558        hym8563->rtc = devm_rtc_device_register(&client->dev, client->name,
 559                                                &hym8563_rtc_ops, THIS_MODULE);
 560        if (IS_ERR(hym8563->rtc))
 561                return PTR_ERR(hym8563->rtc);
 562
 563        /* the hym8563 alarm only supports a minute accuracy */
 564        hym8563->rtc->uie_unsupported = 1;
 565
 566#ifdef CONFIG_COMMON_CLK
 567        hym8563_clkout_register_clk(hym8563);
 568#endif
 569
 570        return 0;
 571}
 572
 573static const struct i2c_device_id hym8563_id[] = {
 574        { "hym8563", 0 },
 575        {},
 576};
 577MODULE_DEVICE_TABLE(i2c, hym8563_id);
 578
 579static const struct of_device_id hym8563_dt_idtable[] = {
 580        { .compatible = "haoyu,hym8563" },
 581        {},
 582};
 583MODULE_DEVICE_TABLE(of, hym8563_dt_idtable);
 584
 585static struct i2c_driver hym8563_driver = {
 586        .driver         = {
 587                .name   = "rtc-hym8563",
 588                .pm     = &hym8563_pm_ops,
 589                .of_match_table = hym8563_dt_idtable,
 590        },
 591        .probe          = hym8563_probe,
 592        .id_table       = hym8563_id,
 593};
 594
 595module_i2c_driver(hym8563_driver);
 596
 597MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
 598MODULE_DESCRIPTION("HYM8563 RTC driver");
 599MODULE_LICENSE("GPL");
 600