usb: chipidea: Add dynamic pinctrl selection
authorLoic Poulain <loic.poulain@linaro.org>
Tue, 4 Sep 2018 15:18:55 +0000 (17:18 +0200)
committerPeter Chen <peter.chen@nxp.com>
Thu, 20 Sep 2018 09:04:21 +0000 (17:04 +0800)
Some hardware implementations require to configure pins differently
according to the USB role (host/device), this can be an update of the
pins routing or a simple GPIO value change.

This patch introduces new optional "host" and "device" pinctrls.
If these pinctrls are defined by the device, they are respectively
selected on host/device role start.

If a default pinctrl exist, it is restored on host/device role stop.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
drivers/usb/chipidea/core.c
drivers/usb/chipidea/host.c
drivers/usb/chipidea/udc.c
include/linux/usb/chipidea.h

index 85fc6db48e449214e092c7a36443995d7544b713..7bfcbb23c2a42b53e1566788b53b46d7d7c9cc9c 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
@@ -723,6 +724,24 @@ static int ci_get_platdata(struct device *dev,
                else
                        cable->connected = false;
        }
+
+       platdata->pctl = devm_pinctrl_get(dev);
+       if (!IS_ERR(platdata->pctl)) {
+               struct pinctrl_state *p;
+
+               p = pinctrl_lookup_state(platdata->pctl, "default");
+               if (!IS_ERR(p))
+                       platdata->pins_default = p;
+
+               p = pinctrl_lookup_state(platdata->pctl, "host");
+               if (!IS_ERR(p))
+                       platdata->pins_host = p;
+
+               p = pinctrl_lookup_state(platdata->pctl, "device");
+               if (!IS_ERR(p))
+                       platdata->pins_device = p;
+       }
+
        return 0;
 }
 
index 4638d9b066bea7ad2b35f6c966ee7acec428facf..d858a82c4f44ea16ca8235b93460429e2adbc52e 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/usb/hcd.h>
 #include <linux/usb/chipidea.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
 
 #include "../host/ehci.h"
 
@@ -153,6 +154,10 @@ static int host_start(struct ci_hdrc *ci)
                }
        }
 
+       if (ci->platdata->pins_host)
+               pinctrl_select_state(ci->platdata->pctl,
+                                    ci->platdata->pins_host);
+
        ret = usb_add_hcd(hcd, 0, 0);
        if (ret) {
                goto disable_reg;
@@ -197,6 +202,10 @@ static void host_stop(struct ci_hdrc *ci)
        }
        ci->hcd = NULL;
        ci->otg.host = NULL;
+
+       if (ci->platdata->pins_host && ci->platdata->pins_default)
+               pinctrl_select_state(ci->platdata->pctl,
+                                    ci->platdata->pins_default);
 }
 
 
index 9852ec5e6e017e91049d1ecd082137c3eb53ce5f..829e947cabf53d58c05a4f0b4193b3654b8c8549 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg-fsm.h>
@@ -1965,6 +1966,10 @@ void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
 
 static int udc_id_switch_for_device(struct ci_hdrc *ci)
 {
+       if (ci->platdata->pins_device)
+               pinctrl_select_state(ci->platdata->pctl,
+                                    ci->platdata->pins_device);
+
        if (ci->is_otg)
                /* Clear and enable BSV irq */
                hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE,
@@ -1983,6 +1988,10 @@ static void udc_id_switch_for_host(struct ci_hdrc *ci)
                hw_write_otgsc(ci, OTGSC_BSVIE | OTGSC_BSVIS, OTGSC_BSVIS);
 
        ci->vbus_active = 0;
+
+       if (ci->platdata->pins_device && ci->platdata->pins_default)
+               pinctrl_select_state(ci->platdata->pctl,
+                                    ci->platdata->pins_default);
 }
 
 /**
index 07f99362bc906b67dc4360d4341d23d2b3e0e3b8..63758c399e4e270d0905f46de5580f2daa1f80f4 100644 (file)
@@ -77,6 +77,12 @@ struct ci_hdrc_platform_data {
        struct ci_hdrc_cable            vbus_extcon;
        struct ci_hdrc_cable            id_extcon;
        u32                     phy_clkgate_delay_us;
+
+       /* pins */
+       struct pinctrl *pctl;
+       struct pinctrl_state *pins_default;
+       struct pinctrl_state *pins_host;
+       struct pinctrl_state *pins_device;
 };
 
 /* Default offset of capability registers */