diff options
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/f75375s.c | 109 |
1 files changed, 83 insertions, 26 deletions
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 59a3470d6cf9..19b3427b5e9e 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c | |||
@@ -86,7 +86,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375); | |||
86 | 86 | ||
87 | struct f75375_data { | 87 | struct f75375_data { |
88 | unsigned short addr; | 88 | unsigned short addr; |
89 | struct i2c_client client; | 89 | struct i2c_client *client; |
90 | struct device *hwmon_dev; | 90 | struct device *hwmon_dev; |
91 | 91 | ||
92 | const char *name; | 92 | const char *name; |
@@ -116,15 +116,25 @@ struct f75375_data { | |||
116 | static int f75375_attach_adapter(struct i2c_adapter *adapter); | 116 | static int f75375_attach_adapter(struct i2c_adapter *adapter); |
117 | static int f75375_detect(struct i2c_adapter *adapter, int address, int kind); | 117 | static int f75375_detect(struct i2c_adapter *adapter, int address, int kind); |
118 | static int f75375_detach_client(struct i2c_client *client); | 118 | static int f75375_detach_client(struct i2c_client *client); |
119 | static int f75375_probe(struct i2c_client *client); | ||
120 | static int f75375_remove(struct i2c_client *client); | ||
119 | 121 | ||
120 | static struct i2c_driver f75375_driver = { | 122 | static struct i2c_driver f75375_legacy_driver = { |
121 | .driver = { | 123 | .driver = { |
122 | .name = "f75375", | 124 | .name = "f75375_legacy", |
123 | }, | 125 | }, |
124 | .attach_adapter = f75375_attach_adapter, | 126 | .attach_adapter = f75375_attach_adapter, |
125 | .detach_client = f75375_detach_client, | 127 | .detach_client = f75375_detach_client, |
126 | }; | 128 | }; |
127 | 129 | ||
130 | static struct i2c_driver f75375_driver = { | ||
131 | .driver = { | ||
132 | .name = "f75375", | ||
133 | }, | ||
134 | .probe = f75375_probe, | ||
135 | .remove = f75375_remove, | ||
136 | }; | ||
137 | |||
128 | static inline int f75375_read8(struct i2c_client *client, u8 reg) | 138 | static inline int f75375_read8(struct i2c_client *client, u8 reg) |
129 | { | 139 | { |
130 | return i2c_smbus_read_byte_data(client, reg); | 140 | return i2c_smbus_read_byte_data(client, reg); |
@@ -580,12 +590,9 @@ static const struct attribute_group f75375_group = { | |||
580 | 590 | ||
581 | static int f75375_detach_client(struct i2c_client *client) | 591 | static int f75375_detach_client(struct i2c_client *client) |
582 | { | 592 | { |
583 | struct f75375_data *data = i2c_get_clientdata(client); | ||
584 | int err; | 593 | int err; |
585 | 594 | ||
586 | hwmon_device_unregister(data->hwmon_dev); | 595 | f75375_remove(client); |
587 | sysfs_remove_group(&client->dev.kobj, &f75375_group); | ||
588 | |||
589 | err = i2c_detach_client(client); | 596 | err = i2c_detach_client(client); |
590 | if (err) { | 597 | if (err) { |
591 | dev_err(&client->dev, | 598 | dev_err(&client->dev, |
@@ -593,7 +600,60 @@ static int f75375_detach_client(struct i2c_client *client) | |||
593 | "client not detached.\n"); | 600 | "client not detached.\n"); |
594 | return err; | 601 | return err; |
595 | } | 602 | } |
603 | kfree(client); | ||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | static int f75375_probe(struct i2c_client *client) | ||
608 | { | ||
609 | struct f75375_data *data = i2c_get_clientdata(client); | ||
610 | int err; | ||
611 | |||
612 | if (!i2c_check_functionality(client->adapter, | ||
613 | I2C_FUNC_SMBUS_BYTE_DATA)) | ||
614 | return -EIO; | ||
615 | if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) | ||
616 | return -ENOMEM; | ||
617 | |||
618 | i2c_set_clientdata(client, data); | ||
619 | data->client = client; | ||
620 | mutex_init(&data->update_lock); | ||
621 | |||
622 | if (strcmp(client->name, "f75375") == 0) | ||
623 | data->kind = f75375; | ||
624 | else if (strcmp(client->name, "f75373") == 0) | ||
625 | data->kind = f75373; | ||
626 | else { | ||
627 | dev_err(&client->dev, "Unsupported device: %s\n", client->name); | ||
628 | return -ENODEV; | ||
629 | } | ||
630 | |||
631 | if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group))) | ||
632 | goto exit_free; | ||
633 | |||
634 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
635 | if (IS_ERR(data->hwmon_dev)) { | ||
636 | err = PTR_ERR(data->hwmon_dev); | ||
637 | goto exit_remove; | ||
638 | } | ||
639 | |||
640 | return 0; | ||
641 | |||
642 | exit_remove: | ||
643 | sysfs_remove_group(&client->dev.kobj, &f75375_group); | ||
644 | exit_free: | ||
645 | kfree(data); | ||
646 | i2c_set_clientdata(client, NULL); | ||
647 | return err; | ||
648 | } | ||
649 | |||
650 | static int f75375_remove(struct i2c_client *client) | ||
651 | { | ||
652 | struct f75375_data *data = i2c_get_clientdata(client); | ||
653 | hwmon_device_unregister(data->hwmon_dev); | ||
654 | sysfs_remove_group(&client->dev.kobj, &f75375_group); | ||
596 | kfree(data); | 655 | kfree(data); |
656 | i2c_set_clientdata(client, NULL); | ||
597 | return 0; | 657 | return 0; |
598 | } | 658 | } |
599 | 659 | ||
@@ -608,20 +668,17 @@ static int f75375_attach_adapter(struct i2c_adapter *adapter) | |||
608 | static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) | 668 | static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) |
609 | { | 669 | { |
610 | struct i2c_client *client; | 670 | struct i2c_client *client; |
611 | struct f75375_data *data; | ||
612 | u8 version = 0; | 671 | u8 version = 0; |
613 | int err = 0; | 672 | int err = 0; |
614 | const char *name = ""; | 673 | const char *name = ""; |
615 | 674 | ||
616 | if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) { | 675 | if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) { |
617 | err = -ENOMEM; | 676 | err = -ENOMEM; |
618 | goto exit; | 677 | goto exit; |
619 | } | 678 | } |
620 | client = &data->client; | ||
621 | i2c_set_clientdata(client, data); | ||
622 | client->addr = address; | 679 | client->addr = address; |
623 | client->adapter = adapter; | 680 | client->adapter = adapter; |
624 | client->driver = &f75375_driver; | 681 | client->driver = &f75375_legacy_driver; |
625 | 682 | ||
626 | if (kind < 0) { | 683 | if (kind < 0) { |
627 | u16 vendid = f75375_read16(client, F75375_REG_VENDOR); | 684 | u16 vendid = f75375_read16(client, F75375_REG_VENDOR); |
@@ -644,42 +701,42 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) | |||
644 | } else if (kind == f75373) { | 701 | } else if (kind == f75373) { |
645 | name = "f75373"; | 702 | name = "f75373"; |
646 | } | 703 | } |
647 | |||
648 | dev_info(&adapter->dev, "found %s version: %02X\n", name, version); | 704 | dev_info(&adapter->dev, "found %s version: %02X\n", name, version); |
649 | strlcpy(client->name, name, I2C_NAME_SIZE); | 705 | strlcpy(client->name, name, I2C_NAME_SIZE); |
650 | data->kind = kind; | 706 | |
651 | mutex_init(&data->update_lock); | ||
652 | if ((err = i2c_attach_client(client))) | 707 | if ((err = i2c_attach_client(client))) |
653 | goto exit_free; | 708 | goto exit_free; |
654 | 709 | ||
655 | if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group))) | 710 | if ((err = f75375_probe(client)) < 0) |
656 | goto exit_detach; | 711 | goto exit_detach; |
657 | 712 | ||
658 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
659 | if (IS_ERR(data->hwmon_dev)) { | ||
660 | err = PTR_ERR(data->hwmon_dev); | ||
661 | goto exit_remove; | ||
662 | } | ||
663 | |||
664 | return 0; | 713 | return 0; |
665 | 714 | ||
666 | exit_remove: | ||
667 | sysfs_remove_group(&client->dev.kobj, &f75375_group); | ||
668 | exit_detach: | 715 | exit_detach: |
669 | i2c_detach_client(client); | 716 | i2c_detach_client(client); |
670 | exit_free: | 717 | exit_free: |
671 | kfree(data); | 718 | kfree(client); |
672 | exit: | 719 | exit: |
673 | return err; | 720 | return err; |
674 | } | 721 | } |
675 | 722 | ||
676 | static int __init sensors_f75375_init(void) | 723 | static int __init sensors_f75375_init(void) |
677 | { | 724 | { |
678 | return i2c_add_driver(&f75375_driver); | 725 | int status; |
726 | status = i2c_add_driver(&f75375_driver); | ||
727 | if (status) | ||
728 | return status; | ||
729 | |||
730 | status = i2c_add_driver(&f75375_legacy_driver); | ||
731 | if (status) | ||
732 | i2c_del_driver(&f75375_driver); | ||
733 | |||
734 | return status; | ||
679 | } | 735 | } |
680 | 736 | ||
681 | static void __exit sensors_f75375_exit(void) | 737 | static void __exit sensors_f75375_exit(void) |
682 | { | 738 | { |
739 | i2c_del_driver(&f75375_legacy_driver); | ||
683 | i2c_del_driver(&f75375_driver); | 740 | i2c_del_driver(&f75375_driver); |
684 | } | 741 | } |
685 | 742 | ||