linux/drivers/rtc/rtc-st-lpc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * rtc-st-lpc.c - ST's LPC RTC, powered by the Low Power Timer
   4 *
   5 * Copyright (C) 2014 STMicroelectronics Limited
   6 *
   7 * Author: David Paris <david.paris@st.com> for STMicroelectronics
   8 *         Lee Jones <lee.jones@linaro.org> for STMicroelectronics
   9 *
  10 * Based on the original driver written by Stuart Menefy.
  11 */
  12
  13#include <linux/clk.h>
  14#include <linux/delay.h>
  15#include <linux/init.h>
  16#include <linux/io.h>
  17#include <linux/irq.h>
  18#include <linux/kernel.h>
  19#include <linux/module.h>
  20#include <linux/of.h>
  21#include <linux/of_irq.h>
  22#include <linux/platform_device.h>
  23#include <linux/rtc.h>
  24
  25#include <dt-bindings/mfd/st-lpc.h>
  26
  27/* Low Power Timer */
  28#define LPC_LPT_LSB_OFF         0x400
  29#define LPC_LPT_MSB_OFF         0x404
  30#define LPC_LPT_START_OFF       0x408
  31
  32/* Low Power Alarm */
  33#define LPC_LPA_LSB_OFF         0x410
  34#define LPC_LPA_MSB_OFF         0x414
  35#define LPC_LPA_START_OFF       0x418
  36
  37/* LPC as WDT */
  38#define LPC_WDT_OFF             0x510
  39#define LPC_WDT_FLAG_OFF        0x514
  40
  41struct st_rtc {
  42        struct rtc_device *rtc_dev;
  43        struct rtc_wkalrm alarm;
  44        struct clk *clk;
  45        unsigned long clkrate;
  46        void __iomem *ioaddr;
  47        bool irq_enabled:1;
  48        spinlock_t lock;
  49        short irq;
  50};
  51
  52static void st_rtc_set_hw_alarm(struct st_rtc *rtc,
  53                                unsigned long msb, unsigned long  lsb)
  54{
  55        unsigned long flags;
  56
  57        spin_lock_irqsave(&rtc->lock, flags);
  58
  59        writel_relaxed(1, rtc->ioaddr + LPC_WDT_OFF);
  60
  61        writel_relaxed(msb, rtc->ioaddr + LPC_LPA_MSB_OFF);
  62        writel_relaxed(lsb, rtc->ioaddr + LPC_LPA_LSB_OFF);
  63        writel_relaxed(1, rtc->ioaddr + LPC_LPA_START_OFF);
  64
  65        writel_relaxed(0, rtc->ioaddr + LPC_WDT_OFF);
  66
  67        spin_unlock_irqrestore(&rtc->lock, flags);
  68}
  69
  70static irqreturn_t st_rtc_handler(int this_irq, void *data)
  71{
  72        struct st_rtc *rtc = (struct st_rtc *)data;
  73
  74        rtc_update_irq(rtc->rtc_dev, 1, RTC_AF);
  75
  76        return IRQ_HANDLED;
  77}
  78
  79static int st_rtc_read_time(struct device *dev, struct rtc_time *tm)
  80{
  81        struct st_rtc *rtc = dev_get_drvdata(dev);
  82        unsigned long lpt_lsb, lpt_msb;
  83        unsigned long long lpt;
  84        unsigned long flags;
  85
  86        spin_lock_irqsave(&rtc->lock, flags);
  87
  88        do {
  89                lpt_msb = readl_relaxed(rtc->ioaddr + LPC_LPT_MSB_OFF);
  90                lpt_lsb = readl_relaxed(rtc->ioaddr + LPC_LPT_LSB_OFF);
  91        } while (readl_relaxed(rtc->ioaddr + LPC_LPT_MSB_OFF) != lpt_msb);
  92
  93        spin_unlock_irqrestore(&rtc->lock, flags);
  94
  95        lpt = ((unsigned long long)lpt_msb << 32) | lpt_lsb;
  96        do_div(lpt, rtc->clkrate);
  97        rtc_time64_to_tm(lpt, tm);
  98
  99        return 0;
 100}
 101
 102static int st_rtc_set_time(struct device *dev, struct rtc_time *tm)
 103{
 104        struct st_rtc *rtc = dev_get_drvdata(dev);
 105        unsigned long long lpt, secs;
 106        unsigned long flags;
 107
 108        secs = rtc_tm_to_time64(tm);
 109
 110        lpt = (unsigned long long)secs * rtc->clkrate;
 111
 112        spin_lock_irqsave(&rtc->lock, flags);
 113
 114        writel_relaxed(lpt >> 32, rtc->ioaddr + LPC_LPT_MSB_OFF);
 115        writel_relaxed(lpt, rtc->ioaddr + LPC_LPT_LSB_OFF);
 116        writel_relaxed(1, rtc->ioaddr + LPC_LPT_START_OFF);
 117
 118        spin_unlock_irqrestore(&rtc->lock, flags);
 119
 120        return 0;
 121}
 122
 123static int st_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 124{
 125        struct st_rtc *rtc = dev_get_drvdata(dev);
 126        unsigned long flags;
 127
 128        spin_lock_irqsave(&rtc->lock, flags);
 129
 130        memcpy(wkalrm, &rtc->alarm, sizeof(struct rtc_wkalrm));
 131
 132        spin_unlock_irqrestore(&rtc->lock, flags);
 133
 134        return 0;
 135}
 136
 137static int st_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 138{
 139        struct st_rtc *rtc = dev_get_drvdata(dev);
 140
 141        if (enabled && !rtc->irq_enabled) {
 142                enable_irq(rtc->irq);
 143                rtc->irq_enabled = true;
 144        } else if (!enabled && rtc->irq_enabled) {
 145                disable_irq(rtc->irq);
 146                rtc->irq_enabled = false;
 147        }
 148
 149        return 0;
 150}
 151
 152static int st_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 153{
 154        struct st_rtc *rtc = dev_get_drvdata(dev);
 155        struct rtc_time now;
 156        unsigned long long now_secs;
 157        unsigned long long alarm_secs;
 158        unsigned long long lpa;
 159
 160        st_rtc_read_time(dev, &now);
 161        now_secs = rtc_tm_to_time64(&now);
 162        alarm_secs = rtc_tm_to_time64(&t->time);
 163
 164        memcpy(&rtc->alarm, t, sizeof(struct rtc_wkalrm));
 165
 166        /* Now many secs to fire */
 167        alarm_secs -= now_secs;
 168        lpa = (unsigned long long)alarm_secs * rtc->clkrate;
 169
 170        st_rtc_set_hw_alarm(rtc, lpa >> 32, lpa);
 171        st_rtc_alarm_irq_enable(dev, t->enabled);
 172
 173        return 0;
 174}
 175
 176static struct rtc_class_ops st_rtc_ops = {
 177        .read_time              = st_rtc_read_time,
 178        .set_time               = st_rtc_set_time,
 179        .read_alarm             = st_rtc_read_alarm,
 180        .set_alarm              = st_rtc_set_alarm,
 181        .alarm_irq_enable       = st_rtc_alarm_irq_enable,
 182};
 183
 184static int st_rtc_probe(struct platform_device *pdev)
 185{
 186        struct device_node *np = pdev->dev.of_node;
 187        struct st_rtc *rtc;
 188        uint32_t mode;
 189        int ret = 0;
 190
 191        ret = of_property_read_u32(np, "st,lpc-mode", &mode);
 192        if (ret) {
 193                dev_err(&pdev->dev, "An LPC mode must be provided\n");
 194                return -EINVAL;
 195        }
 196
 197        /* LPC can either run as a Clocksource or in RTC or WDT mode */
 198        if (mode != ST_LPC_MODE_RTC)
 199                return -ENODEV;
 200
 201        rtc = devm_kzalloc(&pdev->dev, sizeof(struct st_rtc), GFP_KERNEL);
 202        if (!rtc)
 203                return -ENOMEM;
 204
 205        rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
 206        if (IS_ERR(rtc->rtc_dev))
 207                return PTR_ERR(rtc->rtc_dev);
 208
 209        spin_lock_init(&rtc->lock);
 210
 211        rtc->ioaddr = devm_platform_ioremap_resource(pdev, 0);
 212        if (IS_ERR(rtc->ioaddr))
 213                return PTR_ERR(rtc->ioaddr);
 214
 215        rtc->irq = irq_of_parse_and_map(np, 0);
 216        if (!rtc->irq) {
 217                dev_err(&pdev->dev, "IRQ missing or invalid\n");
 218                return -EINVAL;
 219        }
 220
 221        ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler, 0,
 222                               pdev->name, rtc);
 223        if (ret) {
 224                dev_err(&pdev->dev, "Failed to request irq %i\n", rtc->irq);
 225                return ret;
 226        }
 227
 228        enable_irq_wake(rtc->irq);
 229        disable_irq(rtc->irq);
 230
 231        rtc->clk = clk_get(&pdev->dev, NULL);
 232        if (IS_ERR(rtc->clk)) {
 233                dev_err(&pdev->dev, "Unable to request clock\n");
 234                return PTR_ERR(rtc->clk);
 235        }
 236
 237        clk_prepare_enable(rtc->clk);
 238
 239        rtc->clkrate = clk_get_rate(rtc->clk);
 240        if (!rtc->clkrate) {
 241                dev_err(&pdev->dev, "Unable to fetch clock rate\n");
 242                return -EINVAL;
 243        }
 244
 245        device_set_wakeup_capable(&pdev->dev, 1);
 246
 247        platform_set_drvdata(pdev, rtc);
 248
 249        rtc->rtc_dev->ops = &st_rtc_ops;
 250        rtc->rtc_dev->range_max = U64_MAX;
 251        do_div(rtc->rtc_dev->range_max, rtc->clkrate);
 252
 253        ret = rtc_register_device(rtc->rtc_dev);
 254        if (ret) {
 255                clk_disable_unprepare(rtc->clk);
 256                return ret;
 257        }
 258
 259        return 0;
 260}
 261
 262#ifdef CONFIG_PM_SLEEP
 263static int st_rtc_suspend(struct device *dev)
 264{
 265        struct st_rtc *rtc = dev_get_drvdata(dev);
 266
 267        if (device_may_wakeup(dev))
 268                return 0;
 269
 270        writel_relaxed(1, rtc->ioaddr + LPC_WDT_OFF);
 271        writel_relaxed(0, rtc->ioaddr + LPC_LPA_START_OFF);
 272        writel_relaxed(0, rtc->ioaddr + LPC_WDT_OFF);
 273
 274        return 0;
 275}
 276
 277static int st_rtc_resume(struct device *dev)
 278{
 279        struct st_rtc *rtc = dev_get_drvdata(dev);
 280
 281        rtc_alarm_irq_enable(rtc->rtc_dev, 0);
 282
 283        /*
 284         * clean 'rtc->alarm' to allow a new
 285         * .set_alarm to the upper RTC layer
 286         */
 287        memset(&rtc->alarm, 0, sizeof(struct rtc_wkalrm));
 288
 289        writel_relaxed(0, rtc->ioaddr + LPC_LPA_MSB_OFF);
 290        writel_relaxed(0, rtc->ioaddr + LPC_LPA_LSB_OFF);
 291        writel_relaxed(1, rtc->ioaddr + LPC_WDT_OFF);
 292        writel_relaxed(1, rtc->ioaddr + LPC_LPA_START_OFF);
 293        writel_relaxed(0, rtc->ioaddr + LPC_WDT_OFF);
 294
 295        return 0;
 296}
 297#endif
 298
 299static SIMPLE_DEV_PM_OPS(st_rtc_pm_ops, st_rtc_suspend, st_rtc_resume);
 300
 301static const struct of_device_id st_rtc_match[] = {
 302        { .compatible = "st,stih407-lpc" },
 303        {}
 304};
 305MODULE_DEVICE_TABLE(of, st_rtc_match);
 306
 307static struct platform_driver st_rtc_platform_driver = {
 308        .driver = {
 309                .name = "st-lpc-rtc",
 310                .pm = &st_rtc_pm_ops,
 311                .of_match_table = st_rtc_match,
 312        },
 313        .probe = st_rtc_probe,
 314};
 315
 316module_platform_driver(st_rtc_platform_driver);
 317
 318MODULE_DESCRIPTION("STMicroelectronics LPC RTC driver");
 319MODULE_AUTHOR("David Paris <david.paris@st.com>");
 320MODULE_LICENSE("GPL");
 321