diff options
Diffstat (limited to 'drivers/rtc/rtc-x1205.c')
-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); |