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        /* optional override of the clockname */
 422        of_property_read_string(node, "clock-output-names", &init.name);
 423
 424        /* register the clock */
 425        clk = clk_register(&client->dev, &hym8563->clkout_hw);
 426
 427        if (!IS_ERR(clk))
 428                of_clk_add_provider(node, of_clk_src_simple_get, clk);
 429
 430        return clk;
 431}
 432#endif
 433
 434/*
 435 * The alarm interrupt is implemented as a level-low interrupt in the
 436 * hym8563, while the timer interrupt uses a falling edge.
 437 * We don't use the timer at all, so the interrupt is requested to
 438 * use the level-low trigger.
 439 */
 440static irqreturn_t hym8563_irq(int irq, void *dev_id)
 441{
 442        struct hym8563 *hym8563 = (struct hym8563 *)dev_id;
 443        struct i2c_client *client = hym8563->client;
 444        struct mutex *lock = &hym8563->rtc->ops_lock;
 445        int data, ret;
 446
 447        mutex_lock(lock);
 448
 449        /* Clear the alarm flag */
 450
 451        data = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
 452        if (data < 0) {
 453                dev_err(&client->dev, "%s: error reading i2c data %d\n",
 454                        __func__, data);
 455                goto out;
 456        }
 457
 458        data &= ~HYM8563_CTL2_AF;
 459
 460        ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, data);
 461        if (ret < 0) {
 462                dev_err(&client->dev, "%s: error writing i2c data %d\n",
 463                        __func__, ret);
 464        }
 465
 466out:
 467        mutex_unlock(lock);
 468        return IRQ_HANDLED;
 469}
 470
 471static int hym8563_init_device(struct i2c_client *client)
 472{
 473        int ret;
 474
 475        /* Clear stop flag if present */
 476        ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0);
 477        if (ret < 0)
 478                return ret;
 479
 480        ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
 481        if (ret < 0)
 482                return ret;
 483
 484        /* Disable alarm and timer interrupts */
 485        ret &= ~HYM8563_CTL2_AIE;
 486        ret &= ~HYM8563_CTL2_TIE;
 487
 488        /* Clear any pending alarm and timer flags */
 489        if (ret & HYM8563_CTL2_AF)
 490                ret &= ~HYM8563_CTL2_AF;
 491
 492        if (ret & HYM8563_CTL2_TF)
 493                ret &= ~HYM8563_CTL2_TF;
 494
 495        ret &= ~HYM8563_CTL2_TI_TP;
 496
 497        return i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret);
 498}
 499
 500#ifdef CONFIG_PM_SLEEP
 501static int hym8563_suspend(struct device *dev)
 502{
 503        struct i2c_client *client = to_i2c_client(dev);
 504        int ret;
 505
 506        if (device_may_wakeup(dev)) {
 507                ret = enable_irq_wake(client->irq);
 508                if (ret) {
 509                        dev_err(dev, "enable_irq_wake failed, %d\n", ret);
 510                        return ret;
 511                }
 512        }
 513
 514        return 0;
 515}
 516
 517static int hym8563_resume(struct device *dev)
 518{
 519        struct i2c_client *client = to_i2c_client(dev);
 520
 521        if (device_may_wakeup(dev))
 522                disable_irq_wake(client->irq);
 523
 524        return 0;
 525}
 526#endif
 527
 528static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
 529
 530static int hym8563_probe(struct i2c_client *client,
 531                         const struct i2c_device_id *id)
 532{
 533        struct hym8563 *hym8563;
 534        int ret;
 535
 536        hym8563 = devm_kzalloc(&client->dev, sizeof(*hym8563), GFP_KERNEL);
 537        if (!hym8563)
 538                return -ENOMEM;
 539
 540        hym8563->client = client;
 541        i2c_set_clientdata(client, hym8563);
 542
 543        device_set_wakeup_capable(&client->dev, true);
 544
 545        ret = hym8563_init_device(client);
 546        if (ret) {
 547                dev_err(&client->dev, "could not init device, %d\n", ret);
 548                return ret;
 549        }
 550
 551        ret = devm_request_threaded_irq(&client->dev, client->irq,
 552                                        NULL, hym8563_irq,
 553                                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 554                                        client->name, hym8563);
 555        if (ret < 0) {
 556                dev_err(&client->dev, "irq %d request failed, %d\n",
 557                        client->irq, ret);
 558                return ret;
 559        }
 560
 561        /* check state of calendar information */
 562        ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);
 563        if (ret < 0)
 564                return ret;
 565
 566        hym8563->valid = !(ret & HYM8563_SEC_VL);
 567        dev_dbg(&client->dev, "rtc information is %s\n",
 568                hym8563->valid ? "valid" : "invalid");
 569
 570        hym8563->rtc = devm_rtc_device_register(&client->dev, client->name,
 571                                                &hym8563_rtc_ops, THIS_MODULE);
 572        if (IS_ERR(hym8563->rtc))
 573                return PTR_ERR(hym8563->rtc);
 574
 575        /* the hym8563 alarm only supports a minute accuracy */
 576        hym8563->rtc->uie_unsupported = 1;
 577
 578#ifdef CONFIG_COMMON_CLK
 579        hym8563_clkout_register_clk(hym8563);
 580#endif
 581
 582        return 0;
 583}
 584
 585static const struct i2c_device_id hym8563_id[] = {
 586        { "hym8563", 0 },
 587        {},
 588};
 589MODULE_DEVICE_TABLE(i2c, hym8563_id);
 590
 591static const struct of_device_id hym8563_dt_idtable[] = {
 592        { .compatible = "haoyu,hym8563" },
 593        {},
 594};
 595MODULE_DEVICE_TABLE(of, hym8563_dt_idtable);
 596
 597static struct i2c_driver hym8563_driver = {
 598        .driver         = {
 599                .name   = "rtc-hym8563",
 600                .owner  = THIS_MODULE,
 601                .pm     = &hym8563_pm_ops,
 602                .of_match_table = hym8563_dt_idtable,
 603        },
 604        .probe          = hym8563_probe,
 605        .id_table       = hym8563_id,
 606};
 607
 608module_i2c_driver(hym8563_driver);
 609
 610MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
 611MODULE_DESCRIPTION("HYM8563 RTC driver");
 612MODULE_LICENSE("GPL");
 613
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.