From: Hans de Goede Date: Sat, 13 Jun 2015 12:37:46 +0000 (+0200) Subject: phy-sun4i-usb: Add extcon support for the otg phy (phy0) X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=1a52abe6821da728b41187c6676b6ab7294e6e2c;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git phy-sun4i-usb: Add extcon support for the otg phy (phy0) The sunxi musb glue needs to know if a host or normal usb cable is plugged in, add extcon support so that the musb glue can monitor the host status. Signed-off-by: Hans de Goede Acked-by: Chanwoo Choi Signed-off-by: Kishon Vijay Abraham I --- diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index e2f2a4d394e1..c0c1ad2e2c01 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -208,6 +208,7 @@ config PHY_SUN4I_USB tristate "Allwinner sunxi SoC USB PHY driver" depends on ARCH_SUNXI && HAS_IOMEM && OF depends on RESET_CONTROLLER + depends on EXTCON select GENERIC_PHY help Enable this to support the transceiver that is part of Allwinner diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index 37f52f73fdba..a6ea2e6b1d5c 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -99,6 +100,7 @@ struct sun4i_usb_phy_data { int index; } phys[MAX_PHYS]; /* phy0 / otg related variables */ + struct extcon_dev *extcon; bool phy0_init; bool phy0_poll; struct gpio_desc *id_det_gpio; @@ -343,7 +345,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) struct sun4i_usb_phy_data *data = container_of(work, struct sun4i_usb_phy_data, detect.work); struct phy *phy0 = data->phys[0].phy; - int id_det, vbus_det; + int id_det, vbus_det, id_notify = 0, vbus_notify = 0; id_det = gpiod_get_value_cansleep(data->id_det_gpio); vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio); @@ -358,15 +360,24 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) if (id_det != data->id_det) { sun4i_usb_phy0_set_id_detect(phy0, id_det); data->id_det = id_det; + id_notify = 1; } if (vbus_det != data->vbus_det) { sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det); data->vbus_det = vbus_det; + vbus_notify = 1; } mutex_unlock(&phy0->mutex); + if (id_notify) + extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST, + !id_det); + + if (vbus_notify) + extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det); + if (data->phy0_poll) queue_delayed_work(system_wq, &data->detect, POLL_TIME); } @@ -407,6 +418,12 @@ static int sun4i_usb_phy_remove(struct platform_device *pdev) return 0; } +static const unsigned int sun4i_usb_phy0_cable[] = { + EXTCON_USB, + EXTCON_USB_HOST, + EXTCON_NONE, +}; + static int sun4i_usb_phy_probe(struct platform_device *pdev) { struct sun4i_usb_phy_data *data; @@ -466,6 +483,19 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) return -ENODEV; } + if (data->id_det_gpio) { + data->extcon = devm_extcon_dev_allocate(dev, + sun4i_usb_phy0_cable); + if (IS_ERR(data->extcon)) + return PTR_ERR(data->extcon); + + ret = devm_extcon_dev_register(dev, data->extcon); + if (ret) { + dev_err(dev, "failed to register extcon: %d\n", ret); + return ret; + } + } + for (i = 0; i < data->num_phys; i++) { struct sun4i_usb_phy *phy = data->phys + i; char name[16];