xref: /openbmc/linux/drivers/usb/dwc3/dwc3-am62.c (revision d32fd6bb9f2bc8178cdd65ebec1ad670a8bfa241)
1e8784c0aSAswath Govindraju // SPDX-License-Identifier: GPL-2.0
2e8784c0aSAswath Govindraju /*
3e8784c0aSAswath Govindraju  * dwc3-am62.c - TI specific Glue layer for AM62 DWC3 USB Controller
4e8784c0aSAswath Govindraju  *
5e8784c0aSAswath Govindraju  * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com
6e8784c0aSAswath Govindraju  */
7e8784c0aSAswath Govindraju 
8e8784c0aSAswath Govindraju #include <linux/init.h>
9e8784c0aSAswath Govindraju #include <linux/kernel.h>
10e8784c0aSAswath Govindraju #include <linux/module.h>
11e8784c0aSAswath Govindraju #include <linux/platform_device.h>
12e8784c0aSAswath Govindraju #include <linux/mfd/syscon.h>
13e8784c0aSAswath Govindraju #include <linux/of.h>
14091b813dSRob Herring #include <linux/of_platform.h>
15e8784c0aSAswath Govindraju #include <linux/pm_runtime.h>
16e8784c0aSAswath Govindraju #include <linux/clk.h>
17e8784c0aSAswath Govindraju #include <linux/regmap.h>
18e8784c0aSAswath Govindraju #include <linux/pinctrl/consumer.h>
19e8784c0aSAswath Govindraju 
2084364a00SAswath Govindraju #include "core.h"
2184364a00SAswath Govindraju 
22e8784c0aSAswath Govindraju /* USB WRAPPER register offsets */
23e8784c0aSAswath Govindraju #define USBSS_PID			0x0
24e8784c0aSAswath Govindraju #define USBSS_OVERCURRENT_CTRL		0x4
25e8784c0aSAswath Govindraju #define USBSS_PHY_CONFIG		0x8
26e8784c0aSAswath Govindraju #define USBSS_PHY_TEST			0xc
27e8784c0aSAswath Govindraju #define USBSS_CORE_STAT			0x14
28e8784c0aSAswath Govindraju #define USBSS_HOST_VBUS_CTRL		0x18
29e8784c0aSAswath Govindraju #define USBSS_MODE_CONTROL		0x1c
30e8784c0aSAswath Govindraju #define USBSS_WAKEUP_CONFIG		0x30
31e8784c0aSAswath Govindraju #define USBSS_WAKEUP_STAT		0x34
32e8784c0aSAswath Govindraju #define USBSS_OVERRIDE_CONFIG		0x38
33e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_STATUS_RAW	0x430
34e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_STATUS		0x434
35e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_ENABLE_SET	0x438
36e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_ENABLE_CLR	0x43c
37e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_EOI		0x440
38e8784c0aSAswath Govindraju #define USBSS_INTR_TEST			0x490
39e8784c0aSAswath Govindraju #define USBSS_VBUS_FILTER		0x614
40e8784c0aSAswath Govindraju #define USBSS_VBUS_STAT			0x618
41e8784c0aSAswath Govindraju #define USBSS_DEBUG_CFG			0x708
42e8784c0aSAswath Govindraju #define USBSS_DEBUG_DATA		0x70c
43e8784c0aSAswath Govindraju #define USBSS_HOST_HUB_CTRL		0x714
44e8784c0aSAswath Govindraju 
45e8784c0aSAswath Govindraju /* PHY CONFIG register bits */
46e8784c0aSAswath Govindraju #define USBSS_PHY_VBUS_SEL_MASK		GENMASK(2, 1)
47e8784c0aSAswath Govindraju #define USBSS_PHY_VBUS_SEL_SHIFT	1
48e8784c0aSAswath Govindraju #define USBSS_PHY_LANE_REVERSE		BIT(0)
49e8784c0aSAswath Govindraju 
5084364a00SAswath Govindraju /* CORE STAT register bits */
5184364a00SAswath Govindraju #define USBSS_CORE_OPERATIONAL_MODE_MASK	GENMASK(13, 12)
5284364a00SAswath Govindraju #define USBSS_CORE_OPERATIONAL_MODE_SHIFT	12
5384364a00SAswath Govindraju 
54e8784c0aSAswath Govindraju /* MODE CONTROL register bits */
55e8784c0aSAswath Govindraju #define USBSS_MODE_VALID	BIT(0)
56e8784c0aSAswath Govindraju 
57e8784c0aSAswath Govindraju /* WAKEUP CONFIG register bits */
58e8784c0aSAswath Govindraju #define USBSS_WAKEUP_CFG_OVERCURRENT_EN	BIT(3)
59e8784c0aSAswath Govindraju #define USBSS_WAKEUP_CFG_LINESTATE_EN	BIT(2)
60e8784c0aSAswath Govindraju #define USBSS_WAKEUP_CFG_SESSVALID_EN	BIT(1)
61e8784c0aSAswath Govindraju #define USBSS_WAKEUP_CFG_VBUSVALID_EN	BIT(0)
62e8784c0aSAswath Govindraju 
632926c527SRoger Quadros #define USBSS_WAKEUP_CFG_ALL	(USBSS_WAKEUP_CFG_VBUSVALID_EN | \
642926c527SRoger Quadros 				 USBSS_WAKEUP_CFG_SESSVALID_EN | \
652926c527SRoger Quadros 				 USBSS_WAKEUP_CFG_LINESTATE_EN | \
662926c527SRoger Quadros 				 USBSS_WAKEUP_CFG_OVERCURRENT_EN)
672926c527SRoger Quadros 
682926c527SRoger Quadros #define USBSS_WAKEUP_CFG_NONE	0
692926c527SRoger Quadros 
70e8784c0aSAswath Govindraju /* WAKEUP STAT register bits */
71e8784c0aSAswath Govindraju #define USBSS_WAKEUP_STAT_OVERCURRENT	BIT(4)
72e8784c0aSAswath Govindraju #define USBSS_WAKEUP_STAT_LINESTATE	BIT(3)
73e8784c0aSAswath Govindraju #define USBSS_WAKEUP_STAT_SESSVALID	BIT(2)
74e8784c0aSAswath Govindraju #define USBSS_WAKEUP_STAT_VBUSVALID	BIT(1)
75e8784c0aSAswath Govindraju #define USBSS_WAKEUP_STAT_CLR		BIT(0)
76e8784c0aSAswath Govindraju 
77e8784c0aSAswath Govindraju /* IRQ_MISC_STATUS_RAW register bits */
78e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_RAW_VBUSVALID	BIT(22)
79e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_RAW_SESSVALID	BIT(20)
80e8784c0aSAswath Govindraju 
81e8784c0aSAswath Govindraju /* IRQ_MISC_STATUS register bits */
82e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_VBUSVALID	BIT(22)
83e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_SESSVALID	BIT(20)
84e8784c0aSAswath Govindraju 
85e8784c0aSAswath Govindraju /* IRQ_MISC_ENABLE_SET register bits */
86e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_ENABLE_SET_VBUSVALID	BIT(22)
87e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_ENABLE_SET_SESSVALID	BIT(20)
88e8784c0aSAswath Govindraju 
89e8784c0aSAswath Govindraju /* IRQ_MISC_ENABLE_CLR register bits */
90e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_ENABLE_CLR_VBUSVALID	BIT(22)
91e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_ENABLE_CLR_SESSVALID	BIT(20)
92e8784c0aSAswath Govindraju 
93e8784c0aSAswath Govindraju /* IRQ_MISC_EOI register bits */
94e8784c0aSAswath Govindraju #define USBSS_IRQ_MISC_EOI_VECTOR	BIT(0)
95e8784c0aSAswath Govindraju 
96e8784c0aSAswath Govindraju /* VBUS_STAT register bits */
97e8784c0aSAswath Govindraju #define USBSS_VBUS_STAT_SESSVALID	BIT(2)
98e8784c0aSAswath Govindraju #define USBSS_VBUS_STAT_VBUSVALID	BIT(0)
99e8784c0aSAswath Govindraju 
100e8784c0aSAswath Govindraju /* Mask for PHY PLL REFCLK */
101e8784c0aSAswath Govindraju #define PHY_PLL_REFCLK_MASK	GENMASK(3, 0)
102e8784c0aSAswath Govindraju 
103e8784c0aSAswath Govindraju #define DWC3_AM62_AUTOSUSPEND_DELAY	100
104e8784c0aSAswath Govindraju 
1053609699cSLadislav Michl struct dwc3_am62 {
106e8784c0aSAswath Govindraju 	struct device *dev;
107e8784c0aSAswath Govindraju 	void __iomem *usbss;
108e8784c0aSAswath Govindraju 	struct clk *usb2_refclk;
109e8784c0aSAswath Govindraju 	int rate_code;
110e8784c0aSAswath Govindraju 	struct regmap *syscon;
111e8784c0aSAswath Govindraju 	unsigned int offset;
112e8784c0aSAswath Govindraju 	unsigned int vbus_divider;
1132926c527SRoger Quadros 	u32 wakeup_stat;
114e8784c0aSAswath Govindraju };
115e8784c0aSAswath Govindraju 
116e8784c0aSAswath Govindraju static const int dwc3_ti_rate_table[] = {	/* in KHZ */
117e8784c0aSAswath Govindraju 	9600,
118e8784c0aSAswath Govindraju 	10000,
119e8784c0aSAswath Govindraju 	12000,
120e8784c0aSAswath Govindraju 	19200,
121e8784c0aSAswath Govindraju 	20000,
122e8784c0aSAswath Govindraju 	24000,
123e8784c0aSAswath Govindraju 	25000,
124e8784c0aSAswath Govindraju 	26000,
125e8784c0aSAswath Govindraju 	38400,
126e8784c0aSAswath Govindraju 	40000,
127e8784c0aSAswath Govindraju 	58000,
128e8784c0aSAswath Govindraju 	50000,
129e8784c0aSAswath Govindraju 	52000,
130e8784c0aSAswath Govindraju };
131e8784c0aSAswath Govindraju 
dwc3_ti_readl(struct dwc3_am62 * am62,u32 offset)1323609699cSLadislav Michl static inline u32 dwc3_ti_readl(struct dwc3_am62 *am62, u32 offset)
133e8784c0aSAswath Govindraju {
1343609699cSLadislav Michl 	return readl((am62->usbss) + offset);
135e8784c0aSAswath Govindraju }
136e8784c0aSAswath Govindraju 
dwc3_ti_writel(struct dwc3_am62 * am62,u32 offset,u32 value)1373609699cSLadislav Michl static inline void dwc3_ti_writel(struct dwc3_am62 *am62, u32 offset, u32 value)
138e8784c0aSAswath Govindraju {
1393609699cSLadislav Michl 	writel(value, (am62->usbss) + offset);
140e8784c0aSAswath Govindraju }
141e8784c0aSAswath Govindraju 
phy_syscon_pll_refclk(struct dwc3_am62 * am62)1423609699cSLadislav Michl static int phy_syscon_pll_refclk(struct dwc3_am62 *am62)
143e8784c0aSAswath Govindraju {
1443609699cSLadislav Michl 	struct device *dev = am62->dev;
145e8784c0aSAswath Govindraju 	struct device_node *node = dev->of_node;
146e8784c0aSAswath Govindraju 	struct of_phandle_args args;
147e8784c0aSAswath Govindraju 	struct regmap *syscon;
148e8784c0aSAswath Govindraju 	int ret;
149e8784c0aSAswath Govindraju 
150e8784c0aSAswath Govindraju 	syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-phy-pll-refclk");
151e8784c0aSAswath Govindraju 	if (IS_ERR(syscon)) {
152e8784c0aSAswath Govindraju 		dev_err(dev, "unable to get ti,syscon-phy-pll-refclk regmap\n");
153e8784c0aSAswath Govindraju 		return PTR_ERR(syscon);
154e8784c0aSAswath Govindraju 	}
155e8784c0aSAswath Govindraju 
1563609699cSLadislav Michl 	am62->syscon = syscon;
157e8784c0aSAswath Govindraju 
158e8784c0aSAswath Govindraju 	ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-phy-pll-refclk", 1,
159e8784c0aSAswath Govindraju 					       0, &args);
160e8784c0aSAswath Govindraju 	if (ret)
161e8784c0aSAswath Govindraju 		return ret;
162e8784c0aSAswath Govindraju 
1633609699cSLadislav Michl 	am62->offset = args.args[0];
164e8784c0aSAswath Govindraju 
1653609699cSLadislav Michl 	ret = regmap_update_bits(am62->syscon, am62->offset, PHY_PLL_REFCLK_MASK, am62->rate_code);
166e8784c0aSAswath Govindraju 	if (ret) {
167e8784c0aSAswath Govindraju 		dev_err(dev, "failed to set phy pll reference clock rate\n");
168e8784c0aSAswath Govindraju 		return ret;
169e8784c0aSAswath Govindraju 	}
170e8784c0aSAswath Govindraju 
171e8784c0aSAswath Govindraju 	return 0;
172e8784c0aSAswath Govindraju }
173e8784c0aSAswath Govindraju 
dwc3_ti_probe(struct platform_device * pdev)174e8784c0aSAswath Govindraju static int dwc3_ti_probe(struct platform_device *pdev)
175e8784c0aSAswath Govindraju {
176e8784c0aSAswath Govindraju 	struct device *dev = &pdev->dev;
177e8784c0aSAswath Govindraju 	struct device_node *node = pdev->dev.of_node;
1783609699cSLadislav Michl 	struct dwc3_am62 *am62;
179e8784c0aSAswath Govindraju 	int i, ret;
180e8784c0aSAswath Govindraju 	unsigned long rate;
181e8784c0aSAswath Govindraju 	u32 reg;
182e8784c0aSAswath Govindraju 
1833609699cSLadislav Michl 	am62 = devm_kzalloc(dev, sizeof(*am62), GFP_KERNEL);
1843609699cSLadislav Michl 	if (!am62)
185e8784c0aSAswath Govindraju 		return -ENOMEM;
186e8784c0aSAswath Govindraju 
1873609699cSLadislav Michl 	am62->dev = dev;
1883609699cSLadislav Michl 	platform_set_drvdata(pdev, am62);
189e8784c0aSAswath Govindraju 
1903609699cSLadislav Michl 	am62->usbss = devm_platform_ioremap_resource(pdev, 0);
1913609699cSLadislav Michl 	if (IS_ERR(am62->usbss)) {
192e8784c0aSAswath Govindraju 		dev_err(dev, "can't map IOMEM resource\n");
1933609699cSLadislav Michl 		return PTR_ERR(am62->usbss);
194e8784c0aSAswath Govindraju 	}
195e8784c0aSAswath Govindraju 
1963609699cSLadislav Michl 	am62->usb2_refclk = devm_clk_get(dev, "ref");
1973609699cSLadislav Michl 	if (IS_ERR(am62->usb2_refclk)) {
198e8784c0aSAswath Govindraju 		dev_err(dev, "can't get usb2_refclk\n");
1993609699cSLadislav Michl 		return PTR_ERR(am62->usb2_refclk);
200e8784c0aSAswath Govindraju 	}
201e8784c0aSAswath Govindraju 
202e8784c0aSAswath Govindraju 	/* Calculate the rate code */
2033609699cSLadislav Michl 	rate = clk_get_rate(am62->usb2_refclk);
204e8784c0aSAswath Govindraju 	rate /= 1000;	// To KHz
205e8784c0aSAswath Govindraju 	for (i = 0; i < ARRAY_SIZE(dwc3_ti_rate_table); i++) {
206e8784c0aSAswath Govindraju 		if (dwc3_ti_rate_table[i] == rate)
207e8784c0aSAswath Govindraju 			break;
208e8784c0aSAswath Govindraju 	}
209e8784c0aSAswath Govindraju 
210e8784c0aSAswath Govindraju 	if (i == ARRAY_SIZE(dwc3_ti_rate_table)) {
211e8784c0aSAswath Govindraju 		dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
21258121753SYang Yingliang 		return -EINVAL;
213e8784c0aSAswath Govindraju 	}
214e8784c0aSAswath Govindraju 
2153609699cSLadislav Michl 	am62->rate_code = i;
216e8784c0aSAswath Govindraju 
217e8784c0aSAswath Govindraju 	/* Read the syscon property and set the rate code */
2183609699cSLadislav Michl 	ret = phy_syscon_pll_refclk(am62);
219e8784c0aSAswath Govindraju 	if (ret)
22058121753SYang Yingliang 		return ret;
221e8784c0aSAswath Govindraju 
222e8784c0aSAswath Govindraju 	/* VBUS divider select */
2233609699cSLadislav Michl 	am62->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
2243609699cSLadislav Michl 	reg = dwc3_ti_readl(am62, USBSS_PHY_CONFIG);
2253609699cSLadislav Michl 	if (am62->vbus_divider)
226e8784c0aSAswath Govindraju 		reg |= 1 << USBSS_PHY_VBUS_SEL_SHIFT;
227e8784c0aSAswath Govindraju 
2283609699cSLadislav Michl 	dwc3_ti_writel(am62, USBSS_PHY_CONFIG, reg);
229e8784c0aSAswath Govindraju 
230e8784c0aSAswath Govindraju 	pm_runtime_set_active(dev);
231e8784c0aSAswath Govindraju 	pm_runtime_enable(dev);
232e8784c0aSAswath Govindraju 	/*
233e8784c0aSAswath Govindraju 	 * Don't ignore its dependencies with its children
234e8784c0aSAswath Govindraju 	 */
235e8784c0aSAswath Govindraju 	pm_suspend_ignore_children(dev, false);
2363609699cSLadislav Michl 	clk_prepare_enable(am62->usb2_refclk);
237e8784c0aSAswath Govindraju 	pm_runtime_get_noresume(dev);
238e8784c0aSAswath Govindraju 
239e8784c0aSAswath Govindraju 	ret = of_platform_populate(node, NULL, NULL, dev);
240e8784c0aSAswath Govindraju 	if (ret) {
241e8784c0aSAswath Govindraju 		dev_err(dev, "failed to create dwc3 core: %d\n", ret);
242e8784c0aSAswath Govindraju 		goto err_pm_disable;
243e8784c0aSAswath Govindraju 	}
244e8784c0aSAswath Govindraju 
245e8784c0aSAswath Govindraju 	/* Set mode valid bit to indicate role is valid */
2463609699cSLadislav Michl 	reg = dwc3_ti_readl(am62, USBSS_MODE_CONTROL);
247e8784c0aSAswath Govindraju 	reg |= USBSS_MODE_VALID;
2483609699cSLadislav Michl 	dwc3_ti_writel(am62, USBSS_MODE_CONTROL, reg);
249e8784c0aSAswath Govindraju 
25084364a00SAswath Govindraju 	/* Device has capability to wakeup system from sleep */
25184364a00SAswath Govindraju 	device_set_wakeup_capable(dev, true);
2524e3972b5SRoger Quadros 	ret = device_wakeup_enable(dev);
2534e3972b5SRoger Quadros 	if (ret)
2544e3972b5SRoger Quadros 		dev_err(dev, "couldn't enable device as a wakeup source: %d\n", ret);
25584364a00SAswath Govindraju 
256e8784c0aSAswath Govindraju 	/* Setting up autosuspend */
257e8784c0aSAswath Govindraju 	pm_runtime_set_autosuspend_delay(dev, DWC3_AM62_AUTOSUSPEND_DELAY);
258e8784c0aSAswath Govindraju 	pm_runtime_use_autosuspend(dev);
259e8784c0aSAswath Govindraju 	pm_runtime_mark_last_busy(dev);
260e8784c0aSAswath Govindraju 	pm_runtime_put_autosuspend(dev);
261e8784c0aSAswath Govindraju 	return 0;
262e8784c0aSAswath Govindraju 
263e8784c0aSAswath Govindraju err_pm_disable:
2643609699cSLadislav Michl 	clk_disable_unprepare(am62->usb2_refclk);
265e8784c0aSAswath Govindraju 	pm_runtime_disable(dev);
266e8784c0aSAswath Govindraju 	pm_runtime_set_suspended(dev);
267e8784c0aSAswath Govindraju 	return ret;
268e8784c0aSAswath Govindraju }
269e8784c0aSAswath Govindraju 
dwc3_ti_remove(struct platform_device * pdev)270890258e2SUwe Kleine-König static void dwc3_ti_remove(struct platform_device *pdev)
271e8784c0aSAswath Govindraju {
272e8784c0aSAswath Govindraju 	struct device *dev = &pdev->dev;
2733609699cSLadislav Michl 	struct dwc3_am62 *am62 = platform_get_drvdata(pdev);
274e8784c0aSAswath Govindraju 	u32 reg;
275e8784c0aSAswath Govindraju 
2767dfed985SRoger Quadros 	pm_runtime_get_sync(dev);
2771846bd4fSRoger Quadros 	device_init_wakeup(dev, false);
2787dfed985SRoger Quadros 	of_platform_depopulate(dev);
279e8784c0aSAswath Govindraju 
280e8784c0aSAswath Govindraju 	/* Clear mode valid bit */
2813609699cSLadislav Michl 	reg = dwc3_ti_readl(am62, USBSS_MODE_CONTROL);
282e8784c0aSAswath Govindraju 	reg &= ~USBSS_MODE_VALID;
2833609699cSLadislav Michl 	dwc3_ti_writel(am62, USBSS_MODE_CONTROL, reg);
284e8784c0aSAswath Govindraju 
285e8784c0aSAswath Govindraju 	pm_runtime_put_sync(dev);
286e8784c0aSAswath Govindraju 	pm_runtime_disable(dev);
287*7c3f7c3cSPrashanth K 	pm_runtime_dont_use_autosuspend(dev);
288e8784c0aSAswath Govindraju 	pm_runtime_set_suspended(dev);
289e8784c0aSAswath Govindraju }
290e8784c0aSAswath Govindraju 
291e8784c0aSAswath Govindraju #ifdef CONFIG_PM
dwc3_ti_suspend_common(struct device * dev)292e8784c0aSAswath Govindraju static int dwc3_ti_suspend_common(struct device *dev)
293e8784c0aSAswath Govindraju {
2943609699cSLadislav Michl 	struct dwc3_am62 *am62 = dev_get_drvdata(dev);
29584364a00SAswath Govindraju 	u32 reg, current_prtcap_dir;
29684364a00SAswath Govindraju 
29784364a00SAswath Govindraju 	if (device_may_wakeup(dev)) {
2983609699cSLadislav Michl 		reg = dwc3_ti_readl(am62, USBSS_CORE_STAT);
29984364a00SAswath Govindraju 		current_prtcap_dir = (reg & USBSS_CORE_OPERATIONAL_MODE_MASK)
30084364a00SAswath Govindraju 				     >> USBSS_CORE_OPERATIONAL_MODE_SHIFT;
30184364a00SAswath Govindraju 		/* Set wakeup config enable bits */
3023609699cSLadislav Michl 		reg = dwc3_ti_readl(am62, USBSS_WAKEUP_CONFIG);
30384364a00SAswath Govindraju 		if (current_prtcap_dir == DWC3_GCTL_PRTCAP_HOST) {
3042926c527SRoger Quadros 			reg = USBSS_WAKEUP_CFG_LINESTATE_EN | USBSS_WAKEUP_CFG_OVERCURRENT_EN;
30584364a00SAswath Govindraju 		} else {
3062926c527SRoger Quadros 			reg = USBSS_WAKEUP_CFG_VBUSVALID_EN | USBSS_WAKEUP_CFG_SESSVALID_EN;
3072926c527SRoger Quadros 			/*
3082926c527SRoger Quadros 			 * Enable LINESTATE wake up only if connected to bus
3092926c527SRoger Quadros 			 * and in U2/L3 state else it causes spurious wake-up.
3102926c527SRoger Quadros 			 */
31184364a00SAswath Govindraju 		}
3123609699cSLadislav Michl 		dwc3_ti_writel(am62, USBSS_WAKEUP_CONFIG, reg);
3132926c527SRoger Quadros 		/* clear wakeup status so we know what caused the wake up */
3143609699cSLadislav Michl 		dwc3_ti_writel(am62, USBSS_WAKEUP_STAT, USBSS_WAKEUP_STAT_CLR);
31584364a00SAswath Govindraju 	}
316e8784c0aSAswath Govindraju 
3173609699cSLadislav Michl 	clk_disable_unprepare(am62->usb2_refclk);
318e8784c0aSAswath Govindraju 
319e8784c0aSAswath Govindraju 	return 0;
320e8784c0aSAswath Govindraju }
321e8784c0aSAswath Govindraju 
dwc3_ti_resume_common(struct device * dev)322e8784c0aSAswath Govindraju static int dwc3_ti_resume_common(struct device *dev)
323e8784c0aSAswath Govindraju {
3243609699cSLadislav Michl 	struct dwc3_am62 *am62 = dev_get_drvdata(dev);
32584364a00SAswath Govindraju 	u32 reg;
326e8784c0aSAswath Govindraju 
3273609699cSLadislav Michl 	clk_prepare_enable(am62->usb2_refclk);
328e8784c0aSAswath Govindraju 
32984364a00SAswath Govindraju 	if (device_may_wakeup(dev)) {
33084364a00SAswath Govindraju 		/* Clear wakeup config enable bits */
3313609699cSLadislav Michl 		dwc3_ti_writel(am62, USBSS_WAKEUP_CONFIG, USBSS_WAKEUP_CFG_NONE);
33284364a00SAswath Govindraju 	}
33384364a00SAswath Govindraju 
3343609699cSLadislav Michl 	reg = dwc3_ti_readl(am62, USBSS_WAKEUP_STAT);
3353609699cSLadislav Michl 	am62->wakeup_stat = reg;
33684364a00SAswath Govindraju 
337e8784c0aSAswath Govindraju 	return 0;
338e8784c0aSAswath Govindraju }
339e8784c0aSAswath Govindraju 
340e8784c0aSAswath Govindraju static UNIVERSAL_DEV_PM_OPS(dwc3_ti_pm_ops, dwc3_ti_suspend_common,
341e8784c0aSAswath Govindraju 			    dwc3_ti_resume_common, NULL);
342e8784c0aSAswath Govindraju 
343e8784c0aSAswath Govindraju #define DEV_PM_OPS	(&dwc3_ti_pm_ops)
344e8784c0aSAswath Govindraju #else
345e8784c0aSAswath Govindraju #define DEV_PM_OPS	NULL
346e8784c0aSAswath Govindraju #endif /* CONFIG_PM */
347e8784c0aSAswath Govindraju 
348e8784c0aSAswath Govindraju static const struct of_device_id dwc3_ti_of_match[] = {
349e8784c0aSAswath Govindraju 	{ .compatible = "ti,am62-usb"},
350e8784c0aSAswath Govindraju 	{},
351e8784c0aSAswath Govindraju };
352e8784c0aSAswath Govindraju MODULE_DEVICE_TABLE(of, dwc3_ti_of_match);
353e8784c0aSAswath Govindraju 
354e8784c0aSAswath Govindraju static struct platform_driver dwc3_ti_driver = {
355e8784c0aSAswath Govindraju 	.probe		= dwc3_ti_probe,
356890258e2SUwe Kleine-König 	.remove_new	= dwc3_ti_remove,
357e8784c0aSAswath Govindraju 	.driver		= {
358e8784c0aSAswath Govindraju 		.name	= "dwc3-am62",
359e8784c0aSAswath Govindraju 		.pm	= DEV_PM_OPS,
360e8784c0aSAswath Govindraju 		.of_match_table = dwc3_ti_of_match,
361e8784c0aSAswath Govindraju 	},
362e8784c0aSAswath Govindraju };
363e8784c0aSAswath Govindraju 
364e8784c0aSAswath Govindraju module_platform_driver(dwc3_ti_driver);
365e8784c0aSAswath Govindraju 
366e8784c0aSAswath Govindraju MODULE_ALIAS("platform:dwc3-am62");
367e8784c0aSAswath Govindraju MODULE_AUTHOR("Aswath Govindraju <a-govindraju@ti.com>");
368e8784c0aSAswath Govindraju MODULE_LICENSE("GPL");
369e8784c0aSAswath Govindraju MODULE_DESCRIPTION("DesignWare USB3 TI Glue Layer");
370