diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rtc/Kconfig | 7 | ||||
-rw-r--r-- | drivers/rtc/rtc-m48t59.c | 47 |
2 files changed, 44 insertions, 10 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ecdff2002476..daf08fe980d0 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -406,10 +406,13 @@ config RTC_DRV_M48T86 | |||
406 | will be called rtc-m48t86. | 406 | will be called rtc-m48t86. |
407 | 407 | ||
408 | config RTC_DRV_M48T59 | 408 | config RTC_DRV_M48T59 |
409 | tristate "ST M48T59" | 409 | tristate "ST M48T59/M48T08/M48T02" |
410 | help | 410 | help |
411 | If you say Y here you will get support for the | 411 | If you say Y here you will get support for the |
412 | ST M48T59 RTC chip. | 412 | ST M48T59 RTC chip and compatible ST M48T08 and M48T02. |
413 | |||
414 | These chips are usually found in Sun SPARC and UltraSPARC | ||
415 | workstations. | ||
413 | 416 | ||
414 | This driver can also be built as a module, if so, the module | 417 | This driver can also be built as a module, if so, the module |
415 | will be called "rtc-m48t59". | 418 | will be called "rtc-m48t59". |
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"); |