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

Commit e29cc5ee authored by Tarun Gupta's avatar Tarun Gupta Committed by Gerrit - the friendly Code Review server
Browse files

usb: xhci-msm-hsic: Add support for pinctrl framework



As the newer targets will be using pinctrl framework for gpio
configuration, our drivers need to be compatible with both set of targets
the one which do not use pinctrl and one which do. Adding support for both
these cases. xhci-hsic driver can configure data, strobe and host-ready
gpio's.

Change-Id: Ife1b04ba14013cc62896831e0be50a84b71ab6f0
Signed-off-by: default avatarTarun Gupta <tarung@codeaurora.org>
parent e4e4910c
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -10,8 +10,22 @@ Required properties :
	change in power state.
- <supply-name>-supply: handle to the regulator device tree node
  Required "supply-name" are "hsic-vdd-dig" and "hsic-gdsc-supply".
- pinctrl-names : This should be defined if a target uses pinctrl framework.
  See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt.
  It should specify the names of the configs that pinctrl can install in driver
	Following are the pinctrl configs that can be installed
	"hsic_xhci_active" : Active configuration of pins, this should specify active
	config defined in pin groups of used gpio's from strobe, data and
	host-ready.
	"hsic_xhci_sleep" : Disabled configuration of pins, this should specify sleep
	config defined in pin groups of used gpio's from strobe, data and
	host-ready.
- hsic,<gpio-name>-gpio : handle to the GPIO node, see "gpios property"
  in Documentation/devicetree/bindings/gpio/gpio.txt.
  If pinctrl is being used we need to only define gpio's which drives signals
  using gpiolib api's like host-ready in dt, the node name in such cases should
  be msm_gpio as defined in pinctrl-dtsi. For gpio's only installing active and
  sleep configs it is not required to specify the gpio in dt file.
  Required "gpio-name" are "strobe" and "data".
- qcom,vdd-voltage-level: This property must be a list of three integer
  values (no, min, max) where each value represents either a voltage in
@@ -41,12 +55,20 @@ Example MSM HSIC XHCI controller device node :
		interrupt-map-mask = <0xffffffff>;
		interrupt-map = <0 &intc 0 32 0
				1 &intc 0 29 0
				2 &msmgpio 107 0x8>;
				2 &msm_gpio 107 0x8>;
		interrupt-names = "core_irq", "pwr_event_irq", "wakeup_irq";
		hsic-vdd-dig-supply = <&pma8084_s2_corner>;
		hsic-gdsc-supply = <&gdsc_usb_hsic>;
		/* If pinctrl is used */
		pinctrl-names = "hsic_xhci_active","hsic_xhci_sleep";
		pinctrl-0 = <&hsic_act>;
		pinctrl-1 = <&hsic_sus>;
		qcom,host-ready-gpio = <&msm_gpio 106 0x00>;
		/* else (pinctrl is not used) */
		hsic,strobe-gpio = <&msmgpio 134 0x00>;
		hsic,data-gpio = <&msmgpio 135 0x00>;
		qcom,host-ready-gpio = <&msmgpio 106 0x00>;
		/* End */
		qcom,vdd-voltage-level = <1 5 7>;

		qcom,msm-bus,name = "hsic";
+70 −23
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/of_gpio.h>
#include <linux/irq.h>
#include <linux/dma-mapping.h>
#include <linux/pinctrl/consumer.h>
#include <linux/bitops.h>
#include <linux/workqueue.h>
#include <linux/clk/msm-clk.h>
@@ -117,6 +118,7 @@ struct mxhci_hsic_hcd {

	uint32_t		wakeup_int_cnt;
	uint32_t		pwr_evt_irq_inlpm;
	struct pinctrl		*hsic_pinctrl;
};

