diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2008-09-03 18:12:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-03 18:39:11 -0400 |
commit | 94fe7424a4c21940b4569200faaf0a0a5efd2924 (patch) | |
tree | 1c19837578b0774008df1e2430cf32353cf95286 /drivers/rtc/rtc-m48t59.c | |
parent | 3ca60f6e637cee8c735a7448fd912fe1a6e42fc1 (diff) |
rtc-m48t59: add support for M48T02 and M48T59 chips
Add support for two compatible RTC:
- M48T08 which does not have alarm part,
- M48T08 which does not have alarm part and has
only 2KB of NVRAM
These types covers all Mostek's RTC used in Sun UltraSparc workstations.
Tested on Sun Ultra60 with M48T59 RTC.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/rtc/rtc-m48t59.c')
-rw-r--r-- | drivers/rtc/rtc-m48t59.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index e085ab2c3dbe..50f9f10b32f0 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)) |
@@ -309,6 +310,11 @@ static const struct rtc_class_ops m48t59_rtc_ops = { | |||
309 | .proc = m48t59_rtc_proc, | 310 | .proc = m48t59_rtc_proc, |
310 | }; | 311 | }; |
311 | 312 | ||
313 | static const struct rtc_class_ops m48t02_rtc_ops = { | ||
314 | .read_time = m48t59_rtc_read_time, | ||
315 | .set_time = m48t59_rtc_set_time, | ||
316 | }; | ||
317 | |||
312 | static ssize_t m48t59_nvram_read(struct kobject *kobj, | 318 | static ssize_t m48t59_nvram_read(struct kobject *kobj, |
313 | struct bin_attribute *bin_attr, | 319 | struct bin_attribute *bin_attr, |
314 | char *buf, loff_t pos, size_t size) | 320 | char *buf, loff_t pos, size_t size) |
@@ -320,7 +326,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj, | |||
320 | ssize_t cnt = 0; | 326 | ssize_t cnt = 0; |
321 | unsigned long flags; | 327 | unsigned long flags; |
322 | 328 | ||
323 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 329 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
324 | spin_lock_irqsave(&m48t59->lock, flags); | 330 | spin_lock_irqsave(&m48t59->lock, flags); |
325 | *buf++ = M48T59_READ(cnt); | 331 | *buf++ = M48T59_READ(cnt); |
326 | spin_unlock_irqrestore(&m48t59->lock, flags); | 332 | spin_unlock_irqrestore(&m48t59->lock, flags); |
@@ -340,7 +346,7 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj, | |||
340 | ssize_t cnt = 0; | 346 | ssize_t cnt = 0; |
341 | unsigned long flags; | 347 | unsigned long flags; |
342 | 348 | ||
343 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 349 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
344 | spin_lock_irqsave(&m48t59->lock, flags); | 350 | spin_lock_irqsave(&m48t59->lock, flags); |
345 | M48T59_WRITE(*buf++, cnt); | 351 | M48T59_WRITE(*buf++, cnt); |
346 | spin_unlock_irqrestore(&m48t59->lock, flags); | 352 | spin_unlock_irqrestore(&m48t59->lock, flags); |
@@ -357,7 +363,6 @@ static struct bin_attribute m48t59_nvram_attr = { | |||
357 | }, | 363 | }, |
358 | .read = m48t59_nvram_read, | 364 | .read = m48t59_nvram_read, |
359 | .write = m48t59_nvram_write, | 365 | .write = m48t59_nvram_write, |
360 | .size = M48T59_NVRAM_SIZE, | ||
361 | }; | 366 | }; |
362 | 367 | ||
363 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | 368 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) |
@@ -366,6 +371,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
366 | struct m48t59_private *m48t59 = NULL; | 371 | struct m48t59_private *m48t59 = NULL; |
367 | struct resource *res; | 372 | struct resource *res; |
368 | int ret = -ENOMEM; | 373 | int ret = -ENOMEM; |
374 | char *name; | ||
375 | const struct rtc_class_ops *ops; | ||
369 | 376 | ||
370 | /* This chip could be memory-mapped or I/O-mapped */ | 377 | /* This chip could be memory-mapped or I/O-mapped */ |
371 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 378 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -390,6 +397,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
390 | /* Ensure we only kmalloc platform data once */ | 397 | /* Ensure we only kmalloc platform data once */ |
391 | pdev->dev.platform_data = pdata; | 398 | pdev->dev.platform_data = pdata; |
392 | } | 399 | } |
400 | if (!pdata->type) | ||
401 | pdata->type = M48T59RTC_TYPE_M48T59; | ||
393 | 402 | ||
394 | /* Try to use the generic memory read/write ops */ | 403 | /* Try to use the generic memory read/write ops */ |
395 | if (!pdata->write_byte) | 404 | if (!pdata->write_byte) |
@@ -419,14 +428,36 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
419 | if (ret) | 428 | if (ret) |
420 | goto out; | 429 | goto out; |
421 | } | 430 | } |
431 | switch (pdata->type) { | ||
432 | case M48T59RTC_TYPE_M48T59: | ||
433 | name = "m48t59"; | ||
434 | ops = &m48t59_rtc_ops; | ||
435 | pdata->offset = 0x1ff0; | ||
436 | break; | ||
437 | case M48T59RTC_TYPE_M48T02: | ||
438 | name = "m48t02"; | ||
439 | ops = &m48t02_rtc_ops; | ||
440 | pdata->offset = 0x7f0; | ||
441 | break; | ||
442 | case M48T59RTC_TYPE_M48T08: | ||
443 | name = "m48t08"; | ||
444 | ops = &m48t02_rtc_ops; | ||
445 | pdata->offset = 0x1ff0; | ||
446 | break; | ||
447 | default: | ||
448 | dev_err(&pdev->dev, "Unknown RTC type\n"); | ||
449 | ret = -ENODEV; | ||
450 | goto out; | ||
451 | } | ||
422 | 452 | ||
423 | m48t59->rtc = rtc_device_register("m48t59", &pdev->dev, | 453 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); |
424 | &m48t59_rtc_ops, THIS_MODULE); | ||
425 | if (IS_ERR(m48t59->rtc)) { | 454 | if (IS_ERR(m48t59->rtc)) { |
426 | ret = PTR_ERR(m48t59->rtc); | 455 | ret = PTR_ERR(m48t59->rtc); |
427 | goto out; | 456 | goto out; |
428 | } | 457 | } |
429 | 458 | ||
459 | m48t59_nvram_attr.size = pdata->offset; | ||
460 | |||
430 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 461 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
431 | if (ret) | 462 | if (ret) |
432 | goto out; | 463 | goto out; |
@@ -489,5 +520,5 @@ module_init(m48t59_rtc_init); | |||
489 | module_exit(m48t59_rtc_exit); | 520 | module_exit(m48t59_rtc_exit); |
490 | 521 | ||
491 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); | 522 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); |
492 | MODULE_DESCRIPTION("M48T59 RTC driver"); | 523 | MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver"); |
493 | MODULE_LICENSE("GPL"); | 524 | MODULE_LICENSE("GPL"); |