summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/power_supply/power_supply_extcon.txt11
-rw-r--r--drivers/power/power_supply_extcon.c51
2 files changed, 57 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/power_supply/power_supply_extcon.txt b/Documentation/devicetree/bindings/power_supply/power_supply_extcon.txt
new file mode 100644
index 000000000000..fd4a1a476ce9
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/power_supply_extcon.txt
@@ -0,0 +1,11 @@
+power_supply_extcon
+~~~~~~~~~~~~~~~~
+Required properties :
+ - compatible : Should contain "power-supply-extcon".
+ - power-supply,extcon-dev: Extcon device name.
+
+Example:
+ psy_extcon {
+ compatible = "power-supply-extcon";
+ power-supply,extcon-dev = "udc-extcon";
+ };
diff --git a/drivers/power/power_supply_extcon.c b/drivers/power/power_supply_extcon.c
index 44e19d67df4a..1236738968b0 100644
--- a/drivers/power/power_supply_extcon.c
+++ b/drivers/power/power_supply_extcon.c
@@ -23,6 +23,8 @@
#include <linux/err.h>
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/power/power_supply_extcon.h>
@@ -185,6 +187,25 @@ static int psy_extcon_extcon_notifier(struct notifier_block *self,
return NOTIFY_DONE;
}
+static struct power_supply_extcon_plat_data *psy_extcon_get_dt_pdata(
+ struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct power_supply_extcon_plat_data *pdata;
+ char const *pstr;
+ int ret;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_string(np, "power-supply,extcon-dev", &pstr);
+ if (!ret)
+ pdata->extcon_name = pstr;
+
+ return pdata;
+}
+
static int psy_extcon_probe(struct platform_device *pdev)
{
int ret = 0;
@@ -192,6 +213,14 @@ static int psy_extcon_probe(struct platform_device *pdev)
struct power_supply_extcon *psy_extcon;
struct power_supply_extcon_plat_data *pdata = pdev->dev.platform_data;
+ if (!pdata && pdev->dev.of_node) {
+ pdata = psy_extcon_get_dt_pdata(pdev);
+ if (IS_ERR(pdata)) {
+ ret = PTR_ERR(pdata);
+ pdata = NULL;
+ }
+ }
+
if (!pdata) {
dev_err(&pdev->dev, "No platform data, exiting..\n");
return -ENODEV;
@@ -206,6 +235,8 @@ static int psy_extcon_probe(struct platform_device *pdev)
psy_extcon->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, psy_extcon);
+ dev_info(psy_extcon->dev, "Extcon name %s\n", pdata->extcon_name);
+
psy_extcon->ac.name = "ac";
psy_extcon->ac.type = POWER_SUPPLY_TYPE_MAINS;
psy_extcon->ac.get_property = power_supply_extcon_get_property;
@@ -247,13 +278,17 @@ static int psy_extcon_probe(struct platform_device *pdev)
pdata->extcon_name,
cable->name, &cable->nb);
if (ret < 0)
- dev_err(psy_extcon->dev, "Cannot register for cable: %s\n",
- cable->name);
+ dev_err(psy_extcon->dev,
+ "Cable %s registration failed: %d\n",
+ cable->name, ret);
}
psy_extcon->edev = extcon_get_extcon_dev(pdata->extcon_name);
- if (!psy_extcon->edev)
- goto econ_err;
+ if (!psy_extcon->edev) {
+ dev_err(psy_extcon->dev, "No extcon device with %s\n",
+ pdata->extcon_name);
+ goto econ_err;
+ }
power_supply_extcon_attach_cable(psy_extcon, psy_extcon->edev);
dev_info(&pdev->dev, "%s() get success\n", __func__);
@@ -275,14 +310,20 @@ static int psy_extcon_remove(struct platform_device *pdev)
return 0;
}
+static struct of_device_id power_supply_extcon_of_match[] = {
+ { .compatible = "power-supply-extcon", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, power_supply_extcon_of_match);
+
static struct platform_driver power_supply_extcon_driver = {
.driver = {
.name = "power-supply-extcon",
.owner = THIS_MODULE,
+ .of_match_table = power_supply_extcon_of_match,
},
.probe = psy_extcon_probe,
.remove = psy_extcon_remove,
-
};
static int __init psy_extcon_init(void)