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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJWTCtwAAoJEEhZKYFQ1nG7KpUH+QHw/KjEga4r4BnT6WUMhcZe BqxZXDCSp1kZKYyxiBy69HlCcCnREC3sjpkWEyPEZUGCMPIyA1phnF0H6Qtb+7Pq 2qBJan82jXnetWLggKTDpU3vgEJL6xZ9LTv2RIZkz5cR7iFLnBF63djB461v86pl lnSfFHtEKhSFlD1qRhlvO9rl8pOO5XYT9IOOvQi/D1llGBfhu7XRlld8Iv6xxpwA yBTWWv26Ct51TNtmTt+EpO0VC+/JzyrA2s1zkrZyoPvhrLULCir/+ALHWSkdCdWg JZedk3w/bxzyinQfIllmcz9kKIkoZSeij6dQAiSHRjSDRCUvRlLOF3hpnBlvok8= =HJSS -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
53de980796
|
@ -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 {
|
||||
|
|
|
@ -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 = clk_prepare_enable(data->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to prepare or enable clock, err=%d\n", ret);
|
||||
ret = imx_get_clks(&pdev->dev);
|
||||
if (ret)
|
||||
return 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue