aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-tx4939.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-tx4939.c')
-rw-r--r--drivers/rtc/rtc-tx4939.c56
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
17struct tx4939rtc_plat_data { 18struct 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
22static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) 24static 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
188static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, 191static 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
207static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, 210static 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)
277static int __exit tx4939_rtc_remove(struct platform_device *pdev) 281static 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