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_ENABLE   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] = bin2bcd(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 = 0;
 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        ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
 217        if (ret < 0)
 218                return ret;
 219
 220        if (ret & HYM8563_CTL2_AIE)
 221                alm->enabled = 1;
 222
 223        return 0;
 224}
 225
 226static int hym8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 227{
 228        struct i2c_client *client = to_i2c_client(dev);
 229        struct rtc_time *alm_tm = &alm->time;
 230        u8 buf[4];
 231        int ret;
 232
 233        /*
 234         * The alarm has no seconds so deal with it
 235         */
 236        if (alm_tm->tm_sec) {
 237                alm_tm->tm_sec = 0;
 238                alm_tm->tm_min++;
 239                if (alm_tm->tm_min >= 60) {
 240                        alm_tm->tm_min = 0;
 241                        alm_tm->tm_hour++;
 242                        if (alm_tm->tm_hour >= 24) {
 243                                alm_tm->tm_hour = 0;
 244                                alm_tm->tm_mday++;
 245                                if (alm_tm->tm_mday > 31)
 246                                        alm_tm->tm_mday = 0;
 247                        }
 248                }
 249        }
 250
 251        ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
 252        if (ret < 0)
 253                return ret;
 254
 255        ret &= ~HYM8563_CTL2_AIE;
 256
 257        ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret);
 258        if (ret < 0)
 259                return ret;
 260
 261        buf[0] = (alm_tm->tm_min < 60 && alm_tm->tm_min >= 0) ?
 262                        bin2bcd(alm_tm->tm_min) : HYM8563_ALM_BIT_DISABLE;
 263
 264        buf[1] = (alm_tm->tm_hour < 24 && alm_tm->tm_hour >= 0) ?
 265                        bin2bcd(alm_tm->tm_hour) : HYM8563_ALM_BIT_DISABLE;
 266
 267        buf[2] = (alm_tm->tm_mday <= 31 && alm_tm->tm_mday >= 1) ?
 268                        bin2bcd(alm_tm->tm_mday) : HYM8563_ALM_BIT_DISABLE;
 269
 270        buf[3] = (alm_tm->tm_wday < 7 && alm_tm->tm_wday >= 0) ?
 271                        bin2bcd(alm_tm->tm_wday) : HYM8563_ALM_BIT_DISABLE;
 272
 273        ret = i2c_smbus_write_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf);
 274        if (ret < 0)
 275                return ret;
 276
 277        return hym8563_rtc_alarm_irq_enable(dev, alm->enabled);
 278}
 279
 280static const struct rtc_class_ops hym8563_rtc_ops = {
 281        .read_time              = hym8563_rtc_read_time,
 282        .set_time               = hym8563_rtc_set_time,
 283        .alarm_irq_enable       = hym8563_rtc_alarm_irq_enable,
 284        .read_alarm             = hym8563_rtc_read_alarm,
 285        .set_alarm              = hym8563_rtc_set_alarm,
 286};
 287
 288/*
 289 * Handling of the clkout
 290 */
 291
 292#ifdef CONFIG_COMMON_CLK
 293#define clkout_hw_to_hym8563(_hw) container_of(_hw, struct hym8563, clkout_hw)
 294
 295static int clkout_rates[] = {
 296        32768,
 297        1024,
 298        32,
 299        1,
 300};
 301
 302static unsigned long hym8563_clkout_recalc_rate(struct clk_hw *hw,
 303                                                unsigned long parent_rate)
 304{
 305        struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
 306        struct i2c_client *client = hym8563->client;
 307        int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
 308
 309        if (ret < 0)
 310                return 0;
 311
 312        ret &= HYM8563_CLKOUT_MASK;
 313        return clkout_rates[ret];
 314}
 315
 316static long hym8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
 317                                      unsigned long *prate)
 318{
 319        int i;
 320
 321        for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
 322                if (clkout_rates[i] <= rate)
 323                        return clkout_rates[i];
 324
 325        return 0;
 326}
 327
 328static int hym8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
 329                                   unsigned long parent_rate)
 330{
 331        struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
 332        struct i2c_client *client = hym8563->client;
 333        int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
 334        int i;
 335
 336        if (ret < 0)
 337                return ret;
 338
 339        for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
 340                if (clkout_rates[i] == rate) {
 341                        ret &= ~HYM8563_CLKOUT_MASK;
 342                        ret |= i;
 343                        return i2c_smbus_write_byte_data(client,
 344                                                         HYM8563_CLKOUT, ret);
 345                }
 346
 347        return -EINVAL;
 348}
 349
 350static int hym8563_clkout_control(struct clk_hw *hw, bool enable)
 351{
 352        struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
 353        struct i2c_client *client = hym8563->client;
 354        int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
 355
 356        if (ret < 0)
 357                return ret;
 358
 359        if (enable)
 360                ret |= HYM8563_CLKOUT_ENABLE;
 361        else
 362                ret &= ~HYM8563_CLKOUT_ENABLE;
 363
 364        return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret);
 365}
 366
 367static int hym8563_clkout_prepare(struct clk_hw *hw)
 368{
 369        return hym8563_clkout_control(hw, 1);
 370}
 371
 372static void hym8563_clkout_unprepare(struct clk_hw *hw)
 373{
 374        hym8563_clkout_control(hw, 0);
 375}
 376
 377static int hym8563_clkout_is_prepared(struct clk_hw *hw)
 378{
 379        struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
 380        struct i2c_client *client = hym8563->client;
 381        int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
 382
 383        if (ret < 0)
 384                return ret;
 385
 386        return !!(ret & HYM8563_CLKOUT_ENABLE);
 387}
 388
 389static const struct clk_ops hym8563_clkout_ops = {
 390        .prepare = hym8563_clkout_prepare,
 391        .unprepare = hym8563_clkout_unprepare,
 392        .is_prepared = hym8563_clkout_is_prepared,
 393        .recalc_rate = hym8563_clkout_recalc_rate,
 394        .round_rate = hym8563_clkout_round_rate,
 395        .set_rate = hym8563_clkout_set_rate,
 396};
 397
 398static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563)
 399{
 400        struct i2c_client *client = hym8563->client;
 401        struct device_node *node = client->dev.of_node;
 402        struct clk *clk;
 403        struct clk_init_data init;
 404        int ret;
 405
 406        ret = i2c_smbus_write_byte_data(client, HYM8563_CLKOUT,
 407                                                0);
 408        if (ret < 0)
 409                return ERR_PTR(ret);
 410
 411        init.name = "hym8563-clkout";
 412        init.ops = &hym8563_clkout_ops;
 413        init.flags = 0;
 414        init.parent_names = NULL;
 415        init.num_parents = 0;
 416        hym8563->clkout_hw.init = &init;
 417
 418        /* optional override of the clockname */
 419        of_property_read_string(node, "clock-output-names", &init.name);
 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        if (client->irq > 0) {
 549                ret = devm_request_threaded_irq(&client->dev, client->irq,
 550                                                NULL, hym8563_irq,
 551                                                IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 552                                                client->name, hym8563);
 553                if (ret < 0) {
 554                        dev_err(&client->dev, "irq %d request failed, %d\n",
 555                                client->irq, ret);
 556                        return ret;
 557                }
 558        }
 559
 560        /* check state of calendar information */
 561        ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);
 562        if (ret < 0)
 563                return ret;
 564
 565        hym8563->valid = !(ret & HYM8563_SEC_VL);
 566        dev_dbg(&client->dev, "rtc information is %s\n",
 567                hym8563->valid ? "valid" : "invalid");
 568
 569        hym8563->rtc = devm_rtc_device_register(&client->dev, client->name,
 570                                                &hym8563_rtc_ops, THIS_MODULE);
 571        if (IS_ERR(hym8563->rtc))
 572                return PTR_ERR(hym8563->rtc);
 573
 574        /* the hym8563 alarm only supports a minute accuracy */
 575        hym8563->rtc->uie_unsupported = 1;
 576
 577#ifdef CONFIG_COMMON_CLK
 578        hym8563_clkout_register_clk(hym8563);
 579#endif
 580
 581        return 0;
 582}
 583
 584static const struct i2c_device_id hym8563_id[] = {
 585        { "hym8563", 0 },
 586        {},
 587};
 588MODULE_DEVICE_TABLE(i2c, hym8563_id);
 589
 590static const struct of_device_id hym8563_dt_idtable[] = {
 591        { .compatible = "haoyu,hym8563" },
 592        {},
 593};
 594MODULE_DEVICE_TABLE(of, hym8563_dt_idtable);
 595
 596static struct i2c_driver hym8563_driver = {
 597        .driver         = {
 598                .name   = "rtc-hym8563",
 599                .pm     = &hym8563_pm_ops,
 600                .of_match_table = hym8563_dt_idtable,
 601        },
 602        .probe          = hym8563_probe,
 603        .id_table       = hym8563_id,
 604};
 605
 606module_i2c_driver(hym8563_driver);
 607
 608MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
 609MODULE_DESCRIPTION("HYM8563 RTC driver");
 610MODULE_LICENSE("GPL");
 611
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.