Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.13 327 lines 7.9 kB view raw
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 40struct jz4740_rtc { 41 struct resource *mem; 42 void __iomem *base; 43 44 struct rtc_device *rtc; 45 46 int irq; 47 48 spinlock_t lock; 49}; 50 51static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg) 52{ 53 return readl(rtc->base + reg); 54} 55 56static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) 57{ 58 uint32_t ctrl; 59 int timeout = 1000; 60 61 do { 62 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); 63 } while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout); 64 65 return timeout ? 0 : -EIO; 66} 67 68static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, 69 uint32_t val) 70{ 71 int ret; 72 ret = jz4740_rtc_wait_write_ready(rtc); 73 if (ret == 0) 74 writel(val, rtc->base + reg); 75 76 return ret; 77} 78 79static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, 80 bool set) 81{ 82 int ret; 83 unsigned long flags; 84 uint32_t ctrl; 85 86 spin_lock_irqsave(&rtc->lock, flags); 87 88 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); 89 90 /* Don't clear interrupt flags by accident */ 91 ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF; 92 93 if (set) 94 ctrl |= mask; 95 else 96 ctrl &= ~mask; 97 98 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); 99 100 spin_unlock_irqrestore(&rtc->lock, flags); 101 102 return ret; 103} 104 105static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time) 106{ 107 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 108 uint32_t secs, secs2; 109 int timeout = 5; 110 111 /* If the seconds register is read while it is updated, it can contain a 112 * bogus value. This can be avoided by making sure that two consecutive 113 * reads have the same value. 114 */ 115 secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); 116 secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); 117 118 while (secs != secs2 && --timeout) { 119 secs = secs2; 120 secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); 121 } 122 123 if (timeout == 0) 124 return -EIO; 125 126 rtc_time_to_tm(secs, time); 127 128 return rtc_valid_tm(time); 129} 130 131static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs) 132{ 133 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 134 135 return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); 136} 137 138static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 139{ 140 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 141 uint32_t secs; 142 uint32_t ctrl; 143 144 secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM); 145 146 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); 147 148 alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE); 149 alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF); 150 151 rtc_time_to_tm(secs, &alrm->time); 152 153 return rtc_valid_tm(&alrm->time); 154} 155 156static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 157{ 158 int ret; 159 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 160 unsigned long secs; 161 162 rtc_tm_to_time(&alrm->time, &secs); 163 164 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); 165 if (!ret) 166 ret = jz4740_rtc_ctrl_set_bits(rtc, 167 JZ_RTC_CTRL_AE | JZ_RTC_CTRL_AF_IRQ, alrm->enabled); 168 169 return ret; 170} 171 172static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) 173{ 174 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 175 return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable); 176} 177 178static struct rtc_class_ops jz4740_rtc_ops = { 179 .read_time = jz4740_rtc_read_time, 180 .set_mmss = jz4740_rtc_set_mmss, 181 .read_alarm = jz4740_rtc_read_alarm, 182 .set_alarm = jz4740_rtc_set_alarm, 183 .alarm_irq_enable = jz4740_rtc_alarm_irq_enable, 184}; 185 186static irqreturn_t jz4740_rtc_irq(int irq, void *data) 187{ 188 struct jz4740_rtc *rtc = data; 189 uint32_t ctrl; 190 unsigned long events = 0; 191 192 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); 193 194 if (ctrl & JZ_RTC_CTRL_1HZ) 195 events |= (RTC_UF | RTC_IRQF); 196 197 if (ctrl & JZ_RTC_CTRL_AF) 198 events |= (RTC_AF | RTC_IRQF); 199 200 rtc_update_irq(rtc->rtc, 1, events); 201 202 jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false); 203 204 return IRQ_HANDLED; 205} 206 207void jz4740_rtc_poweroff(struct device *dev) 208{ 209 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 210 jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1); 211} 212EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff); 213 214static int jz4740_rtc_probe(struct platform_device *pdev) 215{ 216 int ret; 217 struct jz4740_rtc *rtc; 218 uint32_t scratchpad; 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 rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 231 if (!rtc->mem) { 232 dev_err(&pdev->dev, "Failed to get platform mmio memory\n"); 233 return -ENOENT; 234 } 235 236 rtc->mem = devm_request_mem_region(&pdev->dev, rtc->mem->start, 237 resource_size(rtc->mem), pdev->name); 238 if (!rtc->mem) { 239 dev_err(&pdev->dev, "Failed to request mmio memory region\n"); 240 return -EBUSY; 241 } 242 243 rtc->base = devm_ioremap_nocache(&pdev->dev, rtc->mem->start, 244 resource_size(rtc->mem)); 245 if (!rtc->base) { 246 dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); 247 return -EBUSY; 248 } 249 250 spin_lock_init(&rtc->lock); 251 252 platform_set_drvdata(pdev, rtc); 253 254 device_init_wakeup(&pdev->dev, 1); 255 256 rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 257 &jz4740_rtc_ops, THIS_MODULE); 258 if (IS_ERR(rtc->rtc)) { 259 ret = PTR_ERR(rtc->rtc); 260 dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret); 261 return ret; 262 } 263 264 ret = devm_request_irq(&pdev->dev, rtc->irq, jz4740_rtc_irq, 0, 265 pdev->name, rtc); 266 if (ret) { 267 dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret); 268 return ret; 269 } 270 271 scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD); 272 if (scratchpad != 0x12345678) { 273 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); 274 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); 275 if (ret) { 276 dev_err(&pdev->dev, "Could not write write to RTC registers\n"); 277 return ret; 278 } 279 } 280 281 return 0; 282} 283 284#ifdef CONFIG_PM 285static int jz4740_rtc_suspend(struct device *dev) 286{ 287 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 288 289 if (device_may_wakeup(dev)) 290 enable_irq_wake(rtc->irq); 291 return 0; 292} 293 294static int jz4740_rtc_resume(struct device *dev) 295{ 296 struct jz4740_rtc *rtc = dev_get_drvdata(dev); 297 298 if (device_may_wakeup(dev)) 299 disable_irq_wake(rtc->irq); 300 return 0; 301} 302 303static const struct dev_pm_ops jz4740_pm_ops = { 304 .suspend = jz4740_rtc_suspend, 305 .resume = jz4740_rtc_resume, 306}; 307#define JZ4740_RTC_PM_OPS (&jz4740_pm_ops) 308 309#else 310#define JZ4740_RTC_PM_OPS NULL 311#endif /* CONFIG_PM */ 312 313static struct platform_driver jz4740_rtc_driver = { 314 .probe = jz4740_rtc_probe, 315 .driver = { 316 .name = "jz4740-rtc", 317 .owner = THIS_MODULE, 318 .pm = JZ4740_RTC_PM_OPS, 319 }, 320}; 321 322module_platform_driver(jz4740_rtc_driver); 323 324MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 325MODULE_LICENSE("GPL"); 326MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n"); 327MODULE_ALIAS("platform:jz4740-rtc");