Hi Robert, +Roger On Thu, Mar 19, 2015 at 5:37 PM, Robert Baldyga <r.bald...@samsung.com> wrote: > Hi George, > > On 03/19/2015 09:50 AM, George Cherian wrote: >> Hi Robert, >> >> This looks like a extcon driver based on gpio for USB. >> >> Roger posted a generic one a while back. >> https://lkml.org/lkml/2015/2/2/187 >> >> Doesn't this serve the purpose rather than adding this driver? > > Roger's driver doesn't support VBUS state detection so it cannot handle I feel Roger's driver could be extended for supporting VBUS. Also I think Roger's driver is about to get merged. Probably, Roger or Chanwoo can better tell that
> situation when USB cable is unpluged. In addition some of Odroid boards > has only VBUS detection (without ID pin), so this driver cannot handle > them at all. > > Best regards, > Robert > >> >> On Wed, Mar 18, 2015 at 7:34 PM, Robert Baldyga <r.bald...@samsung.com> >> wrote: >>> This patch adds extcon driver for Odroid U3, U3+ and X boards. >>> It recognizes type of USB cable connected to Odroid board basing on >>> two signal lines VBUS_DET and OTG_ID (the second one is present only >>> on Odroid U3+ board). >>> >>> Following table of states presents relationship between this signals >>> and detected cable type: >>> >>> state | VBUS_DET | OTG_ID >>> ------------------------------- >>> USB | H | H >>> USB_HOST | H | L >>> disconn. | L | H >>> USB-HOST | L | L >>> >>> This driver is based on extcon-gpio driver. >>> >>> Signed-off-by: Ćukasz Stelmach <l.stelm...@samsung.com> >>> Signed-off-by: Robert Baldyga <r.bald...@samsung.com> >>> --- >>> drivers/extcon/Kconfig | 4 + >>> drivers/extcon/Makefile | 1 + >>> drivers/extcon/extcon-odroid-usbotg.c | 256 >>> ++++++++++++++++++++++++++++++++++ >>> 3 files changed, 261 insertions(+) >>> create mode 100644 drivers/extcon/extcon-odroid-usbotg.c >>> >>> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig >>> index 6a1f7de..891dca3 100644 >>> --- a/drivers/extcon/Kconfig >>> +++ b/drivers/extcon/Kconfig >>> @@ -93,4 +93,8 @@ config EXTCON_SM5502 >>> Silicon Mitus SM5502. The SM5502 is a USB port accessory >>> detector and switch. >>> >>> +config EXTCON_ODROID_USBOTG >>> + tristate "Extcon Odroid U3, U3+, X and XU USB OTG port" >>> + depends on OF_GPIO >>> + >>> endif # MULTISTATE_SWITCH >>> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile >>> index 0370b42..514384e 100644 >>> --- a/drivers/extcon/Makefile >>> +++ b/drivers/extcon/Makefile >>> @@ -12,3 +12,4 @@ obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o >>> obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o >>> obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o >>> obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o >>> +obj-$(CONFIG_EXTCON_ODROID_USBOTG) += extcon-odroid-usbotg.o >>> diff --git a/drivers/extcon/extcon-odroid-usbotg.c >>> b/drivers/extcon/extcon-odroid-usbotg.c >>> new file mode 100644 >>> index 0000000..7f71c48 >>> --- /dev/null >>> +++ b/drivers/extcon/extcon-odroid-usbotg.c >>> @@ -0,0 +1,256 @@ >>> +/* >>> + * drivers/extcon/extcon-odroid-usbotg.c >>> + * >>> + * USB cable extcon driver for Odroid U3, Odroid U3+ and Odroid X >>> + * >>> + * Copyright (C) 2014 Samsung Electronics >>> + * Author: Lukasz Stelmach <l.stelm...@samsung.com> >>> + * Author: Robert Baldyga <r.bald...@samsung.com> >>> + * >>> + * based on drivers/extcon/extcon-gpio.c >>> + * Copyright (C) 2008 Google, Inc. >>> + * Author: Mike Lockwood <lockw...@android.com> >>> + * >>> + * This software is licensed under the terms of the GNU General Public >>> + * License version 2, as published by the Free Software Foundation, and >>> + * may be copied, distributed, and modified under those terms. >>> + * >>> + * This program is distributed in the hope that it will be useful, >>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>> + * GNU General Public License for more details. >>> + * >>> + */ >>> + >>> +#include <linux/module.h> >>> +#include <linux/kernel.h> >>> +#include <linux/init.h> >>> +#include <linux/interrupt.h> >>> +#include <linux/platform_device.h> >>> +#include <linux/slab.h> >>> +#include <linux/gpio.h> >>> +#include <linux/of_gpio.h> >>> +#include <linux/extcon.h> >>> +#include <linux/extcon/extcon-gpio.h> >>> +#include <linux/delay.h> >>> + >>> +enum { >>> + EXTCON_CABLE_USB = 0, >>> + EXTCON_CABLE_USB_HOST, >>> + >>> + _EXTCON_CABLE_NUM, >>> +}; >>> + >>> +static const char * const odroid_usbotg_cable[] = { >>> + [EXTCON_CABLE_USB] = "USB", >>> + [EXTCON_CABLE_USB_HOST] = "USB-HOST", >>> + >>> + NULL, >>> +}; >>> + >>> +struct odroid_usbotg_data { >>> + struct extcon_dev *edev; >>> + struct gpio_desc *otg_id; >>> + struct gpio_desc *vbus_det; >>> + int otg_id_irq; >>> + int vbus_det_irq; >>> + unsigned long debounce_ms; >>> +}; >>> + >>> +/* >>> + * state | VBUS_DET | OTG_ID >>> + * ------------------------------- >>> + * USB | H | H >>> + * USB-HOST | H | L >>> + * disconn. | L | H >>> + * USB-HOST | L | L >>> + * >>> + * Only Odroid U3+ has OTG_ID line. U3 and X versions can detect only >>> + * USB slave cable. >>> + */ >>> + >>> +static void odroid_usbotg_detect_cable(struct odroid_usbotg_data >>> *extcon_data) >>> +{ >>> + int state; >>> + >>> + mdelay(extcon_data->debounce_ms); >>> + >>> + if (extcon_data->otg_id) >>> + state = (gpiod_get_value(extcon_data->vbus_det) << 1) | >>> + gpiod_get_value(extcon_data->otg_id); >>> + else >>> + state = (gpiod_get_value(extcon_data->vbus_det) << 1) | 1; >>> + >>> + dev_dbg(&extcon_data->edev->dev, "cable state changed to %d\n", >>> state); >>> + >>> + if (state & 0x1) >>> + extcon_set_cable_state_(extcon_data->edev, >>> + EXTCON_CABLE_USB_HOST, false); >>> + if (state != 0x3) >>> + extcon_set_cable_state_(extcon_data->edev, >>> + EXTCON_CABLE_USB, false); >>> + >>> + if (!(state & 0x1)) >>> + extcon_set_cable_state_(extcon_data->edev, >>> + EXTCON_CABLE_USB_HOST, true); >>> + else if (state == 0x3) >>> + extcon_set_cable_state_(extcon_data->edev, >>> + EXTCON_CABLE_USB, true); >>> +} >>> + >>> +static irqreturn_t gpio_irq_handler(int irq, void *dev_id) >>> +{ >>> + struct odroid_usbotg_data *extcon_data = dev_id; >>> + >>> + odroid_usbotg_detect_cable(extcon_data); >>> + >>> + return IRQ_HANDLED; >>> +} >>> + >>> +static int odroid_usbotg_parse_dt(struct platform_device *pdev, >>> + struct odroid_usbotg_data *extcon_data) >>> +{ >>> + struct device_node *np = pdev->dev.of_node; >>> + u32 val; >>> + >>> + if (!np) >>> + return -ENODEV; >>> + >>> + extcon_data->edev->name = np->name; >>> + >>> + if (of_property_read_u32(np, "debounce", &val) != 0) >>> + val = 50; >>> + extcon_data->debounce_ms = val; >>> + >>> + return 0; >>> +} >>> + >>> +static int odroid_usbotg_probe(struct platform_device *pdev) >>> +{ >>> + struct odroid_usbotg_data *extcon_data; >>> + int ret = 0; >>> + >>> + extcon_data = devm_kzalloc(&pdev->dev, >>> + sizeof(struct odroid_usbotg_data), GFP_KERNEL); >>> + if (!extcon_data) >>> + return -ENOMEM; >>> + >>> + extcon_data->edev = devm_kzalloc(&pdev->dev, sizeof(struct >>> extcon_dev), >>> + GFP_KERNEL); >>> + if (IS_ERR(extcon_data->edev)) { >>> + dev_err(&pdev->dev, "failed to allocate extcon device\n"); >>> + return -ENOMEM; >>> + } >>> + extcon_data->edev->supported_cable = odroid_usbotg_cable; >>> + >>> + ret = odroid_usbotg_parse_dt(pdev, extcon_data); >>> + if (IS_ERR_VALUE(ret)) { >>> + dev_err(&pdev->dev, "failed to get data from device >>> tree\n"); >>> + return ret; >>> + } >>> + >>> + /* gpios */ >>> + extcon_data->vbus_det = devm_gpiod_get(&pdev->dev, "vbus-det"); >>> + if (IS_ERR(extcon_data->vbus_det)) { >>> + dev_err(&pdev->dev, "failed to get vbus_det gpio\n"); >>> + return PTR_ERR(extcon_data->vbus_det); >>> + } >>> + extcon_data->otg_id = devm_gpiod_get_optional(&pdev->dev, "otg-id"); >>> + >>> + extcon_data->edev->dev.parent = &pdev->dev; >>> + ret = extcon_dev_register(extcon_data->edev); >>> + if (ret < 0) >>> + return ret; >>> + >>> + /* irq */ >>> + extcon_data->vbus_det_irq = gpiod_to_irq(extcon_data->vbus_det); >>> + if (extcon_data->vbus_det_irq < 0) { >>> + dev_err(&pdev->dev, "failed to get irq from vbus_det\n"); >>> + ret = extcon_data->vbus_det_irq; >>> + goto err; >>> + } >>> + ret = request_threaded_irq(extcon_data->vbus_det_irq, NULL, >>> + gpio_irq_handler, IRQF_ONESHOT | >>> + IRQF_TRIGGER_RISING | >>> IRQF_TRIGGER_FALLING, >>> + pdev->name, extcon_data); >>> + if (ret < 0) { >>> + dev_err(&pdev->dev, "failed to request vbus_det irq\n"); >>> + goto err; >>> + } >>> + >>> + if (extcon_data->otg_id) { >>> + extcon_data->otg_id_irq = gpiod_to_irq(extcon_data->otg_id); >>> + if (extcon_data->otg_id_irq < 0) { >>> + dev_err(&pdev->dev, "failed to get irq from >>> otg_id\n"); >>> + ret = extcon_data->otg_id_irq; >>> + goto err; >>> + } >>> + ret = request_threaded_irq(extcon_data->otg_id_irq, NULL, >>> + gpio_irq_handler, IRQF_ONESHOT | >>> + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, >>> + pdev->name, extcon_data); >>> + if (ret < 0) { >>> + dev_err(&pdev->dev, "failed to request otg_id >>> irq\n"); >>> + goto err; >>> + } >>> + } >>> + >>> + platform_set_drvdata(pdev, extcon_data); >>> + /* Perform initial detection */ >>> + odroid_usbotg_detect_cable(extcon_data); >>> + >>> + dev_dbg(&pdev->dev, "probe: success\n"); >>> + >>> + return 0; >>> + >>> +err: >>> + extcon_dev_unregister(extcon_data->edev); >>> + >>> + return ret; >>> +} >>> + >>> +static int odroid_usbotg_remove(struct platform_device *pdev) >>> +{ >>> + struct odroid_usbotg_data *extcon_data = platform_get_drvdata(pdev); >>> + >>> + free_irq(extcon_data->vbus_det_irq, extcon_data); >>> + if (extcon_data->otg_id) >>> + free_irq(extcon_data->otg_id_irq, extcon_data); >>> + extcon_dev_unregister(extcon_data->edev); >>> + >>> + return 0; >>> +} >>> + >>> +static const struct of_device_id odroid_usbotg_of_match[] = { >>> + { .compatible = "extcon-odroid-usbotg" }, >>> + { }, >>> +}; >>> +MODULE_DEVICE_TABLE(of, odroid_usbotg_of_match); >>> + >>> +static struct platform_driver odroid_usbotg_driver = { >>> + .probe = odroid_usbotg_probe, >>> + .remove = odroid_usbotg_remove, >>> + .driver = { >>> + .name = "odroid-usbotg", >>> + .owner = THIS_MODULE, >>> + .of_match_table = of_match_ptr(odroid_usbotg_of_match) >>> + }, >>> +}; >>> + >>> +static int __init odroid_usbotg_init(void) >>> +{ >>> + return platform_driver_register(&odroid_usbotg_driver); >>> +} >>> + >>> +subsys_initcall(odroid_usbotg_init); >>> + >>> +static void __exit odroid_usbotg_cleanup(void) >>> +{ >>> + platform_driver_unregister(&odroid_usbotg_driver); >>> +} >>> + >>> +module_exit(odroid_usbotg_cleanup); >>> + >>> +MODULE_AUTHOR("Lukasz Stelmach <l.stelm...@samsung.com>, Robert Baldyga >>> <r.bald...@samsung.com>"); >>> +MODULE_DESCRIPTION("USB OTG extcon driver for Odroid U3, U3+ and X"); >>> +MODULE_LICENSE("GPL"); >>> -- >>> 1.9.1 >>> >>> -- >>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in >>> the body of a message to majord...@vger.kernel.org >>> More majordomo info at http://vger.kernel.org/majordomo-info.html >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-usb" in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/