On 2018-02-26 10:23, Peter Chen wrote: > > >> >> Signed-off-by: Yossi Mansharoff <yossim@xxxxxxxxxxxxxx> >> --- >> Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt | 6 ++++++ >> drivers/usb/chipidea/Kconfig | 2 ++ >> drivers/usb/chipidea/core.c | 6 ++++++ >> drivers/usb/chipidea/host.c | 7 +++++++ >> drivers/usb/chipidea/udc.c | 13 ++++++++++++- >> include/linux/usb/chipidea.h | 2 ++ >> 6 files changed, 35 insertions(+), 1 deletion(-) >> >> diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt >> b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt >> index 0e03344..2e93181 100644 >> --- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt >> +++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt >> @@ -76,6 +76,10 @@ Optional properties: >> needs to make sure it does not send more than 90% >> maximum_periodic_data_per_frame. The use case is multiple transactions, but >> less frame rate. >> +- mux-controls: The mux control for toggling host/device output of this >> + controller. It's expected that a mux state of 0 indicates device mode >> +and a >> + mux state of 1 indicates host mode. >> +- mux-control-names: Shall be "usb_switch" if mux-controls is specified. >> >> i.mx specific properties >> - fsl,usbmisc: phandler of non-core register device, with one @@ -102,4 +106,6 >> @@ Example: >> rx-burst-size-dword = <0x10>; >> extcon = <0>, <&usb_id>; >> phy-clkgate-delay-us = <400>; >> + mux-controls = <&usb_switch>; >> + mux-control-names = "usb_switch"; >> }; >> diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index >> 51f4157..72aadfa 100644 >> --- a/drivers/usb/chipidea/Kconfig >> +++ b/drivers/usb/chipidea/Kconfig >> @@ -3,6 +3,8 @@ config USB_CHIPIDEA >> depends on ((USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD >> && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)) && HAS_DMA >> select EXTCON >> select RESET_CONTROLLER >> + select MULTIPLEXER >> + select MUX_GPIO >> help >> Say Y here if your system has a dual role high speed USB >> controller based on ChipIdea silicon IP. It supports: >> diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index >> 43ea5fb..aa71b96 100644 >> --- a/drivers/usb/chipidea/core.c >> +++ b/drivers/usb/chipidea/core.c >> @@ -64,6 +64,7 @@ >> #include <linux/of.h> >> #include <linux/regulator/consumer.h> >> #include <linux/usb/ehci_def.h> >> +#include <linux/mux/consumer.h> >> >> #include "ci.h" >> #include "udc.h" >> @@ -690,6 +691,11 @@ static int ci_get_platdata(struct device *dev, >> if (of_find_property(dev->of_node, "non-zero-ttctrl-ttha", NULL)) >> platdata->flags |= CI_HDRC_SET_NON_ZERO_TTHA; >> >> + platdata->usb_switch = devm_mux_control_get_optional(dev, "usb_switch"); >> + if (IS_ERR(platdata->usb_switch)){ >> + return PTR_ERR(platdata->usb_switch); >> + } >> + >> ext_id = ERR_PTR(-ENODEV); >> ext_vbus = ERR_PTR(-ENODEV); >> if (of_property_read_bool(dev->of_node, "extcon")) { diff --git >> a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 18cb8e4..9ef3ecf >> 100644 >> --- a/drivers/usb/chipidea/host.c >> +++ b/drivers/usb/chipidea/host.c >> @@ -25,6 +25,7 @@ >> #include <linux/usb/hcd.h> >> #include <linux/usb/chipidea.h> >> #include <linux/regulator/consumer.h> >> +#include <linux/mux/consumer.h> >> >> #include "../host/ehci.h" >> >> @@ -175,6 +176,10 @@ static int host_start(struct ci_hdrc *ci) >> if (ci_otg_is_fsm_mode(ci)) { >> otg->host = &hcd->self; >> hcd->self.otg_port = 1; >> + } else { >> + ret = mux_control_select(ci->platdata->usb_switch, 1); >> + if (ret) >> + goto disable_reg; >> } >> } >> >> @@ -195,6 +200,8 @@ static void host_stop(struct ci_hdrc *ci) >> struct usb_hcd *hcd = ci->hcd; >> >> if (hcd) { >> + if (!ci_otg_is_fsm_mode(ci)) >> + mux_control_deselect(ci->platdata->usb_switch); >> if (ci->platdata->notify_event) >> ci->platdata->notify_event(ci, >> CI_HDRC_CONTROLLER_STOPPED_EVENT); >> diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index >> fe8a905..17f22e2 100644 >> --- a/drivers/usb/chipidea/udc.c >> +++ b/drivers/usb/chipidea/udc.c >> @@ -22,6 +22,7 @@ >> #include <linux/usb/gadget.h> >> #include <linux/usb/otg-fsm.h> >> #include <linux/usb/chipidea.h> >> +#include <linux/mux/consumer.h> >> >> #include "ci.h" >> #include "udc.h" >> @@ -1964,16 +1965,26 @@ void ci_hdrc_gadget_destroy(struct ci_hdrc *ci) >> >> static int udc_id_switch_for_device(struct ci_hdrc *ci) { >> + int ret = 0; >> + >> if (ci->is_otg) >> /* Clear and enable BSV irq */ >> hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE, >> OTGSC_BSVIS | OTGSC_BSVIE); >> >> - return 0; >> + if (!ci_otg_is_fsm_mode(ci)) >> + ret = mux_control_select(ci->platdata->usb_switch, 0); >> + >> + if (ci->is_otg && ret) >> + hw_write_otgsc(ci, OTGSC_BSVIE | OTGSC_BSVIS, >> OTGSC_BSVIS); >> + >> + return ret; >> } >> >> static void udc_id_switch_for_host(struct ci_hdrc *ci) { >> + mux_control_deselect(ci->platdata->usb_switch); >> + >> /* >> * host doesn't care B_SESSION_VALID event >> * so clear and disbale BSV irq >> diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index >> d725cff..7e5d008 100644 >> --- a/include/linux/usb/chipidea.h >> +++ b/include/linux/usb/chipidea.h >> @@ -9,6 +9,7 @@ >> #include <linux/usb/otg.h> >> >> struct ci_hdrc; >> +struct mux_control; >> > > I am ok with this patch, would you please send series to linux-usb, then I can save and test it. > > Peter You should be aware that the binding assumes that mux state 0 and mux state 1 are connected to the two functions "device" and "host" respectively. If some future HW designer uses a mux where the states are different some kind of mapping needs to be invented. I.e. similar to how active-low is used for GPIO, but in the mux case the mapping possibilities are endless, and a single bit is not enough to cover all bases. I.e. some kind of dt property like mux-control-mapping = <2 6>; to transform the mux "device" state to state number 2 (and 6 for "host"). Just a heads up. /peda -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html