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

Commit 53de9807 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'usb-ci-v4.4-rc2' of...

Merge tag 'usb-ci-v4.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb into usb-linus

Peter writes:

USB Chipidea Fixes for v4.4-rc2

The first four fixes was for v4.3-rc7, but it is too late
at that time, and other two small fixes are for possible NULL
pointer issue.
parents aa05cfa9 6f51bc34
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -486,7 +486,10 @@
				compatible = "fsl,imx27-usb";
				reg = <0x10024000 0x200>;
				interrupts = <56>;
				clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
				clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
					<&clks IMX27_CLK_USB_AHB_GATE>,
					<&clks IMX27_CLK_USB_DIV>;
				clock-names = "ipg", "ahb", "per";
				fsl,usbmisc = <&usbmisc 0>;
				status = "disabled";
			};
@@ -495,7 +498,10 @@
				compatible = "fsl,imx27-usb";
				reg = <0x10024200 0x200>;
				interrupts = <54>;
				clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
				clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
					<&clks IMX27_CLK_USB_AHB_GATE>,
					<&clks IMX27_CLK_USB_DIV>;
				clock-names = "ipg", "ahb", "per";
				fsl,usbmisc = <&usbmisc 1>;
				dr_mode = "host";
				status = "disabled";
@@ -505,7 +511,10 @@
				compatible = "fsl,imx27-usb";
				reg = <0x10024400 0x200>;
				interrupts = <55>;
				clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
				clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
					<&clks IMX27_CLK_USB_AHB_GATE>,
					<&clks IMX27_CLK_USB_DIV>;
				clock-names = "ipg", "ahb", "per";
				fsl,usbmisc = <&usbmisc 2>;
				dr_mode = "host";
				status = "disabled";
@@ -515,7 +524,6 @@
				#index-cells = <1>;
				compatible = "fsl,imx27-usbmisc";
				reg = <0x10024600 0x200>;
				clocks = <&clks IMX27_CLK_USB_AHB_GATE>;
			};

			sahara2: sahara@10025000 {
+121 −21
Original line number Diff line number Diff line
@@ -84,6 +84,12 @@ struct ci_hdrc_imx_data {
	struct imx_usbmisc_data *usbmisc_data;
	bool supports_runtime_pm;
	bool in_lpm;
	/* SoC before i.mx6 (except imx23/imx28) needs three clks */
	bool need_three_clks;
	struct clk *clk_ipg;
	struct clk *clk_ahb;
	struct clk *clk_per;
	/* --------------------------------- */
};

/* Common functions shared by usbmisc drivers */
@@ -135,6 +141,102 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
}

/* End of common functions shared by usbmisc drivers*/
static int imx_get_clks(struct device *dev)
{
	struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
	int ret = 0;

	data->clk_ipg = devm_clk_get(dev, "ipg");
	if (IS_ERR(data->clk_ipg)) {
		/* If the platform only needs one clocks */
		data->clk = devm_clk_get(dev, NULL);
		if (IS_ERR(data->clk)) {
			ret = PTR_ERR(data->clk);
			dev_err(dev,
				"Failed to get clks, err=%ld,%ld\n",
				PTR_ERR(data->clk), PTR_ERR(data->clk_ipg));
			return ret;
		}
		return ret;
	}

	data->clk_ahb = devm_clk_get(dev, "ahb");
	if (IS_ERR(data->clk_ahb)) {
		ret = PTR_ERR(data->clk_ahb);
		dev_err(dev,
			"Failed to get ahb clock, err=%d\n", ret);
		return ret;
	}

	data->clk_per = devm_clk_get(dev, "per");
	if (IS_ERR(data->clk_per)) {
		ret = PTR_ERR(data->clk_per);
		dev_err(dev,
			"Failed to get per clock, err=%d\n", ret);
		return ret;
	}

	data->need_three_clks = true;
	return ret;
}

static int imx_prepare_enable_clks(struct device *dev)
{
	struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
	int ret = 0;

	if (data->need_three_clks) {
		ret = clk_prepare_enable(data->clk_ipg);
		if (ret) {
			dev_err(dev,
				"Failed to prepare/enable ipg clk, err=%d\n",
				ret);
			return ret;
		}

		ret = clk_prepare_enable(data->clk_ahb);
		if (ret) {
			dev_err(dev,
				"Failed to prepare/enable ahb clk, err=%d\n",
				ret);
			clk_disable_unprepare(data->clk_ipg);
			return ret;
		}

		ret = clk_prepare_enable(data->clk_per);
		if (ret) {
			dev_err(dev,
				"Failed to prepare/enable per clk, err=%d\n",
				ret);
			clk_disable_unprepare(data->clk_ahb);
			clk_disable_unprepare(data->clk_ipg);
			return ret;
		}
	} else {
		ret = clk_prepare_enable(data->clk);
		if (ret) {
			dev_err(dev,
				"Failed to prepare/enable clk, err=%d\n",
				ret);
			return ret;
		}
	}

	return ret;
}

