diff options
author | David Brownell <david-b@pacbell.net> | 2007-07-17 07:04:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-17 13:23:08 -0400 |
commit | d815461c7a73903d0a926b3cace6f69e144c54a3 (patch) | |
tree | eceeae1db5fd3c876160ad517872cd19a74ecdba /drivers/rtc/rtc-rs5c372.c | |
parent | 045e0e85f2f6ee6621d8f7bab3059e9c74076738 (diff) |
rtc-rs5c372 becomes a new-style i2c driver
Convert rtc-rs5c372 to be a "new style" I2C driver, and update the
Kconfig text to be more complete..
Verified on an OMAP H4 development platform, along with a board
init patch to declare its rv5c387a device.
Only one defconfig -- powerpc/linkstation -- uses this driver; but
several other platforms use it, just without defconfig support.
Such platforms need to be converted so (a) their I2C adapter driver
supports new-style drivers, and (b) board init code declares this
I2C device.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Voipio Riku <Riku.Voipio@movial.fi>
Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: Martin Michlmayr <tbm@cyrius.com>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc/rtc-rs5c372.c')
-rw-r--r-- | drivers/rtc/rtc-rs5c372.c | 95 |
1 files changed, 34 insertions, 61 deletions
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 09bbe575647b..6b67b5097927 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -13,13 +13,7 @@ | |||
13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
14 | #include <linux/bcd.h> | 14 | #include <linux/bcd.h> |
15 | 15 | ||
16 | #define DRV_VERSION "0.4" | 16 | #define DRV_VERSION "0.5" |
17 | |||
18 | /* Addresses to scan */ | ||
19 | static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END }; | ||
20 | |||
21 | /* Insmod parameters */ | ||
22 | I2C_CLIENT_INSMOD; | ||
23 | 17 | ||
24 | 18 | ||
25 | /* | 19 | /* |
@@ -88,9 +82,6 @@ struct rs5c372 { | |||
88 | unsigned has_irq:1; | 82 | unsigned has_irq:1; |
89 | char buf[17]; | 83 | char buf[17]; |
90 | char *regs; | 84 | char *regs; |
91 | |||
92 | /* on conversion to a "new style" i2c driver, this vanishes */ | ||
93 | struct i2c_client dev; | ||
94 | }; | 85 | }; |
95 | 86 | ||
96 | static int rs5c_get_regs(struct rs5c372 *rs5c) | 87 | static int rs5c_get_regs(struct rs5c372 *rs5c) |
@@ -483,25 +474,35 @@ static int rs5c_sysfs_register(struct device *dev) | |||
483 | return err; | 474 | return err; |
484 | } | 475 | } |
485 | 476 | ||
477 | static void rs5c_sysfs_unregister(struct device *dev) | ||
478 | { | ||
479 | device_remove_file(dev, &dev_attr_trim); | ||
480 | device_remove_file(dev, &dev_attr_osc); | ||
481 | } | ||
482 | |||
486 | #else | 483 | #else |
487 | static int rs5c_sysfs_register(struct device *dev) | 484 | static int rs5c_sysfs_register(struct device *dev) |
488 | { | 485 | { |
489 | return 0; | 486 | return 0; |
490 | } | 487 | } |
488 | |||
489 | static void rs5c_sysfs_unregister(struct device *dev) | ||
490 | { | ||
491 | /* nothing */ | ||
492 | } | ||
491 | #endif /* SYSFS */ | 493 | #endif /* SYSFS */ |
492 | 494 | ||
493 | static struct i2c_driver rs5c372_driver; | 495 | static struct i2c_driver rs5c372_driver; |
494 | 496 | ||
495 | static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) | 497 | static int rs5c372_probe(struct i2c_client *client) |
496 | { | 498 | { |
497 | int err = 0; | 499 | int err = 0; |
498 | struct i2c_client *client; | ||
499 | struct rs5c372 *rs5c372; | 500 | struct rs5c372 *rs5c372; |
500 | struct rtc_time tm; | 501 | struct rtc_time tm; |
501 | 502 | ||
502 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | 503 | dev_dbg(&client->dev, "%s\n", __FUNCTION__); |
503 | 504 | ||
504 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | 505 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
505 | err = -ENODEV; | 506 | err = -ENODEV; |
506 | goto exit; | 507 | goto exit; |
507 | } | 508 | } |
@@ -514,35 +515,22 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) | |||
514 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ | 515 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ |
515 | rs5c372->regs=&rs5c372->buf[1]; | 516 | rs5c372->regs=&rs5c372->buf[1]; |
516 | 517 | ||
517 | /* On conversion to a "new style" i2c driver, we'll be handed | ||
518 | * the i2c_client (we won't create it) | ||
519 | */ | ||
520 | client = &rs5c372->dev; | ||
521 | rs5c372->client = client; | 518 | rs5c372->client = client; |
522 | |||
523 | /* I2C client */ | ||
524 | client->addr = address; | ||
525 | client->driver = &rs5c372_driver; | ||
526 | client->adapter = adapter; | ||
527 | |||
528 | strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE); | ||
529 | |||
530 | i2c_set_clientdata(client, rs5c372); | 519 | i2c_set_clientdata(client, rs5c372); |
531 | 520 | ||
532 | /* Inform the i2c layer */ | ||
533 | if ((err = i2c_attach_client(client))) | ||
534 | goto exit_kfree; | ||
535 | |||
536 | err = rs5c_get_regs(rs5c372); | 521 | err = rs5c_get_regs(rs5c372); |
537 | if (err < 0) | 522 | if (err < 0) |
538 | goto exit_detach; | 523 | goto exit_kfree; |
539 | 524 | ||
540 | /* For "new style" drivers, irq is in i2c_client and chip type | 525 | if (strcmp(client->name, "rs5c372a") == 0) |
541 | * info comes from i2c_client.dev.platform_data. Meanwhile: | 526 | rs5c372->type = rtc_rs5c372a; |
542 | * | 527 | else if (strcmp(client->name, "rs5c372b") == 0) |
543 | * STICK BOARD-SPECIFIC SETUP CODE RIGHT HERE | 528 | rs5c372->type = rtc_rs5c372b; |
544 | */ | 529 | else if (strcmp(client->name, "rv5c386") == 0) |
545 | if (rs5c372->type == rtc_undef) { | 530 | rs5c372->type = rtc_rv5c386; |
531 | else if (strcmp(client->name, "rv5c387a") == 0) | ||
532 | rs5c372->type = rtc_rv5c387a; | ||
533 | else { | ||
546 | rs5c372->type = rtc_rs5c372b; | 534 | rs5c372->type = rtc_rs5c372b; |
547 | dev_warn(&client->dev, "assuming rs5c372b\n"); | 535 | dev_warn(&client->dev, "assuming rs5c372b\n"); |
548 | } | 536 | } |
@@ -567,7 +555,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) | |||
567 | break; | 555 | break; |
568 | default: | 556 | default: |
569 | dev_err(&client->dev, "unknown RTC type\n"); | 557 | dev_err(&client->dev, "unknown RTC type\n"); |
570 | goto exit_detach; | 558 | goto exit_kfree; |
571 | } | 559 | } |
572 | 560 | ||
573 | /* if the oscillator lost power and no other software (like | 561 | /* if the oscillator lost power and no other software (like |
@@ -601,7 +589,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) | |||
601 | 589 | ||
602 | if ((i2c_master_send(client, buf, 3)) != 3) { | 590 | if ((i2c_master_send(client, buf, 3)) != 3) { |
603 | dev_err(&client->dev, "setup error\n"); | 591 | dev_err(&client->dev, "setup error\n"); |
604 | goto exit_detach; | 592 | goto exit_kfree; |
605 | } | 593 | } |
606 | rs5c372->regs[RS5C_REG_CTRL1] = buf[1]; | 594 | rs5c372->regs[RS5C_REG_CTRL1] = buf[1]; |
607 | rs5c372->regs[RS5C_REG_CTRL2] = buf[2]; | 595 | rs5c372->regs[RS5C_REG_CTRL2] = buf[2]; |
@@ -621,14 +609,14 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) | |||
621 | rs5c372->time24 ? "24hr" : "am/pm" | 609 | rs5c372->time24 ? "24hr" : "am/pm" |
622 | ); | 610 | ); |
623 | 611 | ||
624 | /* FIXME when client->irq exists, use it to register alarm irq */ | 612 | /* REVISIT use client->irq to register alarm irq ... */ |
625 | 613 | ||
626 | rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name, | 614 | rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name, |
627 | &client->dev, &rs5c372_rtc_ops, THIS_MODULE); | 615 | &client->dev, &rs5c372_rtc_ops, THIS_MODULE); |
628 | 616 | ||
629 | if (IS_ERR(rs5c372->rtc)) { | 617 | if (IS_ERR(rs5c372->rtc)) { |
630 | err = PTR_ERR(rs5c372->rtc); | 618 | err = PTR_ERR(rs5c372->rtc); |
631 | goto exit_detach; | 619 | goto exit_kfree; |
632 | } | 620 | } |
633 | 621 | ||
634 | err = rs5c_sysfs_register(&client->dev); | 622 | err = rs5c_sysfs_register(&client->dev); |
@@ -640,9 +628,6 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) | |||
640 | exit_devreg: | 628 | exit_devreg: |
641 | rtc_device_unregister(rs5c372->rtc); | 629 | rtc_device_unregister(rs5c372->rtc); |
642 | 630 | ||
643 | exit_detach: | ||
644 | i2c_detach_client(client); | ||
645 | |||
646 | exit_kfree: | 631 | exit_kfree: |
647 | kfree(rs5c372); | 632 | kfree(rs5c372); |
648 | 633 | ||
@@ -650,24 +635,12 @@ exit: | |||
650 | return err; | 635 | return err; |
651 | } | 636 | } |
652 | 637 | ||
653 | static int rs5c372_attach(struct i2c_adapter *adapter) | 638 | static int rs5c372_remove(struct i2c_client *client) |
654 | { | 639 | { |
655 | return i2c_probe(adapter, &addr_data, rs5c372_probe); | ||
656 | } | ||
657 | |||
658 | static int rs5c372_detach(struct i2c_client *client) | ||
659 | { | ||
660 | int err; | ||
661 | struct rs5c372 *rs5c372 = i2c_get_clientdata(client); | 640 | struct rs5c372 *rs5c372 = i2c_get_clientdata(client); |
662 | 641 | ||
663 | if (rs5c372->rtc) | 642 | rtc_device_unregister(rs5c372->rtc); |
664 | rtc_device_unregister(rs5c372->rtc); | 643 | rs5c_sysfs_unregister(&client->dev); |
665 | |||
666 | /* REVISIT properly destroy the sysfs files ... */ | ||
667 | |||
668 | if ((err = i2c_detach_client(client))) | ||
669 | return err; | ||
670 | |||
671 | kfree(rs5c372); | 644 | kfree(rs5c372); |
672 | return 0; | 645 | return 0; |
673 | } | 646 | } |
@@ -676,8 +649,8 @@ static struct i2c_driver rs5c372_driver = { | |||
676 | .driver = { | 649 | .driver = { |
677 | .name = "rtc-rs5c372", | 650 | .name = "rtc-rs5c372", |
678 | }, | 651 | }, |
679 | .attach_adapter = &rs5c372_attach, | 652 | .probe = rs5c372_probe, |
680 | .detach_client = &rs5c372_detach, | 653 | .remove = rs5c372_remove, |
681 | }; | 654 | }; |
682 | 655 | ||
683 | static __init int rs5c372_init(void) | 656 | static __init int rs5c372_init(void) |