1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2012 Freescale Semiconductor, Inc.
4 * Copyright 2025 NXP
5 */
6
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/err.h>
10 #include <linux/io.h>
11 #include <linux/delay.h>
12 #include <linux/platform_device.h>
13 #include <linux/usb/otg.h>
14
15 #include "ci_hdrc_imx.h"
16
17 #define MX25_USB_PHY_CTRL_OFFSET 0x08
18 #define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23)
19
20 #define MX25_EHCI_INTERFACE_SINGLE_UNI (2 << 0)
21 #define MX25_EHCI_INTERFACE_DIFF_UNI (0 << 0)
22 #define MX25_EHCI_INTERFACE_MASK (0xf)
23
24 #define MX25_OTG_SIC_SHIFT 29
25 #define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT)
26 #define MX25_OTG_PM_BIT BIT(24)
27 #define MX25_OTG_PP_BIT BIT(11)
28 #define MX25_OTG_OCPOL_BIT BIT(3)
29
30 #define MX25_H1_SIC_SHIFT 21
31 #define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT)
32 #define MX25_H1_PP_BIT BIT(18)
33 #define MX25_H1_PM_BIT BIT(16)
34 #define MX25_H1_IPPUE_UP_BIT BIT(7)
35 #define MX25_H1_IPPUE_DOWN_BIT BIT(6)
36 #define MX25_H1_TLL_BIT BIT(5)
37 #define MX25_H1_USBTE_BIT BIT(4)
38 #define MX25_H1_OCPOL_BIT BIT(2)
39
40 #define MX27_H1_PM_BIT BIT(8)
41 #define MX27_H2_PM_BIT BIT(16)
42 #define MX27_OTG_PM_BIT BIT(24)
43
44 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
45 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c
46 #define MX53_USB_CTRL_1_OFFSET 0x10
47 #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
48 #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
49 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
50 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
51 #define MX53_USB_UH2_CTRL_OFFSET 0x14
52 #define MX53_USB_UH3_CTRL_OFFSET 0x18
53 #define MX53_USB_CLKONOFF_CTRL_OFFSET 0x24
54 #define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
55 #define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
56 #define MX53_BM_OVER_CUR_DIS_H1 BIT(5)
57 #define MX53_BM_OVER_CUR_DIS_OTG BIT(8)
58 #define MX53_BM_OVER_CUR_DIS_UHx BIT(30)
59 #define MX53_USB_CTRL_1_UH2_ULPI_EN BIT(26)
60 #define MX53_USB_CTRL_1_UH3_ULPI_EN BIT(27)
61 #define MX53_USB_UHx_CTRL_WAKE_UP_EN BIT(7)
62 #define MX53_USB_UHx_CTRL_ULPI_INT_EN BIT(8)
63 #define MX53_USB_PHYCTRL1_PLLDIV_MASK 0x3
64 #define MX53_USB_PLL_DIV_24_MHZ 0x01
65
66 #define MX6_BM_NON_BURST_SETTING BIT(1)
67 #define MX6_BM_OVER_CUR_DIS BIT(7)
68 #define MX6_BM_OVER_CUR_POLARITY BIT(8)
69 #define MX6_BM_PWR_POLARITY BIT(9)
70 #define MX6_BM_WAKEUP_ENABLE BIT(10)
71 #define MX6_BM_UTMI_ON_CLOCK BIT(13)
72 #define MX6_BM_ID_WAKEUP BIT(16)
73 #define MX6_BM_VBUS_WAKEUP BIT(17)
74 #define MX6SX_BM_DPDM_WAKEUP_EN BIT(29)
75 #define MX6_BM_WAKEUP_INTR BIT(31)
76
77 #define MX6_USB_HSIC_CTRL_OFFSET 0x10
78 /* Send resume signal without 480Mhz PHY clock */
79 #define MX6SX_BM_HSIC_AUTO_RESUME BIT(23)
80 /* set before portsc.suspendM = 1 */
81 #define MX6_BM_HSIC_DEV_CONN BIT(21)
82 /* HSIC enable */
83 #define MX6_BM_HSIC_EN BIT(12)
84 /* Force HSIC module 480M clock on, even when in Host is in suspend mode */
85 #define MX6_BM_HSIC_CLK_ON BIT(11)
86
87 #define MX6_USB_OTG1_PHY_CTRL 0x18
88 /* For imx6dql, it is host-only controller, for later imx6, it is otg's */
89 #define MX6_USB_OTG2_PHY_CTRL 0x1c
90 #define MX6SX_USB_VBUS_WAKEUP_SOURCE(v) (v << 8)
91 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
92 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
93 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
94 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
95
96 #define VF610_OVER_CUR_DIS BIT(7)
97
98 #define MX7D_USBNC_USB_CTRL2 0x4
99 #define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK 0x3
100 #define MX7D_USB_VBUS_WAKEUP_SOURCE(v) (v << 0)
101 #define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS MX7D_USB_VBUS_WAKEUP_SOURCE(0)
102 #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1)
103 #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2)
104 #define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3)
105 #define MX7D_USBNC_AUTO_RESUME BIT(2)
106 /* The default DM/DP value is pull-down */
107 #define MX7D_USBNC_USB_CTRL2_OPMODE(v) (v << 6)
108 #define MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING MX7D_USBNC_USB_CTRL2_OPMODE(1)
109 #define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK (BIT(7) | BIT(6))
110 #define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN BIT(8)
111 #define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_VAL BIT(12)
112 #define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_EN BIT(13)
113 #define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_VAL BIT(14)
114 #define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_EN BIT(15)
115 #define MX7D_USBNC_USB_CTRL2_DP_DM_MASK (BIT(12) | BIT(13) | \
116 BIT(14) | BIT(15))
117
118 #define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL BIT(0)
119 #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 BIT(1)
120 #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 BIT(2)
121 #define MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB BIT(3)
122 #define MX7D_USB_OTG_PHY_CFG2_DRVVBUS0 BIT(16)
123
124 #define MX7D_USB_OTG_PHY_CFG2 0x34
125
126 #define MX7D_USB_OTG_PHY_STATUS 0x3c
127 #define MX7D_USB_OTG_PHY_STATUS_LINE_STATE0 BIT(0)
128 #define MX7D_USB_OTG_PHY_STATUS_LINE_STATE1 BIT(1)
129 #define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD BIT(3)
130 #define MX7D_USB_OTG_PHY_STATUS_CHRGDET BIT(29)
131
132 #define MX7D_USB_OTG_PHY_CFG1 0x30
133 #define TXPREEMPAMPTUNE0_BIT 28
134 #define TXPREEMPAMPTUNE0_MASK (3 << 28)
135 #define TXRISETUNE0_BIT 24
136 #define TXRISETUNE0_MASK (3 << 24)
137 #define TXVREFTUNE0_BIT 20
138 #define TXVREFTUNE0_MASK (0xf << 20)
139
140 #define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \
141 MX6_BM_ID_WAKEUP | MX6SX_BM_DPDM_WAKEUP_EN)
142
143 /*
144 * HSIO Block Control Register
145 */
146
147 #define BLKCTL_USB_WAKEUP_CTRL 0x0
148 #define BLKCTL_OTG_WAKE_ENABLE BIT(31)
149 #define BLKCTL_OTG_VBUS_SESSVALID BIT(4)
150 #define BLKCTL_OTG_ID_WAKEUP_EN BIT(2)
151 #define BLKCTL_OTG_VBUS_WAKEUP_EN BIT(1)
152 #define BLKCTL_OTG_DPDM_WAKEUP_EN BIT(0)
153
154 #define BLKCTL_WAKEUP_SOURCE (BLKCTL_OTG_WAKE_ENABLE | \
155 BLKCTL_OTG_ID_WAKEUP_EN | \
156 BLKCTL_OTG_VBUS_WAKEUP_EN | \
157 BLKCTL_OTG_DPDM_WAKEUP_EN)
158
159 #define S32G_WAKEUP_IE BIT(0)
160 #define S32G_CORE_IE BIT(1)
161 #define S32G_PWRFLTEN BIT(7)
162 #define S32G_WAKEUPCTRL BIT(10)
163 #define S32G_WAKEUPEN BIT(11)
164
165 /* Workaround errata ERR050474 (handle packages that aren't 4 byte aligned) */
166 #define S32G_UCMALLBE BIT(15)
167
168 #define S32G_WAKEUP_BITS (S32G_WAKEUP_IE | S32G_CORE_IE | S32G_WAKEUPEN | \
169 S32G_WAKEUPCTRL)
170
171 struct usbmisc_ops {
172 /* It's called once when probe a usb device */
173 int (*init)(struct imx_usbmisc_data *data);
174 /* It's called once after adding a usb device */
175 int (*post)(struct imx_usbmisc_data *data);
176 /* It's called when we need to enable/disable usb wakeup */
177 int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
178 /* It's called before setting portsc.suspendM */
179 int (*hsic_set_connect)(struct imx_usbmisc_data *data);
180 /* It's called during suspend/resume */
181 int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
182 /* usb charger detection */
183 int (*charger_detection)(struct imx_usbmisc_data *data);
184 /* It's called when system resume from usb power lost */
185 int (*power_lost_check)(struct imx_usbmisc_data *data);
186 /* It's called when device controller changed pullup status */
187 void (*pullup)(struct imx_usbmisc_data *data, bool on);
188 /* It's called during suspend/resume to save power */
189 void (*vbus_comparator_on)(struct imx_usbmisc_data *data, bool on);
190 };
191
192 struct imx_usbmisc {
193 void __iomem *base;
194 void __iomem *blkctl;
195 spinlock_t lock;
196 const struct usbmisc_ops *ops;
197 };
198
199 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data);
200
usbmisc_imx25_init(struct imx_usbmisc_data * data)201 static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
202 {
203 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
204 unsigned long flags;
205 u32 val = 0;
206
207 if (data->index > 1)
208 return -EINVAL;
209
210 spin_lock_irqsave(&usbmisc->lock, flags);
211 switch (data->index) {
212 case 0:
213 val = readl(usbmisc->base);
214 val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
215 val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
216 val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
217
218 /*
219 * If the polarity is not configured assume active high for
220 * historical reasons.
221 */
222 if (data->oc_pol_configured && data->oc_pol_active_low)
223 val &= ~MX25_OTG_OCPOL_BIT;
224
225 writel(val, usbmisc->base);
226 break;
227 case 1:
228 val = readl(usbmisc->base);
229 val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT | MX25_H1_IPPUE_UP_BIT);
230 val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
231 val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
232 MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
233
234 /*
235 * If the polarity is not configured assume active high for
236 * historical reasons.
237 */
238 if (data->oc_pol_configured && data->oc_pol_active_low)
239 val &= ~MX25_H1_OCPOL_BIT;
240
241 writel(val, usbmisc->base);
242
243 break;
244 }
245 spin_unlock_irqrestore(&usbmisc->lock, flags);
246
247 return 0;
248 }
249
usbmisc_imx25_post(struct imx_usbmisc_data * data)250 static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
251 {
252 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
253 void __iomem *reg;
254 unsigned long flags;
255 u32 val;
256
257 if (data->index > 2)
258 return -EINVAL;
259
260 if (data->index)
261 return 0;
262
263 spin_lock_irqsave(&usbmisc->lock, flags);
264 reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
265 val = readl(reg);
266
267 if (data->evdo)
268 val |= MX25_BM_EXTERNAL_VBUS_DIVIDER;
269 else
270 val &= ~MX25_BM_EXTERNAL_VBUS_DIVIDER;
271
272 writel(val, reg);
273 spin_unlock_irqrestore(&usbmisc->lock, flags);
274 usleep_range(5000, 10000); /* needed to stabilize voltage */
275
276 return 0;
277 }
278
usbmisc_imx27_init(struct imx_usbmisc_data * data)279 static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
280 {
281 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
282 unsigned long flags;
283 u32 val;
284
285 switch (data->index) {
286 case 0:
287 val = MX27_OTG_PM_BIT;
288 break;
289 case 1:
290 val = MX27_H1_PM_BIT;
291 break;
292 case 2:
293 val = MX27_H2_PM_BIT;
294 break;
295 default:
296 return -EINVAL;
297 }
298
299 spin_lock_irqsave(&usbmisc->lock, flags);
300 if (data->disable_oc)
301 val = readl(usbmisc->base) | val;
302 else
303 val = readl(usbmisc->base) & ~val;
304 writel(val, usbmisc->base);
305 spin_unlock_irqrestore(&usbmisc->lock, flags);
306
307 return 0;
308 }
309
usbmisc_imx53_init(struct imx_usbmisc_data * data)310 static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
311 {
312 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
313 void __iomem *reg = NULL;
314 unsigned long flags;
315 u32 val = 0;
316
317 if (data->index > 3)
318 return -EINVAL;
319
320 /* Select a 24 MHz reference clock for the PHY */
321 val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
322 val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
323 val |= MX53_USB_PLL_DIV_24_MHZ;
324 writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
325
326 spin_lock_irqsave(&usbmisc->lock, flags);
327
328 switch (data->index) {
329 case 0:
330 if (data->disable_oc) {
331 reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
332 val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
333 writel(val, reg);
334 }
335 break;
336 case 1:
337 if (data->disable_oc) {
338 reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
339 val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
340 writel(val, reg);
341 }
342 break;
343 case 2:
344 if (data->ulpi) {
345 /* set USBH2 into ULPI-mode. */
346 reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
347 val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
348 /* select ULPI clock */
349 val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
350 val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
351 writel(val, reg);
352 /* Set interrupt wake up enable */
353 reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
354 val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
355 | MX53_USB_UHx_CTRL_ULPI_INT_EN;
356 writel(val, reg);
357 if (is_imx53_usbmisc(data)) {
358 /* Disable internal 60Mhz clock */
359 reg = usbmisc->base +
360 MX53_USB_CLKONOFF_CTRL_OFFSET;
361 val = readl(reg) |
362 MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
363 writel(val, reg);
364 }
365
366 }
367 if (data->disable_oc) {
368 reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
369 val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
370 writel(val, reg);
371 }
372 break;
373 case 3:
374 if (data->ulpi) {
375 /* set USBH3 into ULPI-mode. */
376 reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
377 val = readl(reg) | MX53_USB_CTRL_1_UH3_ULPI_EN;
378 /* select ULPI clock */
379 val &= ~MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK;
380 val |= MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI;
381 writel(val, reg);
382 /* Set interrupt wake up enable */
383 reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
384 val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
385 | MX53_USB_UHx_CTRL_ULPI_INT_EN;
386 writel(val, reg);
387
388 if (is_imx53_usbmisc(data)) {
389 /* Disable internal 60Mhz clock */
390 reg = usbmisc->base +
391 MX53_USB_CLKONOFF_CTRL_OFFSET;
392 val = readl(reg) |
393 MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
394 writel(val, reg);
395 }
396 }
397 if (data->disable_oc) {
398 reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
399 val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
400 writel(val, reg);
401 }
402 break;
403 }
404
405 spin_unlock_irqrestore(&usbmisc->lock, flags);
406
407 return 0;
408 }
409
usbmisc_wakeup_setting(struct imx_usbmisc_data * data)410 static u32 usbmisc_wakeup_setting(struct imx_usbmisc_data *data)
411 {
412 u32 wakeup_setting = MX6_USB_OTG_WAKEUP_BITS;
413
414 if (data->ext_id || data->available_role != USB_DR_MODE_OTG)
415 wakeup_setting &= ~MX6_BM_ID_WAKEUP;
416
417 if (data->ext_vbus || data->available_role == USB_DR_MODE_HOST)
418 wakeup_setting &= ~MX6_BM_VBUS_WAKEUP;
419
420 return wakeup_setting;
421 }
422
usbmisc_imx6q_set_wakeup(struct imx_usbmisc_data * data,bool enabled)423 static int usbmisc_imx6q_set_wakeup
424 (struct imx_usbmisc_data *data, bool enabled)
425 {
426 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
427 unsigned long flags;
428 u32 val;
429 int ret = 0;
430
431 if (data->index > 3)
432 return -EINVAL;
433
434 spin_lock_irqsave(&usbmisc->lock, flags);
435 val = readl(usbmisc->base + data->index * 4);
436 if (enabled) {
437 val &= ~MX6_USB_OTG_WAKEUP_BITS;
438 val |= usbmisc_wakeup_setting(data);
439 } else {
440 if (val & MX6_BM_WAKEUP_INTR)
441 pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
442 val &= ~MX6_USB_OTG_WAKEUP_BITS;
443 }
444 writel(val, usbmisc->base + data->index * 4);
445 spin_unlock_irqrestore(&usbmisc->lock, flags);
446
447 return ret;
448 }
449
usbmisc_imx6q_init(struct imx_usbmisc_data * data)450 static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
451 {
452 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
453 unsigned long flags;
454 u32 reg;
455
456 if (data->index > 3)
457 return -EINVAL;
458
459 spin_lock_irqsave(&usbmisc->lock, flags);
460
461 reg = readl(usbmisc->base + data->index * 4);
462 if (data->disable_oc) {
463 reg |= MX6_BM_OVER_CUR_DIS;
464 } else {
465 reg &= ~MX6_BM_OVER_CUR_DIS;
466
467 /*
468 * If the polarity is not configured keep it as setup by the
469 * bootloader.
470 */
471 if (data->oc_pol_configured && data->oc_pol_active_low)
472 reg |= MX6_BM_OVER_CUR_POLARITY;
473 else if (data->oc_pol_configured)
474 reg &= ~MX6_BM_OVER_CUR_POLARITY;
475 }
476 /* If the polarity is not set keep it as setup by the bootloader */
477 if (data->pwr_pol == 1)
478 reg |= MX6_BM_PWR_POLARITY;
479 writel(reg, usbmisc->base + data->index * 4);
480
481 /* SoC non-burst setting */
482 reg = readl(usbmisc->base + data->index * 4);
483 writel(reg | MX6_BM_NON_BURST_SETTING,
484 usbmisc->base + data->index * 4);
485
486 /* For HSIC controller */
487 if (data->hsic) {
488 reg = readl(usbmisc->base + data->index * 4);
489 writel(reg | MX6_BM_UTMI_ON_CLOCK,
490 usbmisc->base + data->index * 4);
491 reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
492 + (data->index - 2) * 4);
493 reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
494 writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
495 + (data->index - 2) * 4);
496 }
497
498 spin_unlock_irqrestore(&usbmisc->lock, flags);
499
500 usbmisc_imx6q_set_wakeup(data, false);
501
502 return 0;
503 }
504
usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data * data)505 static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data)
506 {
507 int offset, ret = 0;
508
509 if (data->index == 2 || data->index == 3) {
510 offset = (data->index - 2) * 4;
511 } else if (data->index == 0) {
512 /*
513 * For SoCs like i.MX7D and later, each USB controller has
514 * its own non-core register region. For SoCs before i.MX7D,
515 * the first two USB controllers are non-HSIC controllers.
516 */
517 offset = 0;
518 } else {
519 dev_err(data->dev, "index is error for usbmisc\n");
520 ret = -EINVAL;
521 }
522
523 return ret ? ret : offset;
524 }
525
usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data * data)526 static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
527 {
528 unsigned long flags;
529 u32 val;
530 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
531 int offset;
532
533 spin_lock_irqsave(&usbmisc->lock, flags);
534 offset = usbmisc_imx6_hsic_get_reg_offset(data);
535 if (offset < 0) {
536 spin_unlock_irqrestore(&usbmisc->lock, flags);
537 return offset;
538 }
539
540 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
541 if (!(val & MX6_BM_HSIC_DEV_CONN))
542 writel(val | MX6_BM_HSIC_DEV_CONN,
543 usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
544
545 spin_unlock_irqrestore(&usbmisc->lock, flags);
546
547 return 0;
548 }
549
usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data * data,bool on)550 static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
551 {
552 unsigned long flags;
553 u32 val;
554 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
555 int offset;
556
557 spin_lock_irqsave(&usbmisc->lock, flags);
558 offset = usbmisc_imx6_hsic_get_reg_offset(data);
559 if (offset < 0) {
560 spin_unlock_irqrestore(&usbmisc->lock, flags);
561 return offset;
562 }
563
564 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
565 val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
566 if (on)
567 val |= MX6_BM_HSIC_CLK_ON;
568 else
569 val &= ~MX6_BM_HSIC_CLK_ON;
570
571 writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
572 spin_unlock_irqrestore(&usbmisc->lock, flags);
573
574 return 0;
575 }
576
577
usbmisc_imx6sx_init(struct imx_usbmisc_data * data)578 static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
579 {
580 void __iomem *reg = NULL;
581 unsigned long flags;
582 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
583 u32 val;
584
585 usbmisc_imx6q_init(data);
586
587 if (data->index == 0 || data->index == 1) {
588 reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
589 spin_lock_irqsave(&usbmisc->lock, flags);
590 /* Set vbus wakeup source as bvalid */
591 val = readl(reg);
592 writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
593 /*
594 * Disable dp/dm wakeup in device mode when vbus is
595 * not there.
596 */
597 val = readl(usbmisc->base + data->index * 4);
598 writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
599 usbmisc->base + data->index * 4);
600 spin_unlock_irqrestore(&usbmisc->lock, flags);
601 }
602
603 /* For HSIC controller */
604 if (data->hsic) {
605 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
606 val |= MX6SX_BM_HSIC_AUTO_RESUME;
607 writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
608 }
609
610 return 0;
611 }
612
usbmisc_vf610_init(struct imx_usbmisc_data * data)613 static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
614 {
615 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
616 u32 reg;
617
618 /*
619 * Vybrid only has one misc register set, but in two different
620 * areas. These is reflected in two instances of this driver.
621 */
622 if (data->index >= 1)
623 return -EINVAL;
624
625 if (data->disable_oc) {
626 reg = readl(usbmisc->base);
627 writel(reg | VF610_OVER_CUR_DIS, usbmisc->base);
628 }
629
630 return 0;
631 }
632
usbmisc_s32g_set_wakeup(struct imx_usbmisc_data * data,bool enabled)633 static int usbmisc_s32g_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
634 {
635 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
636 unsigned long flags;
637 u32 reg;
638
639 spin_lock_irqsave(&usbmisc->lock, flags);
640
641 reg = readl(usbmisc->base);
642 if (enabled)
643 reg |= S32G_WAKEUP_BITS;
644 else
645 reg &= ~S32G_WAKEUP_BITS;
646
647 writel(reg, usbmisc->base);
648 spin_unlock_irqrestore(&usbmisc->lock, flags);
649
650 return 0;
651 }
652
usbmisc_s32g_init(struct imx_usbmisc_data * data,u32 extra_flags)653 static int usbmisc_s32g_init(struct imx_usbmisc_data *data, u32 extra_flags)
654 {
655 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
656 unsigned long flags;
657 u32 reg;
658
659 spin_lock_irqsave(&usbmisc->lock, flags);
660
661 reg = readl(usbmisc->base);
662
663 reg |= S32G_PWRFLTEN;
664 reg |= extra_flags;
665
666 writel(reg, usbmisc->base);
667
668 spin_unlock_irqrestore(&usbmisc->lock, flags);
669 usbmisc_s32g_set_wakeup(data, false);
670
671 return 0;
672 }
673
usbmisc_s32g2_init(struct imx_usbmisc_data * data)674 static int usbmisc_s32g2_init(struct imx_usbmisc_data *data)
675 {
676 return usbmisc_s32g_init(data, S32G_UCMALLBE);
677 }
678
usbmisc_s32g3_init(struct imx_usbmisc_data * data)679 static int usbmisc_s32g3_init(struct imx_usbmisc_data *data)
680 {
681 return usbmisc_s32g_init(data, 0);
682 }
683
usbmisc_imx7d_set_wakeup(struct imx_usbmisc_data * data,bool enabled)684 static int usbmisc_imx7d_set_wakeup
685 (struct imx_usbmisc_data *data, bool enabled)
686 {
687 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
688 unsigned long flags;
689 u32 val;
690
691 spin_lock_irqsave(&usbmisc->lock, flags);
692 val = readl(usbmisc->base);
693 if (enabled) {
694 val &= ~MX6_USB_OTG_WAKEUP_BITS;
695 val |= usbmisc_wakeup_setting(data);
696 writel(val, usbmisc->base);
697 } else {
698 if (val & MX6_BM_WAKEUP_INTR)
699 dev_dbg(data->dev, "wakeup int\n");
700 writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base);
701 }
702 spin_unlock_irqrestore(&usbmisc->lock, flags);
703
704 return 0;
705 }
706
usbmisc_imx7d_init(struct imx_usbmisc_data * data)707 static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
708 {
709 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
710 unsigned long flags;
711 u32 reg;
712
713 if (data->index >= 1)
714 return -EINVAL;
715
716 spin_lock_irqsave(&usbmisc->lock, flags);
717 reg = readl(usbmisc->base);
718 if (data->disable_oc) {
719 reg |= MX6_BM_OVER_CUR_DIS;
720 } else {
721 reg &= ~MX6_BM_OVER_CUR_DIS;
722
723 /*
724 * If the polarity is not configured keep it as setup by the
725 * bootloader.
726 */
727 if (data->oc_pol_configured && data->oc_pol_active_low)
728 reg |= MX6_BM_OVER_CUR_POLARITY;
729 else if (data->oc_pol_configured)
730 reg &= ~MX6_BM_OVER_CUR_POLARITY;
731 }
732 /* If the polarity is not set keep it as setup by the bootloader */
733 if (data->pwr_pol == 1)
734 reg |= MX6_BM_PWR_POLARITY;
735 writel(reg, usbmisc->base);
736
737 /* SoC non-burst setting */
738 reg = readl(usbmisc->base);
739 writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
740
741 if (!data->hsic) {
742 reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
743 reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
744 writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID
745 | MX7D_USBNC_AUTO_RESUME,
746 usbmisc->base + MX7D_USBNC_USB_CTRL2);
747 /* PHY tuning for signal quality */
748 reg = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG1);
749 if (data->emp_curr_control >= 0 &&
750 data->emp_curr_control <=
751 (TXPREEMPAMPTUNE0_MASK >> TXPREEMPAMPTUNE0_BIT)) {
752 reg &= ~TXPREEMPAMPTUNE0_MASK;
753 reg |= (data->emp_curr_control << TXPREEMPAMPTUNE0_BIT);
754 }
755
756 if (data->dc_vol_level_adjust >= 0 &&
757 data->dc_vol_level_adjust <=
758 (TXVREFTUNE0_MASK >> TXVREFTUNE0_BIT)) {
759 reg &= ~TXVREFTUNE0_MASK;
760 reg |= (data->dc_vol_level_adjust << TXVREFTUNE0_BIT);
761 }
762
763 if (data->rise_fall_time_adjust >= 0 &&
764 data->rise_fall_time_adjust <=
765 (TXRISETUNE0_MASK >> TXRISETUNE0_BIT)) {
766 reg &= ~TXRISETUNE0_MASK;
767 reg |= (data->rise_fall_time_adjust << TXRISETUNE0_BIT);
768 }
769
770 writel(reg, usbmisc->base + MX7D_USB_OTG_PHY_CFG1);
771 }
772
773 spin_unlock_irqrestore(&usbmisc->lock, flags);
774
775 usbmisc_imx7d_set_wakeup(data, false);
776
777 return 0;
778 }
779
imx7d_charger_secondary_detection(struct imx_usbmisc_data * data)780 static int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data)
781 {
782 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
783 struct usb_phy *usb_phy = data->usb_phy;
784 int val;
785 unsigned long flags;
786
787 /* Clear VDATSRCENB0 to disable VDP_SRC and IDM_SNK required by BC 1.2 spec */
788 spin_lock_irqsave(&usbmisc->lock, flags);
789 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
790 val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0;
791 writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
792 spin_unlock_irqrestore(&usbmisc->lock, flags);
793
794 /* TVDMSRC_DIS */
795 msleep(20);
796
797 /* VDM_SRC is connected to D- and IDP_SINK is connected to D+ */
798 spin_lock_irqsave(&usbmisc->lock, flags);
799 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
800 writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
801 MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
802 MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL,
803 usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
804 spin_unlock_irqrestore(&usbmisc->lock, flags);
805
806 /* TVDMSRC_ON */
807 msleep(40);
808
809 /*
810 * Per BC 1.2, check voltage of D+:
811 * DCP: if greater than VDAT_REF;
812 * CDP: if less than VDAT_REF.
813 */
814 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
815 if (val & MX7D_USB_OTG_PHY_STATUS_CHRGDET) {
816 dev_dbg(data->dev, "It is a dedicate charging port\n");
817 usb_phy->chg_type = DCP_TYPE;
818 } else {
819 dev_dbg(data->dev, "It is a charging downstream port\n");
820 usb_phy->chg_type = CDP_TYPE;
821 }
822
823 return 0;
824 }
825
imx7_disable_charger_detector(struct imx_usbmisc_data * data)826 static void imx7_disable_charger_detector(struct imx_usbmisc_data *data)
827 {
828 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
829 unsigned long flags;
830 u32 val;
831
832 spin_lock_irqsave(&usbmisc->lock, flags);
833 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
834 val &= ~(MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB |
835 MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
836 MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
837 MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL);
838 writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
839
840 /* Set OPMODE to be 2'b00 and disable its override */
841 val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
842 val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
843 writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
844
845 val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
846 writel(val & ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
847 usbmisc->base + MX7D_USBNC_USB_CTRL2);
848 spin_unlock_irqrestore(&usbmisc->lock, flags);
849 }
850
imx7d_charger_data_contact_detect(struct imx_usbmisc_data * data)851 static int imx7d_charger_data_contact_detect(struct imx_usbmisc_data *data)
852 {
853 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
854 unsigned long flags;
855 u32 val;
856 int i, data_pin_contact_count = 0;
857
858 /* Enable Data Contact Detect (DCD) per the USB BC 1.2 */
859 spin_lock_irqsave(&usbmisc->lock, flags);
860 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
861 writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
862 usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
863 spin_unlock_irqrestore(&usbmisc->lock, flags);
864
865 for (i = 0; i < 100; i = i + 1) {
866 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
867 if (!(val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE0)) {
868 if (data_pin_contact_count++ > 5)
869 /* Data pin makes contact */
870 break;
871 usleep_range(5000, 10000);
872 } else {
873 data_pin_contact_count = 0;
874 usleep_range(5000, 6000);
875 }
876 }
877
878 /* Disable DCD after finished data contact check */
879 spin_lock_irqsave(&usbmisc->lock, flags);
880 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
881 writel(val & ~MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
882 usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
883 spin_unlock_irqrestore(&usbmisc->lock, flags);
884
885 if (i == 100) {
886 dev_err(data->dev,
887 "VBUS is coming from a dedicated power supply.\n");
888 return -ENXIO;
889 }
890
891 return 0;
892 }
893
imx7d_charger_primary_detection(struct imx_usbmisc_data * data)894 static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data)
895 {
896 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
897 struct usb_phy *usb_phy = data->usb_phy;
898 unsigned long flags;
899 u32 val;
900
901 /* VDP_SRC is connected to D+ and IDM_SINK is connected to D- */
902 spin_lock_irqsave(&usbmisc->lock, flags);
903 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
904 val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL;
905 writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
906 MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0,
907 usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
908 spin_unlock_irqrestore(&usbmisc->lock, flags);
909
910 /* TVDPSRC_ON */
911 msleep(40);
912
913 /* Check if D- is less than VDAT_REF to determine an SDP per BC 1.2 */
914 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
915 if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) {
916 dev_dbg(data->dev, "It is a standard downstream port\n");
917 usb_phy->chg_type = SDP_TYPE;
918 }
919
920 return 0;
921 }
922
923 /*
924 * Whole charger detection process:
925 * 1. OPMODE override to be non-driving
926 * 2. Data contact check
927 * 3. Primary detection
928 * 4. Secondary detection
929 * 5. Disable charger detection
930 */
imx7d_charger_detection(struct imx_usbmisc_data * data)931 static int imx7d_charger_detection(struct imx_usbmisc_data *data)
932 {
933 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
934 struct usb_phy *usb_phy = data->usb_phy;
935 unsigned long flags;
936 u32 val;
937 int ret;
938
939 /* Check if vbus is valid */
940 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
941 if (!(val & MX7D_USB_OTG_PHY_STATUS_VBUS_VLD)) {
942 dev_err(data->dev, "vbus is error\n");
943 return -EINVAL;
944 }
945
946 /*
947 * Keep OPMODE to be non-driving mode during the whole
948 * charger detection process.
949 */
950 spin_lock_irqsave(&usbmisc->lock, flags);
951 val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
952 val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
953 val |= MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING;
954 writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
955
956 val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
957 writel(val | MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
958 usbmisc->base + MX7D_USBNC_USB_CTRL2);
959 spin_unlock_irqrestore(&usbmisc->lock, flags);
960
961 ret = imx7d_charger_data_contact_detect(data);
962 if (ret)
963 return ret;
964
965 ret = imx7d_charger_primary_detection(data);
966 if (!ret && usb_phy->chg_type != SDP_TYPE)
967 ret = imx7d_charger_secondary_detection(data);
968
969 imx7_disable_charger_detector(data);
970
971 return ret;
972 }
973
usbmisc_imx7d_vbus_comparator_on(struct imx_usbmisc_data * data,bool on)974 static void usbmisc_imx7d_vbus_comparator_on(struct imx_usbmisc_data *data,
975 bool on)
976 {
977 unsigned long flags;
978 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
979 u32 val;
980
981 if (data->hsic)
982 return;
983
984 spin_lock_irqsave(&usbmisc->lock, flags);
985 /*
986 * Disable VBUS valid comparator when in suspend mode,
987 * when OTG is disabled and DRVVBUS0 is asserted case
988 * the Bandgap circuitry and VBUS Valid comparator are
989 * still powered, even in Suspend or Sleep mode.
990 */
991 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
992 if (on)
993 val |= MX7D_USB_OTG_PHY_CFG2_DRVVBUS0;
994 else
995 val &= ~MX7D_USB_OTG_PHY_CFG2_DRVVBUS0;
996
997 writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
998 spin_unlock_irqrestore(&usbmisc->lock, flags);
999 }
1000
usbmisc_imx7ulp_init(struct imx_usbmisc_data * data)1001 static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data)
1002 {
1003 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
1004 unsigned long flags;
1005 u32 reg;
1006
1007 if (data->index >= 1)
1008 return -EINVAL;
1009
1010 spin_lock_irqsave(&usbmisc->lock, flags);
1011 reg = readl(usbmisc->base);
1012 if (data->disable_oc) {
1013 reg |= MX6_BM_OVER_CUR_DIS;
1014 } else {
1015 reg &= ~MX6_BM_OVER_CUR_DIS;
1016
1017 /*
1018 * If the polarity is not configured keep it as setup by the
1019 * bootloader.
1020 */
1021 if (data->oc_pol_configured && data->oc_pol_active_low)
1022 reg |= MX6_BM_OVER_CUR_POLARITY;
1023 else if (data->oc_pol_configured)
1024 reg &= ~MX6_BM_OVER_CUR_POLARITY;
1025 }
1026 /* If the polarity is not set keep it as setup by the bootloader */
1027 if (data->pwr_pol == 1)
1028 reg |= MX6_BM_PWR_POLARITY;
1029
1030 writel(reg, usbmisc->base);
1031
1032 /* SoC non-burst setting */
1033 reg = readl(usbmisc->base);
1034 writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
1035
1036 if (data->hsic) {
1037 reg = readl(usbmisc->base);
1038 writel(reg | MX6_BM_UTMI_ON_CLOCK, usbmisc->base);
1039
1040 reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
1041 reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
1042 writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
1043
1044 /*
1045 * For non-HSIC controller, the autoresume is enabled
1046 * at MXS PHY driver (usbphy_ctrl bit18).
1047 */
1048 reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
1049 writel(reg | MX7D_USBNC_AUTO_RESUME,
1050 usbmisc->base + MX7D_USBNC_USB_CTRL2);
1051 } else {
1052 reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
1053 reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
1054 writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
1055 usbmisc->base + MX7D_USBNC_USB_CTRL2);
1056 }
1057
1058 spin_unlock_irqrestore(&usbmisc->lock, flags);
1059
1060 usbmisc_imx7d_set_wakeup(data, false);
1061
1062 return 0;
1063 }
1064
usbmisc_imx7d_pullup(struct imx_usbmisc_data * data,bool on)1065 static void usbmisc_imx7d_pullup(struct imx_usbmisc_data *data, bool on)
1066 {
1067 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
1068 unsigned long flags;
1069 u32 val;
1070
1071 if (on)
1072 return;
1073
1074 spin_lock_irqsave(&usbmisc->lock, flags);
1075 val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
1076 val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
1077 val |= MX7D_USBNC_USB_CTRL2_OPMODE(1);
1078 val |= MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN;
1079 writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
1080 spin_unlock_irqrestore(&usbmisc->lock, flags);
1081
1082 /* Last for at least 1 micro-frame to let host see disconnect signal */
1083 usleep_range(125, 150);
1084
1085 spin_lock_irqsave(&usbmisc->lock, flags);
1086 val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
1087 val |= MX7D_USBNC_USB_CTRL2_OPMODE(0);
1088 val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN;
1089 writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
1090 spin_unlock_irqrestore(&usbmisc->lock, flags);
1091 }
1092
usbmisc_imx7d_power_lost_check(struct imx_usbmisc_data * data)1093 static int usbmisc_imx7d_power_lost_check(struct imx_usbmisc_data *data)
1094 {
1095 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
1096 unsigned long flags;
1097 u32 val;
1098
1099 spin_lock_irqsave(&usbmisc->lock, flags);
1100 val = readl(usbmisc->base);
1101 spin_unlock_irqrestore(&usbmisc->lock, flags);
1102 /*
1103 * Here use a power on reset value to judge
1104 * if the controller experienced a power lost
1105 */
1106 if (val == 0x30001000)
1107 return 1;
1108 else
1109 return 0;
1110 }
1111
usbmisc_imx6sx_power_lost_check(struct imx_usbmisc_data * data)1112 static int usbmisc_imx6sx_power_lost_check(struct imx_usbmisc_data *data)
1113 {
1114 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
1115 unsigned long flags;
1116 u32 val;
1117
1118 spin_lock_irqsave(&usbmisc->lock, flags);
1119 val = readl(usbmisc->base + data->index * 4);
1120 spin_unlock_irqrestore(&usbmisc->lock, flags);
1121 /*
1122 * Here use a power on reset value to judge
1123 * if the controller experienced a power lost
1124 */
1125 if (val == 0x30001000)
1126 return 1;
1127 else
1128 return 0;
1129 }
1130
usbmisc_s32g_power_lost_check(struct imx_usbmisc_data * data)1131 static int usbmisc_s32g_power_lost_check(struct imx_usbmisc_data *data)
1132 {
1133 return 1;
1134 }
1135
usbmisc_blkctl_wakeup_setting(struct imx_usbmisc_data * data)1136 static u32 usbmisc_blkctl_wakeup_setting(struct imx_usbmisc_data *data)
1137 {
1138 u32 wakeup_setting = BLKCTL_WAKEUP_SOURCE;
1139
1140 if (data->ext_id || data->available_role != USB_DR_MODE_OTG)
1141 wakeup_setting &= ~BLKCTL_OTG_ID_WAKEUP_EN;
1142
1143 if (data->ext_vbus || data->available_role == USB_DR_MODE_HOST)
1144 wakeup_setting &= ~BLKCTL_OTG_VBUS_WAKEUP_EN;
1145
1146 /* Select session valid as VBUS wakeup source */
1147 wakeup_setting |= BLKCTL_OTG_VBUS_SESSVALID;
1148
1149 return wakeup_setting;
1150 }
1151
usbmisc_imx95_set_wakeup(struct imx_usbmisc_data * data,bool enabled)1152 static int usbmisc_imx95_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
1153 {
1154 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
1155 unsigned long flags;
1156 u32 val;
1157
1158 if (!usbmisc->blkctl)
1159 return 0;
1160
1161 spin_lock_irqsave(&usbmisc->lock, flags);
1162 val = readl(usbmisc->blkctl + BLKCTL_USB_WAKEUP_CTRL);
1163 val &= ~BLKCTL_WAKEUP_SOURCE;
1164
1165 if (enabled)
1166 val |= usbmisc_blkctl_wakeup_setting(data);
1167
1168 writel(val, usbmisc->blkctl + BLKCTL_USB_WAKEUP_CTRL);
1169 spin_unlock_irqrestore(&usbmisc->lock, flags);
1170
1171 return 0;
1172 }
1173
1174 static const struct usbmisc_ops imx25_usbmisc_ops = {
1175 .init = usbmisc_imx25_init,
1176 .post = usbmisc_imx25_post,
1177 };
1178
1179 static const struct usbmisc_ops imx27_usbmisc_ops = {
1180 .init = usbmisc_imx27_init,
1181 };
1182
1183 static const struct usbmisc_ops imx51_usbmisc_ops = {
1184 .init = usbmisc_imx53_init,
1185 };
1186
1187 static const struct usbmisc_ops imx53_usbmisc_ops = {
1188 .init = usbmisc_imx53_init,
1189 };
1190
1191 static const struct usbmisc_ops imx6q_usbmisc_ops = {
1192 .set_wakeup = usbmisc_imx6q_set_wakeup,
1193 .init = usbmisc_imx6q_init,
1194 .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
1195 .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
1196 };
1197
1198 static const struct usbmisc_ops vf610_usbmisc_ops = {
1199 .init = usbmisc_vf610_init,
1200 };
1201
1202 static const struct usbmisc_ops imx6sx_usbmisc_ops = {
1203 .set_wakeup = usbmisc_imx6q_set_wakeup,
1204 .init = usbmisc_imx6sx_init,
1205 .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
1206 .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
1207 .power_lost_check = usbmisc_imx6sx_power_lost_check,
1208 };
1209
1210 static const struct usbmisc_ops imx7d_usbmisc_ops = {
1211 .init = usbmisc_imx7d_init,
1212 .set_wakeup = usbmisc_imx7d_set_wakeup,
1213 .charger_detection = imx7d_charger_detection,
1214 .power_lost_check = usbmisc_imx7d_power_lost_check,
1215 .pullup = usbmisc_imx7d_pullup,
1216 .vbus_comparator_on = usbmisc_imx7d_vbus_comparator_on,
1217 };
1218
1219 static const struct usbmisc_ops imx7ulp_usbmisc_ops = {
1220 .init = usbmisc_imx7ulp_init,
1221 .set_wakeup = usbmisc_imx7d_set_wakeup,
1222 .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
1223 .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
1224 .power_lost_check = usbmisc_imx7d_power_lost_check,
1225 };
1226
1227 static const struct usbmisc_ops imx95_usbmisc_ops = {
1228 .init = usbmisc_imx7d_init,
1229 .set_wakeup = usbmisc_imx95_set_wakeup,
1230 .charger_detection = imx7d_charger_detection,
1231 .power_lost_check = usbmisc_imx7d_power_lost_check,
1232 .pullup = usbmisc_imx7d_pullup,
1233 .vbus_comparator_on = usbmisc_imx7d_vbus_comparator_on,
1234 };
1235
1236 static const struct usbmisc_ops s32g2_usbmisc_ops = {
1237 .init = usbmisc_s32g2_init,
1238 .set_wakeup = usbmisc_s32g_set_wakeup,
1239 .power_lost_check = usbmisc_s32g_power_lost_check,
1240 };
1241
1242 static const struct usbmisc_ops s32g3_usbmisc_ops = {
1243 .init = usbmisc_s32g3_init,
1244 .set_wakeup = usbmisc_s32g_set_wakeup,
1245 .power_lost_check = usbmisc_s32g_power_lost_check,
1246 };
1247
is_imx53_usbmisc(struct imx_usbmisc_data * data)1248 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
1249 {
1250 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
1251
1252 return usbmisc->ops == &imx53_usbmisc_ops;
1253 }
1254
imx_usbmisc_init(struct imx_usbmisc_data * data)1255 int imx_usbmisc_init(struct imx_usbmisc_data *data)
1256 {
1257 struct imx_usbmisc *usbmisc;
1258
1259 if (!data)
1260 return 0;
1261
1262 usbmisc = dev_get_drvdata(data->dev);
1263 if (!usbmisc->ops->init)
1264 return 0;
1265 return usbmisc->ops->init(data);
1266 }
1267 EXPORT_SYMBOL_GPL(imx_usbmisc_init);
1268
imx_usbmisc_init_post(struct imx_usbmisc_data * data)1269 int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
1270 {
1271 struct imx_usbmisc *usbmisc;
1272 int ret = 0;
1273
1274 if (!data)
1275 return 0;
1276
1277 usbmisc = dev_get_drvdata(data->dev);
1278 if (usbmisc->ops->post)
1279 ret = usbmisc->ops->post(data);
1280 if (ret) {
1281 dev_err(data->dev, "post init failed, ret=%d\n", ret);
1282 return ret;
1283 }
1284
1285 if (usbmisc->ops->set_wakeup)
1286 ret = usbmisc->ops->set_wakeup(data, false);
1287 if (ret) {
1288 dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret);
1289 return ret;
1290 }
1291
1292 return 0;
1293 }
1294 EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
1295
imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data * data)1296 int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
1297 {
1298 struct imx_usbmisc *usbmisc;
1299
1300 if (!data)
1301 return 0;
1302
1303 usbmisc = dev_get_drvdata(data->dev);
1304 if (!usbmisc->ops->hsic_set_connect || !data->hsic)
1305 return 0;
1306 return usbmisc->ops->hsic_set_connect(data);
1307 }
1308 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
1309
imx_usbmisc_charger_detection(struct imx_usbmisc_data * data,bool connect)1310 int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect)
1311 {
1312 struct imx_usbmisc *usbmisc;
1313 struct usb_phy *usb_phy;
1314 int ret = 0;
1315
1316 if (!data)
1317 return -EINVAL;
1318
1319 usbmisc = dev_get_drvdata(data->dev);
1320 usb_phy = data->usb_phy;
1321 if (!usbmisc->ops->charger_detection)
1322 return -ENOTSUPP;
1323
1324 if (connect) {
1325 ret = usbmisc->ops->charger_detection(data);
1326 if (ret) {
1327 dev_err(data->dev,
1328 "Error occurs during detection: %d\n",
1329 ret);
1330 usb_phy->chg_state = USB_CHARGER_ABSENT;
1331 } else {
1332 usb_phy->chg_state = USB_CHARGER_PRESENT;
1333 }
1334 } else {
1335 usb_phy->chg_state = USB_CHARGER_ABSENT;
1336 usb_phy->chg_type = UNKNOWN_TYPE;
1337 }
1338 return ret;
1339 }
1340 EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection);
1341
imx_usbmisc_pullup(struct imx_usbmisc_data * data,bool on)1342 int imx_usbmisc_pullup(struct imx_usbmisc_data *data, bool on)
1343 {
1344 struct imx_usbmisc *usbmisc;
1345
1346 if (!data)
1347 return 0;
1348
1349 usbmisc = dev_get_drvdata(data->dev);
1350 if (usbmisc->ops->pullup)
1351 usbmisc->ops->pullup(data, on);
1352
1353 return 0;
1354 }
1355 EXPORT_SYMBOL_GPL(imx_usbmisc_pullup);
1356
imx_usbmisc_suspend(struct imx_usbmisc_data * data,bool wakeup)1357 int imx_usbmisc_suspend(struct imx_usbmisc_data *data, bool wakeup)
1358 {
1359 struct imx_usbmisc *usbmisc;
1360 int ret = 0;
1361
1362 if (!data)
1363 return 0;
1364
1365 usbmisc = dev_get_drvdata(data->dev);
1366
1367 if (usbmisc->ops->vbus_comparator_on)
1368 usbmisc->ops->vbus_comparator_on(data, false);
1369
1370 if (wakeup && usbmisc->ops->set_wakeup)
1371 ret = usbmisc->ops->set_wakeup(data, true);
1372 if (ret) {
1373 dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret);
1374 return ret;
1375 }
1376
1377 if (usbmisc->ops->hsic_set_clk && data->hsic)
1378 ret = usbmisc->ops->hsic_set_clk(data, false);
1379 if (ret) {
1380 dev_err(data->dev, "hsic_set_clk failed, ret=%d\n", ret);
1381 return ret;
1382 }
1383
1384 return ret;
1385 }
1386 EXPORT_SYMBOL_GPL(imx_usbmisc_suspend);
1387
imx_usbmisc_resume(struct imx_usbmisc_data * data,bool wakeup)1388 int imx_usbmisc_resume(struct imx_usbmisc_data *data, bool wakeup)
1389 {
1390 struct imx_usbmisc *usbmisc;
1391 int ret = 0;
1392
1393 if (!data)
1394 return 0;
1395
1396 usbmisc = dev_get_drvdata(data->dev);
1397
1398 if (usbmisc->ops->power_lost_check)
1399 ret = usbmisc->ops->power_lost_check(data);
1400 if (ret > 0) {
1401 /* re-init if resume from power lost */
1402 ret = imx_usbmisc_init(data);
1403 if (ret) {
1404 dev_err(data->dev, "re-init failed, ret=%d\n", ret);
1405 return ret;
1406 }
1407 }
1408
1409 if (wakeup && usbmisc->ops->set_wakeup)
1410 ret = usbmisc->ops->set_wakeup(data, false);
1411 if (ret) {
1412 dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret);
1413 return ret;
1414 }
1415
1416 if (usbmisc->ops->hsic_set_clk && data->hsic)
1417 ret = usbmisc->ops->hsic_set_clk(data, true);
1418 if (ret) {
1419 dev_err(data->dev, "hsic_set_clk failed, ret=%d\n", ret);
1420 goto hsic_set_clk_fail;
1421 }
1422
1423 if (usbmisc->ops->vbus_comparator_on)
1424 usbmisc->ops->vbus_comparator_on(data, true);
1425
1426 return 0;
1427
1428 hsic_set_clk_fail:
1429 if (wakeup && usbmisc->ops->set_wakeup)
1430 usbmisc->ops->set_wakeup(data, true);
1431 return ret;
1432 }
1433 EXPORT_SYMBOL_GPL(imx_usbmisc_resume);
1434
1435 static const struct of_device_id usbmisc_imx_dt_ids[] = {
1436 {
1437 .compatible = "fsl,imx25-usbmisc",
1438 .data = &imx25_usbmisc_ops,
1439 },
1440 {
1441 .compatible = "fsl,imx35-usbmisc",
1442 .data = &imx25_usbmisc_ops,
1443 },
1444 {
1445 .compatible = "fsl,imx27-usbmisc",
1446 .data = &imx27_usbmisc_ops,
1447 },
1448 {
1449 .compatible = "fsl,imx51-usbmisc",
1450 .data = &imx51_usbmisc_ops,
1451 },
1452 {
1453 .compatible = "fsl,imx53-usbmisc",
1454 .data = &imx53_usbmisc_ops,
1455 },
1456 {
1457 .compatible = "fsl,imx6q-usbmisc",
1458 .data = &imx6q_usbmisc_ops,
1459 },
1460 {
1461 .compatible = "fsl,vf610-usbmisc",
1462 .data = &vf610_usbmisc_ops,
1463 },
1464 {
1465 .compatible = "fsl,imx6sx-usbmisc",
1466 .data = &imx6sx_usbmisc_ops,
1467 },
1468 {
1469 .compatible = "fsl,imx6ul-usbmisc",
1470 .data = &imx6sx_usbmisc_ops,
1471 },
1472 {
1473 .compatible = "fsl,imx7d-usbmisc",
1474 .data = &imx7d_usbmisc_ops,
1475 },
1476 {
1477 .compatible = "fsl,imx7ulp-usbmisc",
1478 .data = &imx7ulp_usbmisc_ops,
1479 },
1480 {
1481 .compatible = "fsl,imx8ulp-usbmisc",
1482 .data = &imx7ulp_usbmisc_ops,
1483 },
1484 {
1485 .compatible = "fsl,imx95-usbmisc",
1486 .data = &imx95_usbmisc_ops,
1487 },
1488 {
1489 .compatible = "nxp,s32g2-usbmisc",
1490 .data = &s32g2_usbmisc_ops,
1491 },
1492 {
1493 .compatible = "nxp,s32g3-usbmisc",
1494 .data = &s32g3_usbmisc_ops,
1495 },
1496 { /* sentinel */ }
1497 };
1498 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
1499
usbmisc_imx_probe(struct platform_device * pdev)1500 static int usbmisc_imx_probe(struct platform_device *pdev)
1501 {
1502 struct imx_usbmisc *data;
1503 struct resource *res;
1504
1505 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
1506 if (!data)
1507 return -ENOMEM;
1508
1509 spin_lock_init(&data->lock);
1510
1511 data->base = devm_platform_ioremap_resource(pdev, 0);
1512 if (IS_ERR(data->base))
1513 return PTR_ERR(data->base);
1514
1515 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1516 if (res) {
1517 data->blkctl = devm_ioremap_resource(&pdev->dev, res);
1518 if (IS_ERR(data->blkctl))
1519 return PTR_ERR(data->blkctl);
1520 } else if (device_is_compatible(&pdev->dev, "fsl,imx95-usbmisc")) {
1521 dev_warn(&pdev->dev, "wakeup setting is missing\n");
1522 }
1523
1524 data->ops = of_device_get_match_data(&pdev->dev);
1525 platform_set_drvdata(pdev, data);
1526
1527 return 0;
1528 }
1529
1530 static struct platform_driver usbmisc_imx_driver = {
1531 .probe = usbmisc_imx_probe,
1532 .driver = {
1533 .name = "usbmisc_imx",
1534 .of_match_table = usbmisc_imx_dt_ids,
1535 },
1536 };
1537
1538 module_platform_driver(usbmisc_imx_driver);
1539
1540 MODULE_ALIAS("platform:usbmisc-imx");
1541 MODULE_LICENSE("GPL");
1542 MODULE_DESCRIPTION("driver for imx usb non-core registers");
1543 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
1544