1 /* 2 * Copyright 2012 Freescale Semiconductor, Inc. 3 * Copyright (C) 2012 Marek Vasut <marex@denx.de> 4 * on behalf of DENX Software Engineering GmbH 5 * 6 * The code contained herein is licensed under the GNU General Public 7 * License. You may obtain a copy of the GNU General Public License 8 * Version 2 or later at the following locations: 9 * 10 * http://www.opensource.org/licenses/gpl-license.html 11 * http://www.gnu.org/copyleft/gpl.html 12 */ 13 14 #include <linux/module.h> 15 #include <linux/of_platform.h> 16 #include <linux/of_gpio.h> 17 #include <linux/platform_device.h> 18 #include <linux/pm_runtime.h> 19 #include <linux/dma-mapping.h> 20 #include <linux/usb/chipidea.h> 21 #include <linux/clk.h> 22 23 #include "ci.h" 24 #include "ci_hdrc_imx.h" 25 26 struct ci_hdrc_imx_platform_flag { 27 unsigned int flags; 28 bool runtime_pm; 29 }; 30 31 static const struct ci_hdrc_imx_platform_flag imx23_usb_data = { 32 .flags = CI_HDRC_TURN_VBUS_EARLY_ON | 33 CI_HDRC_DISABLE_STREAMING, 34 }; 35 36 static const struct ci_hdrc_imx_platform_flag imx27_usb_data = { 37 CI_HDRC_DISABLE_STREAMING, 38 }; 39 40 static const struct ci_hdrc_imx_platform_flag imx28_usb_data = { 41 .flags = CI_HDRC_IMX28_WRITE_FIX | 42 CI_HDRC_TURN_VBUS_EARLY_ON | 43 CI_HDRC_DISABLE_STREAMING, 44 }; 45 46 static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = { 47 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | 48 CI_HDRC_TURN_VBUS_EARLY_ON | 49 CI_HDRC_DISABLE_STREAMING, 50 }; 51 52 static const struct ci_hdrc_imx_platform_flag imx6sl_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 imx6sx_usb_data = { 59 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | 60 CI_HDRC_TURN_VBUS_EARLY_ON | 61 CI_HDRC_DISABLE_HOST_STREAMING, 62 }; 63 64 static const struct ci_hdrc_imx_platform_flag imx6ul_usb_data = { 65 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | 66 CI_HDRC_TURN_VBUS_EARLY_ON, 67 }; 68 69 static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = { 70 .flags = CI_HDRC_SUPPORTS_RUNTIME_PM, 71 }; 72 73 static const struct of_device_id ci_hdrc_imx_dt_ids[] = { 74 { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data}, 75 { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data}, 76 { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data}, 77 { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data}, 78 { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data}, 79 { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data}, 80 { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data}, 81 { .compatible = "fsl,imx7d-usb", .data = &imx7d_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 in_lpm; 93 /* SoC before i.mx6 (except imx23/imx28) needs three clks */ 94 bool need_three_clks; 95 struct clk *clk_ipg; 96 struct clk *clk_ahb; 97 struct clk *clk_per; 98 /* --------------------------------- */ 99 }; 100 101 /* Common functions shared by usbmisc drivers */ 102 103 static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) 104 { 105 struct platform_device *misc_pdev; 106 struct device_node *np = dev->of_node; 107 struct of_phandle_args args; 108 struct imx_usbmisc_data *data; 109 int ret; 110 111 /* 112 * In case the fsl,usbmisc property is not present this device doesn't 113 * need usbmisc. Return NULL (which is no error here) 114 */ 115 if (!of_get_property(np, "fsl,usbmisc", NULL)) 116 return NULL; 117 118 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 119 if (!data) 120 return ERR_PTR(-ENOMEM); 121 122 ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells", 123 0, &args); 124 if (ret) { 125 dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n", 126 ret); 127 return ERR_PTR(ret); 128 } 129 130 data->index = args.args[0]; 131 132 misc_pdev = of_find_device_by_node(args.np); 133 of_node_put(args.np); 134 135 if (!misc_pdev || !platform_get_drvdata(misc_pdev)) 136 return ERR_PTR(-EPROBE_DEFER); 137 138 data->dev = &misc_pdev->dev; 139 140 if (of_find_property(np, "disable-over-current", NULL)) 141 data->disable_oc = 1; 142 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; 148 149 return data; 150 } 151 152 /* End of common functions shared by usbmisc drivers*/ 153 static int imx_get_clks(struct device *dev) 154 { 155 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 156 int ret = 0; 157 158 data->clk_ipg = devm_clk_get(dev, "ipg"); 159 if (IS_ERR(data->clk_ipg)) { 160 /* If the platform only needs one clocks */ 161 data->clk = devm_clk_get(dev, NULL); 162 if (IS_ERR(data->clk)) { 163 ret = PTR_ERR(data->clk); 164 dev_err(dev, 165 "Failed to get clks, err=%ld,%ld\n", 166 PTR_ERR(data->clk), PTR_ERR(data->clk_ipg)); 167 return ret; 168 } 169 return ret; 170 } 171 172 data->clk_ahb = devm_clk_get(dev, "ahb"); 173 if (IS_ERR(data->clk_ahb)) { 174 ret = PTR_ERR(data->clk_ahb); 175 dev_err(dev, 176 "Failed to get ahb clock, err=%d\n", ret); 177 return ret; 178 } 179 180 data->clk_per = devm_clk_get(dev, "per"); 181 if (IS_ERR(data->clk_per)) { 182 ret = PTR_ERR(data->clk_per); 183 dev_err(dev, 184 "Failed to get per clock, err=%d\n", ret); 185 return ret; 186 } 187 188 data->need_three_clks = true; 189 return ret; 190 } 191 192 static int imx_prepare_enable_clks(struct device *dev) 193 { 194 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 195 int ret = 0; 196 197 if (data->need_three_clks) { 198 ret = clk_prepare_enable(data->clk_ipg); 199 if (ret) { 200 dev_err(dev, 201 "Failed to prepare/enable ipg clk, err=%d\n", 202 ret); 203 return ret; 204 } 205 206 ret = clk_prepare_enable(data->clk_ahb); 207 if (ret) { 208 dev_err(dev, 209 "Failed to prepare/enable ahb clk, err=%d\n", 210 ret); 211 clk_disable_unprepare(data->clk_ipg); 212 return ret; 213 } 214 215 ret = clk_prepare_enable(data->clk_per); 216 if (ret) { 217 dev_err(dev, 218 "Failed to prepare/enable per clk, err=%d\n", 219 ret); 220 clk_disable_unprepare(data->clk_ahb); 221 clk_disable_unprepare(data->clk_ipg); 222 return ret; 223 } 224 } else { 225 ret = clk_prepare_enable(data->clk); 226 if (ret) { 227 dev_err(dev, 228 "Failed to prepare/enable clk, err=%d\n", 229 ret); 230 return ret; 231 } 232 } 233 234 return ret; 235 } 236 237 static void imx_disable_unprepare_clks(struct device *dev) 238 { 239 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 240 241 if (data->need_three_clks) { 242 clk_disable_unprepare(data->clk_per); 243 clk_disable_unprepare(data->clk_ahb); 244 clk_disable_unprepare(data->clk_ipg); 245 } else { 246 clk_disable_unprepare(data->clk); 247 } 248 } 249 250 static int ci_hdrc_imx_probe(struct platform_device *pdev) 251 { 252 struct ci_hdrc_imx_data *data; 253 struct ci_hdrc_platform_data pdata = { 254 .name = dev_name(&pdev->dev), 255 .capoffset = DEF_CAPOFFSET, 256 }; 257 int ret; 258 const struct of_device_id *of_id; 259 const struct ci_hdrc_imx_platform_flag *imx_platform_flag; 260 261 of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev); 262 if (!of_id) 263 return -ENODEV; 264 265 imx_platform_flag = of_id->data; 266 267 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 268 if (!data) 269 return -ENOMEM; 270 271 platform_set_drvdata(pdev, data); 272 data->usbmisc_data = usbmisc_get_init_data(&pdev->dev); 273 if (IS_ERR(data->usbmisc_data)) 274 return PTR_ERR(data->usbmisc_data); 275 276 ret = imx_get_clks(&pdev->dev); 277 if (ret) 278 return ret; 279 280 ret = imx_prepare_enable_clks(&pdev->dev); 281 if (ret) 282 return ret; 283 284 data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); 285 if (IS_ERR(data->phy)) { 286 ret = PTR_ERR(data->phy); 287 /* Return -EINVAL if no usbphy is available */ 288 if (ret == -ENODEV) 289 ret = -EINVAL; 290 goto err_clk; 291 } 292 293 pdata.usb_phy = data->phy; 294 pdata.flags |= imx_platform_flag->flags; 295 if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM) 296 data->supports_runtime_pm = true; 297 298 ret = imx_usbmisc_init(data->usbmisc_data); 299 if (ret) { 300 dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", ret); 301 goto err_clk; 302 } 303 304 data->ci_pdev = ci_hdrc_add_device(&pdev->dev, 305 pdev->resource, pdev->num_resources, 306 &pdata); 307 if (IS_ERR(data->ci_pdev)) { 308 ret = PTR_ERR(data->ci_pdev); 309 if (ret != -EPROBE_DEFER) 310 dev_err(&pdev->dev, 311 "ci_hdrc_add_device failed, err=%d\n", ret); 312 goto err_clk; 313 } 314 315 ret = imx_usbmisc_init_post(data->usbmisc_data); 316 if (ret) { 317 dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n", ret); 318 goto disable_device; 319 } 320 321 if (data->supports_runtime_pm) { 322 pm_runtime_set_active(&pdev->dev); 323 pm_runtime_enable(&pdev->dev); 324 } 325 326 device_set_wakeup_capable(&pdev->dev, true); 327 328 return 0; 329 330 disable_device: 331 ci_hdrc_remove_device(data->ci_pdev); 332 err_clk: 333 imx_disable_unprepare_clks(&pdev->dev); 334 return ret; 335 } 336 337 static int ci_hdrc_imx_remove(struct platform_device *pdev) 338 { 339 struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev); 340 341 if (data->supports_runtime_pm) { 342 pm_runtime_get_sync(&pdev->dev); 343 pm_runtime_disable(&pdev->dev); 344 pm_runtime_put_noidle(&pdev->dev); 345 } 346 ci_hdrc_remove_device(data->ci_pdev); 347 imx_disable_unprepare_clks(&pdev->dev); 348 349 return 0; 350 } 351 352 static void ci_hdrc_imx_shutdown(struct platform_device *pdev) 353 { 354 ci_hdrc_imx_remove(pdev); 355 } 356 357 #ifdef CONFIG_PM 358 static int imx_controller_suspend(struct device *dev) 359 { 360 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 361 362 dev_dbg(dev, "at %s\n", __func__); 363 364 imx_disable_unprepare_clks(dev); 365 data->in_lpm = true; 366 367 return 0; 368 } 369 370 static int imx_controller_resume(struct device *dev) 371 { 372 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 373 int ret = 0; 374 375 dev_dbg(dev, "at %s\n", __func__); 376 377 if (!data->in_lpm) { 378 WARN_ON(1); 379 return 0; 380 } 381 382 ret = imx_prepare_enable_clks(dev); 383 if (ret) 384 return ret; 385 386 data->in_lpm = false; 387 388 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false); 389 if (ret) { 390 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret); 391 goto clk_disable; 392 } 393 394 return 0; 395 396 clk_disable: 397 imx_disable_unprepare_clks(dev); 398 return ret; 399 } 400 401 #ifdef CONFIG_PM_SLEEP 402 static int ci_hdrc_imx_suspend(struct device *dev) 403 { 404 int ret; 405 406 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 407 408 if (data->in_lpm) 409 /* The core's suspend doesn't run */ 410 return 0; 411 412 if (device_may_wakeup(dev)) { 413 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true); 414 if (ret) { 415 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", 416 ret); 417 return ret; 418 } 419 } 420 421 return imx_controller_suspend(dev); 422 } 423 424 static int ci_hdrc_imx_resume(struct device *dev) 425 { 426 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 427 int ret; 428 429 ret = imx_controller_resume(dev); 430 if (!ret && data->supports_runtime_pm) { 431 pm_runtime_disable(dev); 432 pm_runtime_set_active(dev); 433 pm_runtime_enable(dev); 434 } 435 436 return ret; 437 } 438 #endif /* CONFIG_PM_SLEEP */ 439 440 static int ci_hdrc_imx_runtime_suspend(struct device *dev) 441 { 442 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 443 int ret; 444 445 if (data->in_lpm) { 446 WARN_ON(1); 447 return 0; 448 } 449 450 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true); 451 if (ret) { 452 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret); 453 return ret; 454 } 455 456 return imx_controller_suspend(dev); 457 } 458 459 static int ci_hdrc_imx_runtime_resume(struct device *dev) 460 { 461 return imx_controller_resume(dev); 462 } 463 464 #endif /* CONFIG_PM */ 465 466 static const struct dev_pm_ops ci_hdrc_imx_pm_ops = { 467 SET_SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume) 468 SET_RUNTIME_PM_OPS(ci_hdrc_imx_runtime_suspend, 469 ci_hdrc_imx_runtime_resume, NULL) 470 }; 471 static struct platform_driver ci_hdrc_imx_driver = { 472 .probe = ci_hdrc_imx_probe, 473 .remove = ci_hdrc_imx_remove, 474 .shutdown = ci_hdrc_imx_shutdown, 475 .driver = { 476 .name = "imx_usb", 477 .of_match_table = ci_hdrc_imx_dt_ids, 478 .pm = &ci_hdrc_imx_pm_ops, 479 }, 480 }; 481 482 module_platform_driver(ci_hdrc_imx_driver); 483 484 MODULE_ALIAS("platform:imx-usb"); 485 MODULE_LICENSE("GPL v2"); 486 MODULE_DESCRIPTION("CI HDRC i.MX USB binding"); 487 MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); 488 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); 489