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

Commit 6d2d91b3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull USB fixes from Greg KH:
 "Here are a number of USB fixes and new device ids for 4.4-rc2.  All
  have been in linux-next and the details are in the shortlog"

* tag 'usb-4.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (28 commits)
  usblp: do not set TASK_INTERRUPTIBLE before lock
  USB: MAINTAINERS: cxacru
  usb: kconfig: fix warning of select USB_OTG
  USB: option: add XS Stick W100-2 from 4G Systems
  xhci: Fix a race in usb2 LPM resume, blocking U3 for usb2 devices
  usb: xhci: fix checking ep busy for CFC
  xhci: Workaround to get Intel xHCI reset working more reliably
  usb: chipidea: imx: fix a possible NULL dereference
  usb: chipidea: usbmisc_imx: fix a possible NULL dereference
  usb: chipidea: otg: gadget module load and unload support
  usb: chipidea: debug: disable usb irq while role switch
  ARM: dts: imx27.dtsi: change the clock information for usb
  usb: chipidea: imx: refine clock operations to adapt for all platforms
  usb: gadget: atmel_usba_udc: Expose correct device speed
  usb: musb: enable usb_dma parameter
  usb: phy: phy-mxs-usb: fix a possible NULL dereference
  usb: dwc3: gadget: let us set lower max_speed
  usb: musb: fix tx fifo flush handling
  usb: gadget: f_loopback: fix the warning during the enumeration
  usb: dwc2: host: Fix remote wakeup when not in DWC2_L2
  ...
parents 0ec7dc8d 19cd80a2
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -2931,10 +2931,9 @@ S: Maintained
F:	drivers/platform/x86/compal-laptop.c

CONEXANT ACCESSRUNNER USB DRIVER
M:	Simon Arlott <cxacru@fire.lp0.eu>
L:	accessrunner-general@lists.sourceforge.net
W:	http://accessrunner.sourceforge.net/
S:	Maintained
S:	Orphan
F:	drivers/usb/atm/cxacru.c

CONFIGFS
+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;
}

Loading