linux/drivers/rtc/rtc-cpcap.c
<<
>>
Prefs
   1/*
   2 * Motorola CPCAP PMIC RTC driver
   3 *
   4 * Based on cpcap-regulator.c from Motorola Linux kernel tree
   5 * Copyright (C) 2009 Motorola, Inc.
   6 *
   7 * Rewritten for mainline kernel
   8 *  - use DT
   9 *  - use regmap
  10 *  - use standard interrupt framework
  11 *  - use managed device resources
  12 *  - remove custom "secure clock daemon" helpers
  13 *
  14 * Copyright (C) 2017 Sebastian Reichel <sre@kernel.org>
  15 *
  16 * This program is free software; you can redistribute it and/or modify
  17 * it under the terms of the GNU General Public License version 2 as
  18 * published by the Free Software Foundation.
  19 *
  20 * This program is distributed in the hope that it will be useful,
  21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23 * GNU General Public License for more details.
  24 */
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/init.h>
  28#include <linux/device.h>
  29#include <linux/platform_device.h>
  30#include <linux/rtc.h>
  31#include <linux/err.h>
  32#include <linux/regmap.h>
  33#include <linux/mfd/motorola-cpcap.h>
  34#include <linux/slab.h>
  35#include <linux/sched.h>
  36
  37#define SECS_PER_DAY 86400
  38#define DAY_MASK  0x7FFF
  39#define TOD1_MASK 0x00FF
  40#define TOD2_MASK 0x01FF
  41
  42struct cpcap_time {
  43        int day;
  44        int tod1;
  45        int tod2;
  46};
  47
  48struct cpcap_rtc {
  49        struct regmap *regmap;
  50        struct rtc_device *rtc_dev;
  51        u16 vendor;
  52        int alarm_irq;
  53        bool alarm_enabled;
  54        int update_irq;
  55        bool update_enabled;
  56};
  57
  58static void cpcap2rtc_time(struct rtc_time *rtc, struct cpcap_time *cpcap)
  59{
  60        unsigned long int tod;
  61        unsigned long int time;
  62
  63        tod = (cpcap->tod1 & TOD1_MASK) | ((cpcap->tod2 & TOD2_MASK) << 8);
  64        time = tod + ((cpcap->day & DAY_MASK) * SECS_PER_DAY);
  65
  66        rtc_time_to_tm(time, rtc);
  67}
  68
  69static void rtc2cpcap_time(struct cpcap_time *cpcap, struct rtc_time *rtc)
  70{
  71        unsigned long time;
  72
  73        rtc_tm_to_time(rtc, &time);
  74
  75        cpcap->day = time / SECS_PER_DAY;
  76        time %= SECS_PER_DAY;
  77        cpcap->tod2 = (time >> 8) & TOD2_MASK;
  78        cpcap->tod1 = time & TOD1_MASK;
  79}
  80
  81static int cpcap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
  82{
  83        struct cpcap_rtc *rtc = dev_get_drvdata(dev);
  84
  85        if (rtc->alarm_enabled == enabled)
  86                return 0;
  87
  88        if (enabled)
  89                enable_irq(rtc->alarm_irq);
  90        else
  91                disable_irq(rtc->alarm_irq);
  92
  93        rtc->alarm_enabled = !!enabled;
  94
  95        return 0;
  96}
  97
  98static int cpcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
  99{
 100        struct cpcap_rtc *rtc;
 101        struct cpcap_time cpcap_tm;
 102        int temp_tod2;
 103        int ret;
 104
 105        rtc = dev_get_drvdata(dev);
 106
 107        ret = regmap_read(rtc->regmap, CPCAP_REG_TOD2, &temp_tod2);
 108        ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);
 109        ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD1, &cpcap_tm.tod1);
 110        ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD2, &cpcap_tm.tod2);
 111
 112        if (temp_tod2 > cpcap_tm.tod2)
 113                ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);
 114
 115        if (ret) {
 116                dev_err(dev, "Failed to read time\n");
 117                return -EIO;
 118        }
 119
 120        cpcap2rtc_time(tm, &cpcap_tm);
 121
 122        return 0;
 123}
 124
 125static int cpcap_rtc_set_time(struct device *dev, struct rtc_time *tm)
 126{
 127        struct cpcap_rtc *rtc;
 128        struct cpcap_time cpcap_tm;
 129        int ret = 0;
 130
 131        rtc = dev_get_drvdata(dev);
 132
 133        rtc2cpcap_time(&cpcap_tm, tm);
 134
 135        if (rtc->alarm_enabled)
 136                disable_irq(rtc->alarm_irq);
 137        if (rtc->update_enabled)
 138                disable_irq(rtc->update_irq);
 139
 140        if (rtc->vendor == CPCAP_VENDOR_ST) {
 141                /* The TOD1 and TOD2 registers MUST be written in this order
 142                 * for the change to properly set.
 143                 */
 144                ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
 145                                          TOD1_MASK, cpcap_tm.tod1);
 146                ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD2,
 147                                          TOD2_MASK, cpcap_tm.tod2);
 148                ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_DAY,
 149                                          DAY_MASK, cpcap_tm.day);
 150        } else {
 151                /* Clearing the upper lower 8 bits of the TOD guarantees that
 152                 * the upper half of TOD (TOD2) will not increment for 0xFF RTC
 153                 * ticks (255 seconds).  During this time we can safely write
 154                 * to DAY, TOD2, then TOD1 (in that order) and expect RTC to be
 155                 * synchronized to the exact time requested upon the final write
 156                 * to TOD1.
 157                 */
 158                ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
 159                                          TOD1_MASK, 0);
 160                ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_DAY,
 161                                          DAY_MASK, cpcap_tm.day);
 162                ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD2,
 163                                          TOD2_MASK, cpcap_tm.tod2);
 164                ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
 165                                          TOD1_MASK, cpcap_tm.tod1);
 166        }
 167
 168        if (rtc->update_enabled)
 169                enable_irq(rtc->update_irq);
 170        if (rtc->alarm_enabled)
 171                enable_irq(rtc->alarm_irq);
 172
 173        return ret;
 174}
 175
 176static int cpcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 177{
 178        struct cpcap_rtc *rtc;
 179        struct cpcap_time cpcap_tm;
 180        int ret;
 181
 182        rtc = dev_get_drvdata(dev);
 183
 184        alrm->enabled = rtc->alarm_enabled;
 185
 186        ret = regmap_read(rtc->regmap, CPCAP_REG_DAYA, &cpcap_tm.day);
 187        ret |= regmap_read(rtc->regmap, CPCAP_REG_TODA2, &cpcap_tm.tod2);
 188        ret |= regmap_read(rtc->regmap, CPCAP_REG_TODA1, &cpcap_tm.tod1);
 189
 190        if (ret) {
 191                dev_err(dev, "Failed to read time\n");
 192                return -EIO;
 193        }
 194
 195        cpcap2rtc_time(&alrm->time, &cpcap_tm);
 196        return rtc_valid_tm(&alrm->time);
 197}
 198
 199static int cpcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 200{
 201        struct cpcap_rtc *rtc;
 202        struct cpcap_time cpcap_tm;
 203        int ret;
 204
 205        rtc = dev_get_drvdata(dev);
 206
 207        rtc2cpcap_time(&cpcap_tm, &alrm->time);
 208
 209        if (rtc->alarm_enabled)
 210                disable_irq(rtc->alarm_irq);
 211
 212        ret = regmap_update_bits(rtc->regmap, CPCAP_REG_DAYA, DAY_MASK,
 213                                 cpcap_tm.day);
 214        ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TODA2, TOD2_MASK,
 215                                  cpcap_tm.tod2);
 216        ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TODA1, TOD1_MASK,
 217                                  cpcap_tm.tod1);
 218
 219        if (!ret) {
 220                enable_irq(rtc->alarm_irq);
 221                rtc->alarm_enabled = true;
 222        }
 223
 224        return ret;
 225}
 226
 227static const struct rtc_class_ops cpcap_rtc_ops = {
 228        .read_time              = cpcap_rtc_read_time,
 229        .set_time               = cpcap_rtc_set_time,
 230        .read_alarm             = cpcap_rtc_read_alarm,
 231        .set_alarm              = cpcap_rtc_set_alarm,
 232        .alarm_irq_enable       = cpcap_rtc_alarm_irq_enable,
 233};
 234
 235static irqreturn_t cpcap_rtc_alarm_irq(int irq, void *data)
 236{
 237        struct cpcap_rtc *rtc = data;
 238
 239        rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
 240        return IRQ_HANDLED;
 241}
 242
 243static irqreturn_t cpcap_rtc_update_irq(int irq, void *data)
 244{
 245        struct cpcap_rtc *rtc = data;
 246
 247        rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
 248        return IRQ_HANDLED;
 249}
 250
 251static int cpcap_rtc_probe(struct platform_device *pdev)
 252{
 253        struct device *dev = &pdev->dev;
 254        struct cpcap_rtc *rtc;
 255        int err;
 256
 257        rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
 258        if (!rtc)
 259                return -ENOMEM;
 260
 261        rtc->regmap = dev_get_regmap(dev->parent, NULL);
 262        if (!rtc->regmap)
 263                return -ENODEV;
 264
 265        platform_set_drvdata(pdev, rtc);
 266        rtc->rtc_dev = devm_rtc_device_register(dev, "cpcap_rtc",
 267                                                &cpcap_rtc_ops, THIS_MODULE);
 268
 269        if (IS_ERR(rtc->rtc_dev))
 270                return PTR_ERR(rtc->rtc_dev);
 271
 272        err = cpcap_get_vendor(dev, rtc->regmap, &rtc->vendor);
 273        if (err)
 274                return err;
 275
 276        rtc->alarm_irq = platform_get_irq(pdev, 0);
 277        err = devm_request_threaded_irq(dev, rtc->alarm_irq, NULL,
 278                                        cpcap_rtc_alarm_irq, IRQF_TRIGGER_NONE,
 279                                        "rtc_alarm", rtc);
 280        if (err) {
 281                dev_err(dev, "Could not request alarm irq: %d\n", err);
 282                return err;
 283        }
 284        disable_irq(rtc->alarm_irq);
 285
 286        /* Stock Android uses the 1 Hz interrupt for "secure clock daemon",
 287         * which is not supported by the mainline kernel. The mainline kernel
 288         * does not use the irq at the moment, but we explicitly request and
 289         * disable it, so that its masked and does not wake up the processor
 290         * every second.
 291         */
 292        rtc->update_irq = platform_get_irq(pdev, 1);
 293        err = devm_request_threaded_irq(dev, rtc->update_irq, NULL,
 294                                        cpcap_rtc_update_irq, IRQF_TRIGGER_NONE,
 295                                        "rtc_1hz", rtc);
 296        if (err) {
 297                dev_err(dev, "Could not request update irq: %d\n", err);
 298                return err;
 299        }
 300        disable_irq(rtc->update_irq);
 301
 302        err = device_init_wakeup(dev, 1);
 303        if (err) {
 304                dev_err(dev, "wakeup initialization failed (%d)\n", err);
 305                /* ignore error and continue without wakeup support */
 306        }
 307
 308        return 0;
 309}
 310
 311static const struct of_device_id cpcap_rtc_of_match[] = {
 312        { .compatible = "motorola,cpcap-rtc", },
 313        {},
 314};
 315MODULE_DEVICE_TABLE(of, cpcap_rtc_of_match);
 316
 317static struct platform_driver cpcap_rtc_driver = {
 318        .probe          = cpcap_rtc_probe,
 319        .driver         = {
 320                .name   = "cpcap-rtc",
 321                .of_match_table = cpcap_rtc_of_match,
 322        },
 323};
 324
 325module_platform_driver(cpcap_rtc_driver);
 326
 327MODULE_ALIAS("platform:cpcap-rtc");
 328MODULE_DESCRIPTION("CPCAP RTC driver");
 329MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
 330MODULE_LICENSE("GPL");
 331