diff options
author | Phil Reid <preid@electromag.com.au> | 2016-09-01 03:50:52 -0400 |
---|---|---|
committer | Sebastian Reichel <sre@kernel.org> | 2016-09-01 10:06:14 -0400 |
commit | 3b5dd3a49496220b35af83c96e3d2ff5716550ae (patch) | |
tree | 31b06b095bcfd1920da2759c1db89c3fe46f33d0 /drivers/power | |
parent | 528e3504123d0281c613b83ca46aaf2dd7c3f45e (diff) |
power: supply: sbs-battery: Use gpio_desc and sleeping calls for battery detect
Switch to using new gpio_desc interface and devm gpio get calls to
automatically manage gpio resource. Use gpiod_get_value which handles
active high / low calls.
If gpio_detect is set then force loading of the driver as it is
reasonable to assume that the battery may not be present.
Update the is_present flag immediately in the IRQ.
Remove legacy gpio specification from platform data.
Signed-off-by: Phil Reid <preid@electromag.com.au>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/supply/sbs-battery.c | 101 |
1 files changed, 34 insertions, 67 deletions
diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c index e1dfb3e7aee4..8b4c6a8681b0 100644 --- a/drivers/power/supply/sbs-battery.c +++ b/drivers/power/supply/sbs-battery.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/gpio.h> | 29 | #include <linux/gpio/consumer.h> |
30 | #include <linux/of.h> | 30 | #include <linux/of.h> |
31 | #include <linux/stat.h> | 31 | #include <linux/stat.h> |
32 | 32 | ||
@@ -165,7 +165,7 @@ struct sbs_info { | |||
165 | struct power_supply *power_supply; | 165 | struct power_supply *power_supply; |
166 | struct sbs_platform_data *pdata; | 166 | struct sbs_platform_data *pdata; |
167 | bool is_present; | 167 | bool is_present; |
168 | bool gpio_detect; | 168 | struct gpio_desc *gpio_detect; |
169 | bool enable_detection; | 169 | bool enable_detection; |
170 | int last_state; | 170 | int last_state; |
171 | int poll_time; | 171 | int poll_time; |
@@ -306,13 +306,11 @@ static int sbs_get_battery_presence_and_health( | |||
306 | s32 ret; | 306 | s32 ret; |
307 | struct sbs_info *chip = i2c_get_clientdata(client); | 307 | struct sbs_info *chip = i2c_get_clientdata(client); |
308 | 308 | ||
309 | if (psp == POWER_SUPPLY_PROP_PRESENT && | 309 | if (psp == POWER_SUPPLY_PROP_PRESENT && chip->gpio_detect) { |
310 | chip->gpio_detect) { | 310 | ret = gpiod_get_value_cansleep(chip->gpio_detect); |
311 | ret = gpio_get_value(chip->pdata->battery_detect); | 311 | if (ret < 0) |
312 | if (ret == chip->pdata->battery_detect_present) | 312 | return ret; |
313 | val->intval = 1; | 313 | val->intval = ret; |
314 | else | ||
315 | val->intval = 0; | ||
316 | chip->is_present = val->intval; | 314 | chip->is_present = val->intval; |
317 | return ret; | 315 | return ret; |
318 | } | 316 | } |
@@ -683,7 +681,12 @@ static irqreturn_t sbs_irq(int irq, void *devid) | |||
683 | { | 681 | { |
684 | struct sbs_info *chip = devid; | 682 | struct sbs_info *chip = devid; |
685 | struct power_supply *battery = chip->power_supply; | 683 | struct power_supply *battery = chip->power_supply; |
684 | int ret; | ||
686 | 685 | ||
686 | ret = gpiod_get_value_cansleep(chip->gpio_detect); | ||
687 | if (ret < 0) | ||
688 | return ret; | ||
689 | chip->is_present = ret; | ||
687 | power_supply_changed(battery); | 690 | power_supply_changed(battery); |
688 | 691 | ||
689 | return IRQ_HANDLED; | 692 | return IRQ_HANDLED; |
@@ -750,12 +753,11 @@ static const struct of_device_id sbs_dt_ids[] = { | |||
750 | }; | 753 | }; |
751 | MODULE_DEVICE_TABLE(of, sbs_dt_ids); | 754 | MODULE_DEVICE_TABLE(of, sbs_dt_ids); |
752 | 755 | ||
753 | static struct sbs_platform_data *sbs_of_populate_pdata( | 756 | static struct sbs_platform_data *sbs_of_populate_pdata(struct sbs_info *chip) |
754 | struct i2c_client *client) | ||
755 | { | 757 | { |
758 | struct i2c_client *client = chip->client; | ||
756 | struct device_node *of_node = client->dev.of_node; | 759 | struct device_node *of_node = client->dev.of_node; |
757 | struct sbs_platform_data *pdata = client->dev.platform_data; | 760 | struct sbs_platform_data *pdata; |
758 | enum of_gpio_flags gpio_flags; | ||
759 | int rc; | 761 | int rc; |
760 | u32 prop; | 762 | u32 prop; |
761 | 763 | ||
@@ -763,22 +765,17 @@ static struct sbs_platform_data *sbs_of_populate_pdata( | |||
763 | if (!of_node) | 765 | if (!of_node) |
764 | return NULL; | 766 | return NULL; |
765 | 767 | ||
766 | /* if platform data is set, honor it */ | ||
767 | if (pdata) | ||
768 | return pdata; | ||
769 | |||
770 | /* first make sure at least one property is set, otherwise | 768 | /* first make sure at least one property is set, otherwise |
771 | * it won't change behavior from running without pdata. | 769 | * it won't change behavior from running without pdata. |
772 | */ | 770 | */ |
773 | if (!of_get_property(of_node, "sbs,i2c-retry-count", NULL) && | 771 | if (!of_get_property(of_node, "sbs,i2c-retry-count", NULL) && |
774 | !of_get_property(of_node, "sbs,poll-retry-count", NULL) && | 772 | !of_get_property(of_node, "sbs,poll-retry-count", NULL)) |
775 | !of_get_property(of_node, "sbs,battery-detect-gpios", NULL)) | ||
776 | goto of_out; | 773 | goto of_out; |
777 | 774 | ||
778 | pdata = devm_kzalloc(&client->dev, sizeof(struct sbs_platform_data), | 775 | pdata = devm_kzalloc(&client->dev, sizeof(struct sbs_platform_data), |
779 | GFP_KERNEL); | 776 | GFP_KERNEL); |
780 | if (!pdata) | 777 | if (!pdata) |
781 | goto of_out; | 778 | return ERR_PTR(-ENOMEM); |
782 | 779 | ||
783 | rc = of_property_read_u32(of_node, "sbs,i2c-retry-count", &prop); | 780 | rc = of_property_read_u32(of_node, "sbs,i2c-retry-count", &prop); |
784 | if (!rc) | 781 | if (!rc) |
@@ -788,27 +785,14 @@ static struct sbs_platform_data *sbs_of_populate_pdata( | |||
788 | if (!rc) | 785 | if (!rc) |
789 | pdata->poll_retry_count = prop; | 786 | pdata->poll_retry_count = prop; |
790 | 787 | ||
791 | if (!of_get_property(of_node, "sbs,battery-detect-gpios", NULL)) { | ||
792 | pdata->battery_detect = -1; | ||
793 | goto of_out; | ||
794 | } | ||
795 | |||
796 | pdata->battery_detect = of_get_named_gpio_flags(of_node, | ||
797 | "sbs,battery-detect-gpios", 0, &gpio_flags); | ||
798 | |||
799 | if (gpio_flags & OF_GPIO_ACTIVE_LOW) | ||
800 | pdata->battery_detect_present = 0; | ||
801 | else | ||
802 | pdata->battery_detect_present = 1; | ||
803 | |||
804 | of_out: | 788 | of_out: |
805 | return pdata; | 789 | return pdata; |
806 | } | 790 | } |
807 | #else | 791 | #else |
808 | static struct sbs_platform_data *sbs_of_populate_pdata( | 792 | static struct sbs_platform_data *sbs_of_populate_pdata( |
809 | struct i2c_client *client) | 793 | struct sbs_info *client) |
810 | { | 794 | { |
811 | return client->dev.platform_data; | 795 | return ERR_PTR(-ENOSYS); |
812 | } | 796 | } |
813 | #endif | 797 | #endif |
814 | 798 | ||
@@ -846,7 +830,6 @@ static int sbs_probe(struct i2c_client *client, | |||
846 | 830 | ||
847 | chip->client = client; | 831 | chip->client = client; |
848 | chip->enable_detection = false; | 832 | chip->enable_detection = false; |
849 | chip->gpio_detect = false; | ||
850 | psy_cfg.of_node = client->dev.of_node; | 833 | psy_cfg.of_node = client->dev.of_node; |
851 | psy_cfg.drv_data = chip; | 834 | psy_cfg.drv_data = chip; |
852 | /* ignore first notification of external change, it is generated | 835 | /* ignore first notification of external change, it is generated |
@@ -855,11 +838,20 @@ static int sbs_probe(struct i2c_client *client, | |||
855 | chip->ignore_changes = 1; | 838 | chip->ignore_changes = 1; |
856 | chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN; | 839 | chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN; |
857 | 840 | ||
858 | pdata = sbs_of_populate_pdata(client); | 841 | if (!pdata) |
842 | pdata = sbs_of_populate_pdata(chip); | ||
843 | |||
844 | if (IS_ERR(pdata)) | ||
845 | return PTR_ERR(pdata); | ||
846 | |||
847 | chip->pdata = pdata; | ||
859 | 848 | ||
860 | if (pdata) { | 849 | chip->gpio_detect = devm_gpiod_get_optional(&client->dev, |
861 | chip->gpio_detect = gpio_is_valid(pdata->battery_detect); | 850 | "sbs,battery-detect", GPIOD_IN); |
862 | chip->pdata = pdata; | 851 | if (IS_ERR(chip->gpio_detect)) { |
852 | dev_err(&client->dev, "Failed to get gpio: %ld\n", | ||
853 | PTR_ERR(chip->gpio_detect)); | ||
854 | return PTR_ERR(chip->gpio_detect); | ||
863 | } | 855 | } |
864 | 856 | ||
865 | i2c_set_clientdata(client, chip); | 857 | i2c_set_clientdata(client, chip); |
@@ -867,26 +859,9 @@ static int sbs_probe(struct i2c_client *client, | |||
867 | if (!chip->gpio_detect) | 859 | if (!chip->gpio_detect) |
868 | goto skip_gpio; | 860 | goto skip_gpio; |
869 | 861 | ||
870 | rc = gpio_request(pdata->battery_detect, dev_name(&client->dev)); | 862 | irq = gpiod_to_irq(chip->gpio_detect); |
871 | if (rc) { | ||
872 | dev_warn(&client->dev, "Failed to request gpio: %d\n", rc); | ||
873 | chip->gpio_detect = false; | ||
874 | goto skip_gpio; | ||
875 | } | ||
876 | |||
877 | rc = gpio_direction_input(pdata->battery_detect); | ||
878 | if (rc) { | ||
879 | dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc); | ||
880 | gpio_free(pdata->battery_detect); | ||
881 | chip->gpio_detect = false; | ||
882 | goto skip_gpio; | ||
883 | } | ||
884 | |||
885 | irq = gpio_to_irq(pdata->battery_detect); | ||
886 | if (irq <= 0) { | 863 | if (irq <= 0) { |
887 | dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq); | 864 | dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq); |
888 | gpio_free(pdata->battery_detect); | ||
889 | chip->gpio_detect = false; | ||
890 | goto skip_gpio; | 865 | goto skip_gpio; |
891 | } | 866 | } |
892 | 867 | ||
@@ -895,8 +870,6 @@ static int sbs_probe(struct i2c_client *client, | |||
895 | dev_name(&client->dev), chip); | 870 | dev_name(&client->dev), chip); |
896 | if (rc) { | 871 | if (rc) { |
897 | dev_warn(&client->dev, "Failed to request irq: %d\n", rc); | 872 | dev_warn(&client->dev, "Failed to request irq: %d\n", rc); |
898 | gpio_free(pdata->battery_detect); | ||
899 | chip->gpio_detect = false; | ||
900 | goto skip_gpio; | 873 | goto skip_gpio; |
901 | } | 874 | } |
902 | 875 | ||
@@ -905,7 +878,7 @@ skip_gpio: | |||
905 | * Before we register, we might need to make sure we can actually talk | 878 | * Before we register, we might need to make sure we can actually talk |
906 | * to the battery. | 879 | * to the battery. |
907 | */ | 880 | */ |
908 | if (!force_load) { | 881 | if (!(force_load || chip->gpio_detect)) { |
909 | rc = sbs_read_word_data(client, sbs_data[REG_STATUS].addr); | 882 | rc = sbs_read_word_data(client, sbs_data[REG_STATUS].addr); |
910 | 883 | ||
911 | if (rc < 0) { | 884 | if (rc < 0) { |
@@ -934,9 +907,6 @@ skip_gpio: | |||
934 | return 0; | 907 | return 0; |
935 | 908 | ||
936 | exit_psupply: | 909 | exit_psupply: |
937 | if (chip->gpio_detect) | ||
938 | gpio_free(pdata->battery_detect); | ||
939 | |||
940 | return rc; | 910 | return rc; |
941 | } | 911 | } |
942 | 912 | ||
@@ -944,9 +914,6 @@ static int sbs_remove(struct i2c_client *client) | |||
944 | { | 914 | { |
945 | struct sbs_info *chip = i2c_get_clientdata(client); | 915 | struct sbs_info *chip = i2c_get_clientdata(client); |
946 | 916 | ||
947 | if (chip->gpio_detect) | ||
948 | gpio_free(chip->pdata->battery_detect); | ||
949 | |||
950 | cancel_delayed_work_sync(&chip->work); | 917 | cancel_delayed_work_sync(&chip->work); |
951 | 918 | ||
952 | return 0; | 919 | return 0; |