cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ci_hdrc_imx.c (17826B)


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