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