The chipidea controller in the AR933x SOC supports both host and device modes but not OTG. Which USB mode is used depends on a pin state (GIPO13) during boot - HIGH for host, LOW for device mode. Currently if both host and device modes are available, the code assumes OTG support. Add flags to allow the platform code for force a specific mode based on the pin state. Signed-off-by: Svetoslav Neykov <svetoslav@xxxxxxxxxxx> --- drivers/usb/chipidea/core.c | 22 +++++++++++++++++----- include/linux/usb/chipidea.h | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 3cefb4c..85c72e5 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -398,6 +398,8 @@ static int ci_hdrc_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; int ret; + bool force_host_mode; + bool force_device_mode; if (!dev->platform_data) { dev_err(dev, "platform data missing\n"); @@ -459,21 +461,31 @@ static int ci_hdrc_probe(struct platform_device *pdev) if (ret) dev_info(dev, "doesn't support gadget\n"); - if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { + force_host_mode = ci->platdata->flags & CI13XXX_FORCE_HOST_MODE; + force_device_mode = ci->platdata->flags & CI13XXX_FORCE_DEVICE_MODE; + if ((!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) || + (force_host_mode && !ci->roles[CI_ROLE_HOST]) || + (force_device_mode && !ci->roles[CI_ROLE_GADGET])) { dev_err(dev, "no supported roles\n"); ret = -ENODEV; goto rm_wq; } - if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { + if (!force_host_mode && !force_device_mode && + ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { ci->is_otg = true; /* ID pin needs 1ms debouce time, we delay 2ms for safe */ mdelay(2); ci->role = ci_otg_role(ci); } else { - ci->role = ci->roles[CI_ROLE_HOST] - ? CI_ROLE_HOST - : CI_ROLE_GADGET; + if (force_host_mode) + ci->role = CI_ROLE_HOST; + else if (force_device_mode) + ci->role = CI_ROLE_GADGET; + else + ci->role = ci->roles[CI_ROLE_HOST] + ? CI_ROLE_HOST + : CI_ROLE_GADGET; } ret = ci_role_start(ci, ci->role); diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index 544825d..e6f44d2 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -19,6 +19,8 @@ struct ci13xxx_platform_data { #define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) #define CI13XXX_PULLUP_ON_VBUS BIT(2) #define CI13XXX_DISABLE_STREAMING BIT(3) +#define CI13XXX_FORCE_HOST_MODE BIT(5) +#define CI13XXX_FORCE_DEVICE_MODE BIT(6) #define CI13XXX_CONTROLLER_RESET_EVENT 0 #define CI13XXX_CONTROLLER_STOPPED_EVENT 1 -- 1.7.9.5