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