Merge tag '6.6-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
[sfrench/cifs-2.6.git] / drivers / usb / dwc3 / dwc3-am62.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * dwc3-am62.c - TI specific Glue layer for AM62 DWC3 USB Controller
4  *
5  * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com
6  */
7
8 #include <linux/init.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/of.h>
14 #include <linux/of_platform.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/clk.h>
17 #include <linux/regmap.h>
18 #include <linux/pinctrl/consumer.h>
19
20 #include "core.h"
21
22 /* USB WRAPPER register offsets */
23 #define USBSS_PID                       0x0
24 #define USBSS_OVERCURRENT_CTRL          0x4
25 #define USBSS_PHY_CONFIG                0x8
26 #define USBSS_PHY_TEST                  0xc
27 #define USBSS_CORE_STAT                 0x14
28 #define USBSS_HOST_VBUS_CTRL            0x18
29 #define USBSS_MODE_CONTROL              0x1c
30 #define USBSS_WAKEUP_CONFIG             0x30
31 #define USBSS_WAKEUP_STAT               0x34
32 #define USBSS_OVERRIDE_CONFIG           0x38
33 #define USBSS_IRQ_MISC_STATUS_RAW       0x430
34 #define USBSS_IRQ_MISC_STATUS           0x434
35 #define USBSS_IRQ_MISC_ENABLE_SET       0x438
36 #define USBSS_IRQ_MISC_ENABLE_CLR       0x43c
37 #define USBSS_IRQ_MISC_EOI              0x440
38 #define USBSS_INTR_TEST                 0x490
39 #define USBSS_VBUS_FILTER               0x614
40 #define USBSS_VBUS_STAT                 0x618
41 #define USBSS_DEBUG_CFG                 0x708
42 #define USBSS_DEBUG_DATA                0x70c
43 #define USBSS_HOST_HUB_CTRL             0x714
44
45 /* PHY CONFIG register bits */
46 #define USBSS_PHY_VBUS_SEL_MASK         GENMASK(2, 1)
47 #define USBSS_PHY_VBUS_SEL_SHIFT        1
48 #define USBSS_PHY_LANE_REVERSE          BIT(0)
49
50 /* CORE STAT register bits */
51 #define USBSS_CORE_OPERATIONAL_MODE_MASK        GENMASK(13, 12)
52 #define USBSS_CORE_OPERATIONAL_MODE_SHIFT       12
53
54 /* MODE CONTROL register bits */
55 #define USBSS_MODE_VALID        BIT(0)
56
57 /* WAKEUP CONFIG register bits */
58 #define USBSS_WAKEUP_CFG_OVERCURRENT_EN BIT(3)
59 #define USBSS_WAKEUP_CFG_LINESTATE_EN   BIT(2)
60 #define USBSS_WAKEUP_CFG_SESSVALID_EN   BIT(1)
61 #define USBSS_WAKEUP_CFG_VBUSVALID_EN   BIT(0)
62
63 #define USBSS_WAKEUP_CFG_ALL    (USBSS_WAKEUP_CFG_VBUSVALID_EN | \
64                                  USBSS_WAKEUP_CFG_SESSVALID_EN | \
65                                  USBSS_WAKEUP_CFG_LINESTATE_EN | \
66                                  USBSS_WAKEUP_CFG_OVERCURRENT_EN)
67
68 #define USBSS_WAKEUP_CFG_NONE   0
69
70 /* WAKEUP STAT register bits */
71 #define USBSS_WAKEUP_STAT_OVERCURRENT   BIT(4)
72 #define USBSS_WAKEUP_STAT_LINESTATE     BIT(3)
73 #define USBSS_WAKEUP_STAT_SESSVALID     BIT(2)
74 #define USBSS_WAKEUP_STAT_VBUSVALID     BIT(1)
75 #define USBSS_WAKEUP_STAT_CLR           BIT(0)
76
77 /* IRQ_MISC_STATUS_RAW register bits */
78 #define USBSS_IRQ_MISC_RAW_VBUSVALID    BIT(22)
79 #define USBSS_IRQ_MISC_RAW_SESSVALID    BIT(20)
80
81 /* IRQ_MISC_STATUS register bits */
82 #define USBSS_IRQ_MISC_VBUSVALID        BIT(22)
83 #define USBSS_IRQ_MISC_SESSVALID        BIT(20)
84
85 /* IRQ_MISC_ENABLE_SET register bits */
86 #define USBSS_IRQ_MISC_ENABLE_SET_VBUSVALID     BIT(22)
87 #define USBSS_IRQ_MISC_ENABLE_SET_SESSVALID     BIT(20)
88
89 /* IRQ_MISC_ENABLE_CLR register bits */
90 #define USBSS_IRQ_MISC_ENABLE_CLR_VBUSVALID     BIT(22)
91 #define USBSS_IRQ_MISC_ENABLE_CLR_SESSVALID     BIT(20)
92
93 /* IRQ_MISC_EOI register bits */
94 #define USBSS_IRQ_MISC_EOI_VECTOR       BIT(0)
95
96 /* VBUS_STAT register bits */
97 #define USBSS_VBUS_STAT_SESSVALID       BIT(2)
98 #define USBSS_VBUS_STAT_VBUSVALID       BIT(0)
99
100 /* Mask for PHY PLL REFCLK */
101 #define PHY_PLL_REFCLK_MASK     GENMASK(3, 0)
102
103 #define DWC3_AM62_AUTOSUSPEND_DELAY     100
104
105 struct dwc3_am62 {
106         struct device *dev;
107         void __iomem *usbss;
108         struct clk *usb2_refclk;
109         int rate_code;
110         struct regmap *syscon;
111         unsigned int offset;
112         unsigned int vbus_divider;
113         u32 wakeup_stat;
114 };
115
116 static const int dwc3_ti_rate_table[] = {       /* in KHZ */
117         9600,
118         10000,
119         12000,
120         19200,
121         20000,
122         24000,
123         25000,
124         26000,
125         38400,
126         40000,
127         58000,
128         50000,
129         52000,
130 };
131
132 static inline u32 dwc3_ti_readl(struct dwc3_am62 *am62, u32 offset)
133 {
134         return readl((am62->usbss) + offset);
135 }
136
137 static inline void dwc3_ti_writel(struct dwc3_am62 *am62, u32 offset, u32 value)
138 {
139         writel(value, (am62->usbss) + offset);
140 }
141
142 static int phy_syscon_pll_refclk(struct dwc3_am62 *am62)
143 {
144         struct device *dev = am62->dev;
145         struct device_node *node = dev->of_node;
146         struct of_phandle_args args;
147         struct regmap *syscon;
148         int ret;
149
150         syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-phy-pll-refclk");
151         if (IS_ERR(syscon)) {
152                 dev_err(dev, "unable to get ti,syscon-phy-pll-refclk regmap\n");
153                 return PTR_ERR(syscon);
154         }
155
156         am62->syscon = syscon;
157
158         ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-phy-pll-refclk", 1,
159                                                0, &args);
160         if (ret)
161                 return ret;
162
163         am62->offset = args.args[0];
164
165         ret = regmap_update_bits(am62->syscon, am62->offset, PHY_PLL_REFCLK_MASK, am62->rate_code);
166         if (ret) {
167                 dev_err(dev, "failed to set phy pll reference clock rate\n");
168                 return ret;
169         }
170
171         return 0;
172 }
173
174 static int dwc3_ti_probe(struct platform_device *pdev)
175 {
176         struct device *dev = &pdev->dev;
177         struct device_node *node = pdev->dev.of_node;
178         struct dwc3_am62 *am62;
179         int i, ret;
180         unsigned long rate;
181         u32 reg;
182
183         am62 = devm_kzalloc(dev, sizeof(*am62), GFP_KERNEL);
184         if (!am62)
185                 return -ENOMEM;
186
187         am62->dev = dev;
188         platform_set_drvdata(pdev, am62);
189
190         am62->usbss = devm_platform_ioremap_resource(pdev, 0);
191         if (IS_ERR(am62->usbss)) {
192                 dev_err(dev, "can't map IOMEM resource\n");
193                 return PTR_ERR(am62->usbss);
194         }
195
196         am62->usb2_refclk = devm_clk_get(dev, "ref");
197         if (IS_ERR(am62->usb2_refclk)) {
198                 dev_err(dev, "can't get usb2_refclk\n");
199                 return PTR_ERR(am62->usb2_refclk);
200         }
201
202         /* Calculate the rate code */
203         rate = clk_get_rate(am62->usb2_refclk);
204         rate /= 1000;   // To KHz
205         for (i = 0; i < ARRAY_SIZE(dwc3_ti_rate_table); i++) {
206                 if (dwc3_ti_rate_table[i] == rate)
207                         break;
208         }
209
210         if (i == ARRAY_SIZE(dwc3_ti_rate_table)) {
211                 dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
212                 return -EINVAL;
213         }
214
215         am62->rate_code = i;
216
217         /* Read the syscon property and set the rate code */
218         ret = phy_syscon_pll_refclk(am62);
219         if (ret)
220                 return ret;
221
222         /* VBUS divider select */
223         am62->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
224         reg = dwc3_ti_readl(am62, USBSS_PHY_CONFIG);
225         if (am62->vbus_divider)
226                 reg |= 1 << USBSS_PHY_VBUS_SEL_SHIFT;
227
228         dwc3_ti_writel(am62, USBSS_PHY_CONFIG, reg);
229
230         pm_runtime_set_active(dev);
231         pm_runtime_enable(dev);
232         /*
233          * Don't ignore its dependencies with its children
234          */
235         pm_suspend_ignore_children(dev, false);
236         clk_prepare_enable(am62->usb2_refclk);
237         pm_runtime_get_noresume(dev);
238
239         ret = of_platform_populate(node, NULL, NULL, dev);
240         if (ret) {
241                 dev_err(dev, "failed to create dwc3 core: %d\n", ret);
242                 goto err_pm_disable;
243         }
244
245         /* Set mode valid bit to indicate role is valid */
246         reg = dwc3_ti_readl(am62, USBSS_MODE_CONTROL);
247         reg |= USBSS_MODE_VALID;
248         dwc3_ti_writel(am62, USBSS_MODE_CONTROL, reg);
249
250         /* Device has capability to wakeup system from sleep */
251         device_set_wakeup_capable(dev, true);
252         ret = device_wakeup_enable(dev);
253         if (ret)
254                 dev_err(dev, "couldn't enable device as a wakeup source: %d\n", ret);
255
256         /* Setting up autosuspend */
257         pm_runtime_set_autosuspend_delay(dev, DWC3_AM62_AUTOSUSPEND_DELAY);
258         pm_runtime_use_autosuspend(dev);
259         pm_runtime_mark_last_busy(dev);
260         pm_runtime_put_autosuspend(dev);
261         return 0;
262
263 err_pm_disable:
264         clk_disable_unprepare(am62->usb2_refclk);
265         pm_runtime_disable(dev);
266         pm_runtime_set_suspended(dev);
267         return ret;
268 }
269
270 static int dwc3_ti_remove_core(struct device *dev, void *c)
271 {
272         struct platform_device *pdev = to_platform_device(dev);
273
274         platform_device_unregister(pdev);
275         return 0;
276 }
277
278 static void dwc3_ti_remove(struct platform_device *pdev)
279 {
280         struct device *dev = &pdev->dev;
281         struct dwc3_am62 *am62 = platform_get_drvdata(pdev);
282         u32 reg;
283
284         device_for_each_child(dev, NULL, dwc3_ti_remove_core);
285
286         /* Clear mode valid bit */
287         reg = dwc3_ti_readl(am62, USBSS_MODE_CONTROL);
288         reg &= ~USBSS_MODE_VALID;
289         dwc3_ti_writel(am62, USBSS_MODE_CONTROL, reg);
290
291         pm_runtime_put_sync(dev);
292         clk_disable_unprepare(am62->usb2_refclk);
293         pm_runtime_disable(dev);
294         pm_runtime_set_suspended(dev);
295 }
296
297 #ifdef CONFIG_PM
298 static int dwc3_ti_suspend_common(struct device *dev)
299 {
300         struct dwc3_am62 *am62 = dev_get_drvdata(dev);
301         u32 reg, current_prtcap_dir;
302
303         if (device_may_wakeup(dev)) {
304                 reg = dwc3_ti_readl(am62, USBSS_CORE_STAT);
305                 current_prtcap_dir = (reg & USBSS_CORE_OPERATIONAL_MODE_MASK)
306                                      >> USBSS_CORE_OPERATIONAL_MODE_SHIFT;
307                 /* Set wakeup config enable bits */
308                 reg = dwc3_ti_readl(am62, USBSS_WAKEUP_CONFIG);
309                 if (current_prtcap_dir == DWC3_GCTL_PRTCAP_HOST) {
310                         reg = USBSS_WAKEUP_CFG_LINESTATE_EN | USBSS_WAKEUP_CFG_OVERCURRENT_EN;
311                 } else {
312                         reg = USBSS_WAKEUP_CFG_VBUSVALID_EN | USBSS_WAKEUP_CFG_SESSVALID_EN;
313                         /*
314                          * Enable LINESTATE wake up only if connected to bus
315                          * and in U2/L3 state else it causes spurious wake-up.
316                          */
317                 }
318                 dwc3_ti_writel(am62, USBSS_WAKEUP_CONFIG, reg);
319                 /* clear wakeup status so we know what caused the wake up */
320                 dwc3_ti_writel(am62, USBSS_WAKEUP_STAT, USBSS_WAKEUP_STAT_CLR);
321         }
322
323         clk_disable_unprepare(am62->usb2_refclk);
324
325         return 0;
326 }
327
328 static int dwc3_ti_resume_common(struct device *dev)
329 {
330         struct dwc3_am62 *am62 = dev_get_drvdata(dev);
331         u32 reg;
332
333         clk_prepare_enable(am62->usb2_refclk);
334
335         if (device_may_wakeup(dev)) {
336                 /* Clear wakeup config enable bits */
337                 dwc3_ti_writel(am62, USBSS_WAKEUP_CONFIG, USBSS_WAKEUP_CFG_NONE);
338         }
339
340         reg = dwc3_ti_readl(am62, USBSS_WAKEUP_STAT);
341         am62->wakeup_stat = reg;
342
343         return 0;
344 }
345
346 static UNIVERSAL_DEV_PM_OPS(dwc3_ti_pm_ops, dwc3_ti_suspend_common,
347                             dwc3_ti_resume_common, NULL);
348
349 #define DEV_PM_OPS      (&dwc3_ti_pm_ops)
350 #else
351 #define DEV_PM_OPS      NULL
352 #endif /* CONFIG_PM */
353
354 static const struct of_device_id dwc3_ti_of_match[] = {
355         { .compatible = "ti,am62-usb"},
356         {},
357 };
358 MODULE_DEVICE_TABLE(of, dwc3_ti_of_match);
359
360 static struct platform_driver dwc3_ti_driver = {
361         .probe          = dwc3_ti_probe,
362         .remove_new     = dwc3_ti_remove,
363         .driver         = {
364                 .name   = "dwc3-am62",
365                 .pm     = DEV_PM_OPS,
366                 .of_match_table = dwc3_ti_of_match,
367         },
368 };
369
370 module_platform_driver(dwc3_ti_driver);
371
372 MODULE_ALIAS("platform:dwc3-am62");
373 MODULE_AUTHOR("Aswath Govindraju <a-govindraju@ti.com>");
374 MODULE_LICENSE("GPL");
375 MODULE_DESCRIPTION("DesignWare USB3 TI Glue Layer");