static void imx_disable_unprepare_clks(struct device *dev)
{
	struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);

	if (data->need_three_clks) {
		clk_disable_unprepare(data->clk_per);
		clk_disable_unprepare(data->clk_ahb);
		clk_disable_unprepare(data->clk_ipg);
	} else {
		clk_disable_unprepare(data->clk);
	}
}

static int ci_hdrc_imx_probe(struct platform_device *pdev)
{
@@ -145,31 +247,31 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
		.flags		= CI_HDRC_SET_NON_ZERO_TTHA,
	};
	int ret;
	const struct of_device_id *of_id =
			of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
	const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data;
	const struct of_device_id *of_id;
	const struct ci_hdrc_imx_platform_flag *imx_platform_flag;

	of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
	if (!of_id)
		return -ENODEV;

	imx_platform_flag = of_id->data;

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	platform_set_drvdata(pdev, data);
	data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
	if (IS_ERR(data->usbmisc_data))
		return PTR_ERR(data->usbmisc_data);

	data->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(data->clk)) {
		dev_err(&pdev->dev,
			"Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
		return PTR_ERR(data->clk);
	}
	ret = imx_get_clks(&pdev->dev);
	if (ret)
		return ret;

	ret = clk_prepare_enable(data->clk);
	if (ret) {
		dev_err(&pdev->dev,
			"Failed to prepare or enable clock, err=%d\n", ret);
	ret = imx_prepare_enable_clks(&pdev->dev);
	if (ret)
		return ret;
	}

	data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
	if (IS_ERR(data->phy)) {
@@ -212,8 +314,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
		goto disable_device;
	}

	platform_set_drvdata(pdev, data);

	if (data->supports_runtime_pm) {
		pm_runtime_set_active(&pdev->dev);
		pm_runtime_enable(&pdev->dev);
@@ -226,7 +326,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
disable_device:
	ci_hdrc_remove_device(data->ci_pdev);
err_clk:
	clk_disable_unprepare(data->clk);
	imx_disable_unprepare_clks(&pdev->dev);
	return ret;
}

@@ -240,7 +340,7 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
		pm_runtime_put_noidle(&pdev->dev);
	}
	ci_hdrc_remove_device(data->ci_pdev);
	clk_disable_unprepare(data->clk);
	imx_disable_unprepare_clks(&pdev->dev);

	return 0;
}
@@ -252,7 +352,7 @@ static int imx_controller_suspend(struct device *dev)

	dev_dbg(dev, "at %s\n", __func__);

	clk_disable_unprepare(data->clk);
	imx_disable_unprepare_clks(dev);
	data->in_lpm = true;

	return 0;
@@ -270,7 +370,7 @@ static int imx_controller_resume(struct device *dev)
		return 0;
	}

	ret = clk_prepare_enable(data->clk);
	ret = imx_prepare_enable_clks(dev);
	if (ret)
		return ret;

@@ -285,7 +385,7 @@ static int imx_controller_resume(struct device *dev)
	return 0;

clk_disable:
	clk_disable_unprepare(data->clk);
	imx_disable_unprepare_clks(dev);
	return ret;
}

+2 −0
Original line number Diff line number Diff line
@@ -322,8 +322,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
		return -EINVAL;

	pm_runtime_get_sync(ci->dev);
	disable_irq(ci->irq);
	ci_role_stop(ci);
	ret = ci_role_start(ci, role);
	enable_irq(ci->irq);
	pm_runtime_put_sync(ci->dev);

	return ret ? ret : count;
+17 −0
Original line number Diff line number Diff line
@@ -1751,6 +1751,22 @@ static int ci_udc_start(struct usb_gadget *gadget,
	return retval;
}

static void ci_udc_stop_for_otg_fsm(struct ci_hdrc *ci)
{
	if (!ci_otg_is_fsm_mode(ci))
		return;

	mutex_lock(&ci->fsm.lock);
	if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) {
		ci->fsm.a_bidl_adis_tmout = 1;
		ci_hdrc_otg_fsm_start(ci);
	} else if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) {
		ci->fsm.protocol = PROTO_UNDEF;
		ci->fsm.otg->state = OTG_STATE_UNDEFINED;
	}
	mutex_unlock(&ci->fsm.lock);
}

/**
 * ci_udc_stop: unregister a gadget driver
 */
@@ -1775,6 +1791,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
	ci->driver = NULL;
	spin_unlock_irqrestore(&ci->lock, flags);

	ci_udc_stop_for_otg_fsm(ci);
	return 0;
}

+6 −4
Original line number Diff line number Diff line
@@ -500,7 +500,11 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
{
	struct resource	*res;
	struct imx_usbmisc *data;
	struct of_device_id *tmp_dev;
	const struct of_device_id *of_id;

	of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
	if (!of_id)
		return -ENODEV;

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
@@ -513,9 +517,7 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
	if (IS_ERR(data->base))
		return PTR_ERR(data->base);

	tmp_dev = (struct of_device_id *)
		of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
	data->ops = (const struct usbmisc_ops *)tmp_dev->data;
	data->ops = (const struct usbmisc_ops *)of_id->data;
	platform_set_drvdata(pdev, data);

	return 0;