diff options
Diffstat (limited to 'drivers/rtc/rtc-tx4939.c')
-rw-r--r-- | drivers/rtc/rtc-tx4939.c | 56 |
1 files changed, 29 insertions, 27 deletions
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 4a6ed1104fbb..ec6313d15359 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c | |||
@@ -12,11 +12,13 @@ | |||
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/gfp.h> | ||
15 | #include <asm/txx9/tx4939.h> | 16 | #include <asm/txx9/tx4939.h> |
16 | 17 | ||
17 | struct tx4939rtc_plat_data { | 18 | struct tx4939rtc_plat_data { |
18 | struct rtc_device *rtc; | 19 | struct rtc_device *rtc; |
19 | struct tx4939_rtc_reg __iomem *rtcreg; | 20 | struct tx4939_rtc_reg __iomem *rtcreg; |
21 | spinlock_t lock; | ||
20 | }; | 22 | }; |
21 | 23 | ||
22 | static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) | 24 | static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) |
@@ -52,14 +54,14 @@ static int tx4939_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
52 | buf[3] = secs >> 8; | 54 | buf[3] = secs >> 8; |
53 | buf[4] = secs >> 16; | 55 | buf[4] = secs >> 16; |
54 | buf[5] = secs >> 24; | 56 | buf[5] = secs >> 24; |
55 | spin_lock_irq(&pdata->rtc->irq_lock); | 57 | spin_lock_irq(&pdata->lock); |
56 | __raw_writel(0, &rtcreg->adr); | 58 | __raw_writel(0, &rtcreg->adr); |
57 | for (i = 0; i < 6; i++) | 59 | for (i = 0; i < 6; i++) |
58 | __raw_writel(buf[i], &rtcreg->dat); | 60 | __raw_writel(buf[i], &rtcreg->dat); |
59 | ret = tx4939_rtc_cmd(rtcreg, | 61 | ret = tx4939_rtc_cmd(rtcreg, |
60 | TX4939_RTCCTL_COMMAND_SETTIME | | 62 | TX4939_RTCCTL_COMMAND_SETTIME | |
61 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 63 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
62 | spin_unlock_irq(&pdata->rtc->irq_lock); | 64 | spin_unlock_irq(&pdata->lock); |
63 | return ret; | 65 | return ret; |
64 | } | 66 | } |
65 | 67 | ||
@@ -71,18 +73,18 @@ static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
71 | unsigned long sec; | 73 | unsigned long sec; |
72 | unsigned char buf[6]; | 74 | unsigned char buf[6]; |
73 | 75 | ||
74 | spin_lock_irq(&pdata->rtc->irq_lock); | 76 | spin_lock_irq(&pdata->lock); |
75 | ret = tx4939_rtc_cmd(rtcreg, | 77 | ret = tx4939_rtc_cmd(rtcreg, |
76 | TX4939_RTCCTL_COMMAND_GETTIME | | 78 | TX4939_RTCCTL_COMMAND_GETTIME | |
77 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 79 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
78 | if (ret) { | 80 | if (ret) { |
79 | spin_unlock_irq(&pdata->rtc->irq_lock); | 81 | spin_unlock_irq(&pdata->lock); |
80 | return ret; | 82 | return ret; |
81 | } | 83 | } |
82 | __raw_writel(2, &rtcreg->adr); | 84 | __raw_writel(2, &rtcreg->adr); |
83 | for (i = 2; i < 6; i++) | 85 | for (i = 2; i < 6; i++) |
84 | buf[i] = __raw_readl(&rtcreg->dat); | 86 | buf[i] = __raw_readl(&rtcreg->dat); |
85 | spin_unlock_irq(&pdata->rtc->irq_lock); | 87 | spin_unlock_irq(&pdata->lock); |
86 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; | 88 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; |
87 | rtc_time_to_tm(sec, tm); | 89 | rtc_time_to_tm(sec, tm); |
88 | return rtc_valid_tm(tm); | 90 | return rtc_valid_tm(tm); |
@@ -110,13 +112,13 @@ static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
110 | buf[3] = sec >> 8; | 112 | buf[3] = sec >> 8; |
111 | buf[4] = sec >> 16; | 113 | buf[4] = sec >> 16; |
112 | buf[5] = sec >> 24; | 114 | buf[5] = sec >> 24; |
113 | spin_lock_irq(&pdata->rtc->irq_lock); | 115 | spin_lock_irq(&pdata->lock); |
114 | __raw_writel(0, &rtcreg->adr); | 116 | __raw_writel(0, &rtcreg->adr); |
115 | for (i = 0; i < 6; i++) | 117 | for (i = 0; i < 6; i++) |
116 | __raw_writel(buf[i], &rtcreg->dat); | 118 | __raw_writel(buf[i], &rtcreg->dat); |
117 | ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM | | 119 | ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM | |
118 | (alrm->enabled ? TX4939_RTCCTL_ALME : 0)); | 120 | (alrm->enabled ? TX4939_RTCCTL_ALME : 0)); |
119 | spin_unlock_irq(&pdata->rtc->irq_lock); | 121 | spin_unlock_irq(&pdata->lock); |
120 | return ret; | 122 | return ret; |
121 | } | 123 | } |
122 | 124 | ||
@@ -129,12 +131,12 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
129 | unsigned char buf[6]; | 131 | unsigned char buf[6]; |
130 | u32 ctl; | 132 | u32 ctl; |
131 | 133 | ||
132 | spin_lock_irq(&pdata->rtc->irq_lock); | 134 | spin_lock_irq(&pdata->lock); |
133 | ret = tx4939_rtc_cmd(rtcreg, | 135 | ret = tx4939_rtc_cmd(rtcreg, |
134 | TX4939_RTCCTL_COMMAND_GETALARM | | 136 | TX4939_RTCCTL_COMMAND_GETALARM | |
135 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 137 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
136 | if (ret) { | 138 | if (ret) { |
137 | spin_unlock_irq(&pdata->rtc->irq_lock); | 139 | spin_unlock_irq(&pdata->lock); |
138 | return ret; | 140 | return ret; |
139 | } | 141 | } |
140 | __raw_writel(2, &rtcreg->adr); | 142 | __raw_writel(2, &rtcreg->adr); |
@@ -143,7 +145,7 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
143 | ctl = __raw_readl(&rtcreg->ctl); | 145 | ctl = __raw_readl(&rtcreg->ctl); |
144 | alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; | 146 | alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; |
145 | alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; | 147 | alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; |
146 | spin_unlock_irq(&pdata->rtc->irq_lock); | 148 | spin_unlock_irq(&pdata->lock); |
147 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; | 149 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; |
148 | rtc_time_to_tm(sec, &alrm->time); | 150 | rtc_time_to_tm(sec, &alrm->time); |
149 | return rtc_valid_tm(&alrm->time); | 151 | return rtc_valid_tm(&alrm->time); |
@@ -153,11 +155,11 @@ static int tx4939_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
153 | { | 155 | { |
154 | struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); | 156 | struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); |
155 | 157 | ||
156 | spin_lock_irq(&pdata->rtc->irq_lock); | 158 | spin_lock_irq(&pdata->lock); |
157 | tx4939_rtc_cmd(pdata->rtcreg, | 159 | tx4939_rtc_cmd(pdata->rtcreg, |
158 | TX4939_RTCCTL_COMMAND_NOP | | 160 | TX4939_RTCCTL_COMMAND_NOP | |
159 | (enabled ? TX4939_RTCCTL_ALME : 0)); | 161 | (enabled ? TX4939_RTCCTL_ALME : 0)); |
160 | spin_unlock_irq(&pdata->rtc->irq_lock); | 162 | spin_unlock_irq(&pdata->lock); |
161 | return 0; | 163 | return 0; |
162 | } | 164 | } |
163 | 165 | ||
@@ -167,13 +169,14 @@ static irqreturn_t tx4939_rtc_interrupt(int irq, void *dev_id) | |||
167 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 169 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
168 | unsigned long events = RTC_IRQF; | 170 | unsigned long events = RTC_IRQF; |
169 | 171 | ||
170 | spin_lock(&pdata->rtc->irq_lock); | 172 | spin_lock(&pdata->lock); |
171 | if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) { | 173 | if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) { |
172 | events |= RTC_AF; | 174 | events |= RTC_AF; |
173 | tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP); | 175 | tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP); |
174 | } | 176 | } |
175 | spin_unlock(&pdata->rtc->irq_lock); | 177 | spin_unlock(&pdata->lock); |
176 | rtc_update_irq(pdata->rtc, 1, events); | 178 | if (likely(pdata->rtc)) |
179 | rtc_update_irq(pdata->rtc, 1, events); | ||
177 | return IRQ_HANDLED; | 180 | return IRQ_HANDLED; |
178 | } | 181 | } |
179 | 182 | ||
@@ -185,7 +188,7 @@ static const struct rtc_class_ops tx4939_rtc_ops = { | |||
185 | .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, | 188 | .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, |
186 | }; | 189 | }; |
187 | 190 | ||
188 | static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | 191 | static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj, |
189 | struct bin_attribute *bin_attr, | 192 | struct bin_attribute *bin_attr, |
190 | char *buf, loff_t pos, size_t size) | 193 | char *buf, loff_t pos, size_t size) |
191 | { | 194 | { |
@@ -194,17 +197,17 @@ static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | |||
194 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 197 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
195 | ssize_t count; | 198 | ssize_t count; |
196 | 199 | ||
197 | spin_lock_irq(&pdata->rtc->irq_lock); | 200 | spin_lock_irq(&pdata->lock); |
198 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; | 201 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; |
199 | count++, size--) { | 202 | count++, size--) { |
200 | __raw_writel(pos++, &rtcreg->adr); | 203 | __raw_writel(pos++, &rtcreg->adr); |
201 | *buf++ = __raw_readl(&rtcreg->dat); | 204 | *buf++ = __raw_readl(&rtcreg->dat); |
202 | } | 205 | } |
203 | spin_unlock_irq(&pdata->rtc->irq_lock); | 206 | spin_unlock_irq(&pdata->lock); |
204 | return count; | 207 | return count; |
205 | } | 208 | } |
206 | 209 | ||
207 | static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, | 210 | static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj, |
208 | struct bin_attribute *bin_attr, | 211 | struct bin_attribute *bin_attr, |
209 | char *buf, loff_t pos, size_t size) | 212 | char *buf, loff_t pos, size_t size) |
210 | { | 213 | { |
@@ -213,13 +216,13 @@ static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, | |||
213 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 216 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
214 | ssize_t count; | 217 | ssize_t count; |
215 | 218 | ||
216 | spin_lock_irq(&pdata->rtc->irq_lock); | 219 | spin_lock_irq(&pdata->lock); |
217 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; | 220 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; |
218 | count++, size--) { | 221 | count++, size--) { |
219 | __raw_writel(pos++, &rtcreg->adr); | 222 | __raw_writel(pos++, &rtcreg->adr); |
220 | __raw_writel(*buf++, &rtcreg->dat); | 223 | __raw_writel(*buf++, &rtcreg->dat); |
221 | } | 224 | } |
222 | spin_unlock_irq(&pdata->rtc->irq_lock); | 225 | spin_unlock_irq(&pdata->lock); |
223 | return count; | 226 | return count; |
224 | } | 227 | } |
225 | 228 | ||
@@ -259,6 +262,7 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) | |||
259 | if (!pdata->rtcreg) | 262 | if (!pdata->rtcreg) |
260 | return -EBUSY; | 263 | return -EBUSY; |
261 | 264 | ||
265 | spin_lock_init(&pdata->lock); | ||
262 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | 266 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); |
263 | if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, | 267 | if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, |
264 | IRQF_DISABLED, pdev->name, &pdev->dev) < 0) | 268 | IRQF_DISABLED, pdev->name, &pdev->dev) < 0) |
@@ -277,14 +281,12 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) | |||
277 | static int __exit tx4939_rtc_remove(struct platform_device *pdev) | 281 | static int __exit tx4939_rtc_remove(struct platform_device *pdev) |
278 | { | 282 | { |
279 | struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); | 283 | struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); |
280 | struct rtc_device *rtc = pdata->rtc; | ||
281 | 284 | ||
282 | spin_lock_irq(&rtc->irq_lock); | ||
283 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | ||
284 | spin_unlock_irq(&rtc->irq_lock); | ||
285 | sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); | 285 | sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); |
286 | rtc_device_unregister(rtc); | 286 | rtc_device_unregister(pdata->rtc); |
287 | platform_set_drvdata(pdev, NULL); | 287 | spin_lock_irq(&pdata->lock); |
288 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | ||
289 | spin_unlock_irq(&pdata->lock); | ||
288 | return 0; | 290 | return 0; |
289 | } | 291 | } |
290 | 292 | ||