diff options
-rw-r--r-- | drivers/power/gpio-charger.c | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index 7536933d0ab9..df984ecad1cc 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/power_supply.h> | 23 | #include <linux/power_supply.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/of.h> | ||
26 | #include <linux/of_gpio.h> | ||
25 | 27 | ||
26 | #include <linux/power/gpio-charger.h> | 28 | #include <linux/power/gpio-charger.h> |
27 | 29 | ||
@@ -69,6 +71,59 @@ static enum power_supply_property gpio_charger_properties[] = { | |||
69 | POWER_SUPPLY_PROP_ONLINE, | 71 | POWER_SUPPLY_PROP_ONLINE, |
70 | }; | 72 | }; |
71 | 73 | ||
74 | static | ||
75 | struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev) | ||
76 | { | ||
77 | struct device_node *np = dev->of_node; | ||
78 | struct gpio_charger_platform_data *pdata; | ||
79 | const char *chargetype; | ||
80 | enum of_gpio_flags flags; | ||
81 | int ret; | ||
82 | |||
83 | if (!np) | ||
84 | return ERR_PTR(-ENOENT); | ||
85 | |||
86 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
87 | if (!pdata) | ||
88 | return ERR_PTR(-ENOMEM); | ||
89 | |||
90 | pdata->name = np->name; | ||
91 | |||
92 | pdata->gpio = of_get_gpio_flags(np, 0, &flags); | ||
93 | if (pdata->gpio < 0) { | ||
94 | if (pdata->gpio != -EPROBE_DEFER) | ||
95 | dev_err(dev, "could not get charger gpio\n"); | ||
96 | return ERR_PTR(pdata->gpio); | ||
97 | } | ||
98 | |||
99 | pdata->gpio_active_low = !!(flags & OF_GPIO_ACTIVE_LOW); | ||
100 | |||
101 | pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; | ||
102 | ret = of_property_read_string(np, "charger-type", &chargetype); | ||
103 | if (ret >= 0) { | ||
104 | if (!strncmp("unknown", chargetype, 7)) | ||
105 | pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; | ||
106 | else if (!strncmp("battery", chargetype, 7)) | ||
107 | pdata->type = POWER_SUPPLY_TYPE_BATTERY; | ||
108 | else if (!strncmp("ups", chargetype, 3)) | ||
109 | pdata->type = POWER_SUPPLY_TYPE_UPS; | ||
110 | else if (!strncmp("mains", chargetype, 5)) | ||
111 | pdata->type = POWER_SUPPLY_TYPE_MAINS; | ||
112 | else if (!strncmp("usb-sdp", chargetype, 7)) | ||
113 | pdata->type = POWER_SUPPLY_TYPE_USB; | ||
114 | else if (!strncmp("usb-dcp", chargetype, 7)) | ||
115 | pdata->type = POWER_SUPPLY_TYPE_USB_DCP; | ||
116 | else if (!strncmp("usb-cdp", chargetype, 7)) | ||
117 | pdata->type = POWER_SUPPLY_TYPE_USB_CDP; | ||
118 | else if (!strncmp("usb-aca", chargetype, 7)) | ||
119 | pdata->type = POWER_SUPPLY_TYPE_USB_ACA; | ||
120 | else | ||
121 | dev_warn(dev, "unknown charger type %s\n", chargetype); | ||
122 | } | ||
123 | |||
124 | return pdata; | ||
125 | } | ||
126 | |||
72 | static int gpio_charger_probe(struct platform_device *pdev) | 127 | static int gpio_charger_probe(struct platform_device *pdev) |
73 | { | 128 | { |
74 | const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data; | 129 | const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data; |
@@ -78,8 +133,13 @@ static int gpio_charger_probe(struct platform_device *pdev) | |||
78 | int irq; | 133 | int irq; |
79 | 134 | ||
80 | if (!pdata) { | 135 | if (!pdata) { |
81 | dev_err(&pdev->dev, "No platform data\n"); | 136 | pdata = gpio_charger_parse_dt(&pdev->dev); |
82 | return -EINVAL; | 137 | if (IS_ERR(pdata)) { |
138 | ret = PTR_ERR(pdata); | ||
139 | if (ret != -EPROBE_DEFER) | ||
140 | dev_err(&pdev->dev, "No platform data\n"); | ||
141 | return ret; | ||
142 | } | ||
83 | } | 143 | } |
84 | 144 | ||
85 | if (!gpio_is_valid(pdata->gpio)) { | 145 | if (!gpio_is_valid(pdata->gpio)) { |
@@ -103,6 +163,7 @@ static int gpio_charger_probe(struct platform_device *pdev) | |||
103 | charger->get_property = gpio_charger_get_property; | 163 | charger->get_property = gpio_charger_get_property; |
104 | charger->supplied_to = pdata->supplied_to; | 164 | charger->supplied_to = pdata->supplied_to; |
105 | charger->num_supplicants = pdata->num_supplicants; | 165 | charger->num_supplicants = pdata->num_supplicants; |
166 | charger->of_node = pdev->dev.of_node; | ||
106 | 167 | ||
107 | ret = gpio_request(pdata->gpio, dev_name(&pdev->dev)); | 168 | ret = gpio_request(pdata->gpio, dev_name(&pdev->dev)); |
108 | if (ret) { | 169 | if (ret) { |
@@ -189,6 +250,12 @@ static int gpio_charger_resume(struct device *dev) | |||
189 | static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, | 250 | static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, |
190 | gpio_charger_suspend, gpio_charger_resume); | 251 | gpio_charger_suspend, gpio_charger_resume); |
191 | 252 | ||
253 | static const struct of_device_id gpio_charger_match[] = { | ||
254 | { .compatible = "gpio-charger" }, | ||
255 | { } | ||
256 | }; | ||
257 | MODULE_DEVICE_TABLE(of, gpio_charger_match); | ||
258 | |||
192 | static struct platform_driver gpio_charger_driver = { | 259 | static struct platform_driver gpio_charger_driver = { |
193 | .probe = gpio_charger_probe, | 260 | .probe = gpio_charger_probe, |
194 | .remove = gpio_charger_remove, | 261 | .remove = gpio_charger_remove, |
@@ -196,6 +263,7 @@ static struct platform_driver gpio_charger_driver = { | |||
196 | .name = "gpio-charger", | 263 | .name = "gpio-charger", |
197 | .owner = THIS_MODULE, | 264 | .owner = THIS_MODULE, |
198 | .pm = &gpio_charger_pm_ops, | 265 | .pm = &gpio_charger_pm_ops, |
266 | .of_match_table = gpio_charger_match, | ||
199 | }, | 267 | }, |
200 | }; | 268 | }; |
201 | 269 | ||