linux/drivers/rtc/rtc-da9052.c
<<
>>
Prefs
   1/*
   2 * Real time clock driver for DA9052
   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#include <linux/err.h>
  19#include <linux/delay.h>
  20
  21#include <linux/mfd/da9052/da9052.h>
  22#include <linux/mfd/da9052/reg.h>
  23
  24#define rtc_err(rtc, fmt, ...) \
  25                dev_err(rtc->da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
  26
  27#define DA9052_GET_TIME_RETRIES 5
  28
  29struct da9052_rtc {
  30        struct rtc_device *rtc;
  31        struct da9052 *da9052;
  32};
  33
  34static int da9052_rtc_enable_alarm(struct da9052_rtc *rtc, bool enable)
  35{
  36        int ret;
  37        if (enable) {
  38                ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG,
  39                                DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON,
  40                                DA9052_ALARM_Y_ALARM_ON);
  41                if (ret != 0)
  42                        rtc_err(rtc, "Failed to enable ALM: %d\n", ret);
  43        } else {
  44                ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG,
  45                        DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON, 0);
  46                if (ret != 0)
  47                        rtc_err(rtc, "Write error: %d\n", ret);
  48        }
  49        return ret;
  50}
  51
  52static irqreturn_t da9052_rtc_irq(int irq, void *data)
  53{
  54        struct da9052_rtc *rtc = data;
  55
  56        rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
  57
  58        return IRQ_HANDLED;
  59}
  60
  61static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
  62{
  63        int ret;
  64        uint8_t v[2][5];
  65        int idx = 1;
  66        int timeout = DA9052_GET_TIME_RETRIES;
  67
  68        ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, &v[0][0]);
  69        if (ret) {
  70                rtc_err(rtc, "Failed to group read ALM: %d\n", ret);
  71                return ret;
  72        }
  73
  74        do {
  75                ret = da9052_group_read(rtc->da9052,
  76                                        DA9052_ALARM_MI_REG, 5, &v[idx][0]);
  77                if (ret) {
  78                        rtc_err(rtc, "Failed to group read ALM: %d\n", ret);
  79                        return ret;
  80                }
  81
  82                if (memcmp(&v[0][0], &v[1][0], 5) == 0) {
  83                        rtc_tm->tm_year = (v[0][4] & DA9052_RTC_YEAR) + 100;
  84                        rtc_tm->tm_mon  = (v[0][3] & DA9052_RTC_MONTH) - 1;
  85                        rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY;
  86                        rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR;
  87                        rtc_tm->tm_min  = v[0][0] & DA9052_RTC_MIN;
  88                        rtc_tm->tm_sec = 0;
  89
  90                        ret = rtc_valid_tm(rtc_tm);
  91                        return ret;
  92                }
  93
  94                idx = (1-idx);
  95                msleep(20);
  96
  97        } while (timeout--);
  98
  99        rtc_err(rtc, "Timed out reading alarm time\n");
 100
 101        return -EIO;
 102}
 103
 104static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
 105{
 106        struct da9052 *da9052 = rtc->da9052;
 107        unsigned long alm_time;
 108        int ret;
 109        uint8_t v[3];
 110
 111        ret = rtc_tm_to_time(rtc_tm, &alm_time);
 112        if (ret != 0)
 113                return ret;
 114
 115        if (rtc_tm->tm_sec > 0) {
 116                alm_time += 60 - rtc_tm->tm_sec;
 117                rtc_time_to_tm(alm_time, rtc_tm);
 118        }
 119        BUG_ON(rtc_tm->tm_sec); /* it will cause repeated irqs if not zero */
 120
 121        rtc_tm->tm_year -= 100;
 122        rtc_tm->tm_mon += 1;
 123
 124        ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG,
 125                                DA9052_RTC_MIN, rtc_tm->tm_min);
 126        if (ret != 0) {
 127                rtc_err(rtc, "Failed to write ALRM MIN: %d\n", ret);
 128                return ret;
 129        }
 130
 131        v[0] = rtc_tm->tm_hour;
 132        v[1] = rtc_tm->tm_mday;
 133        v[2] = rtc_tm->tm_mon;
 134
 135        ret = da9052_group_write(da9052, DA9052_ALARM_H_REG, 3, v);
 136        if (ret < 0)
 137                return ret;
 138
 139        ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
 140                                DA9052_RTC_YEAR, rtc_tm->tm_year);
 141        if (ret != 0)
 142                rtc_err(rtc, "Failed to write ALRM YEAR: %d\n", ret);
 143
 144        return ret;
 145}
 146
 147static int da9052_rtc_get_alarm_status(struct da9052_rtc *rtc)
 148{
 149        int ret;
 150
 151        ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_Y_REG);
 152        if (ret < 0) {
 153                rtc_err(rtc, "Failed to read ALM: %d\n", ret);
 154                return ret;
 155        }
 156
 157        return !!(ret&DA9052_ALARM_Y_ALARM_ON);
 158}
 159
 160static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
 161{
 162        struct da9052_rtc *rtc = dev_get_drvdata(dev);
 163        int ret;
 164        uint8_t v[2][6];
 165        int idx = 1;
 166        int timeout = DA9052_GET_TIME_RETRIES;
 167
 168        ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, &v[0][0]);
 169        if (ret) {
 170                rtc_err(rtc, "Failed to read RTC time : %d\n", ret);
 171                return ret;
 172        }
 173
 174        do {
 175                ret = da9052_group_read(rtc->da9052,
 176                                        DA9052_COUNT_S_REG, 6, &v[idx][0]);
 177                if (ret) {
 178                        rtc_err(rtc, "Failed to read RTC time : %d\n", ret);
 179                        return ret;
 180                }
 181
 182                if (memcmp(&v[0][0], &v[1][0], 6) == 0) {
 183                        rtc_tm->tm_year = (v[0][5] & DA9052_RTC_YEAR) + 100;
 184                        rtc_tm->tm_mon  = (v[0][4] & DA9052_RTC_MONTH) - 1;
 185                        rtc_tm->tm_mday = v[0][3] & DA9052_RTC_DAY;
 186                        rtc_tm->tm_hour = v[0][2] & DA9052_RTC_HOUR;
 187                        rtc_tm->tm_min  = v[0][1] & DA9052_RTC_MIN;
 188                        rtc_tm->tm_sec  = v[0][0] & DA9052_RTC_SEC;
 189
 190                        ret = rtc_valid_tm(rtc_tm);
 191                        return ret;
 192                }
 193
 194                idx = (1-idx);
 195                msleep(20);
 196
 197        } while (timeout--);
 198
 199        rtc_err(rtc, "Timed out reading time\n");
 200
 201        return -EIO;
 202}
 203
 204static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm)
 205{
 206        struct da9052_rtc *rtc;
 207        uint8_t v[6];
 208        int ret;
 209
 210        /* DA9052 only has 6 bits for year - to represent 2000-2063 */
 211        if ((tm->tm_year < 100) || (tm->tm_year > 163))
 212                return -EINVAL;
 213
 214        rtc = dev_get_drvdata(dev);
 215
 216        v[0] = tm->tm_sec;
 217        v[1] = tm->tm_min;
 218        v[2] = tm->tm_hour;
 219        v[3] = tm->tm_mday;
 220        v[4] = tm->tm_mon + 1;
 221        v[5] = tm->tm_year - 100;
 222
 223        ret = da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
 224        if (ret < 0)
 225                rtc_err(rtc, "failed to set RTC time: %d\n", ret);
 226        return ret;
 227}
 228
 229static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 230{
 231        int ret;
 232        struct rtc_time *tm = &alrm->time;
 233        struct da9052_rtc *rtc = dev_get_drvdata(dev);
 234
 235        ret = da9052_read_alarm(rtc, tm);
 236        if (ret < 0) {
 237                rtc_err(rtc, "failed to read RTC alarm: %d\n", ret);
 238                return ret;
 239        }
 240
 241        alrm->enabled = da9052_rtc_get_alarm_status(rtc);
 242        return 0;
 243}
 244
 245static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 246{
 247        int ret;
 248        struct rtc_time *tm = &alrm->time;
 249        struct da9052_rtc *rtc = dev_get_drvdata(dev);
 250
 251        /* DA9052 only has 6 bits for year - to represent 2000-2063 */
 252        if ((tm->tm_year < 100) || (tm->tm_year > 163))
 253                return -EINVAL;
 254
 255        ret = da9052_rtc_enable_alarm(rtc, 0);
 256        if (ret < 0)
 257                return ret;
 258
 259        ret = da9052_set_alarm(rtc, tm);
 260        if (ret < 0)
 261                return ret;
 262
 263        ret = da9052_rtc_enable_alarm(rtc, 1);
 264        return ret;
 265}
 266
 267static int da9052_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 268{
 269        struct da9052_rtc *rtc = dev_get_drvdata(dev);
 270
 271        return da9052_rtc_enable_alarm(rtc, enabled);
 272}
 273
 274static const struct rtc_class_ops da9052_rtc_ops = {
 275        .read_time      = da9052_rtc_read_time,
 276        .set_time       = da9052_rtc_set_time,
 277        .read_alarm     = da9052_rtc_read_alarm,
 278        .set_alarm      = da9052_rtc_set_alarm,
 279        .alarm_irq_enable = da9052_rtc_alarm_irq_enable,
 280};
 281
 282static int da9052_rtc_probe(struct platform_device *pdev)
 283{
 284        struct da9052_rtc *rtc;
 285        int ret;
 286
 287        rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9052_rtc), GFP_KERNEL);
 288        if (!rtc)
 289                return -ENOMEM;
 290
 291        rtc->da9052 = dev_get_drvdata(pdev->dev.parent);
 292        platform_set_drvdata(pdev, rtc);
 293
 294        ret = da9052_reg_write(rtc->da9052, DA9052_BBAT_CONT_REG, 0xFE);
 295        if (ret < 0) {
 296                rtc_err(rtc,
 297                        "Failed to setup RTC battery charging: %d\n", ret);
 298                return ret;
 299        }
 300
 301        ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG,
 302                                DA9052_ALARM_Y_TICK_ON, 0);
 303        if (ret != 0)
 304                rtc_err(rtc, "Failed to disable TICKS: %d\n", ret);
 305
 306        device_init_wakeup(&pdev->dev, true);
 307        rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 308                                       &da9052_rtc_ops, THIS_MODULE);
 309
 310        if (IS_ERR(rtc->rtc))
 311                return PTR_ERR(rtc->rtc);
 312
 313        ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM",
 314                                da9052_rtc_irq, rtc);
 315        if (ret != 0) {
 316                rtc_err(rtc, "irq registration failed: %d\n", ret);
 317                return ret;
 318        }
 319
 320        return 0;
 321}
 322
 323static struct platform_driver da9052_rtc_driver = {
 324        .probe  = da9052_rtc_probe,
 325        .driver = {
 326                .name   = "da9052-rtc",
 327        },
 328};
 329
 330module_platform_driver(da9052_rtc_driver);
 331
 332MODULE_AUTHOR("Anthony Olech <Anthony.Olech@diasemi.com>");
 333MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC");
 334MODULE_LICENSE("GPL");
 335MODULE_ALIAS("platform:da9052-rtc");
 336