ci_hdrc_imx.c 18 KB

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