forked from luck/tmp_suning_uos_patched
usb: chipidea: Add dynamic pinctrl selection
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>
This commit is contained in:
parent
1f06072cd2
commit
16caf1fa37
|
@ -53,6 +53,7 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/pinctrl/consumer.h>
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
#include <linux/usb/otg.h>
|
#include <linux/usb/otg.h>
|
||||||
|
@ -723,6 +724,24 @@ static int ci_get_platdata(struct device *dev,
|
||||||
else
|
else
|
||||||
cable->connected = false;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/usb/hcd.h>
|
#include <linux/usb/hcd.h>
|
||||||
#include <linux/usb/chipidea.h>
|
#include <linux/usb/chipidea.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <linux/pinctrl/consumer.h>
|
||||||
|
|
||||||
#include "../host/ehci.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);
|
ret = usb_add_hcd(hcd, 0, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto disable_reg;
|
goto disable_reg;
|
||||||
|
@ -197,6 +202,10 @@ static void host_stop(struct ci_hdrc *ci)
|
||||||
}
|
}
|
||||||
ci->hcd = NULL;
|
ci->hcd = NULL;
|
||||||
ci->otg.host = NULL;
|
ci->otg.host = NULL;
|
||||||
|
|
||||||
|
if (ci->platdata->pins_host && ci->platdata->pins_default)
|
||||||
|
pinctrl_select_state(ci->platdata->pctl,
|
||||||
|
ci->platdata->pins_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/pinctrl/consumer.h>
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
#include <linux/usb/otg-fsm.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)
|
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)
|
if (ci->is_otg)
|
||||||
/* Clear and enable BSV irq */
|
/* Clear and enable BSV irq */
|
||||||
hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE,
|
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);
|
hw_write_otgsc(ci, OTGSC_BSVIE | OTGSC_BSVIS, OTGSC_BSVIS);
|
||||||
|
|
||||||
ci->vbus_active = 0;
|
ci->vbus_active = 0;
|
||||||
|
|
||||||
|
if (ci->platdata->pins_device && ci->platdata->pins_default)
|
||||||
|
pinctrl_select_state(ci->platdata->pctl,
|
||||||
|
ci->platdata->pins_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -77,6 +77,12 @@ struct ci_hdrc_platform_data {
|
||||||
struct ci_hdrc_cable vbus_extcon;
|
struct ci_hdrc_cable vbus_extcon;
|
||||||
struct ci_hdrc_cable id_extcon;
|
struct ci_hdrc_cable id_extcon;
|
||||||
u32 phy_clkgate_delay_us;
|
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 */
|
/* Default offset of capability registers */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user