Merge tag 'sched-urgent-2024-03-24' of git://git.kernel.org/pub/scm/linux/kernel...
[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 /* USB_PHY_CTRL register bits in CTRL_MMR */
101 #define PHY_CORE_VOLTAGE_MASK   BIT(31)
102 #define PHY_PLL_REFCLK_MASK     GENMASK(3, 0)
103
104 /* USB PHY2 register offsets */
105 #define USB_PHY_PLL_REG12               0x130
106 #define USB_PHY_PLL_LDO_REF_EN          BIT(5)
107 #define USB_PHY_PLL_LDO_REF_EN_EN       BIT(4)
108
109 #define DWC3_AM62_AUTOSUSPEND_DELAY     100
110
111 struct dwc3_am62 {
112         struct device *dev;
113         void __iomem *usbss;
114         struct clk *usb2_refclk;
115         int rate_code;
116         struct regmap *syscon;
117         unsigned int offset;
118         unsigned int vbus_divider;
119         u32 wakeup_stat;
120 };
121
122 static const int dwc3_ti_rate_table[] = {       /* in KHZ */
123         9600,
124         10000,
125         12000,
126         19200,
127         20000,
128         24000,
129         25000,
130         26000,
131         38400,
132         40000,
133         58000,
134         50000,
135         52000,
136 };
137
138 static inline u32 dwc3_ti_readl(struct dwc3_am62 *am62, u32 offset)
139 {
140         return readl((am62->usbss) + offset);
141 }
142
143 static inline void dwc3_ti_writel(struct dwc3_am62 *am62, u32 offset, u32 value)
144 {
145         writel(value, (am62->usbss) + offset);
146 }
147
148 static int phy_syscon_pll_refclk(struct dwc3_am62 *am62)
149 {
150         struct device *dev = am62->dev;
151         struct device_node *node = dev->of_node;
152         struct of_phandle_args args;
153         struct regmap *syscon;
154         int ret;
155
156         syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-phy-pll-refclk");
157         if (IS_ERR(syscon)) {
158                 dev_err(dev, "unable to get ti,syscon-phy-pll-refclk regmap\n");
159                 return PTR_ERR(syscon);
160         }
161
162         am62->syscon = syscon;
163
164         ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-phy-pll-refclk", 1,
165                                                0, &args);
166         if (ret)
167                 return ret;
168
169         am62->offset = args.args[0];
170
171         /* Core voltage. PHY_CORE_VOLTAGE bit Recommended to be 0 always */
172         ret = regmap_update_bits(am62->syscon, am62->offset, PHY_CORE_VOLTAGE_MASK, 0);
173         if (ret) {
174                 dev_err(dev, "failed to set phy core voltage\n");
175                 return ret;
176         }
177
178         ret = regmap_update_bits(am62->syscon, am62->offset, PHY_PLL_REFCLK_MASK, am62->rate_code);
179         if (ret) {
180                 dev_err(dev, "failed to set phy pll reference clock rate\n");
181                 return ret;
182         }
183
184         return 0;
185 }
186
187 static int dwc3_ti_probe(struct platform_device *pdev)
188 {
189         struct device *dev = &pdev->dev;
190         struct device_node *node = pdev->dev.of_node;
191         struct dwc3_am62 *am62;
192         unsigned long rate;
193         void __iomem *phy;
194         int i, ret;
195         u32 reg;
196
197         am62 = devm_kzalloc(dev, sizeof(*am62), GFP_KERNEL);
198         if (!am62)
199                 return -ENOMEM;
200
201         am62->dev = dev;
202         platform_set_drvdata(pdev, am62);
203
204         am62->usbss = devm_platform_ioremap_resource(pdev, 0);
205         if (IS_ERR(am62->usbss)) {
206                 dev_err(dev, "can't map IOMEM resource\n");
207                 return PTR_ERR(am62->usbss);
208         }
209
210         am62->usb2_refclk = devm_clk_get(dev, "ref");
211         if (IS_ERR(am62->usb2_refclk)) {
212                 dev_err(dev, "can't get usb2_refclk\n");
213                 return PTR_ERR(am62->usb2_refclk);
214         }
215
216         /* Calculate the rate code */
217         rate = clk_get_rate(am62->usb2_refclk);
218         rate /= 1000;   // To KHz
219         for (i = 0; i < ARRAY_SIZE(dwc3_ti_rate_table); i++) {
220                 if (dwc3_ti_rate_table[i] == rate)
221                         break;
222         }
223
224         if (i == ARRAY_SIZE(dwc3_ti_rate_table)) {
225                 dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
226                 return -EINVAL;
227         }
228
229         am62->rate_code = i;
230
231         /* Read the syscon property and set the rate code */
232         ret = phy_syscon_pll_refclk(am62);
233         if (ret)
234                 return ret;
235
236         /* Workaround Errata i2409 */
237         phy = devm_platform_ioremap_resource(pdev, 1);
238         if (IS_ERR(phy)) {
239                 dev_err(dev, "can't map PHY IOMEM resource. Won't apply i2409 fix.\n");
240                 phy = NULL;
241         } else {
242                 reg = readl(phy + USB_PHY_PLL_REG12);
243                 reg |= USB_PHY_PLL_LDO_REF_EN | USB_PHY_PLL_LDO_REF_EN_EN;
244                 writel(reg, phy + USB_PHY_PLL_REG12);
245         }
246
247         /* VBUS divider select */
248         am62->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
249         reg = dwc3_ti_readl(am62, USBSS_PHY_CONFIG);
250         if (am62->vbus_divider)
251                 reg |= 1 << USBSS_PHY_VBUS_SEL_SHIFT;
252
253         dwc3_ti_writel(am62, USBSS_PHY_CONFIG, reg);
254
255         pm_runtime_set_active(dev);
256         pm_runtime_enable(dev);
257         /*
258          * Don't ignore its dependencies with its children
259          */
260         pm_suspend_ignore_children(dev, false);
261         clk_prepare_enable(am62->usb2_refclk);
262         pm_runtime_get_noresume(dev);
263
264         ret = of_platform_populate(node, NULL, NULL, dev);
265         if (ret) {
266                 dev_err(dev, "failed to create dwc3 core: %d\n", ret);
267                 goto err_pm_disable;
268         }
269
270         /* Set mode valid bit to indicate role is valid */
271         reg = dwc3_ti_readl(am62, USBSS_MODE_CONTROL);
272         reg |= USBSS_MODE_VALID;
273         dwc3_ti_writel(am62, USBSS_MODE_CONTROL, reg);
274
275         /* Device has capability to wakeup system from sleep */
276         device_set_wakeup_capable(dev, true);
277         ret = device_wakeup_enable(dev);
278         if (ret)
279                 dev_err(dev, "couldn't enable device as a wakeup source: %d\n", ret);
280
281         /* Setting up autosuspend */
282         pm_runtime_set_autosuspend_delay(dev, DWC3_AM62_AUTOSUSPEND_DELAY);
283         pm_runtime_use_autosuspend(dev);
284         pm_runtime_mark_last_busy(dev);
285         pm_runtime_put_autosuspend(dev);
286         return 0;
287
288 err_pm_disable:
289         clk_disable_unprepare(am62->usb2_refclk);
290         pm_runtime_disable(dev);
291         pm_runtime_set_suspended(dev);
292         return ret;
293 }
294
295 static void dwc3_ti_remove(struct platform_device *pdev)
296 {
297         struct device *dev = &pdev->dev;
298         struct dwc3_am62 *am62 = platform_get_drvdata(pdev);
299         u32 reg;
300
301         pm_runtime_get_sync(dev);
302         device_init_wakeup(dev, false);
303         of_platform_depopulate(dev);
304
305         /* Clear mode valid bit */
306         reg = dwc3_ti_readl(am62, USBSS_MODE_CONTROL);
307         reg &= ~USBSS_MODE_VALID;
308         dwc3_ti_writel(am62, USBSS_MODE_CONTROL, reg);
309
310         pm_runtime_put_sync(dev);
311         pm_runtime_disable(dev);
312         pm_runtime_set_suspended(dev);
313 }
314
315 #ifdef CONFIG_PM
316 static int dwc3_ti_suspend_common(struct device *dev)
317 {
318         struct dwc3_am62 *am62 = dev_get_drvdata(dev);
319         u32 reg, current_prtcap_dir;
320
321         if (device_may_wakeup(dev)) {
322                 reg = dwc3_ti_readl(am62, USBSS_CORE_STAT);
323                 current_prtcap_dir = (reg & USBSS_CORE_OPERATIONAL_MODE_MASK)
324                                      >> USBSS_CORE_OPERATIONAL_MODE_SHIFT;
325                 /* Set wakeup config enable bits */
326                 reg = dwc3_ti_readl(am62, USBSS_WAKEUP_CONFIG);
327                 if (current_prtcap_dir == DWC3_GCTL_PRTCAP_HOST) {
328                         reg = USBSS_WAKEUP_CFG_LINESTATE_EN | USBSS_WAKEUP_CFG_OVERCURRENT_EN;
329                 } else {
330                         reg = USBSS_WAKEUP_CFG_VBUSVALID_EN | USBSS_WAKEUP_CFG_SESSVALID_EN;
331                         /*
332                          * Enable LINESTATE wake up only if connected to bus
333                          * and in U2/L3 state else it causes spurious wake-up.
334                          */
335                 }
336                 dwc3_ti_writel(am62, USBSS_WAKEUP_CONFIG, reg);
337                 /* clear wakeup status so we know what caused the wake up */
338                 dwc3_ti_writel(am62, USBSS_WAKEUP_STAT, USBSS_WAKEUP_STAT_CLR);
339         }
340
341         clk_disable_unprepare(am62->usb2_refclk);
342
343         return 0;
344 }
345
346 static int dwc3_ti_resume_common(struct device *dev)
347 {
348         struct dwc3_am62 *am62 = dev_get_drvdata(dev);
349         u32 reg;
350
351         clk_prepare_enable(am62->usb2_refclk);
352
353         if (device_may_wakeup(dev)) {
354                 /* Clear wakeup config enable bits */
355                 dwc3_ti_writel(am62, USBSS_WAKEUP_CONFIG, USBSS_WAKEUP_CFG_NONE);
356         }
357
358         reg = dwc3_ti_readl(am62, USBSS_WAKEUP_STAT);
359         am62->wakeup_stat = reg;
360
361         return 0;
362 }
363
364 static UNIVERSAL_DEV_PM_OPS(dwc3_ti_pm_ops, dwc3_ti_suspend_common,
365                             dwc3_ti_resume_common, NULL);
366
367 #define DEV_PM_OPS      (&dwc3_ti_pm_ops)
368 #else
369 #define DEV_PM_OPS      NULL
370 #endif /* CONFIG_PM */
371
372 static const struct of_device_id dwc3_ti_of_match[] = {
373         { .compatible = "ti,am62-usb"},
374         {},
375 };
376 MODULE_DEVICE_TABLE(of, dwc3_ti_of_match);
377
378 static struct platform_driver dwc3_ti_driver = {
379         .probe          = dwc3_ti_probe,
380         .remove_new     = dwc3_ti_remove,
381         .driver         = {
382                 .name   = "dwc3-am62",
383                 .pm     = DEV_PM_OPS,
384                 .of_match_table = dwc3_ti_of_match,
385         },
386 };
387
388 module_platform_driver(dwc3_ti_driver);
389
390 MODULE_ALIAS("platform:dwc3-am62");
391 MODULE_AUTHOR("Aswath Govindraju <a-govindraju@ti.com>");
392 MODULE_LICENSE("GPL");
393 MODULE_DESCRIPTION("DesignWare USB3 TI Glue Layer");