aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-stk17ta8.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/rtc/rtc-stk17ta8.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/rtc/rtc-stk17ta8.c')
-rw-r--r--drivers/rtc/rtc-stk17ta8.c127
1 files changed, 52 insertions, 75 deletions
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index 7d1547b0070e..875ba099e7a5 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -14,6 +14,7 @@
14#include <linux/bcd.h> 14#include <linux/bcd.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/gfp.h>
17#include <linux/delay.h> 18#include <linux/delay.h>
18#include <linux/jiffies.h> 19#include <linux/jiffies.h>
19#include <linux/interrupt.h> 20#include <linux/interrupt.h>
@@ -62,7 +63,6 @@
62struct rtc_plat_data { 63struct rtc_plat_data {
63 struct rtc_device *rtc; 64 struct rtc_device *rtc;
64 void __iomem *ioaddr; 65 void __iomem *ioaddr;
65 unsigned long baseaddr;
66 unsigned long last_jiffies; 66 unsigned long last_jiffies;
67 int irq; 67 int irq;
68 unsigned int irqen; 68 unsigned int irqen;
@@ -70,6 +70,7 @@ struct rtc_plat_data {
70 int alrm_min; 70 int alrm_min;
71 int alrm_hour; 71 int alrm_hour;
72 int alrm_mday; 72 int alrm_mday;
73 spinlock_t lock;
73}; 74};
74 75
75static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) 76static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -142,7 +143,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata)
142 unsigned long irqflags; 143 unsigned long irqflags;
143 u8 flags; 144 u8 flags;
144 145
145 spin_lock_irqsave(&pdata->rtc->irq_lock, irqflags); 146 spin_lock_irqsave(&pdata->lock, irqflags);
146 147
147 flags = readb(ioaddr + RTC_FLAGS); 148 flags = readb(ioaddr + RTC_FLAGS);
148 writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); 149 writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS);
@@ -162,7 +163,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata)
162 writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); 163 writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS);
163 readb(ioaddr + RTC_FLAGS); /* clear interrupts */ 164 readb(ioaddr + RTC_FLAGS); /* clear interrupts */
164 writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS); 165 writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS);
165 spin_unlock_irqrestore(&pdata->rtc->irq_lock, irqflags); 166 spin_unlock_irqrestore(&pdata->lock, irqflags);
166} 167}
167 168
168static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 169static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -202,56 +203,53 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id)
202 struct platform_device *pdev = dev_id; 203 struct platform_device *pdev = dev_id;
203 struct rtc_plat_data *pdata = platform_get_drvdata(pdev); 204 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
204 void __iomem *ioaddr = pdata->ioaddr; 205 void __iomem *ioaddr = pdata->ioaddr;
205 unsigned long events = RTC_IRQF; 206 unsigned long events = 0;
206 207
208 spin_lock(&pdata->lock);
207 /* read and clear interrupt */ 209 /* read and clear interrupt */
208 if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) 210 if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) {
209 return IRQ_NONE; 211 events = RTC_IRQF;
210 if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) 212 if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
211 events |= RTC_UF; 213 events |= RTC_UF;
212 else 214 else
213 events |= RTC_AF; 215 events |= RTC_AF;
214 rtc_update_irq(pdata->rtc, 1, events); 216 if (likely(pdata->rtc))
215 return IRQ_HANDLED; 217 rtc_update_irq(pdata->rtc, 1, events);
218 }
219 spin_unlock(&pdata->lock);
220 return events ? IRQ_HANDLED : IRQ_NONE;
216} 221}
217 222
218static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, 223static int stk17ta8_rtc_alarm_irq_enable(struct device *dev,
219 unsigned long arg) 224 unsigned int enabled)
220{ 225{
221 struct platform_device *pdev = to_platform_device(dev); 226 struct platform_device *pdev = to_platform_device(dev);
222 struct rtc_plat_data *pdata = platform_get_drvdata(pdev); 227 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
223 228
224 if (pdata->irq <= 0) 229 if (pdata->irq <= 0)
225 return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ 230 return -EINVAL;
226 switch (cmd) { 231 if (enabled)
227 case RTC_AIE_OFF:
228 pdata->irqen &= ~RTC_AF;
229 stk17ta8_rtc_update_alarm(pdata);
230 break;
231 case RTC_AIE_ON:
232 pdata->irqen |= RTC_AF; 232 pdata->irqen |= RTC_AF;
233 stk17ta8_rtc_update_alarm(pdata); 233 else
234 break; 234 pdata->irqen &= ~RTC_AF;
235 default: 235 stk17ta8_rtc_update_alarm(pdata);
236 return -ENOIOCTLCMD;
237 }
238 return 0; 236 return 0;
239} 237}
240 238
241static const struct rtc_class_ops stk17ta8_rtc_ops = { 239static const struct rtc_class_ops stk17ta8_rtc_ops = {
242 .read_time = stk17ta8_rtc_read_time, 240 .read_time = stk17ta8_rtc_read_time,
243 .set_time = stk17ta8_rtc_set_time, 241 .set_time = stk17ta8_rtc_set_time,
244 .read_alarm = stk17ta8_rtc_read_alarm, 242 .read_alarm = stk17ta8_rtc_read_alarm,
245 .set_alarm = stk17ta8_rtc_set_alarm, 243 .set_alarm = stk17ta8_rtc_set_alarm,
246 .ioctl = stk17ta8_rtc_ioctl, 244 .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable,
247}; 245};
248 246
249static ssize_t stk17ta8_nvram_read(struct kobject *kobj, 247static ssize_t stk17ta8_nvram_read(struct kobject *kobj,
250 struct bin_attribute *attr, char *buf, 248 struct bin_attribute *attr, char *buf,
251 loff_t pos, size_t size) 249 loff_t pos, size_t size)
252{ 250{
253 struct platform_device *pdev = 251 struct device *dev = container_of(kobj, struct device, kobj);
254 to_platform_device(container_of(kobj, struct device, kobj)); 252 struct platform_device *pdev = to_platform_device(dev);
255 struct rtc_plat_data *pdata = platform_get_drvdata(pdev); 253 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
256 void __iomem *ioaddr = pdata->ioaddr; 254 void __iomem *ioaddr = pdata->ioaddr;
257 ssize_t count; 255 ssize_t count;
@@ -265,8 +263,8 @@ static ssize_t stk17ta8_nvram_write(struct kobject *kobj,
265 struct bin_attribute *attr, char *buf, 263 struct bin_attribute *attr, char *buf,
266 loff_t pos, size_t size) 264 loff_t pos, size_t size)
267{ 265{
268 struct platform_device *pdev = 266 struct device *dev = container_of(kobj, struct device, kobj);
269 to_platform_device(container_of(kobj, struct device, kobj)); 267 struct platform_device *pdev = to_platform_device(dev);
270 struct rtc_plat_data *pdata = platform_get_drvdata(pdev); 268 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
271 void __iomem *ioaddr = pdata->ioaddr; 269 void __iomem *ioaddr = pdata->ioaddr;
272 ssize_t count; 270 ssize_t count;
@@ -286,33 +284,28 @@ static struct bin_attribute stk17ta8_nvram_attr = {
286 .write = stk17ta8_nvram_write, 284 .write = stk17ta8_nvram_write,
287}; 285};
288 286
289static int __init stk17ta8_rtc_probe(struct platform_device *pdev) 287static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev)
290{ 288{
291 struct rtc_device *rtc;
292 struct resource *res; 289 struct resource *res;
293 unsigned int cal; 290 unsigned int cal;
294 unsigned int flags; 291 unsigned int flags;
295 struct rtc_plat_data *pdata; 292 struct rtc_plat_data *pdata;
296 void __iomem *ioaddr = NULL; 293 void __iomem *ioaddr;
297 int ret = 0; 294 int ret = 0;
298 295
299 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 296 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
300 if (!res) 297 if (!res)
301 return -ENODEV; 298 return -ENODEV;
302 299
303 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 300 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
304 if (!pdata) 301 if (!pdata)
305 return -ENOMEM; 302 return -ENOMEM;
306 if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { 303 if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE,
307 ret = -EBUSY; 304 pdev->name))
308 goto out; 305 return -EBUSY;
309 } 306 ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE);
310 pdata->baseaddr = res->start; 307 if (!ioaddr)
311 ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); 308 return -ENOMEM;
312 if (!ioaddr) {
313 ret = -ENOMEM;
314 goto out;
315 }
316 pdata->ioaddr = ioaddr; 309 pdata->ioaddr = ioaddr;
317 pdata->irq = platform_get_irq(pdev, 0); 310 pdata->irq = platform_get_irq(pdev, 0);
318 311
@@ -328,9 +321,13 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev)
328 if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF) 321 if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF)
329 dev_warn(&pdev->dev, "voltage-low detected.\n"); 322 dev_warn(&pdev->dev, "voltage-low detected.\n");
330 323
324 spin_lock_init(&pdata->lock);
325 pdata->last_jiffies = jiffies;
326 platform_set_drvdata(pdev, pdata);
331 if (pdata->irq > 0) { 327 if (pdata->irq > 0) {
332 writeb(0, ioaddr + RTC_INTERRUPTS); 328 writeb(0, ioaddr + RTC_INTERRUPTS);
333 if (request_irq(pdata->irq, stk17ta8_rtc_interrupt, 329 if (devm_request_irq(&pdev->dev, pdata->irq,
330 stk17ta8_rtc_interrupt,
334 IRQF_DISABLED | IRQF_SHARED, 331 IRQF_DISABLED | IRQF_SHARED,
335 pdev->name, pdev) < 0) { 332 pdev->name, pdev) < 0) {
336 dev_warn(&pdev->dev, "interrupt not available.\n"); 333 dev_warn(&pdev->dev, "interrupt not available.\n");
@@ -338,29 +335,14 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev)
338 } 335 }
339 } 336 }
340 337
341 rtc = rtc_device_register(pdev->name, &pdev->dev, 338 pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
342 &stk17ta8_rtc_ops, THIS_MODULE); 339 &stk17ta8_rtc_ops, THIS_MODULE);
343 if (IS_ERR(rtc)) { 340 if (IS_ERR(pdata->rtc))
344 ret = PTR_ERR(rtc); 341 return PTR_ERR(pdata->rtc);
345 goto out; 342
346 }
347 pdata->rtc = rtc;
348 pdata->last_jiffies = jiffies;
349 platform_set_drvdata(pdev, pdata);
350 ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); 343 ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
351 if (ret) 344 if (ret)
352 goto out;
353 return 0;
354 out:
355 if (pdata->rtc)
356 rtc_device_unregister(pdata->rtc); 345 rtc_device_unregister(pdata->rtc);
357 if (pdata->irq > 0)
358 free_irq(pdata->irq, pdev);
359 if (ioaddr)
360 iounmap(ioaddr);
361 if (pdata->baseaddr)
362 release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
363 kfree(pdata);
364 return ret; 346 return ret;
365} 347}
366 348
@@ -370,13 +352,8 @@ static int __devexit stk17ta8_rtc_remove(struct platform_device *pdev)
370 352
371 sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); 353 sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
372 rtc_device_unregister(pdata->rtc); 354 rtc_device_unregister(pdata->rtc);
373 if (pdata->irq > 0) { 355 if (pdata->irq > 0)
374 writeb(0, pdata->ioaddr + RTC_INTERRUPTS); 356 writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
375 free_irq(pdata->irq, pdev);
376 }
377 iounmap(pdata->ioaddr);
378 release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
379 kfree(pdata);
380 return 0; 357 return 0;
381} 358}
382 359