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 275 switch (event) { 276 case CI_HDRC_IMX_HSIC_ACTIVE_EVENT: 277 if (data->pinctrl) { 278 ret = pinctrl_select_state(data->pinctrl, 279 data->pinctrl_hsic_active); 280 if (ret) 281 dev_err(dev, 282 "hsic_active select failed, err=%d\n", 283 ret); 284 } 285 break; 286 case CI_HDRC_IMX_HSIC_SUSPEND_EVENT: 287 ret = imx_usbmisc_hsic_set_connect(data->usbmisc_data); 288 if (ret) 289 dev_err(dev, 290 "hsic_set_connect failed, err=%d\n", ret); 291 break; 292 default: 293 break; 294 } 295 296 return ret; 297 } 298 299 static int ci_hdrc_imx_probe(struct platform_device *pdev) 300 { 301 struct ci_hdrc_imx_data *data; 302 struct ci_hdrc_platform_data pdata = { 303 .name = dev_name(&pdev->dev), 304 .capoffset = DEF_CAPOFFSET, 305 .notify_event = ci_hdrc_imx_notify_event, 306 }; 307 int ret; 308 const struct of_device_id *of_id; 309 const struct ci_hdrc_imx_platform_flag *imx_platform_flag; 310 struct device_node *np = pdev->dev.of_node; 311 struct device *dev = &pdev->dev; 312 313 of_id = of_match_device(ci_hdrc_imx_dt_ids, dev); 314 if (!of_id) 315 return -ENODEV; 316 317 imx_platform_flag = of_id->data; 318 319 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 320 if (!data) 321 return -ENOMEM; 322 323 data->plat_data = imx_platform_flag; 324 pdata.flags |= imx_platform_flag->flags; 325 platform_set_drvdata(pdev, data); 326 data->usbmisc_data = usbmisc_get_init_data(dev); 327 if (IS_ERR(data->usbmisc_data)) 328 return PTR_ERR(data->usbmisc_data); 329 330 if ((of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) 331 && data->usbmisc_data) { 332 pdata.flags |= CI_HDRC_IMX_IS_HSIC; 333 data->usbmisc_data->hsic = 1; 334 data->pinctrl = devm_pinctrl_get(dev); 335 if (PTR_ERR(data->pinctrl) == -ENODEV) 336 data->pinctrl = NULL; 337 else if (IS_ERR(data->pinctrl)) { 338 if (PTR_ERR(data->pinctrl) != -EPROBE_DEFER) 339 dev_err(dev, "pinctrl get failed, err=%ld\n", 340 PTR_ERR(data->pinctrl)); 341 return PTR_ERR(data->pinctrl); 342 } 343 344 data->hsic_pad_regulator = 345 devm_regulator_get_optional(dev, "hsic"); 346 if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) { 347 /* no pad regualator is needed */ 348 data->hsic_pad_regulator = NULL; 349 } else if (IS_ERR(data->hsic_pad_regulator)) { 350 if (PTR_ERR(data->hsic_pad_regulator) != -EPROBE_DEFER) 351 dev_err(dev, 352 "Get HSIC pad regulator error: %ld\n", 353 PTR_ERR(data->hsic_pad_regulator)); 354 return PTR_ERR(data->hsic_pad_regulator); 355 } 356 357 if (data->hsic_pad_regulator) { 358 ret = regulator_enable(data->hsic_pad_regulator); 359 if (ret) { 360 dev_err(dev, 361 "Failed to enable HSIC pad regulator\n"); 362 return ret; 363 } 364 } 365 } 366 367 /* HSIC pinctrl handling */ 368 if (data->pinctrl) { 369 struct pinctrl_state *pinctrl_hsic_idle; 370 371 pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle"); 372 if (IS_ERR(pinctrl_hsic_idle)) { 373 dev_err(dev, 374 "pinctrl_hsic_idle lookup failed, err=%ld\n", 375 PTR_ERR(pinctrl_hsic_idle)); 376 return PTR_ERR(pinctrl_hsic_idle); 377 } 378 379 ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle); 380 if (ret) { 381 dev_err(dev, "hsic_idle select failed, err=%d\n", ret); 382 return ret; 383 } 384 385 data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl, 386 "active"); 387 if (IS_ERR(data->pinctrl_hsic_active)) { 388 dev_err(dev, 389 "pinctrl_hsic_active lookup failed, err=%ld\n", 390 PTR_ERR(data->pinctrl_hsic_active)); 391 return PTR_ERR(data->pinctrl_hsic_active); 392 } 393 } 394 395 if (pdata.flags & CI_HDRC_PMQOS) 396 cpu_latency_qos_add_request(&data->pm_qos_req, 0); 397 398 ret = imx_get_clks(dev); 399 if (ret) 400 goto disable_hsic_regulator; 401 402 ret = imx_prepare_enable_clks(dev); 403 if (ret) 404 goto disable_hsic_regulator; 405 406 data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0); 407 if (IS_ERR(data->phy)) { 408 ret = PTR_ERR(data->phy); 409 /* Return -EINVAL if no usbphy is available */ 410 if (ret == -ENODEV) 411 data->phy = NULL; 412 else 413 goto err_clk; 414 } 415 416 pdata.usb_phy = data->phy; 417 418 if ((of_device_is_compatible(np, "fsl,imx53-usb") || 419 of_device_is_compatible(np, "fsl,imx51-usb")) && pdata.usb_phy && 420 of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) { 421 pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL; 422 data->override_phy_control = true; 423 usb_phy_init(pdata.usb_phy); 424 } 425 426 if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM) 427 data->supports_runtime_pm = true; 428 429 ret = imx_usbmisc_init(data->usbmisc_data); 430 if (ret) { 431 dev_err(dev, "usbmisc init failed, ret=%d\n", ret); 432 goto err_clk; 433 } 434 435 data->ci_pdev = ci_hdrc_add_device(dev, 436 pdev->resource, pdev->num_resources, 437 &pdata); 438 if (IS_ERR(data->ci_pdev)) { 439 ret = PTR_ERR(data->ci_pdev); 440 if (ret != -EPROBE_DEFER) 441 dev_err(dev, "ci_hdrc_add_device failed, err=%d\n", 442 ret); 443 goto err_clk; 444 } 445 446 if (data->usbmisc_data) { 447 if (!IS_ERR(pdata.id_extcon.edev) || 448 of_property_read_bool(np, "usb-role-switch")) 449 data->usbmisc_data->ext_id = 1; 450 451 if (!IS_ERR(pdata.vbus_extcon.edev) || 452 of_property_read_bool(np, "usb-role-switch")) 453 data->usbmisc_data->ext_vbus = 1; 454 } 455 456 ret = imx_usbmisc_init_post(data->usbmisc_data); 457 if (ret) { 458 dev_err(dev, "usbmisc post failed, ret=%d\n", ret); 459 goto disable_device; 460 } 461 462 if (data->supports_runtime_pm) { 463 pm_runtime_set_active(dev); 464 pm_runtime_enable(dev); 465 } 466 467 device_set_wakeup_capable(dev, true); 468 469 return 0; 470 471 disable_device: 472 ci_hdrc_remove_device(data->ci_pdev); 473 err_clk: 474 imx_disable_unprepare_clks(dev); 475 disable_hsic_regulator: 476 if (data->hsic_pad_regulator) 477 /* don't overwrite original ret (cf. EPROBE_DEFER) */ 478 regulator_disable(data->hsic_pad_regulator); 479 if (pdata.flags & CI_HDRC_PMQOS) 480 cpu_latency_qos_remove_request(&data->pm_qos_req); 481 data->ci_pdev = NULL; 482 return ret; 483 } 484 485 static int ci_hdrc_imx_remove(struct platform_device *pdev) 486 { 487 struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev); 488 489 if (data->supports_runtime_pm) { 490 pm_runtime_get_sync(&pdev->dev); 491 pm_runtime_disable(&pdev->dev); 492 pm_runtime_put_noidle(&pdev->dev); 493 } 494 if (data->ci_pdev) 495 ci_hdrc_remove_device(data->ci_pdev); 496 if (data->override_phy_control) 497 usb_phy_shutdown(data->phy); 498 if (data->ci_pdev) { 499 imx_disable_unprepare_clks(&pdev->dev); 500 if (data->plat_data->flags & CI_HDRC_PMQOS) 501 cpu_latency_qos_remove_request(&data->pm_qos_req); 502 if (data->hsic_pad_regulator) 503 regulator_disable(data->hsic_pad_regulator); 504 } 505 506 return 0; 507 } 508 509 static void ci_hdrc_imx_shutdown(struct platform_device *pdev) 510 { 511 ci_hdrc_imx_remove(pdev); 512 } 513 514 static int __maybe_unused imx_controller_suspend(struct device *dev) 515 { 516 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 517 int ret = 0; 518 519 dev_dbg(dev, "at %s\n", __func__); 520 521 ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, false); 522 if (ret) { 523 dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); 524 return ret; 525 } 526 527 imx_disable_unprepare_clks(dev); 528 if (data->plat_data->flags & CI_HDRC_PMQOS) 529 cpu_latency_qos_remove_request(&data->pm_qos_req); 530 531 data->in_lpm = true; 532 533 return 0; 534 } 535 536 static int __maybe_unused imx_controller_resume(struct device *dev) 537 { 538 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 539 int ret = 0; 540 541 dev_dbg(dev, "at %s\n", __func__); 542 543 if (!data->in_lpm) { 544 WARN_ON(1); 545 return 0; 546 } 547 548 if (data->plat_data->flags & CI_HDRC_PMQOS) 549 cpu_latency_qos_add_request(&data->pm_qos_req, 0); 550 551 ret = imx_prepare_enable_clks(dev); 552 if (ret) 553 return ret; 554 555 data->in_lpm = false; 556 557 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false); 558 if (ret) { 559 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret); 560 goto clk_disable; 561 } 562 563 ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, true); 564 if (ret) { 565 dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); 566 goto hsic_set_clk_fail; 567 } 568 569 return 0; 570 571 hsic_set_clk_fail: 572 imx_usbmisc_set_wakeup(data->usbmisc_data, true); 573 clk_disable: 574 imx_disable_unprepare_clks(dev); 575 return ret; 576 } 577 578 static int __maybe_unused ci_hdrc_imx_suspend(struct device *dev) 579 { 580 int ret; 581 582 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 583 584 if (data->in_lpm) 585 /* The core's suspend doesn't run */ 586 return 0; 587 588 if (device_may_wakeup(dev)) { 589 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true); 590 if (ret) { 591 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", 592 ret); 593 return ret; 594 } 595 } 596 597 return imx_controller_suspend(dev); 598 } 599 600 static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) 601 { 602 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 603 int ret; 604 605 ret = imx_controller_resume(dev); 606 if (!ret && data->supports_runtime_pm) { 607 pm_runtime_disable(dev); 608 pm_runtime_set_active(dev); 609 pm_runtime_enable(dev); 610 } 611 612 return ret; 613 } 614 615 static int __maybe_unused ci_hdrc_imx_runtime_suspend(struct device *dev) 616 { 617 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 618 int ret; 619 620 if (data->in_lpm) { 621 WARN_ON(1); 622 return 0; 623 } 624 625 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true); 626 if (ret) { 627 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret); 628 return ret; 629 } 630 631 return imx_controller_suspend(dev); 632 } 633 634 static int __maybe_unused ci_hdrc_imx_runtime_resume(struct device *dev) 635 { 636 return imx_controller_resume(dev); 637 } 638 639 static const struct dev_pm_ops ci_hdrc_imx_pm_ops = { 640 SET_SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume) 641 SET_RUNTIME_PM_OPS(ci_hdrc_imx_runtime_suspend, 642 ci_hdrc_imx_runtime_resume, NULL) 643 }; 644 static struct platform_driver ci_hdrc_imx_driver = { 645 .probe = ci_hdrc_imx_probe, 646 .remove = ci_hdrc_imx_remove, 647 .shutdown = ci_hdrc_imx_shutdown, 648 .driver = { 649 .name = "imx_usb", 650 .of_match_table = ci_hdrc_imx_dt_ids, 651 .pm = &ci_hdrc_imx_pm_ops, 652 }, 653 }; 654 655 module_platform_driver(ci_hdrc_imx_driver); 656 657 MODULE_ALIAS("platform:imx-usb"); 658 MODULE_LICENSE("GPL"); 659 MODULE_DESCRIPTION("CI HDRC i.MX USB binding"); 660 MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); 661 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); 662