rtc-st-lpc.c (7604B)
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 const 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 = devm_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");