As this device is not vendor specific, I haven't included any "vendor," prefixes. For my model I used "regulator-gpio" which takes a similar approach. Signed-off-by: NeilBrown <neilb@xxxxxxx> diff --git a/Documentation/devicetree/bindings/extcon/extcon-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-gpio.txt new file mode 100644 index 000000000000..2346b61cc620 --- /dev/null +++ b/Documentation/devicetree/bindings/extcon/extcon-gpio.txt @@ -0,0 +1,26 @@ +* EXTCON detector using GPIO + +Required Properties: + - compatible: "extcon-gpio" + - gpios: gpio line that detects connector + - interrupts: interrupt generated by that gpio + - debounce-delay-ms: debouncing delay + +Optional Properties: + - label: name for connector. If not given, device name is used. + - state-on: string to report when GPIO is high (else '0') + - state-off: string to report when GPIO is low (else '1') + +Example: + +antenna-detect { + compatible = "extcon-gpio"; + label = "gps_antenna"; + interrupt-parent = <&gpio5>; + interrupts = <16 IRQ_TYPE_EDGE_BOTH>; + gpios = <&gpio5 16 0>; + debounce-delay-ms = <10>; + state-on = "external"; + state-off = "internal"; +}; + diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index f874c30ddbff..a683d2b99213 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -30,6 +30,9 @@ #include <linux/gpio.h> #include <linux/extcon.h> #include <linux/extcon/extcon-gpio.h> +#include <linux/of_platform.h> +#include <linux/of_gpio.h> +#include <linux/of_irq.h> struct gpio_extcon_data { struct extcon_dev edev; @@ -76,6 +79,45 @@ static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf) return -EINVAL; } +#ifdef CONFIG_OF +static struct gpio_extcon_platform_data * +gpio_extcon_parse(struct device *dev) +{ + struct gpio_extcon_platform_data *pdata; + struct device_node *np = dev->of_node; + u32 num; + int irq; + + if (!np) + return NULL; + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + pdata->name = dev_name(dev); + of_property_read_string(np, "label", &pdata->name); + irq = irq_of_parse_and_map(np, 0); + pdata->irq_flags = irq_get_trigger_type(irq); + pdata->gpio = of_get_named_gpio(np, "gpios", 0); + if (pdata->gpio < 0) + return ERR_PTR(pdata->gpio); + if (irq != gpio_to_irq(pdata->gpio)) { + dev_err(dev, "IRQ doesn't match GPIO\n"); + return ERR_PTR(-EINVAL); + } + if (of_property_read_u32(np, "debounce-delay-ms", &num) == 0) + pdata->debounce = num; + of_property_read_string(np, "state-on", &pdata->state_on); + of_property_read_string(np, "state-off", &pdata->state_off); + return pdata; +} +#else +static inline struct gpio_extcon_platform_data * +gpio_extcon_parse(struct device *dev) +{ + return NULL; +} +#endif + static int gpio_extcon_probe(struct platform_device *pdev) { struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data; @@ -83,7 +125,11 @@ static int gpio_extcon_probe(struct platform_device *pdev) int ret = 0; if (!pdata) + pdata = gpio_extcon_parse(&pdev->dev); + if (!pdata) return -EBUSY; + if (IS_ERR(pdata)) + return PTR_ERR(pdata); if (!pdata->irq_flags) { dev_err(&pdev->dev, "IRQ flag is not specified.\n"); return -EINVAL; @@ -148,12 +194,19 @@ static int gpio_extcon_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id gpio_extcon_match[] = { + { .compatible = "extcon-gpio" }, + {} +}; +MODULE_DEVICE_TABLE(of, gpio_extcon_mastch); + static struct platform_driver gpio_extcon_driver = { .probe = gpio_extcon_probe, .remove = gpio_extcon_remove, .driver = { .name = "extcon-gpio", .owner = THIS_MODULE, + .of_match_table = gpio_extcon_match, }, };
Attachment:
signature.asc
Description: PGP signature