summaryrefslogtreecommitdiffstats
path: root/drivers/power/gpio-charger.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-15 17:36:45 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-15 17:36:45 -0800
commit7051d8e6308640aaee2f9d45d0ceaad3a4ee8a78 (patch)
treeb3d15e9232ca6956e255c7e1dd7c3276903440f0 /drivers/power/gpio-charger.c
parentd3255ec483ca048192f6e8a8789e08e32b379b84 (diff)
parentb81180b3fd4814af0459a5b6aeb1ee188fea98dc (diff)
downloadlinux-7051d8e6308640aaee2f9d45d0ceaad3a4ee8a78.tar.gz
linux-7051d8e6308640aaee2f9d45d0ceaad3a4ee8a78.tar.bz2
linux-7051d8e6308640aaee2f9d45d0ceaad3a4ee8a78.zip
Merge tag 'for-v3.19' of git://git.infradead.org/battery-2.6
Pull power supply updates from Sebastian Reichel:: "Power supply and reset changes for the v3.19 series - update power/reset drivers to use kernel restart handler - add power off driver for i.mx6 - add DT support for gpio-charger" * tag 'for-v3.19' of git://git.infradead.org/battery-2.6: power: reset: adjust priority of simple syscon reboot driver power: ds2782_battery: Simplify the PM hooks power/reset: brcmstb: Register with kernel restart handler power/reset: hisi: Register with kernel restart handler power/reset: keystone: Register with kernel restart handler power/reset: axxia: Register with kernel restart handler power/reset: xgene: Register with kernel restart handler power/reset: xgene: Use mdelay instead of jiffies based timeout power/reset: xgene: Use local variable dev instead of pdev->dev power/reset: xgene: Drop devm_kfree power/reset: xgene: Return -ENOMEM if out of memory power/reset: vexpress: Register with kernel restart handler power: reset: imx-snvs-poweroff: add power off driver for i.mx6 power: gpio-charger: add device tree support dt-bindings: document gpio-charger bindings
Diffstat (limited to 'drivers/power/gpio-charger.c')
-rw-r--r--drivers/power/gpio-charger.c72
1 files changed, 70 insertions, 2 deletions
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
index 3ee889fe0021..aef74bdf7ab3 100644
--- a/drivers/power/gpio-charger.c
+++ b/drivers/power/gpio-charger.c
@@ -22,6 +22,8 @@
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/power/gpio-charger.h>
@@ -69,6 +71,59 @@ static enum power_supply_property gpio_charger_properties[] = {
POWER_SUPPLY_PROP_ONLINE,
};
+static
+struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct gpio_charger_platform_data *pdata;
+ const char *chargetype;
+ enum of_gpio_flags flags;
+ int ret;
+
+ if (!np)
+ return ERR_PTR(-ENOENT);
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ pdata->name = np->name;
+
+ pdata->gpio = of_get_gpio_flags(np, 0, &flags);
+ if (pdata->gpio < 0) {
+ if (pdata->gpio != -EPROBE_DEFER)
+ dev_err(dev, "could not get charger gpio\n");
+ return ERR_PTR(pdata->gpio);
+ }
+
+ pdata->gpio_active_low = !!(flags & OF_GPIO_ACTIVE_LOW);
+
+ pdata->type = POWER_SUPPLY_TYPE_UNKNOWN;
+ ret = of_property_read_string(np, "charger-type", &chargetype);
+ if (ret >= 0) {
+ if (!strncmp("unknown", chargetype, 7))
+ pdata->type = POWER_SUPPLY_TYPE_UNKNOWN;
+ else if (!strncmp("battery", chargetype, 7))
+ pdata->type = POWER_SUPPLY_TYPE_BATTERY;
+ else if (!strncmp("ups", chargetype, 3))
+ pdata->type = POWER_SUPPLY_TYPE_UPS;
+ else if (!strncmp("mains", chargetype, 5))
+ pdata->type = POWER_SUPPLY_TYPE_MAINS;
+ else if (!strncmp("usb-sdp", chargetype, 7))
+ pdata->type = POWER_SUPPLY_TYPE_USB;
+ else if (!strncmp("usb-dcp", chargetype, 7))
+ pdata->type = POWER_SUPPLY_TYPE_USB_DCP;
+ else if (!strncmp("usb-cdp", chargetype, 7))
+ pdata->type = POWER_SUPPLY_TYPE_USB_CDP;
+ else if (!strncmp("usb-aca", chargetype, 7))
+ pdata->type = POWER_SUPPLY_TYPE_USB_ACA;
+ else
+ dev_warn(dev, "unknown charger type %s\n", chargetype);
+ }
+
+ return pdata;
+}
+
static int gpio_charger_probe(struct platform_device *pdev)
{
const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
@@ -78,8 +133,13 @@ static int gpio_charger_probe(struct platform_device *pdev)
int irq;
if (!pdata) {
- dev_err(&pdev->dev, "No platform data\n");
- return -EINVAL;
+ pdata = gpio_charger_parse_dt(&pdev->dev);
+ if (IS_ERR(pdata)) {
+ ret = PTR_ERR(pdata);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "No platform data\n");
+ return ret;
+ }
}
if (!gpio_is_valid(pdata->gpio)) {
@@ -103,6 +163,7 @@ static int gpio_charger_probe(struct platform_device *pdev)
charger->get_property = gpio_charger_get_property;
charger->supplied_to = pdata->supplied_to;
charger->num_supplicants = pdata->num_supplicants;
+ charger->of_node = pdev->dev.of_node;
ret = gpio_request(pdata->gpio, dev_name(&pdev->dev));
if (ret) {
@@ -189,12 +250,19 @@ static int gpio_charger_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops,
gpio_charger_suspend, gpio_charger_resume);
+static const struct of_device_id gpio_charger_match[] = {
+ { .compatible = "gpio-charger" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gpio_charger_match);
+
static struct platform_driver gpio_charger_driver = {
.probe = gpio_charger_probe,
.remove = gpio_charger_remove,
.driver = {
.name = "gpio-charger",
.pm = &gpio_charger_pm_ops,
+ .of_match_table = gpio_charger_match,
},
};