| Date: | 2010-06-28 01:30:56 (13 years 5 months ago) |
|---|---|
| Author: | Lars C. |
| Commit: | 3deecc1845ad830cb640d439b23e78824324e153 |
| Message: | RTC: jz4740: Propergate write errors in jz4740_rtc_reg_write up to
its callers |
| Files: |
drivers/rtc/rtc-jz4740.c (10 diffs) |
Change Details
| drivers/rtc/rtc-jz4740.c | ||
|---|---|---|
| 1 | 1 | /* |
| 2 | 2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> |
| 3 | * JZ4740 SoC RTC driver | |
| 3 | * JZ4740 SoC RTC driver | |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | 6 | * under the terms of the GNU General Public License as published by the |
| ... | ... | |
| 51 | 51 | return readl(rtc->base + reg); |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | static inline void jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) | |
| 54 | static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) | |
| 55 | 55 | { |
| 56 | 56 | uint32_t ctrl; |
| 57 | int timeout = 10; | |
| 57 | int timeout = 1000; | |
| 58 | 58 | |
| 59 | 59 | do { |
| 60 | 60 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); |
| 61 | } while (!(ctrl & JZ_RTC_CTRL_WRDY) && timeout--); | |
| 61 | } while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout); | |
| 62 | ||
| 63 | return timeout ? 0 : -EIO; | |
| 62 | 64 | } |
| 63 | 65 | |
| 64 | static inline void jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, | |
| 66 | static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, | |
| 65 | 67 | uint32_t val) |
| 66 | 68 | { |
| 67 | jz4740_rtc_wait_write_ready(rtc); | |
| 68 | writel(val, rtc->base + reg); | |
| 69 | int ret; | |
| 70 | ret = jz4740_rtc_wait_write_ready(rtc); | |
| 71 | if (ret == 0) | |
| 72 | writel(val, rtc->base + reg); | |
| 73 | ||
| 74 | return ret; | |
| 69 | 75 | } |
| 70 | 76 | |
| 71 | static void jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, | |
| 72 | uint32_t val) | |
| 77 | static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, | |
| 78 | bool set) | |
| 73 | 79 | { |
| 80 | int ret; | |
| 74 | 81 | unsigned long flags; |
| 75 | 82 | uint32_t ctrl; |
| 76 | 83 | |
| ... | ... | |
| 81 | 88 | /* Don't clear interrupt flags by accident */ |
| 82 | 89 | ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF; |
| 83 | 90 | |
| 84 | ctrl &= ~mask; | |
| 85 | ctrl |= val; | |
| 91 | if (set) | |
| 92 | ctrl |= mask; | |
| 93 | else | |
| 94 | ctrl &= ~mask; | |
| 86 | 95 | |
| 87 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); | |
| 96 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); | |
| 88 | 97 | |
| 89 | 98 | spin_unlock_irqrestore(&rtc->lock, flags); |
| 99 | ||
| 100 | return ret; | |
| 90 | 101 | } |
| 91 | 102 | |
| 92 | 103 | static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time) |
| ... | ... | |
| 102 | 113 | secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); |
| 103 | 114 | secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); |
| 104 | 115 | |
| 105 | while (secs != secs2 && timeout--) { | |
| 116 | while (secs != secs2 && --timeout) { | |
| 106 | 117 | secs = secs2; |
| 107 | 118 | secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); |
| 108 | 119 | } |
| ... | ... | |
| 119 | 130 | { |
| 120 | 131 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); |
| 121 | 132 | |
| 122 | if ((uint32_t)secs != secs) | |
| 123 | return -EINVAL; | |
| 124 | ||
| 125 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); | |
| 126 | ||
| 127 | return 0; | |
| 133 | return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); | |
| 128 | 134 | } |
| 129 | 135 | |
| 130 | 136 | static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| ... | ... | |
| 147 | 153 | |
| 148 | 154 | static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| 149 | 155 | { |
| 156 | int ret; | |
| 150 | 157 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); |
| 151 | 158 | unsigned long secs; |
| 152 | 159 | |
| 153 | 160 | rtc_tm_to_time(&alrm->time, &secs); |
| 154 | 161 | |
| 155 | if ((uint32_t)secs != secs) | |
| 156 | return -EINVAL; | |
| 157 | ||
| 158 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, (uint32_t)secs); | |
| 159 | jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, | |
| 160 | alrm->enabled ? JZ_RTC_CTRL_AE : 0); | |
| 162 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); | |
| 163 | if (!ret) | |
| 164 | ret = jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, alrm->enabled); | |
| 161 | 165 | |
| 162 | return 0; | |
| 163 | } | |
| 164 | ||
| 165 | static inline int jz4740_irq_enable(struct device *dev, int irq, unsigned int enable) | |
| 166 | { | |
| 167 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | |
| 168 | jz4740_rtc_ctrl_set_bits(rtc, irq, enable ? irq : 0); | |
| 169 | ||
| 170 | return 0; | |
| 166 | return ret; | |
| 171 | 167 | } |
| 172 | 168 | |
| 173 | 169 | static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable) |
| 174 | 170 | { |
| 175 | return jz4740_irq_enable(dev, JZ_RTC_CTRL_1HZ_IRQ, enable); | |
| 171 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | |
| 172 | return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, enable); | |
| 176 | 173 | } |
| 177 | 174 | |
| 178 | 175 | static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) |
| 179 | 176 | { |
| 180 | return jz4740_irq_enable(dev, JZ_RTC_CTRL_AF_IRQ, enable); | |
| 177 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | |
| 178 | return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable); | |
| 181 | 179 | } |
| 182 | 180 | |
| 183 | 181 | static struct rtc_class_ops jz4740_rtc_ops = { |
| ... | ... | |
| 194 | 192 | struct jz4740_rtc *rtc = data; |
| 195 | 193 | uint32_t ctrl; |
| 196 | 194 | unsigned long events = 0; |
| 195 | ||
| 197 | 196 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); |
| 198 | 197 | |
| 199 | 198 | if (ctrl & JZ_RTC_CTRL_1HZ) |
| ... | ... | |
| 204 | 203 | |
| 205 | 204 | rtc_update_irq(rtc->rtc, 1, events); |
| 206 | 205 | |
| 207 | jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, 0); | |
| 206 | jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false); | |
| 208 | 207 | |
| 209 | 208 | return IRQ_HANDLED; |
| 210 | 209 | } |
| ... | ... | |
| 276 | 275 | |
| 277 | 276 | scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD); |
| 278 | 277 | if (scratchpad != 0x12345678) { |
| 279 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); | |
| 280 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); | |
| 278 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); | |
| 279 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); | |
| 280 | if (ret) { | |
| 281 | dev_err(&pdev->dev, "Could not write write to RTC registers\n"); | |
| 282 | goto err_free_irq; | |
| 283 | } | |
| 281 | 284 | } |
| 282 | 285 | |
| 283 | 286 | return 0; |
| 284 | 287 | |
| 288 | err_free_irq: | |
| 289 | free_irq(rtc->irq, rtc); | |
| 285 | 290 | err_unregister_rtc: |
| 286 | 291 | rtc_device_unregister(rtc->rtc); |
| 287 | 292 | err_iounmap: |
| ... | ... | |
| 336 | 341 | |
| 337 | 342 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
| 338 | 343 | MODULE_LICENSE("GPL"); |
| 339 | MODULE_DESCRIPTION("RTC driver for the JZ4720/JZ4740 SoC\n"); | |
| 344 | MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n"); | |
| 340 | 345 | MODULE_ALIAS("platform:jz4740-rtc"); |
Branches:
ben-wpan
ben-wpan-stefan
5396a9238205f20f811ea57898980d3ca82df0b6
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9
