Hi Svetoslav, On Wed, Feb 13, 2013 at 11:38:55PM +0200, Svetoslav Neykov wrote: > 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 We already discuss such functionality: https://patchwork-mail1.kernel.org/patch/2092051/ Regards, Michael -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |