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