linux/drivers/rtc/rtc-tps65910.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * rtc-tps65910.c -- TPS65910 Real Time Clock interface
   4 *
   5 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
   6 * Author: Venu Byravarasu <vbyravarasu@nvidia.com>
   7 *
   8 * Based on original TI driver rtc-twl.c
   9 *   Copyright (C) 2007 MontaVista Software, Inc
  10 *   Author: Alexandre Rusev <source@mvista.com>
  11 */
  12
  13#include <linux/kernel.h>
  14#include <linux/errno.h>
  15#include <linux/init.h>
  16#include <linux/module.h>
  17#include <linux/types.h>
  18#include <linux/rtc.h>
  19#include <linux/bcd.h>
  20#include <linux/math64.h>
  21#include <linux/platform_device.h>
  22#include <linux/interrupt.h>
  23#include <linux/mfd/tps65910.h>
  24
  25struct tps65910_rtc {
  26        struct rtc_device       *rtc;
  27        int irq;
  28};
  29
  30/* Total number of RTC registers needed to set time*/
  31#define NUM_TIME_REGS   (TPS65910_YEARS - TPS65910_SECONDS + 1)
  32
  33/* Total number of RTC registers needed to set compensation registers */
  34#define NUM_COMP_REGS   (TPS65910_RTC_COMP_MSB - TPS65910_RTC_COMP_LSB + 1)
  35
  36/* Min and max values supported with 'offset' interface (swapped sign) */
  37#define MIN_OFFSET      (-277761)
  38#define MAX_OFFSET      (277778)
  39
  40/* Number of ticks per hour */
  41#define TICKS_PER_HOUR  (32768 * 3600)
  42
  43/* Multiplier for ppb conversions */
  44#define PPB_MULT        (1000000000LL)
  45
  46static int tps65910_rtc_alarm_irq_enable(struct device *dev,
  47                                         unsigned int enabled)
  48{
  49        struct tps65910 *tps = dev_get_drvdata(dev->parent);
  50        u8 val = 0;
  51
  52        if (enabled)
  53                val = TPS65910_RTC_INTERRUPTS_IT_ALARM;
  54
  55        return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, val);
  56}
  57
  58/*
  59 * Gets current tps65910 RTC time and date parameters.
  60 *
  61 * The RTC's time/alarm representation is not what gmtime(3) requires
  62 * Linux to use:
  63 *
  64 *  - Months are 1..12 vs Linux 0-11
  65 *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
  66 */
  67static int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm)
  68{
  69        unsigned char rtc_data[NUM_TIME_REGS];
  70        struct tps65910 *tps = dev_get_drvdata(dev->parent);
  71        int ret;
  72
  73        /* Copy RTC counting registers to static registers or latches */
  74        ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL,
  75                TPS65910_RTC_CTRL_GET_TIME, TPS65910_RTC_CTRL_GET_TIME);
  76        if (ret < 0) {
  77                dev_err(dev, "RTC CTRL reg update failed with err:%d\n", ret);
  78                return ret;
  79        }
  80
  81        ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, rtc_data,
  82                NUM_TIME_REGS);
  83        if (ret < 0) {
  84                dev_err(dev, "reading from RTC failed with err:%d\n", ret);
  85                return ret;
  86        }
  87
  88        tm->tm_sec = bcd2bin(rtc_data[0]);
  89        tm->tm_min = bcd2bin(rtc_data[1]);
  90        tm->tm_hour = bcd2bin(rtc_data[2]);
  91        tm->tm_mday = bcd2bin(rtc_data[3]);
  92        tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
  93        tm->tm_year = bcd2bin(rtc_data[5]) + 100;
  94
  95        return ret;
  96}
  97
  98static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm)
  99{
 100        unsigned char rtc_data[NUM_TIME_REGS];
 101        struct tps65910 *tps = dev_get_drvdata(dev->parent);
 102        int ret;
 103
 104        rtc_data[0] = bin2bcd(tm->tm_sec);
 105        rtc_data[1] = bin2bcd(tm->tm_min);
 106        rtc_data[2] = bin2bcd(tm->tm_hour);
 107        rtc_data[3] = bin2bcd(tm->tm_mday);
 108        rtc_data[4] = bin2bcd(tm->tm_mon + 1);
 109        rtc_data[5] = bin2bcd(tm->tm_year - 100);
 110
 111        /* Stop RTC while updating the RTC time registers */
 112        ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL,
 113                TPS65910_RTC_CTRL_STOP_RTC, 0);
 114        if (ret < 0) {
 115                dev_err(dev, "RTC stop failed with err:%d\n", ret);
 116                return ret;
 117        }
 118
 119        /* update all the time registers in one shot */
 120        ret = regmap_bulk_write(tps->regmap, TPS65910_SECONDS, rtc_data,
 121                NUM_TIME_REGS);
 122        if (ret < 0) {
 123                dev_err(dev, "rtc_set_time error %d\n", ret);
 124                return ret;
 125        }
 126
 127        /* Start back RTC */
 128        ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL,
 129                TPS65910_RTC_CTRL_STOP_RTC, 1);
 130        if (ret < 0)
 131                dev_err(dev, "RTC start failed with err:%d\n", ret);
 132
 133        return ret;
 134}
 135
 136/*
 137 * Gets current tps65910 RTC alarm time.
 138 */
 139static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 140{
 141        unsigned char alarm_data[NUM_TIME_REGS];
 142        u32 int_val;
 143        struct tps65910 *tps = dev_get_drvdata(dev->parent);
 144        int ret;
 145
 146        ret = regmap_bulk_read(tps->regmap, TPS65910_ALARM_SECONDS, alarm_data,
 147                NUM_TIME_REGS);
 148        if (ret < 0) {
 149                dev_err(dev, "rtc_read_alarm error %d\n", ret);
 150                return ret;
 151        }
 152
 153        alm->time.tm_sec = bcd2bin(alarm_data[0]);
 154        alm->time.tm_min = bcd2bin(alarm_data[1]);
 155        alm->time.tm_hour = bcd2bin(alarm_data[2]);
 156        alm->time.tm_mday = bcd2bin(alarm_data[3]);
 157        alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1;
 158        alm->time.tm_year = bcd2bin(alarm_data[5]) + 100;
 159
 160        ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, &int_val);
 161        if (ret < 0)
 162                return ret;
 163
 164        if (int_val & TPS65910_RTC_INTERRUPTS_IT_ALARM)
 165                alm->enabled = 1;
 166
 167        return ret;
 168}
 169
 170static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 171{
 172        unsigned char alarm_data[NUM_TIME_REGS];
 173        struct tps65910 *tps = dev_get_drvdata(dev->parent);
 174        int ret;
 175
 176        ret = tps65910_rtc_alarm_irq_enable(dev, 0);
 177        if (ret)
 178                return ret;
 179
 180        alarm_data[0] = bin2bcd(alm->time.tm_sec);
 181        alarm_data[1] = bin2bcd(alm->time.tm_min);
 182        alarm_data[2] = bin2bcd(alm->time.tm_hour);
 183        alarm_data[3] = bin2bcd(alm->time.tm_mday);
 184        alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
 185        alarm_data[5] = bin2bcd(alm->time.tm_year - 100);
 186
 187        /* update all the alarm registers in one shot */
 188        ret = regmap_bulk_write(tps->regmap, TPS65910_ALARM_SECONDS,
 189                alarm_data, NUM_TIME_REGS);
 190        if (ret) {
 191                dev_err(dev, "rtc_set_alarm error %d\n", ret);
 192                return ret;
 193        }
 194
 195        if (alm->enabled)
 196                ret = tps65910_rtc_alarm_irq_enable(dev, 1);
 197
 198        return ret;
 199}
 200
 201static int tps65910_rtc_set_calibration(struct device *dev, int calibration)
 202{
 203        unsigned char comp_data[NUM_COMP_REGS];
 204        struct tps65910 *tps = dev_get_drvdata(dev->parent);
 205        s16 value;
 206        int ret;
 207
 208        /*
 209         * TPS65910 uses two's complement 16 bit value for compensation for RTC
 210         * crystal inaccuracies. One time every hour when seconds counter
 211         * increments from 0 to 1 compensation value will be added to internal
 212         * RTC counter value.
 213         *
 214         * Compensation value 0x7FFF is prohibited value.
 215         *
 216         * Valid range for compensation value: [-32768 .. 32766]
 217         */
 218        if ((calibration < -32768) || (calibration > 32766)) {
 219                dev_err(dev, "RTC calibration value out of range: %d\n",
 220                        calibration);
 221                return -EINVAL;
 222        }
 223
 224        value = (s16)calibration;
 225
 226        comp_data[0] = (u16)value & 0xFF;
 227        comp_data[1] = ((u16)value >> 8) & 0xFF;
 228
 229        /* Update all the compensation registers in one shot */
 230        ret = regmap_bulk_write(tps->regmap, TPS65910_RTC_COMP_LSB,
 231                comp_data, NUM_COMP_REGS);
 232        if (ret < 0) {
 233                dev_err(dev, "rtc_set_calibration error: %d\n", ret);
 234                return ret;
 235        }
 236
 237        /* Enable automatic compensation */
 238        ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL,
 239                TPS65910_RTC_CTRL_AUTO_COMP, TPS65910_RTC_CTRL_AUTO_COMP);
 240        if (ret < 0)
 241                dev_err(dev, "auto_comp enable failed with error: %d\n", ret);
 242
 243        return ret;
 244}
 245
 246static int tps65910_rtc_get_calibration(struct device *dev, int *calibration)
 247{
 248        unsigned char comp_data[NUM_COMP_REGS];
 249        struct tps65910 *tps = dev_get_drvdata(dev->parent);
 250        unsigned int ctrl;
 251        u16 value;
 252        int ret;
 253
 254        ret = regmap_read(tps->regmap, TPS65910_RTC_CTRL, &ctrl);
 255        if (ret < 0)
 256                return ret;
 257
 258        /* If automatic compensation is not enabled report back zero */
 259        if (!(ctrl & TPS65910_RTC_CTRL_AUTO_COMP)) {
 260                *calibration = 0;
 261                return 0;
 262        }
 263
 264        ret = regmap_bulk_read(tps->regmap, TPS65910_RTC_COMP_LSB, comp_data,
 265                NUM_COMP_REGS);
 266        if (ret < 0) {
 267                dev_err(dev, "rtc_get_calibration error: %d\n", ret);
 268                return ret;
 269        }
 270
 271        value = (u16)comp_data[0] | ((u16)comp_data[1] << 8);
 272
 273        *calibration = (s16)value;
 274
 275        return 0;
 276}
 277
 278static int tps65910_read_offset(struct device *dev, long *offset)
 279{
 280        int calibration;
 281        s64 tmp;
 282        int ret;
 283
 284        ret = tps65910_rtc_get_calibration(dev, &calibration);
 285        if (ret < 0)
 286                return ret;
 287
 288        /* Convert from RTC calibration register format to ppb format */
 289        tmp = calibration * (s64)PPB_MULT;
 290        if (tmp < 0)
 291                tmp -= TICKS_PER_HOUR / 2LL;
 292        else
 293                tmp += TICKS_PER_HOUR / 2LL;
 294        tmp = div_s64(tmp, TICKS_PER_HOUR);
 295
 296        /* Offset value operates in negative way, so swap sign */
 297        *offset = (long)-tmp;
 298
 299        return 0;
 300}
 301
 302static int tps65910_set_offset(struct device *dev, long offset)
 303{
 304        int calibration;
 305        s64 tmp;
 306        int ret;
 307
 308        /* Make sure offset value is within supported range */
 309        if (offset < MIN_OFFSET || offset > MAX_OFFSET)
 310                return -ERANGE;
 311
 312        /* Convert from ppb format to RTC calibration register format */
 313        tmp = offset * (s64)TICKS_PER_HOUR;
 314        if (tmp < 0)
 315                tmp -= PPB_MULT / 2LL;
 316        else
 317                tmp += PPB_MULT / 2LL;
 318        tmp = div_s64(tmp, PPB_MULT);
 319
 320        /* Offset value operates in negative way, so swap sign */
 321        calibration = (int)-tmp;
 322
 323        ret = tps65910_rtc_set_calibration(dev, calibration);
 324
 325        return ret;
 326}
 327
 328static irqreturn_t tps65910_rtc_interrupt(int irq, void *rtc)
 329{
 330        struct device *dev = rtc;
 331        unsigned long events = 0;
 332        struct tps65910 *tps = dev_get_drvdata(dev->parent);
 333        struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev);
 334        int ret;
 335        u32 rtc_reg;
 336
 337        ret = regmap_read(tps->regmap, TPS65910_RTC_STATUS, &rtc_reg);
 338        if (ret)
 339                return IRQ_NONE;
 340
 341        if (rtc_reg & TPS65910_RTC_STATUS_ALARM)
 342                events = RTC_IRQF | RTC_AF;
 343
 344        ret = regmap_write(tps->regmap, TPS65910_RTC_STATUS, rtc_reg);
 345        if (ret)
 346                return IRQ_NONE;
 347
 348        /* Notify RTC core on event */
 349        rtc_update_irq(tps_rtc->rtc, 1, events);
 350
 351        return IRQ_HANDLED;
 352}
 353
 354static const struct rtc_class_ops tps65910_rtc_ops = {
 355        .read_time      = tps65910_rtc_read_time,
 356        .set_time       = tps65910_rtc_set_time,
 357        .read_alarm     = tps65910_rtc_read_alarm,
 358        .set_alarm      = tps65910_rtc_set_alarm,
 359        .alarm_irq_enable = tps65910_rtc_alarm_irq_enable,
 360        .read_offset    = tps65910_read_offset,
 361        .set_offset     = tps65910_set_offset,
 362};
 363
 364static int tps65910_rtc_probe(struct platform_device *pdev)
 365{
 366        struct tps65910 *tps65910 = NULL;
 367        struct tps65910_rtc *tps_rtc = NULL;
 368        int ret;
 369        int irq;
 370        u32 rtc_reg;
 371
 372        tps65910 = dev_get_drvdata(pdev->dev.parent);
 373
 374        tps_rtc = devm_kzalloc(&pdev->dev, sizeof(struct tps65910_rtc),
 375                        GFP_KERNEL);
 376        if (!tps_rtc)
 377                return -ENOMEM;
 378
 379        tps_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
 380        if (IS_ERR(tps_rtc->rtc))
 381                return PTR_ERR(tps_rtc->rtc);
 382
 383        /* Clear pending interrupts */
 384        ret = regmap_read(tps65910->regmap, TPS65910_RTC_STATUS, &rtc_reg);
 385        if (ret < 0)
 386                return ret;
 387
 388        ret = regmap_write(tps65910->regmap, TPS65910_RTC_STATUS, rtc_reg);
 389        if (ret < 0)
 390                return ret;
 391
 392        dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n");
 393
 394        /* Enable RTC digital power domain */
 395        ret = regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL,
 396                DEVCTRL_RTC_PWDN_MASK, 0 << DEVCTRL_RTC_PWDN_SHIFT);
 397        if (ret < 0)
 398                return ret;
 399
 400        rtc_reg = TPS65910_RTC_CTRL_STOP_RTC;
 401        ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg);
 402        if (ret < 0)
 403                return ret;
 404
 405        platform_set_drvdata(pdev, tps_rtc);
 406
 407        irq  = platform_get_irq(pdev, 0);
 408        if (irq <= 0) {
 409                dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
 410                        irq);
 411                return -ENXIO;
 412        }
 413
 414        ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
 415                tps65910_rtc_interrupt, IRQF_TRIGGER_LOW,
 416                dev_name(&pdev->dev), &pdev->dev);
 417        if (ret < 0) {
 418                dev_err(&pdev->dev, "IRQ is not free.\n");
 419                return ret;
 420        }
 421        tps_rtc->irq = irq;
 422        device_set_wakeup_capable(&pdev->dev, 1);
 423
 424        tps_rtc->rtc->ops = &tps65910_rtc_ops;
 425        tps_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
 426        tps_rtc->rtc->range_max = RTC_TIMESTAMP_END_2099;
 427
 428        ret = rtc_register_device(tps_rtc->rtc);
 429        if (ret) {
 430                dev_err(&pdev->dev, "RTC device register: err %d\n", ret);
 431                return ret;
 432        }
 433
 434        return 0;
 435}
 436
 437#ifdef CONFIG_PM_SLEEP
 438static int tps65910_rtc_suspend(struct device *dev)
 439{
 440        struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev);
 441
 442        if (device_may_wakeup(dev))
 443                enable_irq_wake(tps_rtc->irq);
 444        return 0;
 445}
 446
 447static int tps65910_rtc_resume(struct device *dev)
 448{
 449        struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev);
 450
 451        if (device_may_wakeup(dev))
 452                disable_irq_wake(tps_rtc->irq);
 453        return 0;
 454}
 455#endif
 456
 457static SIMPLE_DEV_PM_OPS(tps65910_rtc_pm_ops, tps65910_rtc_suspend,
 458                        tps65910_rtc_resume);
 459
 460static struct platform_driver tps65910_rtc_driver = {
 461        .probe          = tps65910_rtc_probe,
 462        .driver         = {
 463                .name   = "tps65910-rtc",
 464                .pm     = &tps65910_rtc_pm_ops,
 465        },
 466};
 467
 468module_platform_driver(tps65910_rtc_driver);
 469MODULE_ALIAS("platform:rtc-tps65910");
 470MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
 471MODULE_LICENSE("GPL");
 472