aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-ds1553.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-ds1553.c')
-rw-r--r--drivers/rtc/rtc-ds1553.c154
1 files changed, 71 insertions, 83 deletions
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 717288527c6b..ff432e2ca275 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -11,6 +11,7 @@
11#include <linux/bcd.h> 11#include <linux/bcd.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/gfp.h>
14#include <linux/delay.h> 15#include <linux/delay.h>
15#include <linux/jiffies.h> 16#include <linux/jiffies.h>
16#include <linux/interrupt.h> 17#include <linux/interrupt.h>
@@ -18,7 +19,7 @@
18#include <linux/platform_device.h> 19#include <linux/platform_device.h>
19#include <linux/io.h> 20#include <linux/io.h>
20 21
21#define DRV_VERSION "0.2" 22#define DRV_VERSION "0.3"
22 23
23#define RTC_REG_SIZE 0x2000 24#define RTC_REG_SIZE 0x2000
24#define RTC_OFFSET 0x1ff0 25#define RTC_OFFSET 0x1ff0
@@ -61,7 +62,6 @@
61struct rtc_plat_data { 62struct rtc_plat_data {
62 struct rtc_device *rtc; 63 struct rtc_device *rtc;
63 void __iomem *ioaddr; 64 void __iomem *ioaddr;
64 resource_size_t baseaddr;
65 unsigned long last_jiffies; 65 unsigned long last_jiffies;
66 int irq; 66 int irq;
67 unsigned int irqen; 67 unsigned int irqen;
@@ -69,6 +69,7 @@ struct rtc_plat_data {
69 int alrm_min; 69 int alrm_min;
70 int alrm_hour; 70 int alrm_hour;
71 int alrm_mday; 71 int alrm_mday;
72 spinlock_t lock;
72}; 73};
73 74
74static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) 75static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -139,7 +140,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata)
139 void __iomem *ioaddr = pdata->ioaddr; 140 void __iomem *ioaddr = pdata->ioaddr;
140 unsigned long flags; 141 unsigned long flags;
141 142
142 spin_lock_irqsave(&pdata->rtc->irq_lock, flags); 143 spin_lock_irqsave(&pdata->lock, flags);
143 writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? 144 writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
144 0x80 : bin2bcd(pdata->alrm_mday), 145 0x80 : bin2bcd(pdata->alrm_mday),
145 ioaddr + RTC_DATE_ALARM); 146 ioaddr + RTC_DATE_ALARM);
@@ -154,7 +155,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata)
154 ioaddr + RTC_SECONDS_ALARM); 155 ioaddr + RTC_SECONDS_ALARM);
155 writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); 156 writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS);
156 readb(ioaddr + RTC_FLAGS); /* clear interrupts */ 157 readb(ioaddr + RTC_FLAGS); /* clear interrupts */
157 spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); 158 spin_unlock_irqrestore(&pdata->lock, flags);
158} 159}
159 160
160static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 161static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -194,64 +195,69 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id)
194 struct platform_device *pdev = dev_id; 195 struct platform_device *pdev = dev_id;
195 struct rtc_plat_data *pdata = platform_get_drvdata(pdev); 196 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
196 void __iomem *ioaddr = pdata->ioaddr; 197 void __iomem *ioaddr = pdata->ioaddr;
197 unsigned long events = RTC_IRQF; 198 unsigned long events = 0;
198 199
200 spin_lock(&pdata->lock);
199 /* read and clear interrupt */ 201 /* read and clear interrupt */
200 if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) 202 if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) {
201 return IRQ_NONE; 203 events = RTC_IRQF;
202 if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) 204 if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
203 events |= RTC_UF; 205 events |= RTC_UF;
204 else 206 else
205 events |= RTC_AF; 207 events |= RTC_AF;
206 rtc_update_irq(pdata->rtc, 1, events); 208 if (likely(pdata->rtc))
207 return IRQ_HANDLED; 209 rtc_update_irq(pdata->rtc, 1, events);
210 }
211 spin_unlock(&pdata->lock);
212 return events ? IRQ_HANDLED : IRQ_NONE;
208} 213}
209 214
210static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, 215static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
211 unsigned long arg)
212{ 216{
213 struct platform_device *pdev = to_platform_device(dev); 217 struct platform_device *pdev = to_platform_device(dev);
214 struct rtc_plat_data *pdata = platform_get_drvdata(pdev); 218 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
215 219
216 if (pdata->irq <= 0) 220 if (pdata->irq <= 0)
217 return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ 221 return -EINVAL;
218 switch (cmd) { 222 if (enabled)
219 case RTC_AIE_OFF:
220 pdata->irqen &= ~RTC_AF;
221 ds1553_rtc_update_alarm(pdata);
222 break;
223 case RTC_AIE_ON:
224 pdata->irqen |= RTC_AF; 223 pdata->irqen |= RTC_AF;
225 ds1553_rtc_update_alarm(pdata); 224 else
226 break; 225 pdata->irqen &= ~RTC_AF;
227 case RTC_UIE_OFF: 226 ds1553_rtc_update_alarm(pdata);
228 pdata->irqen &= ~RTC_UF; 227 return 0;
229 ds1553_rtc_update_alarm(pdata); 228}
230 break; 229
231 case RTC_UIE_ON: 230static int ds1553_rtc_update_irq_enable(struct device *dev,
231 unsigned int enabled)
232{
233 struct platform_device *pdev = to_platform_device(dev);
234 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
235
236 if (pdata->irq <= 0)
237 return -EINVAL;
238 if (enabled)
232 pdata->irqen |= RTC_UF; 239 pdata->irqen |= RTC_UF;
233 ds1553_rtc_update_alarm(pdata); 240 else
234 break; 241 pdata->irqen &= ~RTC_UF;
235 default: 242 ds1553_rtc_update_alarm(pdata);
236 return -ENOIOCTLCMD;
237 }
238 return 0; 243 return 0;
239} 244}
240 245
241static const struct rtc_class_ops ds1553_rtc_ops = { 246static const struct rtc_class_ops ds1553_rtc_ops = {
242 .read_time = ds1553_rtc_read_time, 247 .read_time = ds1553_rtc_read_time,
243 .set_time = ds1553_rtc_set_time, 248 .set_time = ds1553_rtc_set_time,
244 .read_alarm = ds1553_rtc_read_alarm, 249 .read_alarm = ds1553_rtc_read_alarm,
245 .set_alarm = ds1553_rtc_set_alarm, 250 .set_alarm = ds1553_rtc_set_alarm,
246 .ioctl = ds1553_rtc_ioctl, 251 .alarm_irq_enable = ds1553_rtc_alarm_irq_enable,
252 .update_irq_enable = ds1553_rtc_update_irq_enable,
247}; 253};
248 254
249static ssize_t ds1553_nvram_read(struct kobject *kobj, 255static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj,
250 struct bin_attribute *bin_attr, 256 struct bin_attribute *bin_attr,
251 char *buf, loff_t pos, size_t size) 257 char *buf, loff_t pos, size_t size)
252{ 258{
253 struct platform_device *pdev = 259 struct device *dev = container_of(kobj, struct device, kobj);
254 to_platform_device(container_of(kobj, struct device, kobj)); 260 struct platform_device *pdev = to_platform_device(dev);
255 struct rtc_plat_data *pdata = platform_get_drvdata(pdev); 261 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
256 void __iomem *ioaddr = pdata->ioaddr; 262 void __iomem *ioaddr = pdata->ioaddr;
257 ssize_t count; 263 ssize_t count;
@@ -261,12 +267,12 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj,
261 return count; 267 return count;
262} 268}
263 269
264static ssize_t ds1553_nvram_write(struct kobject *kobj, 270static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj,
265 struct bin_attribute *bin_attr, 271 struct bin_attribute *bin_attr,
266 char *buf, loff_t pos, size_t size) 272 char *buf, loff_t pos, size_t size)
267{ 273{
268 struct platform_device *pdev = 274 struct device *dev = container_of(kobj, struct device, kobj);
269 to_platform_device(container_of(kobj, struct device, kobj)); 275 struct platform_device *pdev = to_platform_device(dev);
270 struct rtc_plat_data *pdata = platform_get_drvdata(pdev); 276 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
271 void __iomem *ioaddr = pdata->ioaddr; 277 void __iomem *ioaddr = pdata->ioaddr;
272 ssize_t count; 278 ssize_t count;
@@ -291,26 +297,23 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
291 struct rtc_device *rtc; 297 struct rtc_device *rtc;
292 struct resource *res; 298 struct resource *res;
293 unsigned int cen, sec; 299 unsigned int cen, sec;
294 struct rtc_plat_data *pdata = NULL; 300 struct rtc_plat_data *pdata;
295 void __iomem *ioaddr = NULL; 301 void __iomem *ioaddr;
296 int ret = 0; 302 int ret = 0;
297 303
298 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 304 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
299 if (!res) 305 if (!res)
300 return -ENODEV; 306 return -ENODEV;
301 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 307 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
302 if (!pdata) 308 if (!pdata)
303 return -ENOMEM; 309 return -ENOMEM;
304 if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { 310 if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE,
305 ret = -EBUSY; 311 pdev->name))
306 goto out; 312 return -EBUSY;
307 } 313
308 pdata->baseaddr = res->start; 314 ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE);
309 ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); 315 if (!ioaddr)
310 if (!ioaddr) { 316 return -ENOMEM;
311 ret = -ENOMEM;
312 goto out;
313 }
314 pdata->ioaddr = ioaddr; 317 pdata->ioaddr = ioaddr;
315 pdata->irq = platform_get_irq(pdev, 0); 318 pdata->irq = platform_get_irq(pdev, 0);
316 319
@@ -326,9 +329,13 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
326 if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF) 329 if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF)
327 dev_warn(&pdev->dev, "voltage-low detected.\n"); 330 dev_warn(&pdev->dev, "voltage-low detected.\n");
328 331
332 spin_lock_init(&pdata->lock);
333 pdata->last_jiffies = jiffies;
334 platform_set_drvdata(pdev, pdata);
329 if (pdata->irq > 0) { 335 if (pdata->irq > 0) {
330 writeb(0, ioaddr + RTC_INTERRUPTS); 336 writeb(0, ioaddr + RTC_INTERRUPTS);
331 if (request_irq(pdata->irq, ds1553_rtc_interrupt, 337 if (devm_request_irq(&pdev->dev, pdata->irq,
338 ds1553_rtc_interrupt,
332 IRQF_DISABLED, pdev->name, pdev) < 0) { 339 IRQF_DISABLED, pdev->name, pdev) < 0) {
333 dev_warn(&pdev->dev, "interrupt not available.\n"); 340 dev_warn(&pdev->dev, "interrupt not available.\n");
334 pdata->irq = 0; 341 pdata->irq = 0;
@@ -337,27 +344,13 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
337 344
338 rtc = rtc_device_register(pdev->name, &pdev->dev, 345 rtc = rtc_device_register(pdev->name, &pdev->dev,
339 &ds1553_rtc_ops, THIS_MODULE); 346 &ds1553_rtc_ops, THIS_MODULE);
340 if (IS_ERR(rtc)) { 347 if (IS_ERR(rtc))
341 ret = PTR_ERR(rtc); 348 return PTR_ERR(rtc);
342 goto out;
343 }
344 pdata->rtc = rtc; 349 pdata->rtc = rtc;
345 pdata->last_jiffies = jiffies; 350
346 platform_set_drvdata(pdev, pdata);
347 ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); 351 ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
348 if (ret) 352 if (ret)
349 goto out; 353 rtc_device_unregister(rtc);
350 return 0;
351 out:
352 if (pdata->rtc)
353 rtc_device_unregister(pdata->rtc);
354 if (pdata->irq > 0)
355 free_irq(pdata->irq, pdev);
356 if (ioaddr)
357 iounmap(ioaddr);
358 if (pdata->baseaddr)
359 release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
360 kfree(pdata);
361 return ret; 354 return ret;
362} 355}
363 356
@@ -367,13 +360,8 @@ static int __devexit ds1553_rtc_remove(struct platform_device *pdev)
367 360
368 sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); 361 sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
369 rtc_device_unregister(pdata->rtc); 362 rtc_device_unregister(pdata->rtc);
370 if (pdata->irq > 0) { 363 if (pdata->irq > 0)
371 writeb(0, pdata->ioaddr + RTC_INTERRUPTS); 364 writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
372 free_irq(pdata->irq, pdev);
373 }
374 iounmap(pdata->ioaddr);
375 release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
376 kfree(pdata);
377 return 0; 365 return 0;
378} 366}
379 367