Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16caf1fa authored by Loic Poulain's avatar Loic Poulain Committed by Peter Chen
Browse files

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: default avatarLoic Poulain <loic.poulain@linaro.org>
Signed-off-by: default avatarPeter Chen <peter.chen@nxp.com>
parent 1f06072c
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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;
}

+9 −0
Original line number Diff line number Diff line
@@ -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);
}


+9 −0
Original line number Diff line number Diff line
@@ -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);
}

/**
+6 −0
Original line number Diff line number Diff line
@@ -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 */