aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-m48t59.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-m48t59.c')
-rw-r--r--drivers/rtc/rtc-m48t59.c68
1 files changed, 52 insertions, 16 deletions
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 013e6c103b9c..ce4eff6a8d51 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -24,8 +24,9 @@
24#define NO_IRQ (-1) 24#define NO_IRQ (-1)
25#endif 25#endif
26 26
27#define M48T59_READ(reg) pdata->read_byte(dev, reg) 27#define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg))
28#define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val) 28#define M48T59_WRITE(val, reg) \
29 (pdata->write_byte(dev, pdata->offset + reg, val))
29 30
30#define M48T59_SET_BITS(mask, reg) \ 31#define M48T59_SET_BITS(mask, reg) \
31 M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) 32 M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg))
@@ -34,7 +35,6 @@
34 35
35struct m48t59_private { 36struct m48t59_private {
36 void __iomem *ioaddr; 37 void __iomem *ioaddr;
37 unsigned int size; /* iomem size */
38 int irq; 38 int irq;
39 struct rtc_device *rtc; 39 struct rtc_device *rtc;
40 spinlock_t lock; /* serialize the NVRAM and RTC access */ 40 spinlock_t lock; /* serialize the NVRAM and RTC access */
@@ -82,7 +82,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
82 tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); 82 tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY));
83 83
84 val = M48T59_READ(M48T59_WDAY); 84 val = M48T59_READ(M48T59_WDAY);
85 if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { 85 if ((pdata->type == M48T59RTC_TYPE_M48T59) &&
86 (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
86 dev_dbg(dev, "Century bit is enabled\n"); 87 dev_dbg(dev, "Century bit is enabled\n");
87 tm->tm_year += 100; /* one century */ 88 tm->tm_year += 100; /* one century */
88 } 89 }
@@ -126,7 +127,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
126 M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); 127 M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
127 M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); 128 M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR);
128 129
129 if (tm->tm_year/100) 130 if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100))
130 val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); 131 val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
131 val |= (BIN2BCD(tm->tm_wday) & 0x07); 132 val |= (BIN2BCD(tm->tm_wday) & 0x07);
132 M48T59_WRITE(val, M48T59_WDAY); 133 M48T59_WRITE(val, M48T59_WDAY);
@@ -310,6 +311,11 @@ static const struct rtc_class_ops m48t59_rtc_ops = {
310 .proc = m48t59_rtc_proc, 311 .proc = m48t59_rtc_proc,
311}; 312};
312 313
314static const struct rtc_class_ops m48t02_rtc_ops = {
315 .read_time = m48t59_rtc_read_time,
316 .set_time = m48t59_rtc_set_time,
317};
318
313static ssize_t m48t59_nvram_read(struct kobject *kobj, 319static ssize_t m48t59_nvram_read(struct kobject *kobj,
314 struct bin_attribute *bin_attr, 320 struct bin_attribute *bin_attr,
315 char *buf, loff_t pos, size_t size) 321 char *buf, loff_t pos, size_t size)
@@ -321,7 +327,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj,
321 ssize_t cnt = 0; 327 ssize_t cnt = 0;
322 unsigned long flags; 328 unsigned long flags;
323 329
324 for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { 330 for (; size > 0 && pos < pdata->offset; cnt++, size--) {
325 spin_lock_irqsave(&m48t59->lock, flags); 331 spin_lock_irqsave(&m48t59->lock, flags);
326 *buf++ = M48T59_READ(cnt); 332 *buf++ = M48T59_READ(cnt);
327 spin_unlock_irqrestore(&m48t59->lock, flags); 333 spin_unlock_irqrestore(&m48t59->lock, flags);
@@ -341,7 +347,7 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj,
341 ssize_t cnt = 0; 347 ssize_t cnt = 0;
342 unsigned long flags; 348 unsigned long flags;
343 349
344 for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { 350 for (; size > 0 && pos < pdata->offset; cnt++, size--) {
345 spin_lock_irqsave(&m48t59->lock, flags); 351 spin_lock_irqsave(&m48t59->lock, flags);
346 M48T59_WRITE(*buf++, cnt); 352 M48T59_WRITE(*buf++, cnt);
347 spin_unlock_irqrestore(&m48t59->lock, flags); 353 spin_unlock_irqrestore(&m48t59->lock, flags);
@@ -358,7 +364,6 @@ static struct bin_attribute m48t59_nvram_attr = {
358 }, 364 },
359 .read = m48t59_nvram_read, 365 .read = m48t59_nvram_read,
360 .write = m48t59_nvram_write, 366 .write = m48t59_nvram_write,
361 .size = M48T59_NVRAM_SIZE,
362}; 367};
363 368
364static int __devinit m48t59_rtc_probe(struct platform_device *pdev) 369static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
@@ -367,6 +372,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
367 struct m48t59_private *m48t59 = NULL; 372 struct m48t59_private *m48t59 = NULL;
368 struct resource *res; 373 struct resource *res;
369 int ret = -ENOMEM; 374 int ret = -ENOMEM;
375 char *name;
376 const struct rtc_class_ops *ops;
370 377
371 /* This chip could be memory-mapped or I/O-mapped */ 378 /* This chip could be memory-mapped or I/O-mapped */
372 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 379 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -391,6 +398,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
391 /* Ensure we only kmalloc platform data once */ 398 /* Ensure we only kmalloc platform data once */
392 pdev->dev.platform_data = pdata; 399 pdev->dev.platform_data = pdata;
393 } 400 }
401 if (!pdata->type)
402 pdata->type = M48T59RTC_TYPE_M48T59;
394 403
395 /* Try to use the generic memory read/write ops */ 404 /* Try to use the generic memory read/write ops */
396 if (!pdata->write_byte) 405 if (!pdata->write_byte)
@@ -403,10 +412,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
403 if (!m48t59) 412 if (!m48t59)
404 return -ENOMEM; 413 return -ENOMEM;
405 414
406 m48t59->size = res->end - res->start + 1; 415 m48t59->ioaddr = pdata->ioaddr;
407 m48t59->ioaddr = ioremap(res->start, m48t59->size); 416
408 if (!m48t59->ioaddr) 417 if (!m48t59->ioaddr) {
409 goto out; 418 /* ioaddr not mapped externally */
419 m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1);
420 if (!m48t59->ioaddr)
421 goto out;
422 }
410 423
411 /* Try to get irq number. We also can work in 424 /* Try to get irq number. We also can work in
412 * the mode without IRQ. 425 * the mode without IRQ.
@@ -421,14 +434,36 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
421 if (ret) 434 if (ret)
422 goto out; 435 goto out;
423 } 436 }
437 switch (pdata->type) {
438 case M48T59RTC_TYPE_M48T59:
439 name = "m48t59";
440 ops = &m48t59_rtc_ops;
441 pdata->offset = 0x1ff0;
442 break;
443 case M48T59RTC_TYPE_M48T02:
444 name = "m48t02";
445 ops = &m48t02_rtc_ops;
446 pdata->offset = 0x7f0;
447 break;
448 case M48T59RTC_TYPE_M48T08:
449 name = "m48t08";
450 ops = &m48t02_rtc_ops;
451 pdata->offset = 0x1ff0;
452 break;
453 default:
454 dev_err(&pdev->dev, "Unknown RTC type\n");
455 ret = -ENODEV;
456 goto out;
457 }
424 458
425 m48t59->rtc = rtc_device_register("m48t59", &pdev->dev, 459 m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE);
426 &m48t59_rtc_ops, THIS_MODULE);
427 if (IS_ERR(m48t59->rtc)) { 460 if (IS_ERR(m48t59->rtc)) {
428 ret = PTR_ERR(m48t59->rtc); 461 ret = PTR_ERR(m48t59->rtc);
429 goto out; 462 goto out;
430 } 463 }
431 464
465 m48t59_nvram_attr.size = pdata->offset;
466
432 ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); 467 ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
433 if (ret) 468 if (ret)
434 goto out; 469 goto out;
@@ -452,11 +487,12 @@ out:
452static int __devexit m48t59_rtc_remove(struct platform_device *pdev) 487static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
453{ 488{
454 struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 489 struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
490 struct m48t59_plat_data *pdata = pdev->dev.platform_data;
455 491
456 sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); 492 sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
457 if (!IS_ERR(m48t59->rtc)) 493 if (!IS_ERR(m48t59->rtc))
458 rtc_device_unregister(m48t59->rtc); 494 rtc_device_unregister(m48t59->rtc);
459 if (m48t59->ioaddr) 495 if (m48t59->ioaddr && !pdata->ioaddr)
460 iounmap(m48t59->ioaddr); 496 iounmap(m48t59->ioaddr);
461 if (m48t59->irq != NO_IRQ) 497 if (m48t59->irq != NO_IRQ)
462 free_irq(m48t59->irq, &pdev->dev); 498 free_irq(m48t59->irq, &pdev->dev);
@@ -491,5 +527,5 @@ module_init(m48t59_rtc_init);
491module_exit(m48t59_rtc_exit); 527module_exit(m48t59_rtc_exit);
492 528
493MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); 529MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
494MODULE_DESCRIPTION("M48T59 RTC driver"); 530MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver");
495MODULE_LICENSE("GPL"); 531MODULE_LICENSE("GPL");