1 /*
2  * Copyright 2012 Freescale Semiconductor, Inc.
3  *
4  * The code contained herein is licensed under the GNU General Public
5  * License. You may obtain a copy of the GNU General Public License
6  * Version 2 or later at the following locations:
7  *
8  * http://www.opensource.org/licenses/gpl-license.html
9  * http://www.gnu.org/copyleft/gpl.html
10  */
11 
12 #include <linux/module.h>
13 #include <linux/of_platform.h>
14 #include <linux/err.h>
15 #include <linux/io.h>
16 #include <linux/delay.h>
17 
18 #include "ci_hdrc_imx.h"
19 
20 #define MX25_USB_PHY_CTRL_OFFSET	0x08
21 #define MX25_BM_EXTERNAL_VBUS_DIVIDER	BIT(23)
22 
23 #define MX25_EHCI_INTERFACE_SINGLE_UNI	(2 << 0)
24 #define MX25_EHCI_INTERFACE_DIFF_UNI	(0 << 0)
25 #define MX25_EHCI_INTERFACE_MASK	(0xf)
26 
27 #define MX25_OTG_SIC_SHIFT		29
28 #define MX25_OTG_SIC_MASK		(0x3 << MX25_OTG_SIC_SHIFT)
29 #define MX25_OTG_PM_BIT			BIT(24)
30 #define MX25_OTG_PP_BIT			BIT(11)
31 #define MX25_OTG_OCPOL_BIT		BIT(3)
32 
33 #define MX25_H1_SIC_SHIFT		21
34 #define MX25_H1_SIC_MASK		(0x3 << MX25_H1_SIC_SHIFT)
35 #define MX25_H1_PP_BIT			BIT(18)
36 #define MX25_H1_PM_BIT			BIT(16)
37 #define MX25_H1_IPPUE_UP_BIT		BIT(7)
38 #define MX25_H1_IPPUE_DOWN_BIT		BIT(6)
39 #define MX25_H1_TLL_BIT			BIT(5)
40 #define MX25_H1_USBTE_BIT		BIT(4)
41 #define MX25_H1_OCPOL_BIT		BIT(2)
42 
43 #define MX27_H1_PM_BIT			BIT(8)
44 #define MX27_H2_PM_BIT			BIT(16)
45 #define MX27_OTG_PM_BIT			BIT(24)
46 
47 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET	0x08
48 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET	0x0c
49 #define MX53_USB_UH2_CTRL_OFFSET	0x14
50 #define MX53_USB_UH3_CTRL_OFFSET	0x18
51 #define MX53_BM_OVER_CUR_DIS_H1		BIT(5)
52 #define MX53_BM_OVER_CUR_DIS_OTG	BIT(8)
53 #define MX53_BM_OVER_CUR_DIS_UHx	BIT(30)
54 #define MX53_USB_PHYCTRL1_PLLDIV_MASK	0x3
55 #define MX53_USB_PLL_DIV_24_MHZ		0x01
56 
57 #define MX6_BM_NON_BURST_SETTING	BIT(1)
58 #define MX6_BM_OVER_CUR_DIS		BIT(7)
59 #define MX6_BM_WAKEUP_ENABLE		BIT(10)
60 #define MX6_BM_ID_WAKEUP		BIT(16)
61 #define MX6_BM_VBUS_WAKEUP		BIT(17)
62 #define MX6SX_BM_DPDM_WAKEUP_EN		BIT(29)
63 #define MX6_BM_WAKEUP_INTR		BIT(31)
64 #define MX6_USB_OTG1_PHY_CTRL		0x18
65 /* For imx6dql, it is host-only controller, for later imx6, it is otg's */
66 #define MX6_USB_OTG2_PHY_CTRL		0x1c
67 #define MX6SX_USB_VBUS_WAKEUP_SOURCE(v)	(v << 8)
68 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS	MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
69 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID	MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
70 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID	MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
71 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END	MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
72 
73 #define VF610_OVER_CUR_DIS		BIT(7)
74 
75 #define MX7D_USBNC_USB_CTRL2		0x4
76 #define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK	0x3
77 #define MX7D_USB_VBUS_WAKEUP_SOURCE(v)		(v << 0)
78 #define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS	MX7D_USB_VBUS_WAKEUP_SOURCE(0)
79 #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID	MX7D_USB_VBUS_WAKEUP_SOURCE(1)
80 #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID	MX7D_USB_VBUS_WAKEUP_SOURCE(2)
81 #define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END	MX7D_USB_VBUS_WAKEUP_SOURCE(3)
82 
83 struct usbmisc_ops {
84 	/* It's called once when probe a usb device */
85 	int (*init)(struct imx_usbmisc_data *data);
86 	/* It's called once after adding a usb device */
87 	int (*post)(struct imx_usbmisc_data *data);
88 	/* It's called when we need to enable/disable usb wakeup */
89 	int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
90 };
91 
92 struct imx_usbmisc {
93 	void __iomem *base;
94 	spinlock_t lock;
95 	const struct usbmisc_ops *ops;
96 };
97 
98 static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
99 {
100 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
101 	unsigned long flags;
102 	u32 val = 0;
103 
104 	if (data->index > 1)
105 		return -EINVAL;
106 
107 	spin_lock_irqsave(&usbmisc->lock, flags);
108 	switch (data->index) {
109 	case 0:
110 		val = readl(usbmisc->base);
111 		val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
112 		val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
113 		val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
114 		writel(val, usbmisc->base);
115 		break;
116 	case 1:
117 		val = readl(usbmisc->base);
118 		val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT |  MX25_H1_IPPUE_UP_BIT);
119 		val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
120 		val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
121 			MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
122 
123 		writel(val, usbmisc->base);
124 
125 		break;
126 	}
127 	spin_unlock_irqrestore(&usbmisc->lock, flags);
128 
129 	return 0;
130 }
131 
132 static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
133 {
134 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
135 	void __iomem *reg;
136 	unsigned long flags;
137 	u32 val;
138 
139 	if (data->index > 2)
140 		return -EINVAL;
141 
142 	if (data->evdo) {
143 		spin_lock_irqsave(&usbmisc->lock, flags);
144 		reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
145 		val = readl(reg);
146 		writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg);
147 		spin_unlock_irqrestore(&usbmisc->lock, flags);
148 		usleep_range(5000, 10000); /* needed to stabilize voltage */
149 	}
150 
151 	return 0;
152 }
153 
154 static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
155 {
156 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
157 	unsigned long flags;
158 	u32 val;
159 
160 	switch (data->index) {
161 	case 0:
162 		val = MX27_OTG_PM_BIT;
163 		break;
164 	case 1:
165 		val = MX27_H1_PM_BIT;
166 		break;
167 	case 2:
168 		val = MX27_H2_PM_BIT;
169 		break;
170 	default:
171 		return -EINVAL;
172 	}
173 
174 	spin_lock_irqsave(&usbmisc->lock, flags);
175 	if (data->disable_oc)
176 		val = readl(usbmisc->base) | val;
177 	else
178 		val = readl(usbmisc->base) & ~val;
179 	writel(val, usbmisc->base);
180 	spin_unlock_irqrestore(&usbmisc->lock, flags);
181 
182 	return 0;
183 }
184 
185 static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
186 {
187 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
188 	void __iomem *reg = NULL;
189 	unsigned long flags;
190 	u32 val = 0;
191 
192 	if (data->index > 3)
193 		return -EINVAL;
194 
195 	/* Select a 24 MHz reference clock for the PHY  */
196 	val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
197 	val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
198 	val |= MX53_USB_PLL_DIV_24_MHZ;
199 	writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
200 
201 	if (data->disable_oc) {
202 		spin_lock_irqsave(&usbmisc->lock, flags);
203 		switch (data->index) {
204 		case 0:
205 			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
206 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
207 			break;
208 		case 1:
209 			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
210 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
211 			break;
212 		case 2:
213 			reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
214 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
215 			break;
216 		case 3:
217 			reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
218 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
219 			break;
220 		}
221 		if (reg && val)
222 			writel(val, reg);
223 		spin_unlock_irqrestore(&usbmisc->lock, flags);
224 	}
225 
226 	return 0;
227 }
228 
229 static int usbmisc_imx6q_set_wakeup
230 	(struct imx_usbmisc_data *data, bool enabled)
231 {
232 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
233 	unsigned long flags;
234 	u32 val;
235 	u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
236 		MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
237 	int ret = 0;
238 
239 	if (data->index > 3)
240 		return -EINVAL;
241 
242 	spin_lock_irqsave(&usbmisc->lock, flags);
243 	val = readl(usbmisc->base + data->index * 4);
244 	if (enabled) {
245 		val |= wakeup_setting;
246 		writel(val, usbmisc->base + data->index * 4);
247 	} else {
248 		if (val & MX6_BM_WAKEUP_INTR)
249 			pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
250 		val &= ~wakeup_setting;
251 		writel(val, usbmisc->base + data->index * 4);
252 	}
253 	spin_unlock_irqrestore(&usbmisc->lock, flags);
254 
255 	return ret;
256 }
257 
258 static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
259 {
260 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
261 	unsigned long flags;
262 	u32 reg;
263 
264 	if (data->index > 3)
265 		return -EINVAL;
266 
267 	spin_lock_irqsave(&usbmisc->lock, flags);
268 
269 	if (data->disable_oc) {
270 		reg = readl(usbmisc->base + data->index * 4);
271 		writel(reg | MX6_BM_OVER_CUR_DIS,
272 			usbmisc->base + data->index * 4);
273 	}
274 
275 	/* SoC non-burst setting */
276 	reg = readl(usbmisc->base + data->index * 4);
277 	writel(reg | MX6_BM_NON_BURST_SETTING,
278 			usbmisc->base + data->index * 4);
279 
280 	spin_unlock_irqrestore(&usbmisc->lock, flags);
281 
282 	usbmisc_imx6q_set_wakeup(data, false);
283 
284 	return 0;
285 }
286 
287 static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
288 {
289 	void __iomem *reg = NULL;
290 	unsigned long flags;
291 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
292 	u32 val;
293 
294 	usbmisc_imx6q_init(data);
295 
296 	if (data->index == 0 || data->index == 1) {
297 		reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
298 		spin_lock_irqsave(&usbmisc->lock, flags);
299 		/* Set vbus wakeup source as bvalid */
300 		val = readl(reg);
301 		writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
302 		/*
303 		 * Disable dp/dm wakeup in device mode when vbus is
304 		 * not there.
305 		 */
306 		val = readl(usbmisc->base + data->index * 4);
307 		writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
308 			usbmisc->base + data->index * 4);
309 		spin_unlock_irqrestore(&usbmisc->lock, flags);
310 	}
311 
312 	return 0;
313 }
314 
315 static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
316 {
317 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
318 	u32 reg;
319 
320 	/*
321 	 * Vybrid only has one misc register set, but in two different
322 	 * areas. These is reflected in two instances of this driver.
323 	 */
324 	if (data->index >= 1)
325 		return -EINVAL;
326 
327 	if (data->disable_oc) {
328 		reg = readl(usbmisc->base);
329 		writel(reg | VF610_OVER_CUR_DIS, usbmisc->base);
330 	}
331 
332 	return 0;
333 }
334 
335 static int usbmisc_imx7d_set_wakeup
336 	(struct imx_usbmisc_data *data, bool enabled)
337 {
338 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
339 	unsigned long flags;
340 	u32 val;
341 	u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
342 		MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
343 
344 	spin_lock_irqsave(&usbmisc->lock, flags);
345 	val = readl(usbmisc->base);
346 	if (enabled) {
347 		writel(val | wakeup_setting, usbmisc->base);
348 	} else {
349 		if (val & MX6_BM_WAKEUP_INTR)
350 			dev_dbg(data->dev, "wakeup int\n");
351 		writel(val & ~wakeup_setting, usbmisc->base);
352 	}
353 	spin_unlock_irqrestore(&usbmisc->lock, flags);
354 
355 	return 0;
356 }
357 
358 static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
359 {
360 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
361 	unsigned long flags;
362 	u32 reg;
363 
364 	if (data->index >= 1)
365 		return -EINVAL;
366 
367 	spin_lock_irqsave(&usbmisc->lock, flags);
368 	if (data->disable_oc) {
369 		reg = readl(usbmisc->base);
370 		writel(reg | MX6_BM_OVER_CUR_DIS, usbmisc->base);
371 	}
372 
373 	reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
374 	reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
375 	writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
376 		 usbmisc->base + MX7D_USBNC_USB_CTRL2);
377 	spin_unlock_irqrestore(&usbmisc->lock, flags);
378 
379 	usbmisc_imx7d_set_wakeup(data, false);
380 
381 	return 0;
382 }
383 
384 static const struct usbmisc_ops imx25_usbmisc_ops = {
385 	.init = usbmisc_imx25_init,
386 	.post = usbmisc_imx25_post,
387 };
388 
389 static const struct usbmisc_ops imx27_usbmisc_ops = {
390 	.init = usbmisc_imx27_init,
391 };
392 
393 static const struct usbmisc_ops imx53_usbmisc_ops = {
394 	.init = usbmisc_imx53_init,
395 };
396 
397 static const struct usbmisc_ops imx6q_usbmisc_ops = {
398 	.set_wakeup = usbmisc_imx6q_set_wakeup,
399 	.init = usbmisc_imx6q_init,
400 };
401 
402 static const struct usbmisc_ops vf610_usbmisc_ops = {
403 	.init = usbmisc_vf610_init,
404 };
405 
406 static const struct usbmisc_ops imx6sx_usbmisc_ops = {
407 	.set_wakeup = usbmisc_imx6q_set_wakeup,
408 	.init = usbmisc_imx6sx_init,
409 };
410 
411 static const struct usbmisc_ops imx7d_usbmisc_ops = {
412 	.init = usbmisc_imx7d_init,
413 	.set_wakeup = usbmisc_imx7d_set_wakeup,
414 };
415 
416 int imx_usbmisc_init(struct imx_usbmisc_data *data)
417 {
418 	struct imx_usbmisc *usbmisc;
419 
420 	if (!data)
421 		return 0;
422 
423 	usbmisc = dev_get_drvdata(data->dev);
424 	if (!usbmisc->ops->init)
425 		return 0;
426 	return usbmisc->ops->init(data);
427 }
428 EXPORT_SYMBOL_GPL(imx_usbmisc_init);
429 
430 int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
431 {
432 	struct imx_usbmisc *usbmisc;
433 
434 	if (!data)
435 		return 0;
436 
437 	usbmisc = dev_get_drvdata(data->dev);
438 	if (!usbmisc->ops->post)
439 		return 0;
440 	return usbmisc->ops->post(data);
441 }
442 EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
443 
444 int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
445 {
446 	struct imx_usbmisc *usbmisc;
447 
448 	if (!data)
449 		return 0;
450 
451 	usbmisc = dev_get_drvdata(data->dev);
452 	if (!usbmisc->ops->set_wakeup)
453 		return 0;
454 	return usbmisc->ops->set_wakeup(data, enabled);
455 }
456 EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
457 
458 static const struct of_device_id usbmisc_imx_dt_ids[] = {
459 	{
460 		.compatible = "fsl,imx25-usbmisc",
461 		.data = &imx25_usbmisc_ops,
462 	},
463 	{
464 		.compatible = "fsl,imx35-usbmisc",
465 		.data = &imx25_usbmisc_ops,
466 	},
467 	{
468 		.compatible = "fsl,imx27-usbmisc",
469 		.data = &imx27_usbmisc_ops,
470 	},
471 	{
472 		.compatible = "fsl,imx51-usbmisc",
473 		.data = &imx53_usbmisc_ops,
474 	},
475 	{
476 		.compatible = "fsl,imx53-usbmisc",
477 		.data = &imx53_usbmisc_ops,
478 	},
479 	{
480 		.compatible = "fsl,imx6q-usbmisc",
481 		.data = &imx6q_usbmisc_ops,
482 	},
483 	{
484 		.compatible = "fsl,vf610-usbmisc",
485 		.data = &vf610_usbmisc_ops,
486 	},
487 	{
488 		.compatible = "fsl,imx6sx-usbmisc",
489 		.data = &imx6sx_usbmisc_ops,
490 	},
491 	{
492 		.compatible = "fsl,imx6ul-usbmisc",
493 		.data = &imx6sx_usbmisc_ops,
494 	},
495 	{ /* sentinel */ }
496 };
497 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
498 
499 static int usbmisc_imx_probe(struct platform_device *pdev)
500 {
501 	struct resource	*res;
502 	struct imx_usbmisc *data;
503 	const struct of_device_id *of_id;
504 
505 	of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
506 	if (!of_id)
507 		return -ENODEV;
508 
509 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
510 	if (!data)
511 		return -ENOMEM;
512 
513 	spin_lock_init(&data->lock);
514 
515 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
516 	data->base = devm_ioremap_resource(&pdev->dev, res);
517 	if (IS_ERR(data->base))
518 		return PTR_ERR(data->base);
519 
520 	data->ops = (const struct usbmisc_ops *)of_id->data;
521 	platform_set_drvdata(pdev, data);
522 
523 	return 0;
524 }
525 
526 static int usbmisc_imx_remove(struct platform_device *pdev)
527 {
528 	return 0;
529 }
530 
531 static struct platform_driver usbmisc_imx_driver = {
532 	.probe = usbmisc_imx_probe,
533 	.remove = usbmisc_imx_remove,
534 	.driver = {
535 		.name = "usbmisc_imx",
536 		.of_match_table = usbmisc_imx_dt_ids,
537 	 },
538 };
539 
540 module_platform_driver(usbmisc_imx_driver);
541 
542 MODULE_ALIAS("platform:usbmisc-imx");
543 MODULE_LICENSE("GPL v2");
544 MODULE_DESCRIPTION("driver for imx usb non-core registers");
545 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
546