xref: /rk3399_rockchip-uboot/drivers/usb/host/ehci-marvell.c (revision 1a4f6af8bfd44c8ae6e87a81ff125eed47042cc5)
1a14bd417SAlbert ARIBAUD /*
2a14bd417SAlbert ARIBAUD  * (C) Copyright 2009
3a14bd417SAlbert ARIBAUD  * Marvell Semiconductor <www.marvell.com>
4a14bd417SAlbert ARIBAUD  * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
5a14bd417SAlbert ARIBAUD  *
61a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
7a14bd417SAlbert ARIBAUD  */
8a14bd417SAlbert ARIBAUD 
9a14bd417SAlbert ARIBAUD #include <common.h>
10a14bd417SAlbert ARIBAUD #include <asm/io.h>
11a14bd417SAlbert ARIBAUD #include <usb.h>
12a14bd417SAlbert ARIBAUD #include "ehci.h"
13fe11ae24SStefan Roese #include <linux/mbus.h>
14a14bd417SAlbert ARIBAUD #include <asm/arch/cpu.h>
15cd48225bSStefan Roese #include <dm.h>
16805ad7eeSAlbert ARIBAUD 
17805ad7eeSAlbert ARIBAUD #if defined(CONFIG_KIRKWOOD)
183dc23f78SStefan Roese #include <asm/arch/soc.h>
19805ad7eeSAlbert ARIBAUD #elif defined(CONFIG_ORION5X)
20805ad7eeSAlbert ARIBAUD #include <asm/arch/orion5x.h>
21805ad7eeSAlbert ARIBAUD #endif
22a14bd417SAlbert ARIBAUD 
2374d34421SAlbert ARIBAUD DECLARE_GLOBAL_DATA_PTR;
2474d34421SAlbert ARIBAUD 
25a14bd417SAlbert ARIBAUD #define USB_WINDOW_CTRL(i)	(0x320 + ((i) << 4))
26a14bd417SAlbert ARIBAUD #define USB_WINDOW_BASE(i)	(0x324 + ((i) << 4))
27a14bd417SAlbert ARIBAUD #define USB_TARGET_DRAM		0x0
28a14bd417SAlbert ARIBAUD 
29c6cfcc91SStefan Roese #define USB2_SBUSCFG_OFF	0x90
30c6cfcc91SStefan Roese 
31c6cfcc91SStefan Roese #define USB_SBUSCFG_BAWR_OFF	0x6
32c6cfcc91SStefan Roese #define USB_SBUSCFG_BARD_OFF	0x3
33c6cfcc91SStefan Roese #define USB_SBUSCFG_AHBBRST_OFF	0x0
34c6cfcc91SStefan Roese 
35c6cfcc91SStefan Roese #define USB_SBUSCFG_BAWR_ALIGN_64B	0x4
36c6cfcc91SStefan Roese #define USB_SBUSCFG_BARD_ALIGN_64B	0x4
37c6cfcc91SStefan Roese #define USB_SBUSCFG_AHBBRST_INCR16	0x7
38c6cfcc91SStefan Roese 
39a14bd417SAlbert ARIBAUD /*
40a14bd417SAlbert ARIBAUD  * USB 2.0 Bridge Address Decoding registers setup
41a14bd417SAlbert ARIBAUD  */
42*3739bf7eSSven Schwermer #if CONFIG_IS_ENABLED(DM_USB)
43fe11ae24SStefan Roese 
44cd48225bSStefan Roese struct ehci_mvebu_priv {
45cd48225bSStefan Roese 	struct ehci_ctrl ehci;
46cd48225bSStefan Roese 	fdt_addr_t hcd_base;
47cd48225bSStefan Roese };
48fe11ae24SStefan Roese 
49fe11ae24SStefan Roese /*
50fe11ae24SStefan Roese  * Once all the older Marvell SoC's (Orion, Kirkwood) are converted
51fe11ae24SStefan Roese  * to the common mvebu archticture including the mbus setup, this
52fe11ae24SStefan Roese  * will be the only function needed to configure the access windows
53fe11ae24SStefan Roese  */
usb_brg_adrdec_setup(void * base)54c6cfcc91SStefan Roese static void usb_brg_adrdec_setup(void *base)
55fe11ae24SStefan Roese {
56fe11ae24SStefan Roese 	const struct mbus_dram_target_info *dram;
57fe11ae24SStefan Roese 	int i;
58fe11ae24SStefan Roese 
59fe11ae24SStefan Roese 	dram = mvebu_mbus_dram_info();
60fe11ae24SStefan Roese 
61fe11ae24SStefan Roese 	for (i = 0; i < 4; i++) {
62cd48225bSStefan Roese 		writel(0, base + USB_WINDOW_CTRL(i));
63cd48225bSStefan Roese 		writel(0, base + USB_WINDOW_BASE(i));
64fe11ae24SStefan Roese 	}
65fe11ae24SStefan Roese 
66fe11ae24SStefan Roese 	for (i = 0; i < dram->num_cs; i++) {
67fe11ae24SStefan Roese 		const struct mbus_dram_window *cs = dram->cs + i;
68fe11ae24SStefan Roese 
69fe11ae24SStefan Roese 		/* Write size, attributes and target id to control register */
7082b9143bSStefan Roese 		writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
7182b9143bSStefan Roese 		       (dram->mbus_dram_target_id << 4) | 1,
72cd48225bSStefan Roese 		       base + USB_WINDOW_CTRL(i));
73fe11ae24SStefan Roese 
74fe11ae24SStefan Roese 		/* Write base address to base register */
75cd48225bSStefan Roese 		writel(cs->base, base + USB_WINDOW_BASE(i));
76fe11ae24SStefan Roese 	}
77fe11ae24SStefan Roese }
78cd48225bSStefan Roese 
marvell_ehci_powerup_fixup(struct ehci_ctrl * ctrl,uint32_t * status_reg,uint32_t * reg)79c6cfcc91SStefan Roese static void marvell_ehci_powerup_fixup(struct ehci_ctrl *ctrl,
80c6cfcc91SStefan Roese 				       uint32_t *status_reg, uint32_t *reg)
81c6cfcc91SStefan Roese {
82c6cfcc91SStefan Roese 	struct ehci_mvebu_priv *priv = ctrl->priv;
83c6cfcc91SStefan Roese 
84c6cfcc91SStefan Roese 	/*
85c6cfcc91SStefan Roese 	 * Set default value for reg SBUSCFG, which is Control for the AMBA
86c6cfcc91SStefan Roese 	 * system bus interface:
87c6cfcc91SStefan Roese 	 * BAWR = BARD = 4 : Align rd/wr bursts packets larger than 64 bytes
88c6cfcc91SStefan Roese 	 * AHBBRST = 7     : Align AHB burst for packets larger than 64 bytes
89c6cfcc91SStefan Roese 	 */
90c6cfcc91SStefan Roese 	writel((USB_SBUSCFG_BAWR_ALIGN_64B << USB_SBUSCFG_BAWR_OFF) |
91c6cfcc91SStefan Roese 	       (USB_SBUSCFG_BARD_ALIGN_64B << USB_SBUSCFG_BARD_OFF) |
92c6cfcc91SStefan Roese 	       (USB_SBUSCFG_AHBBRST_INCR16 << USB_SBUSCFG_AHBBRST_OFF),
93c6cfcc91SStefan Roese 	       priv->hcd_base + USB2_SBUSCFG_OFF);
94c6cfcc91SStefan Roese 
95c6cfcc91SStefan Roese 	mdelay(50);
96c6cfcc91SStefan Roese }
97c6cfcc91SStefan Roese 
98c6cfcc91SStefan Roese static struct ehci_ops marvell_ehci_ops = {
99c6cfcc91SStefan Roese 	.powerup_fixup	= NULL,
100c6cfcc91SStefan Roese };
101c6cfcc91SStefan Roese 
ehci_mvebu_probe(struct udevice * dev)102cd48225bSStefan Roese static int ehci_mvebu_probe(struct udevice *dev)
103cd48225bSStefan Roese {
104cd48225bSStefan Roese 	struct ehci_mvebu_priv *priv = dev_get_priv(dev);
105cd48225bSStefan Roese 	struct ehci_hccr *hccr;
106cd48225bSStefan Roese 	struct ehci_hcor *hcor;
107cd48225bSStefan Roese 
108cd48225bSStefan Roese 	/*
109cd48225bSStefan Roese 	 * Get the base address for EHCI controller from the device node
110cd48225bSStefan Roese 	 */
111a821c4afSSimon Glass 	priv->hcd_base = devfdt_get_addr(dev);
112cd48225bSStefan Roese 	if (priv->hcd_base == FDT_ADDR_T_NONE) {
113cd48225bSStefan Roese 		debug("Can't get the EHCI register base address\n");
114cd48225bSStefan Roese 		return -ENXIO;
115cd48225bSStefan Roese 	}
116cd48225bSStefan Roese 
117c6cfcc91SStefan Roese 	/*
118c6cfcc91SStefan Roese 	 * For SoCs without hlock like Armada3700 we need to program the sbuscfg
119c6cfcc91SStefan Roese 	 * reg to guarantee AHB master's burst will not overrun or underrun
120c6cfcc91SStefan Roese 	 * the FIFO. Otherwise all USB2 write option will fail.
121c6cfcc91SStefan Roese 	 * Also, the address decoder doesn't need to get setup with this
122c6cfcc91SStefan Roese 	 * SoC, so don't call usb_brg_adrdec_setup().
123c6cfcc91SStefan Roese 	 */
124911f3aefSSimon Glass 	if (device_is_compatible(dev, "marvell,armada3700-ehci"))
125c6cfcc91SStefan Roese 		marvell_ehci_ops.powerup_fixup = marvell_ehci_powerup_fixup;
126c6cfcc91SStefan Roese 	else
127c6cfcc91SStefan Roese 		usb_brg_adrdec_setup((void *)priv->hcd_base);
128cd48225bSStefan Roese 
129cd48225bSStefan Roese 	hccr = (struct ehci_hccr *)(priv->hcd_base + 0x100);
130cd48225bSStefan Roese 	hcor = (struct ehci_hcor *)
131c6cfcc91SStefan Roese 		((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
132cd48225bSStefan Roese 
133c6cfcc91SStefan Roese 	debug("ehci-marvell: init hccr %lx and hcor %lx hc_length %ld\n",
134c6cfcc91SStefan Roese 	      (uintptr_t)hccr, (uintptr_t)hcor,
135c6cfcc91SStefan Roese 	      (uintptr_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
136cd48225bSStefan Roese 
137c6cfcc91SStefan Roese 	return ehci_register(dev, hccr, hcor, &marvell_ehci_ops, 0,
138c6cfcc91SStefan Roese 			     USB_INIT_HOST);
139cd48225bSStefan Roese }
140cd48225bSStefan Roese 
141cd48225bSStefan Roese static const struct udevice_id ehci_usb_ids[] = {
142cd48225bSStefan Roese 	{ .compatible = "marvell,orion-ehci", },
143c6cfcc91SStefan Roese 	{ .compatible = "marvell,armada3700-ehci", },
144cd48225bSStefan Roese 	{ }
145cd48225bSStefan Roese };
146cd48225bSStefan Roese 
147cd48225bSStefan Roese U_BOOT_DRIVER(ehci_mvebu) = {
148cd48225bSStefan Roese 	.name	= "ehci_mvebu",
149cd48225bSStefan Roese 	.id	= UCLASS_USB,
150cd48225bSStefan Roese 	.of_match = ehci_usb_ids,
151cd48225bSStefan Roese 	.probe = ehci_mvebu_probe,
15240527342SMasahiro Yamada 	.remove = ehci_deregister,
153cd48225bSStefan Roese 	.ops	= &ehci_usb_ops,
154cd48225bSStefan Roese 	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
155cd48225bSStefan Roese 	.priv_auto_alloc_size = sizeof(struct ehci_mvebu_priv),
156cd48225bSStefan Roese 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
157cd48225bSStefan Roese };
158cd48225bSStefan Roese 
159fe11ae24SStefan Roese #else
1608a333716SAnton Schubert #define MVUSB_BASE(port)	MVUSB0_BASE
1618a333716SAnton Schubert 
usb_brg_adrdec_setup(int index)1628a333716SAnton Schubert static void usb_brg_adrdec_setup(int index)
163a14bd417SAlbert ARIBAUD {
164a14bd417SAlbert ARIBAUD 	int i;
16574d34421SAlbert ARIBAUD 	u32 size, base, attrib;
166a14bd417SAlbert ARIBAUD 
167a14bd417SAlbert ARIBAUD 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
168a14bd417SAlbert ARIBAUD 
169a14bd417SAlbert ARIBAUD 		/* Enable DRAM bank */
170a14bd417SAlbert ARIBAUD 		switch (i) {
171a14bd417SAlbert ARIBAUD 		case 0:
17274d34421SAlbert ARIBAUD 			attrib = MVUSB0_CPU_ATTR_DRAM_CS0;
173a14bd417SAlbert ARIBAUD 			break;
174a14bd417SAlbert ARIBAUD 		case 1:
17574d34421SAlbert ARIBAUD 			attrib = MVUSB0_CPU_ATTR_DRAM_CS1;
176a14bd417SAlbert ARIBAUD 			break;
177a14bd417SAlbert ARIBAUD 		case 2:
17874d34421SAlbert ARIBAUD 			attrib = MVUSB0_CPU_ATTR_DRAM_CS2;
179a14bd417SAlbert ARIBAUD 			break;
180a14bd417SAlbert ARIBAUD 		case 3:
18174d34421SAlbert ARIBAUD 			attrib = MVUSB0_CPU_ATTR_DRAM_CS3;
182a14bd417SAlbert ARIBAUD 			break;
183a14bd417SAlbert ARIBAUD 		default:
184a14bd417SAlbert ARIBAUD 			/* invalide bank, disable access */
185a14bd417SAlbert ARIBAUD 			attrib = 0;
186a14bd417SAlbert ARIBAUD 			break;
187a14bd417SAlbert ARIBAUD 		}
188a14bd417SAlbert ARIBAUD 
18974d34421SAlbert ARIBAUD 		size = gd->bd->bi_dram[i].size;
19074d34421SAlbert ARIBAUD 		base = gd->bd->bi_dram[i].start;
191a14bd417SAlbert ARIBAUD 		if ((size) && (attrib))
19282b9143bSStefan Roese 			writel(MVCPU_WIN_CTRL_DATA(size, USB_TARGET_DRAM,
19382b9143bSStefan Roese 						   attrib, MVCPU_WIN_ENABLE),
19482b9143bSStefan Roese 				MVUSB0_BASE + USB_WINDOW_CTRL(i));
195a14bd417SAlbert ARIBAUD 		else
19682b9143bSStefan Roese 			writel(MVCPU_WIN_DISABLE,
19782b9143bSStefan Roese 			       MVUSB0_BASE + USB_WINDOW_CTRL(i));
198a14bd417SAlbert ARIBAUD 
19982b9143bSStefan Roese 		writel(base, MVUSB0_BASE + USB_WINDOW_BASE(i));
200a14bd417SAlbert ARIBAUD 	}
201a14bd417SAlbert ARIBAUD }
202a14bd417SAlbert ARIBAUD 
203a14bd417SAlbert ARIBAUD /*
204a14bd417SAlbert ARIBAUD  * Create the appropriate control structures to manage
205a14bd417SAlbert ARIBAUD  * a new EHCI host controller.
206a14bd417SAlbert ARIBAUD  */
ehci_hcd_init(int index,enum usb_init_type init,struct ehci_hccr ** hccr,struct ehci_hcor ** hcor)207127efc4fSTroy Kisky int ehci_hcd_init(int index, enum usb_init_type init,
208127efc4fSTroy Kisky 		struct ehci_hccr **hccr, struct ehci_hcor **hcor)
209a14bd417SAlbert ARIBAUD {
2108a333716SAnton Schubert 	usb_brg_adrdec_setup(index);
211a14bd417SAlbert ARIBAUD 
2128a333716SAnton Schubert 	*hccr = (struct ehci_hccr *)(MVUSB_BASE(index) + 0x100);
213676ae068SLucas Stach 	*hcor = (struct ehci_hcor *)((uint32_t) *hccr
214676ae068SLucas Stach 			+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
215a14bd417SAlbert ARIBAUD 
21674d34421SAlbert ARIBAUD 	debug("ehci-marvell: init hccr %x and hcor %x hc_length %d\n",
217676ae068SLucas Stach 		(uint32_t)*hccr, (uint32_t)*hcor,
218676ae068SLucas Stach 		(uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
219a14bd417SAlbert ARIBAUD 
220a14bd417SAlbert ARIBAUD 	return 0;
221a14bd417SAlbert ARIBAUD }
222a14bd417SAlbert ARIBAUD 
223a14bd417SAlbert ARIBAUD /*
224a14bd417SAlbert ARIBAUD  * Destroy the appropriate control structures corresponding
225a14bd417SAlbert ARIBAUD  * the the EHCI host controller.
226a14bd417SAlbert ARIBAUD  */
ehci_hcd_stop(int index)227676ae068SLucas Stach int ehci_hcd_stop(int index)
228a14bd417SAlbert ARIBAUD {
229a14bd417SAlbert ARIBAUD 	return 0;
230a14bd417SAlbert ARIBAUD }
231cd48225bSStefan Roese 
232*3739bf7eSSven Schwermer #endif /* CONFIG_IS_ENABLED(DM_USB) */
233