Commit 7d21114d authored by Baolin Wang's avatar Baolin Wang Committed by Felipe Balbi

usb: phy: Introduce one extcon device into usb phy

Usually usb phy need register one extcon device to get the connection
notifications. It will remove some duplicate code if the extcon device
is registered using common code instead of each phy driver having its
own related extcon APIs. So we add one pointer of extcon device into
usb phy structure, and some other helper functions to register extcon.
Signed-off-by: default avatarBaolin Wang <baolin.wang@linaro.org>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 05853ad6
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
menu "USB Physical Layer drivers" menu "USB Physical Layer drivers"
config USB_PHY config USB_PHY
select EXTCON
def_bool n def_bool n
# #
...@@ -109,7 +110,7 @@ config OMAP_OTG ...@@ -109,7 +110,7 @@ config OMAP_OTG
config TAHVO_USB config TAHVO_USB
tristate "Tahvo USB transceiver driver" tristate "Tahvo USB transceiver driver"
depends on MFD_RETU && EXTCON depends on MFD_RETU
depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y' depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
select USB_PHY select USB_PHY
help help
...@@ -141,7 +142,6 @@ config USB_MSM_OTG ...@@ -141,7 +142,6 @@ config USB_MSM_OTG
depends on (USB || USB_GADGET) && (ARCH_QCOM || COMPILE_TEST) depends on (USB || USB_GADGET) && (ARCH_QCOM || COMPILE_TEST)
depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y' depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
depends on RESET_CONTROLLER depends on RESET_CONTROLLER
depends on EXTCON
select USB_PHY select USB_PHY
help help
Enable this to support the USB OTG transceiver on Qualcomm chips. It Enable this to support the USB OTG transceiver on Qualcomm chips. It
...@@ -155,7 +155,7 @@ config USB_MSM_OTG ...@@ -155,7 +155,7 @@ config USB_MSM_OTG
config USB_QCOM_8X16_PHY config USB_QCOM_8X16_PHY
tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support" tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support"
depends on ARCH_QCOM || COMPILE_TEST depends on ARCH_QCOM || COMPILE_TEST
depends on RESET_CONTROLLER && EXTCON depends on RESET_CONTROLLER
select USB_PHY select USB_PHY
select USB_ULPI_VIEWPORT select USB_ULPI_VIEWPORT
help help
......
...@@ -100,6 +100,54 @@ static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) ...@@ -100,6 +100,54 @@ static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
return *phy == match_data; return *phy == match_data;
} }
static int usb_add_extcon(struct usb_phy *x)
{
int ret;
if (of_property_read_bool(x->dev->of_node, "extcon")) {
x->edev = extcon_get_edev_by_phandle(x->dev, 0);
if (IS_ERR(x->edev))
return PTR_ERR(x->edev);
x->id_edev = extcon_get_edev_by_phandle(x->dev, 1);
if (IS_ERR(x->id_edev)) {
x->id_edev = NULL;
dev_info(x->dev, "No separate ID extcon device\n");
}
if (x->vbus_nb.notifier_call) {
ret = devm_extcon_register_notifier(x->dev, x->edev,
EXTCON_USB,
&x->vbus_nb);
if (ret < 0) {
dev_err(x->dev,
"register VBUS notifier failed\n");
return ret;
}
}
if (x->id_nb.notifier_call) {
struct extcon_dev *id_ext;
if (x->id_edev)
id_ext = x->id_edev;
else
id_ext = x->edev;
ret = devm_extcon_register_notifier(x->dev, id_ext,
EXTCON_USB_HOST,
&x->id_nb);
if (ret < 0) {
dev_err(x->dev,
"register ID notifier failed\n");
return ret;
}
}
}
return 0;
}
/** /**
* devm_usb_get_phy - find the USB PHY * devm_usb_get_phy - find the USB PHY
* @dev - device that requests this phy * @dev - device that requests this phy
...@@ -388,6 +436,10 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type) ...@@ -388,6 +436,10 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
return -EINVAL; return -EINVAL;
} }
ret = usb_add_extcon(x);
if (ret)
return ret;
ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
spin_lock_irqsave(&phy_lock, flags); spin_lock_irqsave(&phy_lock, flags);
...@@ -422,12 +474,17 @@ int usb_add_phy_dev(struct usb_phy *x) ...@@ -422,12 +474,17 @@ int usb_add_phy_dev(struct usb_phy *x)
{ {
struct usb_phy_bind *phy_bind; struct usb_phy_bind *phy_bind;
unsigned long flags; unsigned long flags;
int ret;
if (!x->dev) { if (!x->dev) {
dev_err(x->dev, "no device provided for PHY\n"); dev_err(x->dev, "no device provided for PHY\n");
return -EINVAL; return -EINVAL;
} }
ret = usb_add_extcon(x);
if (ret)
return ret;
ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
spin_lock_irqsave(&phy_lock, flags); spin_lock_irqsave(&phy_lock, flags);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#ifndef __LINUX_USB_PHY_H #ifndef __LINUX_USB_PHY_H
#define __LINUX_USB_PHY_H #define __LINUX_USB_PHY_H
#include <linux/extcon.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/usb.h> #include <linux/usb.h>
...@@ -85,6 +86,12 @@ struct usb_phy { ...@@ -85,6 +86,12 @@ struct usb_phy {
struct usb_phy_io_ops *io_ops; struct usb_phy_io_ops *io_ops;
void __iomem *io_priv; void __iomem *io_priv;
/* to support extcon device */
struct extcon_dev *edev;
struct extcon_dev *id_edev;
struct notifier_block vbus_nb;
struct notifier_block id_nb;
/* for notification of usb_phy_events */ /* for notification of usb_phy_events */
struct atomic_notifier_head notifier; struct atomic_notifier_head notifier;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment