linux/drivers/rtc/rtc-as3722.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * rtc-as3722.c - Real Time Clock driver for ams AS3722 PMICs
   4 *
   5 * Copyright (C) 2013 ams AG
   6 * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
   7 *
   8 * Author: Florian Lobmaier <florian.lobmaier@ams.com>
   9 * Author: Laxman Dewangan <ldewangan@nvidia.com>
  10 */
  11
  12#include <linux/bcd.h>
  13#include <linux/completion.h>
  14#include <linux/delay.h>
  15#include <linux/interrupt.h>
  16#include <linux/ioctl.h>
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/mfd/as3722.h>
  20#include <linux/platform_device.h>
  21#include <linux/rtc.h>
  22#include <linux/time.h>
  23
  24#define AS3722_RTC_START_YEAR     2000
  25struct as3722_rtc {
  26        struct rtc_device       *rtc;
  27        struct device           *dev;
  28        struct as3722           *as3722;
  29        int                     alarm_irq;
  30        bool                    irq_enable;
  31};
  32
  33static void as3722_time_to_reg(u8 *rbuff, struct rtc_time *tm)
  34{
  35        rbuff[0] = bin2bcd(tm->tm_sec);
  36        rbuff[1] = bin2bcd(tm->tm_min);
  37        rbuff[2] = bin2bcd(tm->tm_hour);
  38        rbuff[3] = bin2bcd(tm->tm_mday);
  39        rbuff[4] = bin2bcd(tm->tm_mon + 1);
  40        rbuff[5] = bin2bcd(tm->tm_year - (AS3722_RTC_START_YEAR - 1900));
  41}
  42
  43static void as3722_reg_to_time(u8 *rbuff, struct rtc_time *tm)
  44{
  45        tm->tm_sec = bcd2bin(rbuff[0] & 0x7F);
  46        tm->tm_min = bcd2bin(rbuff[1] & 0x7F);
  47        tm->tm_hour = bcd2bin(rbuff[2] & 0x3F);
  48        tm->tm_mday = bcd2bin(rbuff[3] & 0x3F);
  49        tm->tm_mon = bcd2bin(rbuff[4] & 0x1F) - 1;
  50        tm->tm_year = (AS3722_RTC_START_YEAR - 1900) + bcd2bin(rbuff[5] & 0x7F);
  51        return;
  52}
  53
  54static int as3722_rtc_read_time(struct device *dev, struct rtc_time *tm)
  55{
  56        struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
  57        struct as3722 *as3722 = as3722_rtc->as3722;
  58        u8 as_time_array[6];
  59        int ret;
  60
  61        ret = as3722_block_read(as3722, AS3722_RTC_SECOND_REG,
  62                        6, as_time_array);
  63        if (ret < 0) {
  64                dev_err(dev, "RTC_SECOND reg block read failed %d\n", ret);
  65                return ret;
  66        }
  67        as3722_reg_to_time(as_time_array, tm);
  68        return 0;
  69}
  70
  71static int as3722_rtc_set_time(struct device *dev, struct rtc_time *tm)
  72{
  73        struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
  74        struct as3722 *as3722 = as3722_rtc->as3722;
  75        u8 as_time_array[6];
  76        int ret;
  77
  78        if (tm->tm_year < (AS3722_RTC_START_YEAR - 1900))
  79                return -EINVAL;
  80
  81        as3722_time_to_reg(as_time_array, tm);
  82        ret = as3722_block_write(as3722, AS3722_RTC_SECOND_REG, 6,
  83                        as_time_array);
  84        if (ret < 0)
  85                dev_err(dev, "RTC_SECOND reg block write failed %d\n", ret);
  86        return ret;
  87}
  88
  89static int as3722_rtc_alarm_irq_enable(struct device *dev,
  90                unsigned int enabled)
  91{
  92        struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
  93
  94        if (enabled && !as3722_rtc->irq_enable) {
  95                enable_irq(as3722_rtc->alarm_irq);
  96                as3722_rtc->irq_enable = true;
  97        } else if (!enabled && as3722_rtc->irq_enable)  {
  98                disable_irq(as3722_rtc->alarm_irq);
  99                as3722_rtc->irq_enable = false;
 100        }
 101        return 0;
 102}
 103
 104static int as3722_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 105{
 106        struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
 107        struct as3722 *as3722 = as3722_rtc->as3722;
 108        u8 as_time_array[6];
 109        int ret;
 110
 111        ret = as3722_block_read(as3722, AS3722_RTC_ALARM_SECOND_REG, 6,
 112                        as_time_array);
 113        if (ret < 0) {
 114                dev_err(dev, "RTC_ALARM_SECOND block read failed %d\n", ret);
 115                return ret;
 116        }
 117
 118        as3722_reg_to_time(as_time_array, &alrm->time);
 119        return 0;
 120}
 121
 122static int as3722_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 123{
 124        struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
 125        struct as3722 *as3722 = as3722_rtc->as3722;
 126        u8 as_time_array[6];
 127        int ret;
 128
 129        if (alrm->time.tm_year < (AS3722_RTC_START_YEAR - 1900))
 130                return -EINVAL;
 131
 132        ret = as3722_rtc_alarm_irq_enable(dev, 0);
 133        if (ret < 0) {
 134                dev_err(dev, "Disable RTC alarm failed\n");
 135                return ret;
 136        }
 137
 138        as3722_time_to_reg(as_time_array, &alrm->time);
 139        ret = as3722_block_write(as3722, AS3722_RTC_ALARM_SECOND_REG, 6,
 140                        as_time_array);
 141        if (ret < 0) {
 142                dev_err(dev, "RTC_ALARM_SECOND block write failed %d\n", ret);
 143                return ret;
 144        }
 145
 146        if (alrm->enabled)
 147                ret = as3722_rtc_alarm_irq_enable(dev, alrm->enabled);
 148        return ret;
 149}
 150
 151static irqreturn_t as3722_alarm_irq(int irq, void *data)
 152{
 153        struct as3722_rtc *as3722_rtc = data;
 154
 155        rtc_update_irq(as3722_rtc->rtc, 1, RTC_IRQF | RTC_AF);
 156        return IRQ_HANDLED;
 157}
 158
 159static const struct rtc_class_ops as3722_rtc_ops = {
 160        .read_time = as3722_rtc_read_time,
 161        .set_time = as3722_rtc_set_time,
 162        .read_alarm = as3722_rtc_read_alarm,
 163        .set_alarm = as3722_rtc_set_alarm,
 164        .alarm_irq_enable = as3722_rtc_alarm_irq_enable,
 165};
 166
 167static int as3722_rtc_probe(struct platform_device *pdev)
 168{
 169        struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);
 170        struct as3722_rtc *as3722_rtc;
 171        int ret;
 172
 173        as3722_rtc = devm_kzalloc(&pdev->dev, sizeof(*as3722_rtc), GFP_KERNEL);
 174        if (!as3722_rtc)
 175                return -ENOMEM;
 176
 177        as3722_rtc->as3722 = as3722;
 178        as3722_rtc->dev = &pdev->dev;
 179        platform_set_drvdata(pdev, as3722_rtc);
 180
 181        /* Enable the RTC to make sure it is running. */
 182        ret = as3722_update_bits(as3722, AS3722_RTC_CONTROL_REG,
 183                        AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN,
 184                        AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN);
 185        if (ret < 0) {
 186                dev_err(&pdev->dev, "RTC_CONTROL reg write failed: %d\n", ret);
 187                return ret;
 188        }
 189
 190        device_init_wakeup(&pdev->dev, 1);
 191
 192        as3722_rtc->rtc = devm_rtc_device_register(&pdev->dev, "as3722-rtc",
 193                                &as3722_rtc_ops, THIS_MODULE);
 194        if (IS_ERR(as3722_rtc->rtc)) {
 195                ret = PTR_ERR(as3722_rtc->rtc);
 196                dev_err(&pdev->dev, "RTC register failed: %d\n", ret);
 197                return ret;
 198        }
 199
 200        as3722_rtc->alarm_irq = platform_get_irq(pdev, 0);
 201        dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq);
 202
 203        ret = devm_request_threaded_irq(&pdev->dev, as3722_rtc->alarm_irq, NULL,
 204                        as3722_alarm_irq, IRQF_ONESHOT,
 205                        "rtc-alarm", as3722_rtc);
 206        if (ret < 0) {
 207                dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
 208                                as3722_rtc->alarm_irq, ret);
 209                return ret;
 210        }
 211        disable_irq(as3722_rtc->alarm_irq);
 212        return 0;
 213}
 214
 215#ifdef CONFIG_PM_SLEEP
 216static int as3722_rtc_suspend(struct device *dev)
 217{
 218        struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
 219
 220        if (device_may_wakeup(dev))
 221                enable_irq_wake(as3722_rtc->alarm_irq);
 222
 223        return 0;
 224}
 225
 226static int as3722_rtc_resume(struct device *dev)
 227{
 228        struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev);
 229
 230        if (device_may_wakeup(dev))
 231                disable_irq_wake(as3722_rtc->alarm_irq);
 232        return 0;
 233}
 234#endif
 235
 236static SIMPLE_DEV_PM_OPS(as3722_rtc_pm_ops, as3722_rtc_suspend,
 237                         as3722_rtc_resume);
 238
 239static struct platform_driver as3722_rtc_driver = {
 240        .probe = as3722_rtc_probe,
 241        .driver = {
 242                .name = "as3722-rtc",
 243                .pm = &as3722_rtc_pm_ops,
 244        },
 245};
 246module_platform_driver(as3722_rtc_driver);
 247
 248MODULE_DESCRIPTION("RTC driver for AS3722 PMICs");
 249MODULE_ALIAS("platform:as3722-rtc");
 250MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
 251MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
 252MODULE_LICENSE("GPL");
 253