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