diff options
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_imx.c | 142 | ||||
-rw-r--r-- | drivers/usb/chipidea/debug.c | 2 | ||||
-rw-r--r-- | drivers/usb/chipidea/udc.c | 17 | ||||
-rw-r--r-- | drivers/usb/chipidea/usbmisc_imx.c | 10 |
4 files changed, 146 insertions, 25 deletions
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 6ccbf60cdd5c..5a048b7b92e8 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c | |||
@@ -84,6 +84,12 @@ struct ci_hdrc_imx_data { | |||
84 | struct imx_usbmisc_data *usbmisc_data; | 84 | struct imx_usbmisc_data *usbmisc_data; |
85 | bool supports_runtime_pm; | 85 | bool supports_runtime_pm; |
86 | bool in_lpm; | 86 | bool in_lpm; |
87 | /* SoC before i.mx6 (except imx23/imx28) needs three clks */ | ||
88 | bool need_three_clks; | ||
89 | struct clk *clk_ipg; | ||
90 | struct clk *clk_ahb; | ||
91 | struct clk *clk_per; | ||
92 | /* --------------------------------- */ | ||
87 | }; | 93 | }; |
88 | 94 | ||
89 | /* Common functions shared by usbmisc drivers */ | 95 | /* Common functions shared by usbmisc drivers */ |
@@ -135,6 +141,102 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) | |||
135 | } | 141 | } |
136 | 142 | ||
137 | /* End of common functions shared by usbmisc drivers*/ | 143 | /* End of common functions shared by usbmisc drivers*/ |
144 | static int imx_get_clks(struct device *dev) | ||
145 | { | ||
146 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); | ||
147 | int ret = 0; | ||
148 | |||
149 | data->clk_ipg = devm_clk_get(dev, "ipg"); | ||
150 | if (IS_ERR(data->clk_ipg)) { | ||
151 | /* If the platform only needs one clocks */ | ||
152 | data->clk = devm_clk_get(dev, NULL); | ||
153 | if (IS_ERR(data->clk)) { | ||
154 | ret = PTR_ERR(data->clk); | ||
155 | dev_err(dev, | ||
156 | "Failed to get clks, err=%ld,%ld\n", | ||
157 | PTR_ERR(data->clk), PTR_ERR(data->clk_ipg)); | ||
158 | return ret; | ||
159 | } | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | data->clk_ahb = devm_clk_get(dev, "ahb"); | ||
164 | if (IS_ERR(data->clk_ahb)) { | ||
165 | ret = PTR_ERR(data->clk_ahb); | ||
166 | dev_err(dev, | ||
167 | "Failed to get ahb clock, err=%d\n", ret); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | data->clk_per = devm_clk_get(dev, "per"); | ||
172 | if (IS_ERR(data->clk_per)) { | ||
173 | ret = PTR_ERR(data->clk_per); | ||
174 | dev_err(dev, | ||
175 | "Failed to get per clock, err=%d\n", ret); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | data->need_three_clks = true; | ||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | static int imx_prepare_enable_clks(struct device *dev) | ||
184 | { | ||
185 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); | ||
186 | int ret = 0; | ||
187 | |||
188 | if (data->need_three_clks) { | ||
189 | ret = clk_prepare_enable(data->clk_ipg); | ||
190 | if (ret) { | ||
191 | dev_err(dev, | ||
192 | "Failed to prepare/enable ipg clk, err=%d\n", | ||
193 | ret); | ||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | ret = clk_prepare_enable(data->clk_ahb); | ||
198 | if (ret) { | ||
199 | dev_err(dev, | ||
200 | "Failed to prepare/enable ahb clk, err=%d\n", | ||
201 | ret); | ||
202 | clk_disable_unprepare(data->clk_ipg); | ||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | ret = clk_prepare_enable(data->clk_per); | ||
207 | if (ret) { | ||
208 | dev_err(dev, | ||
209 | "Failed to prepare/enable per clk, err=%d\n", | ||
210 | ret); | ||
211 | clk_disable_unprepare(data->clk_ahb); | ||
212 | clk_disable_unprepare(data->clk_ipg); | ||
213 | return ret; | ||
214 | } | ||
215 | } else { | ||
216 | ret = clk_prepare_enable(data->clk); | ||
217 | if (ret) { | ||
218 | dev_err(dev, | ||
219 | "Failed to prepare/enable clk, err=%d\n", | ||
220 | ret); | ||
221 | return ret; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static void imx_disable_unprepare_clks(struct device *dev) | ||
229 | { | ||
230 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); | ||
231 | |||
232 | if (data->need_three_clks) { | ||
233 | clk_disable_unprepare(data->clk_per); | ||
234 | clk_disable_unprepare(data->clk_ahb); | ||
235 | clk_disable_unprepare(data->clk_ipg); | ||
236 | } else { | ||
237 | clk_disable_unprepare(data->clk); | ||
238 | } | ||
239 | } | ||
138 | 240 | ||
139 | static int ci_hdrc_imx_probe(struct platform_device *pdev) | 241 | static int ci_hdrc_imx_probe(struct platform_device *pdev) |
140 | { | 242 | { |
@@ -145,31 +247,31 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) | |||
145 | .flags = CI_HDRC_SET_NON_ZERO_TTHA, | 247 | .flags = CI_HDRC_SET_NON_ZERO_TTHA, |
146 | }; | 248 | }; |
147 | int ret; | 249 | int ret; |
148 | const struct of_device_id *of_id = | 250 | const struct of_device_id *of_id; |
149 | of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev); | 251 | const struct ci_hdrc_imx_platform_flag *imx_platform_flag; |
150 | const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data; | 252 | |
253 | of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev); | ||
254 | if (!of_id) | ||
255 | return -ENODEV; | ||
256 | |||
257 | imx_platform_flag = of_id->data; | ||
151 | 258 | ||
152 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 259 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
153 | if (!data) | 260 | if (!data) |
154 | return -ENOMEM; | 261 | return -ENOMEM; |
155 | 262 | ||
263 | platform_set_drvdata(pdev, data); | ||
156 | data->usbmisc_data = usbmisc_get_init_data(&pdev->dev); | 264 | data->usbmisc_data = usbmisc_get_init_data(&pdev->dev); |
157 | if (IS_ERR(data->usbmisc_data)) | 265 | if (IS_ERR(data->usbmisc_data)) |
158 | return PTR_ERR(data->usbmisc_data); | 266 | return PTR_ERR(data->usbmisc_data); |
159 | 267 | ||
160 | data->clk = devm_clk_get(&pdev->dev, NULL); | 268 | ret = imx_get_clks(&pdev->dev); |
161 | if (IS_ERR(data->clk)) { | 269 | if (ret) |
162 | dev_err(&pdev->dev, | 270 | return ret; |
163 | "Failed to get clock, err=%ld\n", PTR_ERR(data->clk)); | ||
164 | return PTR_ERR(data->clk); | ||
165 | } | ||
166 | 271 | ||
167 | ret = clk_prepare_enable(data->clk); | 272 | ret = imx_prepare_enable_clks(&pdev->dev); |
168 | if (ret) { | 273 | if (ret) |
169 | dev_err(&pdev->dev, | ||
170 | "Failed to prepare or enable clock, err=%d\n", ret); | ||
171 | return ret; | 274 | return ret; |
172 | } | ||
173 | 275 | ||
174 | data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); | 276 | data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); |
175 | if (IS_ERR(data->phy)) { | 277 | if (IS_ERR(data->phy)) { |
@@ -212,8 +314,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) | |||
212 | goto disable_device; | 314 | goto disable_device; |
213 | } | 315 | } |
214 | 316 | ||
215 | platform_set_drvdata(pdev, data); | ||
216 | |||
217 | if (data->supports_runtime_pm) { | 317 | if (data->supports_runtime_pm) { |
218 | pm_runtime_set_active(&pdev->dev); | 318 | pm_runtime_set_active(&pdev->dev); |
219 | pm_runtime_enable(&pdev->dev); | 319 | pm_runtime_enable(&pdev->dev); |
@@ -226,7 +326,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) | |||
226 | disable_device: | 326 | disable_device: |
227 | ci_hdrc_remove_device(data->ci_pdev); | 327 | ci_hdrc_remove_device(data->ci_pdev); |
228 | err_clk: | 328 | err_clk: |
229 | clk_disable_unprepare(data->clk); | 329 | imx_disable_unprepare_clks(&pdev->dev); |
230 | return ret; | 330 | return ret; |
231 | } | 331 | } |
232 | 332 | ||
@@ -240,7 +340,7 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev) | |||
240 | pm_runtime_put_noidle(&pdev->dev); | 340 | pm_runtime_put_noidle(&pdev->dev); |
241 | } | 341 | } |
242 | ci_hdrc_remove_device(data->ci_pdev); | 342 | ci_hdrc_remove_device(data->ci_pdev); |
243 | clk_disable_unprepare(data->clk); | 343 | imx_disable_unprepare_clks(&pdev->dev); |
244 | 344 | ||
245 | return 0; | 345 | return 0; |
246 | } | 346 | } |
@@ -252,7 +352,7 @@ static int imx_controller_suspend(struct device *dev) | |||
252 | 352 | ||
253 | dev_dbg(dev, "at %s\n", __func__); | 353 | dev_dbg(dev, "at %s\n", __func__); |
254 | 354 | ||
255 | clk_disable_unprepare(data->clk); | 355 | imx_disable_unprepare_clks(dev); |
256 | data->in_lpm = true; | 356 | data->in_lpm = true; |
257 | 357 | ||
258 | return 0; | 358 | return 0; |
@@ -270,7 +370,7 @@ static int imx_controller_resume(struct device *dev) | |||
270 | return 0; | 370 | return 0; |
271 | } | 371 | } |
272 | 372 | ||
273 | ret = clk_prepare_enable(data->clk); | 373 | ret = imx_prepare_enable_clks(dev); |
274 | if (ret) | 374 | if (ret) |
275 | return ret; | 375 | return ret; |
276 | 376 | ||
@@ -285,7 +385,7 @@ static int imx_controller_resume(struct device *dev) | |||
285 | return 0; | 385 | return 0; |
286 | 386 | ||
287 | clk_disable: | 387 | clk_disable: |
288 | clk_disable_unprepare(data->clk); | 388 | imx_disable_unprepare_clks(dev); |
289 | return ret; | 389 | return ret; |
290 | } | 390 | } |
291 | 391 | ||
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 080b7be3daf0..58c8485a0715 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c | |||
@@ -322,8 +322,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf, | |||
322 | return -EINVAL; | 322 | return -EINVAL; |
323 | 323 | ||
324 | pm_runtime_get_sync(ci->dev); | 324 | pm_runtime_get_sync(ci->dev); |
325 | disable_irq(ci->irq); | ||
325 | ci_role_stop(ci); | 326 | ci_role_stop(ci); |
326 | ret = ci_role_start(ci, role); | 327 | ret = ci_role_start(ci, role); |
328 | enable_irq(ci->irq); | ||
327 | pm_runtime_put_sync(ci->dev); | 329 | pm_runtime_put_sync(ci->dev); |
328 | 330 | ||
329 | return ret ? ret : count; | 331 | return ret ? ret : count; |
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 8223fe73ea85..391a1225b0ba 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c | |||
@@ -1751,6 +1751,22 @@ static int ci_udc_start(struct usb_gadget *gadget, | |||
1751 | return retval; | 1751 | return retval; |
1752 | } | 1752 | } |
1753 | 1753 | ||
1754 | static void ci_udc_stop_for_otg_fsm(struct ci_hdrc *ci) | ||
1755 | { | ||
1756 | if (!ci_otg_is_fsm_mode(ci)) | ||
1757 | return; | ||
1758 | |||
1759 | mutex_lock(&ci->fsm.lock); | ||
1760 | if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) { | ||
1761 | ci->fsm.a_bidl_adis_tmout = 1; | ||
1762 | ci_hdrc_otg_fsm_start(ci); | ||
1763 | } else if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) { | ||
1764 | ci->fsm.protocol = PROTO_UNDEF; | ||
1765 | ci->fsm.otg->state = OTG_STATE_UNDEFINED; | ||
1766 | } | ||
1767 | mutex_unlock(&ci->fsm.lock); | ||
1768 | } | ||
1769 | |||
1754 | /** | 1770 | /** |
1755 | * ci_udc_stop: unregister a gadget driver | 1771 | * ci_udc_stop: unregister a gadget driver |
1756 | */ | 1772 | */ |
@@ -1775,6 +1791,7 @@ static int ci_udc_stop(struct usb_gadget *gadget) | |||
1775 | ci->driver = NULL; | 1791 | ci->driver = NULL; |
1776 | spin_unlock_irqrestore(&ci->lock, flags); | 1792 | spin_unlock_irqrestore(&ci->lock, flags); |
1777 | 1793 | ||
1794 | ci_udc_stop_for_otg_fsm(ci); | ||
1778 | return 0; | 1795 | return 0; |
1779 | } | 1796 | } |
1780 | 1797 | ||
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index fcea4eb36eee..ab8b027e8cc8 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c | |||
@@ -500,7 +500,11 @@ static int usbmisc_imx_probe(struct platform_device *pdev) | |||
500 | { | 500 | { |
501 | struct resource *res; | 501 | struct resource *res; |
502 | struct imx_usbmisc *data; | 502 | struct imx_usbmisc *data; |
503 | struct of_device_id *tmp_dev; | 503 | const struct of_device_id *of_id; |
504 | |||
505 | of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev); | ||
506 | if (!of_id) | ||
507 | return -ENODEV; | ||
504 | 508 | ||
505 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 509 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
506 | if (!data) | 510 | if (!data) |
@@ -513,9 +517,7 @@ static int usbmisc_imx_probe(struct platform_device *pdev) | |||
513 | if (IS_ERR(data->base)) | 517 | if (IS_ERR(data->base)) |
514 | return PTR_ERR(data->base); | 518 | return PTR_ERR(data->base); |
515 | 519 | ||
516 | tmp_dev = (struct of_device_id *) | 520 | data->ops = (const struct usbmisc_ops *)of_id->data; |
517 | of_match_device(usbmisc_imx_dt_ids, &pdev->dev); | ||
518 | data->ops = (const struct usbmisc_ops *)tmp_dev->data; | ||
519 | platform_set_drvdata(pdev, data); | 521 | platform_set_drvdata(pdev, data); |
520 | 522 | ||
521 | return 0; | 523 | return 0; |