linux/drivers/rtc/rtc-da9055.c
<<
>>
Prefs
   1/*
   2 * Real time clock driver for DA9055
   3 *
   4 * Copyright(c) 2012 Dialog Semiconductor Ltd.
   5 *
   6 * Author: Dajun Dajun Chen <dajun.chen@diasemi.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/platform_device.h>
  17#include <linux/rtc.h>
  18
  19#include <linux/mfd/da9055/core.h>
  20#include <linux/mfd/da9055/reg.h>
  21#include <linux/mfd/da9055/pdata.h>
  22
  23struct da9055_rtc {
  24        struct rtc_device *rtc;
  25        struct da9055 *da9055;
  26        int alarm_enable;
  27};
  28
  29static int da9055_rtc_enable_alarm(struct da9055_rtc *rtc, bool enable)
  30{
  31        int ret;
  32        if (enable) {
  33                ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y,
  34                                        DA9055_RTC_ALM_EN,
  35                                        DA9055_RTC_ALM_EN);
  36                if (ret != 0)
  37                        dev_err(rtc->da9055->dev, "Failed to enable ALM: %d\n",
  38                                ret);
  39                rtc->alarm_enable = 1;
  40        } else {
  41                ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y,
  42                                        DA9055_RTC_ALM_EN, 0);
  43                if (ret != 0)
  44                        dev_err(rtc->da9055->dev,
  45                                "Failed to disable ALM: %d\n", ret);
  46                rtc->alarm_enable = 0;
  47        }
  48        return ret;
  49}
  50
  51static irqreturn_t da9055_rtc_alm_irq(int irq, void *data)
  52{
  53        struct da9055_rtc *rtc = data;
  54
  55        da9055_rtc_enable_alarm(rtc, 0);
  56        rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
  57
  58        return IRQ_HANDLED;
  59}
  60
  61static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm)
  62{
  63        int ret;
  64        uint8_t v[5];
  65
  66        ret = da9055_group_read(da9055, DA9055_REG_ALARM_MI, 5, v);
  67        if (ret != 0) {
  68                dev_err(da9055->dev, "Failed to group read ALM: %d\n", ret);
  69                return ret;
  70        }
  71
  72        rtc_tm->tm_year = (v[4] & DA9055_RTC_ALM_YEAR) + 100;
  73        rtc_tm->tm_mon  = (v[3] & DA9055_RTC_ALM_MONTH) - 1;
  74        rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY;
  75        rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR;
  76        rtc_tm->tm_min  = v[0] & DA9055_RTC_ALM_MIN;
  77        rtc_tm->tm_sec = 0;
  78
  79        return rtc_valid_tm(rtc_tm);
  80}
  81
  82static int da9055_set_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm)
  83{
  84        int ret;
  85        uint8_t v[2];
  86
  87        rtc_tm->tm_year -= 100;
  88        rtc_tm->tm_mon += 1;
  89
  90        ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MI,
  91                                DA9055_RTC_ALM_MIN, rtc_tm->tm_min);
  92        if (ret != 0) {
  93                dev_err(da9055->dev, "Failed to write ALRM MIN: %d\n", ret);
  94                return ret;
  95        }
  96
  97        v[0] = rtc_tm->tm_hour;
  98        v[1] = rtc_tm->tm_mday;
  99
 100        ret = da9055_group_write(da9055, DA9055_REG_ALARM_H, 2, v);
 101        if (ret < 0)
 102                return ret;
 103
 104        ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO,
 105                                DA9055_RTC_ALM_MONTH, rtc_tm->tm_mon);
 106        if (ret < 0)
 107                dev_err(da9055->dev, "Failed to write ALM Month:%d\n", ret);
 108
 109        ret = da9055_reg_update(da9055, DA9055_REG_ALARM_Y,
 110                                DA9055_RTC_ALM_YEAR, rtc_tm->tm_year);
 111        if (ret < 0)
 112                dev_err(da9055->dev, "Failed to write ALM Year:%d\n", ret);
 113
 114        return ret;
 115}
 116
 117static int da9055_rtc_get_alarm_status(struct da9055 *da9055)
 118{
 119        int ret;
 120
 121        ret = da9055_reg_read(da9055, DA9055_REG_ALARM_Y);
 122        if (ret < 0) {
 123                dev_err(da9055->dev, "Failed to read ALM: %d\n", ret);
 124                return ret;
 125        }
 126        ret &= DA9055_RTC_ALM_EN;
 127        return (ret > 0) ? 1 : 0;
 128}
 129
 130static int da9055_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
 131{
 132        struct da9055_rtc *rtc = dev_get_drvdata(dev);
 133        uint8_t v[6];
 134        int ret;
 135
 136        ret = da9055_reg_read(rtc->da9055, DA9055_REG_COUNT_S);
 137        if (ret < 0)
 138                return ret;
 139
 140        /*
 141         * Registers are only valid when RTC_READ
 142         * status bit is asserted
 143         */
 144        if (!(ret & DA9055_RTC_READ))
 145                return -EBUSY;
 146
 147        ret = da9055_group_read(rtc->da9055, DA9055_REG_COUNT_S, 6, v);
 148        if (ret < 0) {
 149                dev_err(rtc->da9055->dev, "Failed to read RTC time : %d\n",
 150                        ret);
 151                return ret;
 152        }
 153
 154        rtc_tm->tm_year = (v[5] & DA9055_RTC_YEAR) + 100;
 155        rtc_tm->tm_mon  = (v[4] & DA9055_RTC_MONTH) - 1;
 156        rtc_tm->tm_mday = v[3] & DA9055_RTC_DAY;
 157        rtc_tm->tm_hour = v[2] & DA9055_RTC_HOUR;
 158        rtc_tm->tm_min  = v[1] & DA9055_RTC_MIN;
 159        rtc_tm->tm_sec  = v[0] & DA9055_RTC_SEC;
 160
 161        return rtc_valid_tm(rtc_tm);
 162}
 163
 164static int da9055_rtc_set_time(struct device *dev, struct rtc_time *tm)
 165{
 166        struct da9055_rtc *rtc;
 167        uint8_t v[6];
 168
 169        rtc = dev_get_drvdata(dev);
 170
 171        v[0] = tm->tm_sec;
 172        v[1] = tm->tm_min;
 173        v[2] = tm->tm_hour;
 174        v[3] = tm->tm_mday;
 175        v[4] = tm->tm_mon + 1;
 176        v[5] = tm->tm_year - 100;
 177
 178        return da9055_group_write(rtc->da9055, DA9055_REG_COUNT_S, 6, v);
 179}
 180
 181static int da9055_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 182{
 183        int ret;
 184        struct rtc_time *tm = &alrm->time;
 185        struct da9055_rtc *rtc = dev_get_drvdata(dev);
 186
 187        ret = da9055_read_alarm(rtc->da9055, tm);
 188
 189        if (ret)
 190                return ret;
 191
 192        alrm->enabled = da9055_rtc_get_alarm_status(rtc->da9055);
 193
 194        return 0;
 195}
 196
 197static int da9055_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 198{
 199        int ret;
 200        struct rtc_time *tm = &alrm->time;
 201        struct da9055_rtc *rtc = dev_get_drvdata(dev);
 202
 203        ret = da9055_rtc_enable_alarm(rtc, 0);
 204        if (ret < 0)
 205                return ret;
 206
 207        ret = da9055_set_alarm(rtc->da9055, tm);
 208        if (ret)
 209                return ret;
 210
 211        ret = da9055_rtc_enable_alarm(rtc, 1);
 212
 213        return ret;
 214}
 215
 216static int da9055_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 217{
 218        struct da9055_rtc *rtc = dev_get_drvdata(dev);
 219
 220        return da9055_rtc_enable_alarm(rtc, enabled);
 221}
 222
 223static const struct rtc_class_ops da9055_rtc_ops = {
 224        .read_time      = da9055_rtc_read_time,
 225        .set_time       = da9055_rtc_set_time,
 226        .read_alarm     = da9055_rtc_read_alarm,
 227        .set_alarm      = da9055_rtc_set_alarm,
 228        .alarm_irq_enable = da9055_rtc_alarm_irq_enable,
 229};
 230
 231static int da9055_rtc_device_init(struct da9055 *da9055,
 232                                        struct da9055_pdata *pdata)
 233{
 234        int ret;
 235
 236        /* Enable RTC and the internal Crystal */
 237        ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B,
 238                                DA9055_RTC_EN, DA9055_RTC_EN);
 239        if (ret < 0)
 240                return ret;
 241        ret = da9055_reg_update(da9055, DA9055_REG_EN_32K,
 242                                DA9055_CRYSTAL_EN, DA9055_CRYSTAL_EN);
 243        if (ret < 0)
 244                return ret;
 245
 246        /* Enable RTC in Power Down mode */
 247        ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B,
 248                                DA9055_RTC_MODE_PD, DA9055_RTC_MODE_PD);
 249        if (ret < 0)
 250                return ret;
 251
 252        /* Enable RTC in Reset mode */
 253        if (pdata && pdata->reset_enable) {
 254                ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B,
 255                                        DA9055_RTC_MODE_SD,
 256                                        DA9055_RTC_MODE_SD <<
 257                                        DA9055_RTC_MODE_SD_SHIFT);
 258                if (ret < 0)
 259                        return ret;
 260        }
 261
 262        /* Disable the RTC TICK ALM */
 263        ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO,
 264                                DA9055_RTC_TICK_WAKE_MASK, 0);
 265        if (ret < 0)
 266                return ret;
 267
 268        return 0;
 269}
 270
 271static int da9055_rtc_probe(struct platform_device *pdev)
 272{
 273        struct da9055_rtc *rtc;
 274        struct da9055_pdata *pdata = NULL;
 275        int ret, alm_irq;
 276
 277        rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9055_rtc), GFP_KERNEL);
 278        if (!rtc)
 279                return -ENOMEM;
 280
 281        rtc->da9055 = dev_get_drvdata(pdev->dev.parent);
 282        pdata = dev_get_platdata(rtc->da9055->dev);
 283        platform_set_drvdata(pdev, rtc);
 284
 285        ret = da9055_rtc_device_init(rtc->da9055, pdata);
 286        if (ret < 0)
 287                goto err_rtc;
 288
 289        ret = da9055_reg_read(rtc->da9055, DA9055_REG_ALARM_Y);
 290        if (ret < 0)
 291                goto err_rtc;
 292
 293        if (ret & DA9055_RTC_ALM_EN)
 294                rtc->alarm_enable = 1;
 295
 296        device_init_wakeup(&pdev->dev, 1);
 297
 298        rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 299                                        &da9055_rtc_ops, THIS_MODULE);
 300        if (IS_ERR(rtc->rtc)) {
 301                ret = PTR_ERR(rtc->rtc);
 302                goto err_rtc;
 303        }
 304
 305        alm_irq = platform_get_irq_byname(pdev, "ALM");
 306        if (alm_irq < 0)
 307                return alm_irq;
 308
 309        ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL,
 310                                        da9055_rtc_alm_irq,
 311                                        IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 312                                        "ALM", rtc);
 313        if (ret != 0)
 314                dev_err(rtc->da9055->dev, "irq registration failed: %d\n", ret);
 315
 316err_rtc:
 317        return ret;
 318
 319}
 320
 321#ifdef CONFIG_PM
 322/* Turn off the alarm if it should not be a wake source. */
 323static int da9055_rtc_suspend(struct device *dev)
 324{
 325        struct platform_device *pdev = to_platform_device(dev);
 326        struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev);
 327        int ret;
 328
 329        if (!device_may_wakeup(&pdev->dev)) {
 330                /* Disable the ALM IRQ */
 331                ret = da9055_rtc_enable_alarm(rtc, 0);
 332                if (ret < 0)
 333                        dev_err(&pdev->dev, "Failed to disable RTC ALM\n");
 334        }
 335
 336        return 0;
 337}
 338
 339/* Enable the alarm if it should be enabled (in case it was disabled to
 340 * prevent use as a wake source).
 341 */
 342static int da9055_rtc_resume(struct device *dev)
 343{
 344        struct platform_device *pdev = to_platform_device(dev);
 345        struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev);
 346        int ret;
 347
 348        if (!device_may_wakeup(&pdev->dev)) {
 349                if (rtc->alarm_enable) {
 350                        ret = da9055_rtc_enable_alarm(rtc, 1);
 351                        if (ret < 0)
 352                                dev_err(&pdev->dev,
 353                                        "Failed to restart RTC ALM\n");
 354                }
 355        }
 356
 357        return 0;
 358}
 359
 360/* Unconditionally disable the alarm */
 361static int da9055_rtc_freeze(struct device *dev)
 362{
 363        struct platform_device *pdev = to_platform_device(dev);
 364        struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev);
 365        int ret;
 366
 367        ret = da9055_rtc_enable_alarm(rtc, 0);
 368        if (ret < 0)
 369                dev_err(&pdev->dev, "Failed to freeze RTC ALMs\n");
 370
 371        return 0;
 372
 373}
 374#else
 375#define da9055_rtc_suspend NULL
 376#define da9055_rtc_resume NULL
 377#define da9055_rtc_freeze NULL
 378#endif
 379
 380static const struct dev_pm_ops da9055_rtc_pm_ops = {
 381        .suspend = da9055_rtc_suspend,
 382        .resume = da9055_rtc_resume,
 383
 384        .freeze = da9055_rtc_freeze,
 385        .thaw = da9055_rtc_resume,
 386        .restore = da9055_rtc_resume,
 387
 388        .poweroff = da9055_rtc_suspend,
 389};
 390
 391static struct platform_driver da9055_rtc_driver = {
 392        .probe  = da9055_rtc_probe,
 393        .driver = {
 394                .name   = "da9055-rtc",
 395                .pm = &da9055_rtc_pm_ops,
 396        },
 397};
 398
 399module_platform_driver(da9055_rtc_driver);
 400
 401MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
 402MODULE_DESCRIPTION("RTC driver for Dialog DA9055 PMIC");
 403MODULE_LICENSE("GPL");
 404MODULE_ALIAS("platform:da9055-rtc");
 405