#define SYNOPSIS_DWC3_VENDOR	0x5533
@@ -361,18 +363,31 @@ static int mxhci_msm_config_gdsc(struct mxhci_hsic_hcd *mxhci, int on)
static int mxhci_hsic_config_gpios(struct mxhci_hsic_hcd *mxhci)
{
	int rc = 0;

	rc = devm_gpio_request(mxhci->dev, mxhci->strobe, "HSIC_STROBE_GPIO");
	struct pinctrl_state *set_state;

	if (mxhci->hsic_pinctrl) {
		set_state = pinctrl_lookup_state(mxhci->hsic_pinctrl,
				"hsic_xhci_active");
		if (IS_ERR(set_state)) {
			pr_err("cannot get hsic pinctrl active state\n");
			rc = PTR_ERR(set_state);
			goto out;
		}
		rc = pinctrl_select_state(mxhci->hsic_pinctrl, set_state);
	} else {
		rc = devm_gpio_request(mxhci->dev, mxhci->strobe,
				"HSIC_STROBE_GPIO");
		if (rc < 0) {
			dev_err(mxhci->dev, "gpio request failed for HSIC STROBE\n");
			goto out;
		}

	rc = devm_gpio_request(mxhci->dev, mxhci->data, "HSIC_DATA_GPIO");
		rc = devm_gpio_request(mxhci->dev, mxhci->data,
				"HSIC_DATA_GPIO");
		if (rc < 0) {
			dev_err(mxhci->dev, "gpio request failed for HSIC DATA\n");
			goto out;
		}
	}

	if (mxhci->host_ready) {
		rc = devm_gpio_request(mxhci->dev,
@@ -395,7 +410,6 @@ static int mxhci_hsic_config_gpios(struct mxhci_hsic_hcd *mxhci)
			rc = 0;
		}
	}

out:
	return rc;
}
@@ -980,6 +994,7 @@ static int mxhci_hsic_probe(struct platform_device *pdev)
	struct xhci_hcd		*xhci;
	struct resource *res;
	struct usb_hcd *hcd;
	struct pinctrl_state *set_state;
	unsigned int reg;
	int ret;
	int irq;
@@ -1031,6 +1046,19 @@ static int mxhci_hsic_probe(struct platform_device *pdev)
	mxhci = hcd_to_hsic(hcd);
	mxhci->dev = &pdev->dev;

	/* Get pinctrl if target uses pinctrl */
	mxhci->hsic_pinctrl = devm_pinctrl_get(&pdev->dev);
	if (IS_ERR(mxhci->hsic_pinctrl)) {
		if (of_property_read_bool(pdev->dev.of_node, "pinctrl-names")) {
			dev_err(&pdev->dev, "Error encountered while getting pinctrl");
			ret = PTR_ERR(mxhci->hsic_pinctrl);
			goto put_hcd;
		}
		dev_dbg(&pdev->dev, "Target does not use pinctrl\n");
		mxhci->hsic_pinctrl = NULL;
	}

	if (IS_ERR_OR_NULL(mxhci->hsic_pinctrl)) {
		mxhci->strobe = of_get_named_gpio(node, "hsic,strobe-gpio", 0);
		if (mxhci->strobe < 0) {
			ret = -EINVAL;
@@ -1042,7 +1070,7 @@ static int mxhci_hsic_probe(struct platform_device *pdev)
			ret = -EINVAL;
			goto put_hcd;
		}

	}
	mxhci->host_ready = of_get_named_gpio(node,
					"qcom,host-ready-gpio", 0);
	if (mxhci->host_ready < 0)
@@ -1134,13 +1162,13 @@ static int mxhci_hsic_probe(struct platform_device *pdev)
		if (ret) {
			dev_err(&pdev->dev,
					"request irq failed (wakeup irq)\n");
			goto deinit_vddcx;
			goto pinctrl_sleep;
		}
	}

	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
	if (ret)
		goto deinit_vddcx;
		goto pinctrl_sleep;

	hcd = dev_get_drvdata(&pdev->dev);
	xhci = hcd_to_xhci(hcd);
@@ -1249,6 +1277,15 @@ remove_usb2_hcd:
	usb_remove_hcd(hcd);
deinit_vddcx:
	mxhci_hsic_init_vddcx(mxhci, 0);
pinctrl_sleep:
	if (mxhci->hsic_pinctrl) {
		set_state = pinctrl_lookup_state(mxhci->hsic_pinctrl,
				"hsic_xhci_sleep");
		if (IS_ERR(set_state))
			pr_err("cannot get hsic pinctrl sleep state\n");
		else
			pinctrl_select_state(mxhci->hsic_pinctrl, set_state);
	}
deinit_clocks:
	mxhci_hsic_init_clocks(mxhci, 0);
put_hcd:
@@ -1262,6 +1299,7 @@ static int mxhci_hsic_remove(struct platform_device *pdev)
	struct usb_hcd	*hcd = platform_get_drvdata(pdev);
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	struct mxhci_hsic_hcd *mxhci = hcd_to_hsic(hcd);
	struct pinctrl_state *set_state;
	u32 reg;

	/* disable STROBE_PAD_CTL */
@@ -1299,6 +1337,15 @@ static int mxhci_hsic_remove(struct platform_device *pdev)

	destroy_workqueue(mxhci->wq);

	if (mxhci->hsic_pinctrl) {
		set_state = pinctrl_lookup_state(mxhci->hsic_pinctrl,
				"hsic_xhci_sleep");
		if (IS_ERR(set_state))
			pr_err("cannot get hsic pinctrl sleep state\n");
		else
			pinctrl_select_state(mxhci->hsic_pinctrl, set_state);
	}

	device_wakeup_disable(&pdev->dev);
	mxhci_hsic_init_vddcx(mxhci, 0);
	mxhci_hsic_init_clocks(mxhci, 0);