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