diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/rtc-x1205.c | 130 |
1 files changed, 43 insertions, 87 deletions
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index b90fb1866ce9..bb3290360091 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c | |||
| @@ -22,20 +22,7 @@ | |||
| 22 | #include <linux/rtc.h> | 22 | #include <linux/rtc.h> |
| 23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 24 | 24 | ||
| 25 | #define DRV_VERSION "1.0.7" | 25 | #define DRV_VERSION "1.0.8" |
| 26 | |||
| 27 | /* Addresses to scan: none. This chip is located at | ||
| 28 | * 0x6f and uses a two bytes register addressing. | ||
| 29 | * Two bytes need to be written to read a single register, | ||
| 30 | * while most other chips just require one and take the second | ||
| 31 | * one as the data to be written. To prevent corrupting | ||
| 32 | * unknown chips, the user must explicitly set the probe parameter. | ||
| 33 | */ | ||
| 34 | |||
| 35 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
| 36 | |||
| 37 | /* Insmod parameters */ | ||
| 38 | I2C_CLIENT_INSMOD; | ||
| 39 | 26 | ||
| 40 | /* offsets into CCR area */ | 27 | /* offsets into CCR area */ |
| 41 | 28 | ||
| @@ -91,19 +78,7 @@ I2C_CLIENT_INSMOD; | |||
| 91 | 78 | ||
| 92 | #define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ | 79 | #define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ |
| 93 | 80 | ||
| 94 | /* Prototypes */ | 81 | static struct i2c_driver x1205_driver; |
| 95 | static int x1205_attach(struct i2c_adapter *adapter); | ||
| 96 | static int x1205_detach(struct i2c_client *client); | ||
| 97 | static int x1205_probe(struct i2c_adapter *adapter, int address, int kind); | ||
| 98 | |||
| 99 | static struct i2c_driver x1205_driver = { | ||
| 100 | .driver = { | ||
| 101 | .name = "x1205", | ||
| 102 | }, | ||
| 103 | .id = I2C_DRIVERID_X1205, | ||
| 104 | .attach_adapter = &x1205_attach, | ||
| 105 | .detach_client = &x1205_detach, | ||
| 106 | }; | ||
| 107 | 82 | ||
| 108 | /* | 83 | /* |
| 109 | * In the routines that deal directly with the x1205 hardware, we use | 84 | * In the routines that deal directly with the x1205 hardware, we use |
| @@ -497,58 +472,49 @@ static ssize_t x1205_sysfs_show_dtrim(struct device *dev, | |||
| 497 | } | 472 | } |
| 498 | static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL); | 473 | static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL); |
| 499 | 474 | ||
| 500 | static int x1205_attach(struct i2c_adapter *adapter) | 475 | static int x1205_sysfs_register(struct device *dev) |
| 476 | { | ||
| 477 | int err; | ||
| 478 | |||
| 479 | err = device_create_file(dev, &dev_attr_atrim); | ||
| 480 | if (err) | ||
| 481 | return err; | ||
| 482 | |||
| 483 | err = device_create_file(dev, &dev_attr_dtrim); | ||
| 484 | if (err) | ||
| 485 | device_remove_file(dev, &dev_attr_atrim); | ||
| 486 | |||
| 487 | return err; | ||
| 488 | } | ||
| 489 | |||
| 490 | static void x1205_sysfs_unregister(struct device *dev) | ||
| 501 | { | 491 | { |
| 502 | return i2c_probe(adapter, &addr_data, x1205_probe); | 492 | device_remove_file(dev, &dev_attr_atrim); |
| 493 | device_remove_file(dev, &dev_attr_dtrim); | ||
| 503 | } | 494 | } |
| 504 | 495 | ||
| 505 | static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) | 496 | |
| 497 | static int x1205_probe(struct i2c_client *client) | ||
| 506 | { | 498 | { |
| 507 | int err = 0; | 499 | int err = 0; |
| 508 | unsigned char sr; | 500 | unsigned char sr; |
| 509 | struct i2c_client *client; | ||
| 510 | struct rtc_device *rtc; | 501 | struct rtc_device *rtc; |
| 511 | 502 | ||
| 512 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | 503 | dev_dbg(&client->dev, "%s\n", __func__); |
| 513 | |||
| 514 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
| 515 | err = -ENODEV; | ||
| 516 | goto exit; | ||
| 517 | } | ||
| 518 | |||
| 519 | if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { | ||
| 520 | err = -ENOMEM; | ||
| 521 | goto exit; | ||
| 522 | } | ||
| 523 | |||
| 524 | /* I2C client */ | ||
| 525 | client->addr = address; | ||
| 526 | client->driver = &x1205_driver; | ||
| 527 | client->adapter = adapter; | ||
| 528 | 504 | ||
| 529 | strlcpy(client->name, x1205_driver.driver.name, I2C_NAME_SIZE); | 505 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
| 530 | 506 | return -ENODEV; | |
| 531 | /* Verify the chip is really an X1205 */ | ||
| 532 | if (kind < 0) { | ||
| 533 | if (x1205_validate_client(client) < 0) { | ||
| 534 | err = -ENODEV; | ||
| 535 | goto exit_kfree; | ||
| 536 | } | ||
| 537 | } | ||
| 538 | 507 | ||
| 539 | /* Inform the i2c layer */ | 508 | if (x1205_validate_client(client) < 0) |
| 540 | if ((err = i2c_attach_client(client))) | 509 | return -ENODEV; |
| 541 | goto exit_kfree; | ||
| 542 | 510 | ||
| 543 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 511 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
| 544 | 512 | ||
| 545 | rtc = rtc_device_register(x1205_driver.driver.name, &client->dev, | 513 | rtc = rtc_device_register(x1205_driver.driver.name, &client->dev, |
| 546 | &x1205_rtc_ops, THIS_MODULE); | 514 | &x1205_rtc_ops, THIS_MODULE); |
| 547 | 515 | ||
| 548 | if (IS_ERR(rtc)) { | 516 | if (IS_ERR(rtc)) |
| 549 | err = PTR_ERR(rtc); | 517 | return PTR_ERR(rtc); |
| 550 | goto exit_detach; | ||
| 551 | } | ||
| 552 | 518 | ||
| 553 | i2c_set_clientdata(client, rtc); | 519 | i2c_set_clientdata(client, rtc); |
| 554 | 520 | ||
| @@ -565,45 +531,35 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) | |||
| 565 | else | 531 | else |
| 566 | dev_err(&client->dev, "couldn't read status\n"); | 532 | dev_err(&client->dev, "couldn't read status\n"); |
| 567 | 533 | ||
| 568 | err = device_create_file(&client->dev, &dev_attr_atrim); | 534 | err = x1205_sysfs_register(&client->dev); |
| 569 | if (err) goto exit_devreg; | 535 | if (err) |
| 570 | err = device_create_file(&client->dev, &dev_attr_dtrim); | 536 | goto exit_devreg; |
| 571 | if (err) goto exit_atrim; | ||
| 572 | 537 | ||
| 573 | return 0; | 538 | return 0; |
| 574 | 539 | ||
| 575 | exit_atrim: | ||
| 576 | device_remove_file(&client->dev, &dev_attr_atrim); | ||
| 577 | |||
| 578 | exit_devreg: | 540 | exit_devreg: |
| 579 | rtc_device_unregister(rtc); | 541 | rtc_device_unregister(rtc); |
| 580 | 542 | ||
| 581 | exit_detach: | ||
| 582 | i2c_detach_client(client); | ||
| 583 | |||
| 584 | exit_kfree: | ||
| 585 | kfree(client); | ||
| 586 | |||
| 587 | exit: | ||
| 588 | return err; | 543 | return err; |
| 589 | } | 544 | } |
| 590 | 545 | ||
| 591 | static int x1205_detach(struct i2c_client *client) | 546 | static int x1205_remove(struct i2c_client *client) |
| 592 | { | 547 | { |
| 593 | int err; | ||
| 594 | struct rtc_device *rtc = i2c_get_clientdata(client); | 548 | struct rtc_device *rtc = i2c_get_clientdata(client); |
| 595 | 549 | ||
| 596 | if (rtc) | 550 | rtc_device_unregister(rtc); |
| 597 | rtc_device_unregister(rtc); | 551 | x1205_sysfs_unregister(&client->dev); |
| 598 | |||
| 599 | if ((err = i2c_detach_client(client))) | ||
| 600 | return err; | ||
| 601 | |||
| 602 | kfree(client); | ||
| 603 | |||
| 604 | return 0; | 552 | return 0; |
| 605 | } | 553 | } |
| 606 | 554 | ||
| 555 | static struct i2c_driver x1205_driver = { | ||
| 556 | .driver = { | ||
| 557 | .name = "rtc-x1205", | ||
| 558 | }, | ||
| 559 | .probe = x1205_probe, | ||
| 560 | .remove = x1205_remove, | ||
| 561 | }; | ||
| 562 | |||
| 607 | static int __init x1205_init(void) | 563 | static int __init x1205_init(void) |
| 608 | { | 564 | { |
| 609 | return i2c_add_driver(&x1205_driver); | 565 | return i2c_add_driver(&x1205_driver); |
