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