1 /* 2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> 3 * Copyright (C) 2010, Paul Cercueil <paul@crapouillou.net> 4 * JZ4740 SoC RTC driver 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your 9 * option) any later version. 10 * 11 * You should have received a copy of the GNU General Public License along 12 * with this program; if not, write to the Free Software Foundation, Inc., 13 * 675 Mass Ave, Cambridge, MA 02139, USA. 14 * 15 */ 16 17 #include <linux/io.h> 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/platform_device.h> 21 #include <linux/rtc.h> 22 #include <linux/slab.h> 23 #include <linux/spinlock.h> 24 25 #define JZ_REG_RTC_CTRL 0x00 26 #define JZ_REG_RTC_SEC 0x04 27 #define JZ_REG_RTC_SEC_ALARM 0x08 28 #define JZ_REG_RTC_REGULATOR 0x0C 29 #define JZ_REG_RTC_HIBERNATE 0x20 30 #define JZ_REG_RTC_SCRATCHPAD 0x34 31 32 #define JZ_RTC_CTRL_WRDY BIT(7) 33 #define JZ_RTC_CTRL_1HZ BIT(6) 34 #define JZ_RTC_CTRL_1HZ_IRQ BIT(5) 35 #define JZ_RTC_CTRL_AF BIT(4) 36 #define JZ_RTC_CTRL_AF_IRQ BIT(3) 37 #define JZ_RTC_CTRL_AE BIT(2) 38 #define JZ_RTC_CTRL_ENABLE BIT(0) 39 40 struct jz4740_rtc { 41 void __iomem *base; 42 43 struct rtc_device *rtc; 44 45 int irq; 46 47 spinlock_t lock; 48 }; 49 50 static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg) 51 { 52 return readl(rtc->base + reg); 53 } 54 55 static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) 56 { 57 uint32_t ctrl; 58 int timeout = 1000; 59 60 do { 61 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); 62 } while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout); 63 64 return timeout ? 0 : -EIO; 65 } 66 67 static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, 68 uint32_t val) 69 { 70 int ret; 71 ret = jz4740_rtc_wait_write_ready(rtc); 72 if (ret == 0) 73 writel(val, rtc->base + reg); 74 75 return ret; 76 } 77 78 static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, 79 bool set) 80 { 81 int ret; 82 unsigned long flags; 83 uint32_t ctrl; 84 85 spin_lock_irqsave(&rtc->lock, flags); 86 87 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); 88 89 /* Don't clear interrupt flags by accident */ 90 ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF; 91 92 if (set) 93 ctrl |= mask; 94 else 95 ctrl &= ~mask; 96 97 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); 98 99 spin_unlock_irqrestore(&rtc->lock, flags); 100 101 return ret; 102 } 103 104 static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time) 105 { 106 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 107 uint32_t secs, secs2; 108 int timeout = 5; 109 110 /* If the seconds register is read while it is updated, it can contain a 111 * bogus value. This can be avoided by making sure that two consecutive 112 * reads have the same value. 113 */ 114 secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); 115 secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); 116 117 while (secs != secs2 && --timeout) { 118 secs = secs2; 119 secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); 120 } 121 122 if (timeout == 0) 123 return -EIO; 124 125 rtc_time_to_tm(secs, time); 126 127 return rtc_valid_tm(time); 128 } 129 130 static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs) 131 { 132 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 133 134 return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); 135 } 136 137 static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 138 { 139 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 140 uint32_t secs; 141 uint32_t ctrl; 142 143 secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM); 144 145 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); 146 147 alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE); 148 alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF); 149 150 rtc_time_to_tm(secs, &alrm->time); 151 152 return rtc_valid_tm(&alrm->time); 153 } 154 155 static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 156 { 157 int ret; 158 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 159 unsigned long secs; 160 161 rtc_tm_to_time(&alrm->time, &secs); 162 163 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); 164 if (!ret) 165 ret = jz4740_rtc_ctrl_set_bits(rtc, 166 JZ_RTC_CTRL_AE | JZ_RTC_CTRL_AF_IRQ, alrm->enabled); 167 168 return ret; 169 } 170 171 static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) 172 { 173 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 174 return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable); 175 } 176 177 static struct rtc_class_ops jz4740_rtc_ops = { 178 .read_time = jz4740_rtc_read_time, 179 .set_mmss = jz4740_rtc_set_mmss, 180 .read_alarm = jz4740_rtc_read_alarm, 181 .set_alarm = jz4740_rtc_set_alarm, 182 .alarm_irq_enable = jz4740_rtc_alarm_irq_enable, 183 }; 184 185 static irqreturn_t jz4740_rtc_irq(int irq, void *data) 186 { 187 struct jz4740_rtc *rtc = data; 188 uint32_t ctrl; 189 unsigned long events = 0; 190 191 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); 192 193 if (ctrl & JZ_RTC_CTRL_1HZ) 194 events |= (RTC_UF | RTC_IRQF); 195 196 if (ctrl & JZ_RTC_CTRL_AF) 197 events |= (RTC_AF | RTC_IRQF); 198 199 rtc_update_irq(rtc->rtc, 1, events); 200 201 jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false); 202 203 return IRQ_HANDLED; 204 } 205 206 void jz4740_rtc_poweroff(struct device *dev) 207 { 208 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 209 jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1); 210 } 211 EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff); 212 213 static int jz4740_rtc_probe(struct platform_device *pdev) 214 { 215 int ret; 216 struct jz4740_rtc *rtc; 217 uint32_t scratchpad; 218 struct resource *mem; 219 220 rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); 221 if (!rtc) 222 return -ENOMEM; 223 224 rtc->irq = platform_get_irq(pdev, 0); 225 if (rtc->irq < 0) { 226 dev_err(&pdev->dev, "Failed to get platform irq\n"); 227 return -ENOENT; 228 } 229 230 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 231 rtc->base = devm_ioremap_resource(&pdev->dev, mem); 232 if (IS_ERR(rtc->base)) 233 return PTR_ERR(rtc->base); 234 235 spin_lock_init(&rtc->lock); 236 237 platform_set_drvdata(pdev, rtc); 238 239 device_init_wakeup(&pdev->dev, 1); 240 241 rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 242 &jz4740_rtc_ops, THIS_MODULE); 243 if (IS_ERR(rtc->rtc)) { 244 ret = PTR_ERR(rtc->rtc); 245 dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret); 246 return ret; 247 } 248 249 ret = devm_request_irq(&pdev->dev, rtc->irq, jz4740_rtc_irq, 0, 250 pdev->name, rtc); 251 if (ret) { 252 dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret); 253 return ret; 254 } 255 256 scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD); 257 if (scratchpad != 0x12345678) { 258 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); 259 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); 260 if (ret) { 261 dev_err(&pdev->dev, "Could not write write to RTC registers\n"); 262 return ret; 263 } 264 } 265 266 return 0; 267 } 268 269 #ifdef CONFIG_PM 270 static int jz4740_rtc_suspend(struct device *dev) 271 { 272 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 273 274 if (device_may_wakeup(dev)) 275 enable_irq_wake(rtc->irq); 276 return 0; 277 } 278 279 static int jz4740_rtc_resume(struct device *dev) 280 { 281 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 282 283 if (device_may_wakeup(dev)) 284 disable_irq_wake(rtc->irq); 285 return 0; 286 } 287 288 static const struct dev_pm_ops jz4740_pm_ops = { 289 .suspend = jz4740_rtc_suspend, 290 .resume = jz4740_rtc_resume, 291 }; 292 #define JZ4740_RTC_PM_OPS (&jz4740_pm_ops) 293 294 #else 295 #define JZ4740_RTC_PM_OPS NULL 296 #endif /* CONFIG_PM */ 297 298 static struct platform_driver jz4740_rtc_driver = { 299 .probe = jz4740_rtc_probe, 300 .driver = { 301 .name = "jz4740-rtc", 302 .owner = THIS_MODULE, 303 .pm = JZ4740_RTC_PM_OPS, 304 }, 305 }; 306 307 module_platform_driver(jz4740_rtc_driver); 308 309 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 310 MODULE_LICENSE("GPL"); 311 MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n"); 312 MODULE_ALIAS("platform:jz4740-rtc"); 313