1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2012 Freescale Semiconductor, Inc. 4 * Copyright (C) 2012 Marek Vasut <marex@denx.de> 5 * on behalf of DENX Software Engineering GmbH 6 */ 7 8 #include <linux/module.h> 9 #include <linux/of_platform.h> 10 #include <linux/platform_device.h> 11 #include <linux/pm_runtime.h> 12 #include <linux/usb/chipidea.h> 13 #include <linux/usb/of.h> 14 #include <linux/clk.h> 15 #include <linux/pinctrl/consumer.h> 16 #include <linux/pm_qos.h> 17 18 #include "ci.h" 19 #include "ci_hdrc_imx.h" 20 21 struct ci_hdrc_imx_platform_flag { 22 unsigned int flags; 23 }; 24 25 static const struct ci_hdrc_imx_platform_flag imx23_usb_data = { 26 .flags = CI_HDRC_TURN_VBUS_EARLY_ON | 27 CI_HDRC_DISABLE_STREAMING, 28 }; 29 30 static const struct ci_hdrc_imx_platform_flag imx27_usb_data = { 31 .flags = CI_HDRC_DISABLE_STREAMING, 32 }; 33 34 static const struct ci_hdrc_imx_platform_flag imx28_usb_data = { 35 .flags = CI_HDRC_IMX28_WRITE_FIX | 36 CI_HDRC_TURN_VBUS_EARLY_ON | 37 CI_HDRC_DISABLE_STREAMING, 38 }; 39 40 static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = { 41 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | 42 CI_HDRC_TURN_VBUS_EARLY_ON | 43 CI_HDRC_DISABLE_STREAMING, 44 }; 45 46 static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = { 47 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | 48 CI_HDRC_TURN_VBUS_EARLY_ON | 49 CI_HDRC_DISABLE_HOST_STREAMING, 50 }; 51 52 static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = { 53 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | 54 CI_HDRC_TURN_VBUS_EARLY_ON | 55 CI_HDRC_DISABLE_HOST_STREAMING, 56 }; 57 58 static const struct ci_hdrc_imx_platform_flag imx6ul_usb_data = { 59 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | 60 CI_HDRC_TURN_VBUS_EARLY_ON, 61 }; 62 63 static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = { 64 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM, 65 }; 66 67 static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = { 68 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | 69 CI_HDRC_PMQOS, 70 }; 71 72 static const struct of_device_id ci_hdrc_imx_dt_ids[] = { 73 { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data}, 74 { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data}, 75 { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data}, 76 { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data}, 77 { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data}, 78 { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data}, 79 { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data}, 80 { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data}, 81 { .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data}, 82 { /* sentinel */ } 83 }; 84 MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); 85 86 struct ci_hdrc_imx_data { 87 struct usb_phy *phy; 88 struct platform_device *ci_pdev; 89 struct clk *clk; 90 struct imx_usbmisc_data *usbmisc_data; 91 bool supports_runtime_pm; 92 bool override_phy_control; 93 bool in_lpm; 94 struct pinctrl *pinctrl; 95 struct pinctrl_state *pinctrl_hsic_active; 96 struct regulator *hsic_pad_regulator; 97 /* SoC before i.mx6 (except imx23/imx28) needs three clks */ 98 bool need_three_clks; 99 struct clk *clk_ipg; 100 struct clk *clk_ahb; 101 struct clk *clk_per; 102 /* --------------------------------- */ 103 struct pm_qos_request pm_qos_req; 104 const struct ci_hdrc_imx_platform_flag *plat_data; 105 }; 106 107 /* Common functions shared by usbmisc drivers */ 108 109 static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) 110 { 111 struct platform_device *misc_pdev; 112 struct device_node *np = dev->of_node; 113 struct of_phandle_args args; 114 struct imx_usbmisc_data *data; 115 int ret; 116 117 /* 118 * In case the fsl,usbmisc property is not present this device doesn't 119 * need usbmisc. Return NULL (which is no error here) 120 */ 121 if (!of_get_property(np, "fsl,usbmisc", NULL)) 122 return NULL; 123 124 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 125 if (!data) 126 return ERR_PTR(-ENOMEM); 127 128 ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells", 129 0, &args); 130 if (ret) { 131 dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n", 132 ret); 133 return ERR_PTR(ret); 134 } 135 136 data->index = args.args[0]; 137 138 misc_pdev = of_find_device_by_node(args.np); 139 of_node_put(args.np); 140 141 if (!misc_pdev || !platform_get_drvdata(misc_pdev)) 142 return ERR_PTR(-EPROBE_DEFER); 143 144 data->dev = &misc_pdev->dev; 145 146 /* 147 * Check the various over current related properties. If over current 148 * detection is disabled we're not interested in the polarity. 149 */ 150 if (of_find_property(np, "disable-over-current", NULL)) { 151 data->disable_oc = 1; 152 } else if (of_find_property(np, "over-current-active-high", NULL)) { 153 data->oc_pol_active_low = 0; 154 data->oc_pol_configured = 1; 155 } else if (of_find_property(np, "over-current-active-low", NULL)) { 156 data->oc_pol_active_low = 1; 157 data->oc_pol_configured = 1; 158 } else { 159 dev_warn(dev, "No over current polarity defined\n"); 160 } 161 162 data->pwr_pol = of_property_read_bool(np, "power-active-high"); 163 data->evdo = of_property_read_bool(np, "external-vbus-divider"); 164 165 if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) 166 data->ulpi = 1; 167 168 return data; 169 } 170 171 /* End of common functions shared by usbmisc drivers*/ 172 static int imx_get_clks(struct device *dev) 173 { 174 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 175 int ret = 0; 176 177 data->clk_ipg = devm_clk_get(dev, "ipg"); 178 if (IS_ERR(data->clk_ipg)) { 179 /* If the platform only needs one clocks */ 180 data->clk = devm_clk_get(dev, NULL); 181 if (IS_ERR(data->clk)) { 182 ret = PTR_ERR(data->clk); 183 dev_err(dev, 184 "Failed to get clks, err=%ld,%ld\n", 185 PTR_ERR(data->clk), PTR_ERR(data->clk_ipg)); 186 return ret; 187 } 188 return ret; 189 } 190 191 data->clk_ahb = devm_clk_get(dev, "ahb"); 192 if (IS_ERR(data->clk_ahb)) { 193 ret = PTR_ERR(data->clk_ahb); 194 dev_err(dev, 195 "Failed to get ahb clock, err=%d\n", ret); 196 return ret; 197 } 198 199 data->clk_per = devm_clk_get(dev, "per"); 200 if (IS_ERR(data->clk_per)) { 201 ret = PTR_ERR(data->clk_per); 202 dev_err(dev, 203 "Failed to get per clock, err=%d\n", ret); 204 return ret; 205 } 206 207 data->need_three_clks = true; 208 return ret; 209 } 210 211 static int imx_prepare_enable_clks(struct device *dev) 212 { 213 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 214 int ret = 0; 215 216 if (data->need_three_clks) { 217 ret = clk_prepare_enable(data->clk_ipg); 218 if (ret) { 219 dev_err(dev, 220 "Failed to prepare/enable ipg clk, err=%d\n", 221 ret); 222 return ret; 223 } 224 225 ret = clk_prepare_enable(data->clk_ahb); 226 if (ret) { 227 dev_err(dev, 228 "Failed to prepare/enable ahb clk, err=%d\n", 229 ret); 230 clk_disable_unprepare(data->clk_ipg); 231 return ret; 232 } 233 234 ret = clk_prepare_enable(data->clk_per); 235 if (ret) { 236 dev_err(dev, 237 "Failed to prepare/enable per clk, err=%d\n", 238 ret); 239 clk_disable_unprepare(data->clk_ahb); 240 clk_disable_unprepare(data->clk_ipg); 241 return ret; 242 } 243 } else { 244 ret = clk_prepare_enable(data->clk); 245 if (ret) { 246 dev_err(dev, 247 "Failed to prepare/enable clk, err=%d\n", 248 ret); 249 return ret; 250 } 251 } 252 253 return ret; 254 } 255 256 static void imx_disable_unprepare_clks(struct device *dev) 257 { 258 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 259 260 if (data->need_three_clks) { 261 clk_disable_unprepare(data->clk_per); 262 clk_disable_unprepare(data->clk_ahb); 263 clk_disable_unprepare(data->clk_ipg); 264 } else { 265 clk_disable_unprepare(data->clk); 266 } 267 } 268 269 static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event) 270 { 271 struct device *dev = ci->dev->parent; 272 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 273 int ret = 0; 274 struct imx_usbmisc_data *mdata = data->usbmisc_data; 275 276 switch (event) { 277 case CI_HDRC_IMX_HSIC_ACTIVE_EVENT: 278 if (data->pinctrl) { 279 ret = pinctrl_select_state(data->pinctrl, 280 data->pinctrl_hsic_active); 281 if (ret) 282 dev_err(dev, 283 "hsic_active select failed, err=%d\n", 284 ret); 285 } 286 break; 287 case CI_HDRC_IMX_HSIC_SUSPEND_EVENT: 288 ret = imx_usbmisc_hsic_set_connect(mdata); 289 if (ret) 290 dev_err(dev, 291 "hsic_set_connect failed, err=%d\n", ret); 292 break; 293 case CI_HDRC_CONTROLLER_VBUS_EVENT: 294 if (ci->vbus_active) 295 ret = imx_usbmisc_charger_detection(mdata, true); 296 else 297 ret = imx_usbmisc_charger_detection(mdata, false); 298 if (ci->usb_phy) 299 schedule_work(&ci->usb_phy->chg_work); 300 break; 301 default: 302 break; 303 } 304 305 return ret; 306 } 307 308 static int ci_hdrc_imx_probe(struct platform_device *pdev) 309 { 310 struct ci_hdrc_imx_data *data; 311 struct ci_hdrc_platform_data pdata = { 312 .name = dev_name(&pdev->dev), 313 .capoffset = DEF_CAPOFFSET, 314 .notify_event = ci_hdrc_imx_notify_event, 315 }; 316 int ret; 317 const struct of_device_id *of_id; 318 const struct ci_hdrc_imx_platform_flag *imx_platform_flag; 319 struct device_node *np = pdev->dev.of_node; 320 struct device *dev = &pdev->dev; 321 322 of_id = of_match_device(ci_hdrc_imx_dt_ids, dev); 323 if (!of_id) 324 return -ENODEV; 325 326 imx_platform_flag = of_id->data; 327 328 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 329 if (!data) 330 return -ENOMEM; 331 332 data->plat_data = imx_platform_flag; 333 pdata.flags |= imx_platform_flag->flags; 334 platform_set_drvdata(pdev, data); 335 data->usbmisc_data = usbmisc_get_init_data(dev); 336 if (IS_ERR(data->usbmisc_data)) 337 return PTR_ERR(data->usbmisc_data); 338 339 if ((of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) 340 && data->usbmisc_data) { 341 pdata.flags |= CI_HDRC_IMX_IS_HSIC; 342 data->usbmisc_data->hsic = 1; 343 data->pinctrl = devm_pinctrl_get(dev); 344 if (PTR_ERR(data->pinctrl) == -ENODEV) 345 data->pinctrl = NULL; 346 else if (IS_ERR(data->pinctrl)) { 347 if (PTR_ERR(data->pinctrl) != -EPROBE_DEFER) 348 dev_err(dev, "pinctrl get failed, err=%ld\n", 349 PTR_ERR(data->pinctrl)); 350 return PTR_ERR(data->pinctrl); 351 } 352 353 data->hsic_pad_regulator = 354 devm_regulator_get_optional(dev, "hsic"); 355 if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) { 356 /* no pad regualator is needed */ 357 data->hsic_pad_regulator = NULL; 358 } else if (IS_ERR(data->hsic_pad_regulator)) { 359 if (PTR_ERR(data->hsic_pad_regulator) != -EPROBE_DEFER) 360 dev_err(dev, 361 "Get HSIC pad regulator error: %ld\n", 362 PTR_ERR(data->hsic_pad_regulator)); 363 return PTR_ERR(data->hsic_pad_regulator); 364 } 365 366 if (data->hsic_pad_regulator) { 367 ret = regulator_enable(data->hsic_pad_regulator); 368 if (ret) { 369 dev_err(dev, 370 "Failed to enable HSIC pad regulator\n"); 371 return ret; 372 } 373 } 374 } 375 376 /* HSIC pinctrl handling */ 377 if (data->pinctrl) { 378 struct pinctrl_state *pinctrl_hsic_idle; 379 380 pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle"); 381 if (IS_ERR(pinctrl_hsic_idle)) { 382 dev_err(dev, 383 "pinctrl_hsic_idle lookup failed, err=%ld\n", 384 PTR_ERR(pinctrl_hsic_idle)); 385 return PTR_ERR(pinctrl_hsic_idle); 386 } 387 388 ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle); 389 if (ret) { 390 dev_err(dev, "hsic_idle select failed, err=%d\n", ret); 391 return ret; 392 } 393 394 data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl, 395 "active"); 396 if (IS_ERR(data->pinctrl_hsic_active)) { 397 dev_err(dev, 398 "pinctrl_hsic_active lookup failed, err=%ld\n", 399 PTR_ERR(data->pinctrl_hsic_active)); 400 return PTR_ERR(data->pinctrl_hsic_active); 401 } 402 } 403 404 if (pdata.flags & CI_HDRC_PMQOS) 405 cpu_latency_qos_add_request(&data->pm_qos_req, 0); 406 407 ret = imx_get_clks(dev); 408 if (ret) 409 goto disable_hsic_regulator; 410 411 ret = imx_prepare_enable_clks(dev); 412 if (ret) 413 goto disable_hsic_regulator; 414 415 data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0); 416 if (IS_ERR(data->phy)) { 417 ret = PTR_ERR(data->phy); 418 /* Return -EINVAL if no usbphy is available */ 419 if (ret == -ENODEV) 420 data->phy = NULL; 421 else 422 goto err_clk; 423 } 424 425 pdata.usb_phy = data->phy; 426 if (data->usbmisc_data) 427 data->usbmisc_data->usb_phy = data->phy; 428 429 if ((of_device_is_compatible(np, "fsl,imx53-usb") || 430 of_device_is_compatible(np, "fsl,imx51-usb")) && pdata.usb_phy && 431 of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) { 432 pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL; 433 data->override_phy_control = true; 434 usb_phy_init(pdata.usb_phy); 435 } 436 437 if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM) 438 data->supports_runtime_pm = true; 439 440 ret = imx_usbmisc_init(data->usbmisc_data); 441 if (ret) { 442 dev_err(dev, "usbmisc init failed, ret=%d\n", ret); 443 goto err_clk; 444 } 445 446 data->ci_pdev = ci_hdrc_add_device(dev, 447 pdev->resource, pdev->num_resources, 448 &pdata); 449 if (IS_ERR(data->ci_pdev)) { 450 ret = PTR_ERR(data->ci_pdev); 451 if (ret != -EPROBE_DEFER) 452 dev_err(dev, "ci_hdrc_add_device failed, err=%d\n", 453 ret); 454 goto err_clk; 455 } 456 457 if (data->usbmisc_data) { 458 if (!IS_ERR(pdata.id_extcon.edev) || 459 of_property_read_bool(np, "usb-role-switch")) 460 data->usbmisc_data->ext_id = 1; 461 462 if (!IS_ERR(pdata.vbus_extcon.edev) || 463 of_property_read_bool(np, "usb-role-switch")) 464 data->usbmisc_data->ext_vbus = 1; 465 } 466 467 ret = imx_usbmisc_init_post(data->usbmisc_data); 468 if (ret) { 469 dev_err(dev, "usbmisc post failed, ret=%d\n", ret); 470 goto disable_device; 471 } 472 473 if (data->supports_runtime_pm) { 474 pm_runtime_set_active(dev); 475 pm_runtime_enable(dev); 476 } 477 478 device_set_wakeup_capable(dev, true); 479 480 return 0; 481 482 disable_device: 483 ci_hdrc_remove_device(data->ci_pdev); 484 err_clk: 485 imx_disable_unprepare_clks(dev); 486 disable_hsic_regulator: 487 if (data->hsic_pad_regulator) 488 /* don't overwrite original ret (cf. EPROBE_DEFER) */ 489 regulator_disable(data->hsic_pad_regulator); 490 if (pdata.flags & CI_HDRC_PMQOS) 491 cpu_latency_qos_remove_request(&data->pm_qos_req); 492 data->ci_pdev = NULL; 493 return ret; 494 } 495 496 static int ci_hdrc_imx_remove(struct platform_device *pdev) 497 { 498 struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev); 499 500 if (data->supports_runtime_pm) { 501 pm_runtime_get_sync(&pdev->dev); 502 pm_runtime_disable(&pdev->dev); 503 pm_runtime_put_noidle(&pdev->dev); 504 } 505 if (data->ci_pdev) 506 ci_hdrc_remove_device(data->ci_pdev); 507 if (data->override_phy_control) 508 usb_phy_shutdown(data->phy); 509 if (data->ci_pdev) { 510 imx_disable_unprepare_clks(&pdev->dev); 511 if (data->plat_data->flags & CI_HDRC_PMQOS) 512 cpu_latency_qos_remove_request(&data->pm_qos_req); 513 if (data->hsic_pad_regulator) 514 regulator_disable(data->hsic_pad_regulator); 515 } 516 517 return 0; 518 } 519 520 static void ci_hdrc_imx_shutdown(struct platform_device *pdev) 521 { 522 ci_hdrc_imx_remove(pdev); 523 } 524 525 static int __maybe_unused imx_controller_suspend(struct device *dev) 526 { 527 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 528 int ret = 0; 529 530 dev_dbg(dev, "at %s\n", __func__); 531 532 ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, false); 533 if (ret) { 534 dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); 535 return ret; 536 } 537 538 imx_disable_unprepare_clks(dev); 539 if (data->plat_data->flags & CI_HDRC_PMQOS) 540 cpu_latency_qos_remove_request(&data->pm_qos_req); 541 542 data->in_lpm = true; 543 544 return 0; 545 } 546 547 static int __maybe_unused imx_controller_resume(struct device *dev) 548 { 549 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 550 int ret = 0; 551 552 dev_dbg(dev, "at %s\n", __func__); 553 554 if (!data->in_lpm) { 555 WARN_ON(1); 556 return 0; 557 } 558 559 if (data->plat_data->flags & CI_HDRC_PMQOS) 560 cpu_latency_qos_add_request(&data->pm_qos_req, 0); 561 562 ret = imx_prepare_enable_clks(dev); 563 if (ret) 564 return ret; 565 566 data->in_lpm = false; 567 568 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false); 569 if (ret) { 570 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret); 571 goto clk_disable; 572 } 573 574 ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, true); 575 if (ret) { 576 dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); 577 goto hsic_set_clk_fail; 578 } 579 580 return 0; 581 582 hsic_set_clk_fail: 583 imx_usbmisc_set_wakeup(data->usbmisc_data, true); 584 clk_disable: 585 imx_disable_unprepare_clks(dev); 586 return ret; 587 } 588 589 static int __maybe_unused ci_hdrc_imx_suspend(struct device *dev) 590 { 591 int ret; 592 593 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 594 595 if (data->in_lpm) 596 /* The core's suspend doesn't run */ 597 return 0; 598 599 if (device_may_wakeup(dev)) { 600 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true); 601 if (ret) { 602 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", 603 ret); 604 return ret; 605 } 606 } 607 608 return imx_controller_suspend(dev); 609 } 610 611 static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) 612 { 613 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 614 int ret; 615 616 ret = imx_controller_resume(dev); 617 if (!ret && data->supports_runtime_pm) { 618 pm_runtime_disable(dev); 619 pm_runtime_set_active(dev); 620 pm_runtime_enable(dev); 621 } 622 623 return ret; 624 } 625 626 static int __maybe_unused ci_hdrc_imx_runtime_suspend(struct device *dev) 627 { 628 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 629 int ret; 630 631 if (data->in_lpm) { 632 WARN_ON(1); 633 return 0; 634 } 635 636 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true); 637 if (ret) { 638 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret); 639 return ret; 640 } 641 642 return imx_controller_suspend(dev); 643 } 644 645 static int __maybe_unused ci_hdrc_imx_runtime_resume(struct device *dev) 646 { 647 return imx_controller_resume(dev); 648 } 649 650 static const struct dev_pm_ops ci_hdrc_imx_pm_ops = { 651 SET_SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume) 652 SET_RUNTIME_PM_OPS(ci_hdrc_imx_runtime_suspend, 653 ci_hdrc_imx_runtime_resume, NULL) 654 }; 655 static struct platform_driver ci_hdrc_imx_driver = { 656 .probe = ci_hdrc_imx_probe, 657 .remove = ci_hdrc_imx_remove, 658 .shutdown = ci_hdrc_imx_shutdown, 659 .driver = { 660 .name = "imx_usb", 661 .of_match_table = ci_hdrc_imx_dt_ids, 662 .pm = &ci_hdrc_imx_pm_ops, 663 }, 664 }; 665 666 module_platform_driver(ci_hdrc_imx_driver); 667 668 MODULE_ALIAS("platform:imx-usb"); 669 MODULE_LICENSE("GPL"); 670 MODULE_DESCRIPTION("CI HDRC i.MX USB binding"); 671 MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); 672 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); 673