.. | .. |
---|
7 | 7 | |
---|
8 | 8 | #include <linux/module.h> |
---|
9 | 9 | #include <linux/of_platform.h> |
---|
10 | | -#include <linux/of_gpio.h> |
---|
11 | 10 | #include <linux/platform_device.h> |
---|
12 | 11 | #include <linux/pm_runtime.h> |
---|
13 | | -#include <linux/dma-mapping.h> |
---|
14 | 12 | #include <linux/usb/chipidea.h> |
---|
15 | 13 | #include <linux/usb/of.h> |
---|
16 | 14 | #include <linux/clk.h> |
---|
| 15 | +#include <linux/pinctrl/consumer.h> |
---|
| 16 | +#include <linux/pm_qos.h> |
---|
17 | 17 | |
---|
18 | 18 | #include "ci.h" |
---|
19 | 19 | #include "ci_hdrc_imx.h" |
---|
.. | .. |
---|
65 | 65 | .flags = CI_HDRC_SUPPORTS_RUNTIME_PM, |
---|
66 | 66 | }; |
---|
67 | 67 | |
---|
| 68 | +static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = { |
---|
| 69 | + .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | |
---|
| 70 | + CI_HDRC_PMQOS, |
---|
| 71 | +}; |
---|
| 72 | + |
---|
| 73 | +static const struct ci_hdrc_imx_platform_flag imx8ulp_usb_data = { |
---|
| 74 | + .flags = CI_HDRC_SUPPORTS_RUNTIME_PM, |
---|
| 75 | +}; |
---|
| 76 | + |
---|
68 | 77 | static const struct of_device_id ci_hdrc_imx_dt_ids[] = { |
---|
69 | 78 | { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data}, |
---|
70 | 79 | { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data}, |
---|
.. | .. |
---|
74 | 83 | { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data}, |
---|
75 | 84 | { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data}, |
---|
76 | 85 | { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data}, |
---|
| 86 | + { .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data}, |
---|
| 87 | + { .compatible = "fsl,imx8ulp-usb", .data = &imx8ulp_usb_data}, |
---|
77 | 88 | { /* sentinel */ } |
---|
78 | 89 | }; |
---|
79 | 90 | MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); |
---|
.. | .. |
---|
86 | 97 | bool supports_runtime_pm; |
---|
87 | 98 | bool override_phy_control; |
---|
88 | 99 | bool in_lpm; |
---|
| 100 | + struct pinctrl *pinctrl; |
---|
| 101 | + struct pinctrl_state *pinctrl_hsic_active; |
---|
| 102 | + struct regulator *hsic_pad_regulator; |
---|
89 | 103 | /* SoC before i.mx6 (except imx23/imx28) needs three clks */ |
---|
90 | 104 | bool need_three_clks; |
---|
91 | 105 | struct clk *clk_ipg; |
---|
92 | 106 | struct clk *clk_ahb; |
---|
93 | 107 | struct clk *clk_per; |
---|
94 | 108 | /* --------------------------------- */ |
---|
| 109 | + struct pm_qos_request pm_qos_req; |
---|
| 110 | + const struct ci_hdrc_imx_platform_flag *plat_data; |
---|
95 | 111 | }; |
---|
96 | 112 | |
---|
97 | 113 | /* Common functions shared by usbmisc drivers */ |
---|
.. | .. |
---|
137 | 153 | } |
---|
138 | 154 | data->dev = &misc_pdev->dev; |
---|
139 | 155 | |
---|
140 | | - if (of_find_property(np, "disable-over-current", NULL)) |
---|
| 156 | + /* |
---|
| 157 | + * Check the various over current related properties. If over current |
---|
| 158 | + * detection is disabled we're not interested in the polarity. |
---|
| 159 | + */ |
---|
| 160 | + if (of_find_property(np, "disable-over-current", NULL)) { |
---|
141 | 161 | data->disable_oc = 1; |
---|
| 162 | + } else if (of_find_property(np, "over-current-active-high", NULL)) { |
---|
| 163 | + data->oc_pol_active_low = 0; |
---|
| 164 | + data->oc_pol_configured = 1; |
---|
| 165 | + } else if (of_find_property(np, "over-current-active-low", NULL)) { |
---|
| 166 | + data->oc_pol_active_low = 1; |
---|
| 167 | + data->oc_pol_configured = 1; |
---|
| 168 | + } else { |
---|
| 169 | + dev_warn(dev, "No over current polarity defined\n"); |
---|
| 170 | + } |
---|
142 | 171 | |
---|
143 | | - if (of_find_property(np, "over-current-active-high", NULL)) |
---|
144 | | - data->oc_polarity = 1; |
---|
145 | | - |
---|
146 | | - if (of_find_property(np, "external-vbus-divider", NULL)) |
---|
147 | | - data->evdo = 1; |
---|
| 172 | + data->pwr_pol = of_property_read_bool(np, "power-active-high"); |
---|
| 173 | + data->evdo = of_property_read_bool(np, "external-vbus-divider"); |
---|
148 | 174 | |
---|
149 | 175 | if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) |
---|
150 | 176 | data->ulpi = 1; |
---|
| 177 | + |
---|
| 178 | + if (of_property_read_u32(np, "samsung,picophy-pre-emp-curr-control", |
---|
| 179 | + &data->emp_curr_control)) |
---|
| 180 | + data->emp_curr_control = -1; |
---|
| 181 | + if (of_property_read_u32(np, "samsung,picophy-dc-vol-level-adjust", |
---|
| 182 | + &data->dc_vol_level_adjust)) |
---|
| 183 | + data->dc_vol_level_adjust = -1; |
---|
151 | 184 | |
---|
152 | 185 | return data; |
---|
153 | 186 | } |
---|
.. | .. |
---|
250 | 283 | } |
---|
251 | 284 | } |
---|
252 | 285 | |
---|
| 286 | +static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event) |
---|
| 287 | +{ |
---|
| 288 | + struct device *dev = ci->dev->parent; |
---|
| 289 | + struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); |
---|
| 290 | + int ret = 0; |
---|
| 291 | + struct imx_usbmisc_data *mdata = data->usbmisc_data; |
---|
| 292 | + |
---|
| 293 | + switch (event) { |
---|
| 294 | + case CI_HDRC_IMX_HSIC_ACTIVE_EVENT: |
---|
| 295 | + if (data->pinctrl) { |
---|
| 296 | + ret = pinctrl_select_state(data->pinctrl, |
---|
| 297 | + data->pinctrl_hsic_active); |
---|
| 298 | + if (ret) |
---|
| 299 | + dev_err(dev, |
---|
| 300 | + "hsic_active select failed, err=%d\n", |
---|
| 301 | + ret); |
---|
| 302 | + } |
---|
| 303 | + break; |
---|
| 304 | + case CI_HDRC_IMX_HSIC_SUSPEND_EVENT: |
---|
| 305 | + ret = imx_usbmisc_hsic_set_connect(mdata); |
---|
| 306 | + if (ret) |
---|
| 307 | + dev_err(dev, |
---|
| 308 | + "hsic_set_connect failed, err=%d\n", ret); |
---|
| 309 | + break; |
---|
| 310 | + case CI_HDRC_CONTROLLER_VBUS_EVENT: |
---|
| 311 | + if (ci->vbus_active) |
---|
| 312 | + ret = imx_usbmisc_charger_detection(mdata, true); |
---|
| 313 | + else |
---|
| 314 | + ret = imx_usbmisc_charger_detection(mdata, false); |
---|
| 315 | + if (ci->usb_phy) |
---|
| 316 | + schedule_work(&ci->usb_phy->chg_work); |
---|
| 317 | + break; |
---|
| 318 | + default: |
---|
| 319 | + break; |
---|
| 320 | + } |
---|
| 321 | + |
---|
| 322 | + return ret; |
---|
| 323 | +} |
---|
| 324 | + |
---|
253 | 325 | static int ci_hdrc_imx_probe(struct platform_device *pdev) |
---|
254 | 326 | { |
---|
255 | 327 | struct ci_hdrc_imx_data *data; |
---|
256 | 328 | struct ci_hdrc_platform_data pdata = { |
---|
257 | 329 | .name = dev_name(&pdev->dev), |
---|
258 | 330 | .capoffset = DEF_CAPOFFSET, |
---|
| 331 | + .notify_event = ci_hdrc_imx_notify_event, |
---|
259 | 332 | }; |
---|
260 | 333 | int ret; |
---|
261 | 334 | const struct of_device_id *of_id; |
---|
262 | 335 | const struct ci_hdrc_imx_platform_flag *imx_platform_flag; |
---|
263 | 336 | struct device_node *np = pdev->dev.of_node; |
---|
| 337 | + struct device *dev = &pdev->dev; |
---|
264 | 338 | |
---|
265 | | - of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev); |
---|
| 339 | + of_id = of_match_device(ci_hdrc_imx_dt_ids, dev); |
---|
266 | 340 | if (!of_id) |
---|
267 | 341 | return -ENODEV; |
---|
268 | 342 | |
---|
.. | .. |
---|
272 | 346 | if (!data) |
---|
273 | 347 | return -ENOMEM; |
---|
274 | 348 | |
---|
| 349 | + data->plat_data = imx_platform_flag; |
---|
| 350 | + pdata.flags |= imx_platform_flag->flags; |
---|
275 | 351 | platform_set_drvdata(pdev, data); |
---|
276 | | - data->usbmisc_data = usbmisc_get_init_data(&pdev->dev); |
---|
| 352 | + data->usbmisc_data = usbmisc_get_init_data(dev); |
---|
277 | 353 | if (IS_ERR(data->usbmisc_data)) |
---|
278 | 354 | return PTR_ERR(data->usbmisc_data); |
---|
279 | 355 | |
---|
280 | | - ret = imx_get_clks(&pdev->dev); |
---|
281 | | - if (ret) |
---|
282 | | - return ret; |
---|
| 356 | + if ((of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) |
---|
| 357 | + && data->usbmisc_data) { |
---|
| 358 | + pdata.flags |= CI_HDRC_IMX_IS_HSIC; |
---|
| 359 | + data->usbmisc_data->hsic = 1; |
---|
| 360 | + data->pinctrl = devm_pinctrl_get(dev); |
---|
| 361 | + if (PTR_ERR(data->pinctrl) == -ENODEV) |
---|
| 362 | + data->pinctrl = NULL; |
---|
| 363 | + else if (IS_ERR(data->pinctrl)) { |
---|
| 364 | + if (PTR_ERR(data->pinctrl) != -EPROBE_DEFER) |
---|
| 365 | + dev_err(dev, "pinctrl get failed, err=%ld\n", |
---|
| 366 | + PTR_ERR(data->pinctrl)); |
---|
| 367 | + return PTR_ERR(data->pinctrl); |
---|
| 368 | + } |
---|
283 | 369 | |
---|
284 | | - ret = imx_prepare_enable_clks(&pdev->dev); |
---|
285 | | - if (ret) |
---|
286 | | - return ret; |
---|
| 370 | + data->hsic_pad_regulator = |
---|
| 371 | + devm_regulator_get_optional(dev, "hsic"); |
---|
| 372 | + if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) { |
---|
| 373 | + /* no pad regualator is needed */ |
---|
| 374 | + data->hsic_pad_regulator = NULL; |
---|
| 375 | + } else if (IS_ERR(data->hsic_pad_regulator)) { |
---|
| 376 | + if (PTR_ERR(data->hsic_pad_regulator) != -EPROBE_DEFER) |
---|
| 377 | + dev_err(dev, |
---|
| 378 | + "Get HSIC pad regulator error: %ld\n", |
---|
| 379 | + PTR_ERR(data->hsic_pad_regulator)); |
---|
| 380 | + return PTR_ERR(data->hsic_pad_regulator); |
---|
| 381 | + } |
---|
287 | 382 | |
---|
288 | | - data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); |
---|
| 383 | + if (data->hsic_pad_regulator) { |
---|
| 384 | + ret = regulator_enable(data->hsic_pad_regulator); |
---|
| 385 | + if (ret) { |
---|
| 386 | + dev_err(dev, |
---|
| 387 | + "Failed to enable HSIC pad regulator\n"); |
---|
| 388 | + return ret; |
---|
| 389 | + } |
---|
| 390 | + } |
---|
| 391 | + } |
---|
| 392 | + |
---|
| 393 | + /* HSIC pinctrl handling */ |
---|
| 394 | + if (data->pinctrl) { |
---|
| 395 | + struct pinctrl_state *pinctrl_hsic_idle; |
---|
| 396 | + |
---|
| 397 | + pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle"); |
---|
| 398 | + if (IS_ERR(pinctrl_hsic_idle)) { |
---|
| 399 | + dev_err(dev, |
---|
| 400 | + "pinctrl_hsic_idle lookup failed, err=%ld\n", |
---|
| 401 | + PTR_ERR(pinctrl_hsic_idle)); |
---|
| 402 | + return PTR_ERR(pinctrl_hsic_idle); |
---|
| 403 | + } |
---|
| 404 | + |
---|
| 405 | + ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle); |
---|
| 406 | + if (ret) { |
---|
| 407 | + dev_err(dev, "hsic_idle select failed, err=%d\n", ret); |
---|
| 408 | + return ret; |
---|
| 409 | + } |
---|
| 410 | + |
---|
| 411 | + data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl, |
---|
| 412 | + "active"); |
---|
| 413 | + if (IS_ERR(data->pinctrl_hsic_active)) { |
---|
| 414 | + dev_err(dev, |
---|
| 415 | + "pinctrl_hsic_active lookup failed, err=%ld\n", |
---|
| 416 | + PTR_ERR(data->pinctrl_hsic_active)); |
---|
| 417 | + return PTR_ERR(data->pinctrl_hsic_active); |
---|
| 418 | + } |
---|
| 419 | + } |
---|
| 420 | + |
---|
| 421 | + if (pdata.flags & CI_HDRC_PMQOS) |
---|
| 422 | + cpu_latency_qos_add_request(&data->pm_qos_req, 0); |
---|
| 423 | + |
---|
| 424 | + ret = imx_get_clks(dev); |
---|
| 425 | + if (ret) |
---|
| 426 | + goto disable_hsic_regulator; |
---|
| 427 | + |
---|
| 428 | + ret = imx_prepare_enable_clks(dev); |
---|
| 429 | + if (ret) |
---|
| 430 | + goto disable_hsic_regulator; |
---|
| 431 | + |
---|
| 432 | + data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0); |
---|
289 | 433 | if (IS_ERR(data->phy)) { |
---|
290 | 434 | ret = PTR_ERR(data->phy); |
---|
291 | | - /* Return -EINVAL if no usbphy is available */ |
---|
292 | | - if (ret == -ENODEV) |
---|
293 | | - ret = -EINVAL; |
---|
294 | | - goto err_clk; |
---|
| 435 | + if (ret != -ENODEV) |
---|
| 436 | + goto err_clk; |
---|
| 437 | + data->phy = devm_usb_get_phy_by_phandle(dev, "phys", 0); |
---|
| 438 | + if (IS_ERR(data->phy)) { |
---|
| 439 | + ret = PTR_ERR(data->phy); |
---|
| 440 | + if (ret == -ENODEV) |
---|
| 441 | + data->phy = NULL; |
---|
| 442 | + else |
---|
| 443 | + goto err_clk; |
---|
| 444 | + } |
---|
295 | 445 | } |
---|
296 | 446 | |
---|
297 | 447 | pdata.usb_phy = data->phy; |
---|
| 448 | + if (data->usbmisc_data) |
---|
| 449 | + data->usbmisc_data->usb_phy = data->phy; |
---|
298 | 450 | |
---|
299 | 451 | if ((of_device_is_compatible(np, "fsl,imx53-usb") || |
---|
300 | 452 | of_device_is_compatible(np, "fsl,imx51-usb")) && pdata.usb_phy && |
---|
.. | .. |
---|
304 | 456 | usb_phy_init(pdata.usb_phy); |
---|
305 | 457 | } |
---|
306 | 458 | |
---|
307 | | - pdata.flags |= imx_platform_flag->flags; |
---|
308 | 459 | if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM) |
---|
309 | 460 | data->supports_runtime_pm = true; |
---|
310 | 461 | |
---|
311 | 462 | ret = imx_usbmisc_init(data->usbmisc_data); |
---|
312 | 463 | if (ret) { |
---|
313 | | - dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", ret); |
---|
| 464 | + dev_err(dev, "usbmisc init failed, ret=%d\n", ret); |
---|
314 | 465 | goto err_clk; |
---|
315 | 466 | } |
---|
316 | 467 | |
---|
317 | | - data->ci_pdev = ci_hdrc_add_device(&pdev->dev, |
---|
| 468 | + data->ci_pdev = ci_hdrc_add_device(dev, |
---|
318 | 469 | pdev->resource, pdev->num_resources, |
---|
319 | 470 | &pdata); |
---|
320 | 471 | if (IS_ERR(data->ci_pdev)) { |
---|
321 | 472 | ret = PTR_ERR(data->ci_pdev); |
---|
322 | 473 | if (ret != -EPROBE_DEFER) |
---|
323 | | - dev_err(&pdev->dev, |
---|
324 | | - "ci_hdrc_add_device failed, err=%d\n", ret); |
---|
| 474 | + dev_err(dev, "ci_hdrc_add_device failed, err=%d\n", |
---|
| 475 | + ret); |
---|
325 | 476 | goto err_clk; |
---|
| 477 | + } |
---|
| 478 | + |
---|
| 479 | + if (data->usbmisc_data) { |
---|
| 480 | + if (!IS_ERR(pdata.id_extcon.edev) || |
---|
| 481 | + of_property_read_bool(np, "usb-role-switch")) |
---|
| 482 | + data->usbmisc_data->ext_id = 1; |
---|
| 483 | + |
---|
| 484 | + if (!IS_ERR(pdata.vbus_extcon.edev) || |
---|
| 485 | + of_property_read_bool(np, "usb-role-switch")) |
---|
| 486 | + data->usbmisc_data->ext_vbus = 1; |
---|
| 487 | + |
---|
| 488 | + /* usbmisc needs to know dr mode to choose wakeup setting */ |
---|
| 489 | + data->usbmisc_data->available_role = |
---|
| 490 | + ci_hdrc_query_available_role(data->ci_pdev); |
---|
326 | 491 | } |
---|
327 | 492 | |
---|
328 | 493 | ret = imx_usbmisc_init_post(data->usbmisc_data); |
---|
329 | 494 | if (ret) { |
---|
330 | | - dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n", ret); |
---|
| 495 | + dev_err(dev, "usbmisc post failed, ret=%d\n", ret); |
---|
331 | 496 | goto disable_device; |
---|
332 | 497 | } |
---|
333 | 498 | |
---|
334 | 499 | if (data->supports_runtime_pm) { |
---|
335 | | - pm_runtime_set_active(&pdev->dev); |
---|
336 | | - pm_runtime_enable(&pdev->dev); |
---|
| 500 | + pm_runtime_set_active(dev); |
---|
| 501 | + pm_runtime_enable(dev); |
---|
337 | 502 | } |
---|
338 | 503 | |
---|
339 | | - device_set_wakeup_capable(&pdev->dev, true); |
---|
| 504 | + device_set_wakeup_capable(dev, true); |
---|
340 | 505 | |
---|
341 | 506 | return 0; |
---|
342 | 507 | |
---|
343 | 508 | disable_device: |
---|
344 | 509 | ci_hdrc_remove_device(data->ci_pdev); |
---|
345 | 510 | err_clk: |
---|
346 | | - imx_disable_unprepare_clks(&pdev->dev); |
---|
| 511 | + imx_disable_unprepare_clks(dev); |
---|
| 512 | +disable_hsic_regulator: |
---|
| 513 | + if (data->hsic_pad_regulator) |
---|
| 514 | + /* don't overwrite original ret (cf. EPROBE_DEFER) */ |
---|
| 515 | + regulator_disable(data->hsic_pad_regulator); |
---|
| 516 | + if (pdata.flags & CI_HDRC_PMQOS) |
---|
| 517 | + cpu_latency_qos_remove_request(&data->pm_qos_req); |
---|
| 518 | + data->ci_pdev = NULL; |
---|
347 | 519 | return ret; |
---|
348 | 520 | } |
---|
349 | 521 | |
---|
.. | .. |
---|
356 | 528 | pm_runtime_disable(&pdev->dev); |
---|
357 | 529 | pm_runtime_put_noidle(&pdev->dev); |
---|
358 | 530 | } |
---|
359 | | - ci_hdrc_remove_device(data->ci_pdev); |
---|
| 531 | + if (data->ci_pdev) |
---|
| 532 | + ci_hdrc_remove_device(data->ci_pdev); |
---|
360 | 533 | if (data->override_phy_control) |
---|
361 | 534 | usb_phy_shutdown(data->phy); |
---|
362 | | - imx_disable_unprepare_clks(&pdev->dev); |
---|
| 535 | + if (data->ci_pdev) { |
---|
| 536 | + imx_disable_unprepare_clks(&pdev->dev); |
---|
| 537 | + if (data->plat_data->flags & CI_HDRC_PMQOS) |
---|
| 538 | + cpu_latency_qos_remove_request(&data->pm_qos_req); |
---|
| 539 | + if (data->hsic_pad_regulator) |
---|
| 540 | + regulator_disable(data->hsic_pad_regulator); |
---|
| 541 | + } |
---|
363 | 542 | |
---|
364 | 543 | return 0; |
---|
365 | 544 | } |
---|
.. | .. |
---|
369 | 548 | ci_hdrc_imx_remove(pdev); |
---|
370 | 549 | } |
---|
371 | 550 | |
---|
372 | | -#ifdef CONFIG_PM |
---|
373 | | -static int imx_controller_suspend(struct device *dev) |
---|
| 551 | +static int __maybe_unused imx_controller_suspend(struct device *dev) |
---|
374 | 552 | { |
---|
375 | 553 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); |
---|
| 554 | + int ret = 0; |
---|
376 | 555 | |
---|
377 | 556 | dev_dbg(dev, "at %s\n", __func__); |
---|
378 | 557 | |
---|
| 558 | + ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, false); |
---|
| 559 | + if (ret) { |
---|
| 560 | + dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); |
---|
| 561 | + return ret; |
---|
| 562 | + } |
---|
| 563 | + |
---|
379 | 564 | imx_disable_unprepare_clks(dev); |
---|
| 565 | + if (data->plat_data->flags & CI_HDRC_PMQOS) |
---|
| 566 | + cpu_latency_qos_remove_request(&data->pm_qos_req); |
---|
| 567 | + |
---|
380 | 568 | data->in_lpm = true; |
---|
381 | 569 | |
---|
382 | 570 | return 0; |
---|
383 | 571 | } |
---|
384 | 572 | |
---|
385 | | -static int imx_controller_resume(struct device *dev) |
---|
| 573 | +static int __maybe_unused imx_controller_resume(struct device *dev) |
---|
386 | 574 | { |
---|
387 | 575 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); |
---|
388 | 576 | int ret = 0; |
---|
.. | .. |
---|
393 | 581 | WARN_ON(1); |
---|
394 | 582 | return 0; |
---|
395 | 583 | } |
---|
| 584 | + |
---|
| 585 | + if (data->plat_data->flags & CI_HDRC_PMQOS) |
---|
| 586 | + cpu_latency_qos_add_request(&data->pm_qos_req, 0); |
---|
396 | 587 | |
---|
397 | 588 | ret = imx_prepare_enable_clks(dev); |
---|
398 | 589 | if (ret) |
---|
.. | .. |
---|
406 | 597 | goto clk_disable; |
---|
407 | 598 | } |
---|
408 | 599 | |
---|
| 600 | + ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, true); |
---|
| 601 | + if (ret) { |
---|
| 602 | + dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); |
---|
| 603 | + goto hsic_set_clk_fail; |
---|
| 604 | + } |
---|
| 605 | + |
---|
409 | 606 | return 0; |
---|
410 | 607 | |
---|
| 608 | +hsic_set_clk_fail: |
---|
| 609 | + imx_usbmisc_set_wakeup(data->usbmisc_data, true); |
---|
411 | 610 | clk_disable: |
---|
412 | 611 | imx_disable_unprepare_clks(dev); |
---|
413 | 612 | return ret; |
---|
414 | 613 | } |
---|
415 | 614 | |
---|
416 | | -#ifdef CONFIG_PM_SLEEP |
---|
417 | | -static int ci_hdrc_imx_suspend(struct device *dev) |
---|
| 615 | +static int __maybe_unused ci_hdrc_imx_suspend(struct device *dev) |
---|
418 | 616 | { |
---|
419 | 617 | int ret; |
---|
420 | 618 | |
---|
.. | .. |
---|
433 | 631 | } |
---|
434 | 632 | } |
---|
435 | 633 | |
---|
436 | | - return imx_controller_suspend(dev); |
---|
| 634 | + ret = imx_controller_suspend(dev); |
---|
| 635 | + if (ret) |
---|
| 636 | + return ret; |
---|
| 637 | + |
---|
| 638 | + pinctrl_pm_select_sleep_state(dev); |
---|
| 639 | + return ret; |
---|
437 | 640 | } |
---|
438 | 641 | |
---|
439 | | -static int ci_hdrc_imx_resume(struct device *dev) |
---|
| 642 | +static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) |
---|
440 | 643 | { |
---|
441 | 644 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); |
---|
442 | 645 | int ret; |
---|
443 | 646 | |
---|
| 647 | + pinctrl_pm_select_default_state(dev); |
---|
444 | 648 | ret = imx_controller_resume(dev); |
---|
445 | 649 | if (!ret && data->supports_runtime_pm) { |
---|
446 | 650 | pm_runtime_disable(dev); |
---|
.. | .. |
---|
450 | 654 | |
---|
451 | 655 | return ret; |
---|
452 | 656 | } |
---|
453 | | -#endif /* CONFIG_PM_SLEEP */ |
---|
454 | 657 | |
---|
455 | | -static int ci_hdrc_imx_runtime_suspend(struct device *dev) |
---|
| 658 | +static int __maybe_unused ci_hdrc_imx_runtime_suspend(struct device *dev) |
---|
456 | 659 | { |
---|
457 | 660 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); |
---|
458 | 661 | int ret; |
---|
.. | .. |
---|
471 | 674 | return imx_controller_suspend(dev); |
---|
472 | 675 | } |
---|
473 | 676 | |
---|
474 | | -static int ci_hdrc_imx_runtime_resume(struct device *dev) |
---|
| 677 | +static int __maybe_unused ci_hdrc_imx_runtime_resume(struct device *dev) |
---|
475 | 678 | { |
---|
476 | 679 | return imx_controller_resume(dev); |
---|
477 | 680 | } |
---|
478 | | - |
---|
479 | | -#endif /* CONFIG_PM */ |
---|
480 | 681 | |
---|
481 | 682 | static const struct dev_pm_ops ci_hdrc_imx_pm_ops = { |
---|
482 | 683 | SET_SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume) |
---|
.. | .. |
---|
497 | 698 | module_platform_driver(ci_hdrc_imx_driver); |
---|
498 | 699 | |
---|
499 | 700 | MODULE_ALIAS("platform:imx-usb"); |
---|
500 | | -MODULE_LICENSE("GPL v2"); |
---|
| 701 | +MODULE_LICENSE("GPL"); |
---|
501 | 702 | MODULE_DESCRIPTION("CI HDRC i.MX USB binding"); |
---|
502 | 703 | MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); |
---|
503 | 704 | MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); |
---|