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