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

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
...@@ -486,7 +486,10 @@ usbotg: usb@10024000 { ...@@ -486,7 +486,10 @@ usbotg: usb@10024000 {
compatible = "fsl,imx27-usb"; compatible = "fsl,imx27-usb";
reg = <0x10024000 0x200>; reg = <0x10024000 0x200>;
interrupts = <56>; 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>; fsl,usbmisc = <&usbmisc 0>;
status = "disabled"; status = "disabled";
}; };
...@@ -495,7 +498,10 @@ usbh1: usb@10024200 { ...@@ -495,7 +498,10 @@ usbh1: usb@10024200 {
compatible = "fsl,imx27-usb"; compatible = "fsl,imx27-usb";
reg = <0x10024200 0x200>; reg = <0x10024200 0x200>;
interrupts = <54>; 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>; fsl,usbmisc = <&usbmisc 1>;
dr_mode = "host"; dr_mode = "host";
status = "disabled"; status = "disabled";
...@@ -505,7 +511,10 @@ usbh2: usb@10024400 { ...@@ -505,7 +511,10 @@ usbh2: usb@10024400 {
compatible = "fsl,imx27-usb"; compatible = "fsl,imx27-usb";
reg = <0x10024400 0x200>; reg = <0x10024400 0x200>;
interrupts = <55>; 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>; fsl,usbmisc = <&usbmisc 2>;
dr_mode = "host"; dr_mode = "host";
status = "disabled"; status = "disabled";
...@@ -515,7 +524,6 @@ usbmisc: usbmisc@10024600 { ...@@ -515,7 +524,6 @@ usbmisc: usbmisc@10024600 {
#index-cells = <1>; #index-cells = <1>;
compatible = "fsl,imx27-usbmisc"; compatible = "fsl,imx27-usbmisc";
reg = <0x10024600 0x200>; reg = <0x10024600 0x200>;
clocks = <&clks IMX27_CLK_USB_AHB_GATE>;
}; };
sahara2: sahara@10025000 { sahara2: sahara@10025000 {
......
...@@ -84,6 +84,12 @@ struct ci_hdrc_imx_data { ...@@ -84,6 +84,12 @@ struct ci_hdrc_imx_data {
struct imx_usbmisc_data *usbmisc_data; struct imx_usbmisc_data *usbmisc_data;
bool supports_runtime_pm; bool supports_runtime_pm;
bool in_lpm; 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 */ /* Common functions shared by usbmisc drivers */
...@@ -135,6 +141,102 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) ...@@ -135,6 +141,102 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
} }
/* End of common functions shared by usbmisc drivers*/ /* 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) static int ci_hdrc_imx_probe(struct platform_device *pdev)
{ {
...@@ -145,31 +247,31 @@ 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, .flags = CI_HDRC_SET_NON_ZERO_TTHA,
}; };
int ret; int ret;
const struct of_device_id *of_id = 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;
const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data;
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); data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, data);
data->usbmisc_data = usbmisc_get_init_data(&pdev->dev); data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
if (IS_ERR(data->usbmisc_data)) if (IS_ERR(data->usbmisc_data))
return PTR_ERR(data->usbmisc_data); return PTR_ERR(data->usbmisc_data);
data->clk = devm_clk_get(&pdev->dev, NULL); ret = imx_get_clks(&pdev->dev);
if (IS_ERR(data->clk)) { if (ret)
dev_err(&pdev->dev, return ret;
"Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
return PTR_ERR(data->clk);
}
ret = clk_prepare_enable(data->clk); ret = imx_prepare_enable_clks(&pdev->dev);
if (ret) { if (ret)
dev_err(&pdev->dev,
"Failed to prepare or enable clock, err=%d\n", ret);
return ret; return ret;
}
data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
if (IS_ERR(data->phy)) { if (IS_ERR(data->phy)) {
...@@ -212,8 +314,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ...@@ -212,8 +314,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
goto disable_device; goto disable_device;
} }
platform_set_drvdata(pdev, data);
if (data->supports_runtime_pm) { if (data->supports_runtime_pm) {
pm_runtime_set_active(&pdev->dev); pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
...@@ -226,7 +326,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ...@@ -226,7 +326,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
disable_device: disable_device:
ci_hdrc_remove_device(data->ci_pdev); ci_hdrc_remove_device(data->ci_pdev);
err_clk: err_clk:
clk_disable_unprepare(data->clk); imx_disable_unprepare_clks(&pdev->dev);
return ret; return ret;
} }
...@@ -240,7 +340,7 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev) ...@@ -240,7 +340,7 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
} }
ci_hdrc_remove_device(data->ci_pdev); ci_hdrc_remove_device(data->ci_pdev);
clk_disable_unprepare(data->clk); imx_disable_unprepare_clks(&pdev->dev);
return 0; return 0;
} }
...@@ -252,7 +352,7 @@ static int imx_controller_suspend(struct device *dev) ...@@ -252,7 +352,7 @@ static int imx_controller_suspend(struct device *dev)
dev_dbg(dev, "at %s\n", __func__); dev_dbg(dev, "at %s\n", __func__);
clk_disable_unprepare(data->clk); imx_disable_unprepare_clks(dev);
data->in_lpm = true; data->in_lpm = true;
return 0; return 0;
...@@ -270,7 +370,7 @@ static int imx_controller_resume(struct device *dev) ...@@ -270,7 +370,7 @@ static int imx_controller_resume(struct device *dev)
return 0; return 0;
} }
ret = clk_prepare_enable(data->clk); ret = imx_prepare_enable_clks(dev);
if (ret) if (ret)
return ret; return ret;
...@@ -285,7 +385,7 @@ static int imx_controller_resume(struct device *dev) ...@@ -285,7 +385,7 @@ static int imx_controller_resume(struct device *dev)
return 0; return 0;
clk_disable: clk_disable:
clk_disable_unprepare(data->clk); imx_disable_unprepare_clks(dev);
return ret; return ret;
} }
......
...@@ -322,8 +322,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf, ...@@ -322,8 +322,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
return -EINVAL; return -EINVAL;
pm_runtime_get_sync(ci->dev); pm_runtime_get_sync(ci->dev);
disable_irq(ci->irq);
ci_role_stop(ci); ci_role_stop(ci);
ret = ci_role_start(ci, role); ret = ci_role_start(ci, role);
enable_irq(ci->irq);
pm_runtime_put_sync(ci->dev); pm_runtime_put_sync(ci->dev);
return ret ? ret : count; return ret ? ret : count;
......
...@@ -1751,6 +1751,22 @@ static int ci_udc_start(struct usb_gadget *gadget, ...@@ -1751,6 +1751,22 @@ static int ci_udc_start(struct usb_gadget *gadget,
return retval; 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 * ci_udc_stop: unregister a gadget driver
*/ */
...@@ -1775,6 +1791,7 @@ static int ci_udc_stop(struct usb_gadget *gadget) ...@@ -1775,6 +1791,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
ci->driver = NULL; ci->driver = NULL;
spin_unlock_irqrestore(&ci->lock, flags); spin_unlock_irqrestore(&ci->lock, flags);
ci_udc_stop_for_otg_fsm(ci);
return 0; return 0;
} }
......
...@@ -500,7 +500,11 @@ static int usbmisc_imx_probe(struct platform_device *pdev) ...@@ -500,7 +500,11 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
struct imx_usbmisc *data; 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); data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
...@@ -513,9 +517,7 @@ static int usbmisc_imx_probe(struct platform_device *pdev) ...@@ -513,9 +517,7 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
if (IS_ERR(data->base)) if (IS_ERR(data->base))
return PTR_ERR(data->base); return PTR_ERR(data->base);
tmp_dev = (struct of_device_id *) data->ops = (const struct usbmisc_ops *)of_id->data;
of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
data->ops = (const struct usbmisc_ops *)tmp_dev->data;
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment