183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2f55c1538SÁlvaro Fernández Rojas /*
3*25d8380fSÁlvaro Fernández Rojas * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
4f55c1538SÁlvaro Fernández Rojas *
5f55c1538SÁlvaro Fernández Rojas * Derived from linux/arch/mips/bcm63xx/usb-common.c:
6f55c1538SÁlvaro Fernández Rojas * Copyright 2008 Maxime Bizon <mbizon@freebox.fr>
7f55c1538SÁlvaro Fernández Rojas * Copyright 2013 Florian Fainelli <florian@openwrt.org>
8f55c1538SÁlvaro Fernández Rojas */
9f55c1538SÁlvaro Fernández Rojas
10f55c1538SÁlvaro Fernández Rojas #include <common.h>
11f55c1538SÁlvaro Fernández Rojas #include <clk.h>
12f55c1538SÁlvaro Fernández Rojas #include <dm.h>
13f55c1538SÁlvaro Fernández Rojas #include <generic-phy.h>
14f55c1538SÁlvaro Fernández Rojas #include <power-domain.h>
15f55c1538SÁlvaro Fernández Rojas #include <reset.h>
16f55c1538SÁlvaro Fernández Rojas #include <asm/io.h>
17f55c1538SÁlvaro Fernández Rojas #include <dm/device.h>
18f55c1538SÁlvaro Fernández Rojas
19f55c1538SÁlvaro Fernández Rojas /* USBH PLL Control register */
20f55c1538SÁlvaro Fernández Rojas #define USBH_PLL_REG 0x18
21f55c1538SÁlvaro Fernández Rojas #define USBH_PLL_IDDQ_PWRDN BIT(9)
22f55c1538SÁlvaro Fernández Rojas #define USBH_PLL_PWRDN_DELAY BIT(10)
23f55c1538SÁlvaro Fernández Rojas
24f55c1538SÁlvaro Fernández Rojas /* USBH Swap Control register */
25f55c1538SÁlvaro Fernández Rojas #define USBH_SWAP_REG 0x1c
26f55c1538SÁlvaro Fernández Rojas #define USBH_SWAP_OHCI_DATA BIT(0)
27f55c1538SÁlvaro Fernández Rojas #define USBH_SWAP_OHCI_ENDIAN BIT(1)
28f55c1538SÁlvaro Fernández Rojas #define USBH_SWAP_EHCI_DATA BIT(3)
29f55c1538SÁlvaro Fernández Rojas #define USBH_SWAP_EHCI_ENDIAN BIT(4)
30f55c1538SÁlvaro Fernández Rojas
31f55c1538SÁlvaro Fernández Rojas /* USBH Setup register */
32f55c1538SÁlvaro Fernández Rojas #define USBH_SETUP_REG 0x28
33f55c1538SÁlvaro Fernández Rojas #define USBH_SETUP_IOC BIT(4)
34f55c1538SÁlvaro Fernández Rojas #define USBH_SETUP_IPP BIT(5)
35f55c1538SÁlvaro Fernández Rojas
36f55c1538SÁlvaro Fernández Rojas struct bcm6368_usbh_hw {
37f55c1538SÁlvaro Fernández Rojas uint32_t setup_clr;
38f55c1538SÁlvaro Fernández Rojas uint32_t pll_clr;
39f55c1538SÁlvaro Fernández Rojas };
40f55c1538SÁlvaro Fernández Rojas
41f55c1538SÁlvaro Fernández Rojas struct bcm6368_usbh_priv {
42f55c1538SÁlvaro Fernández Rojas const struct bcm6368_usbh_hw *hw;
43f55c1538SÁlvaro Fernández Rojas void __iomem *regs;
44f55c1538SÁlvaro Fernández Rojas };
45f55c1538SÁlvaro Fernández Rojas
bcm6368_usbh_init(struct phy * phy)46f55c1538SÁlvaro Fernández Rojas static int bcm6368_usbh_init(struct phy *phy)
47f55c1538SÁlvaro Fernández Rojas {
48f55c1538SÁlvaro Fernández Rojas struct bcm6368_usbh_priv *priv = dev_get_priv(phy->dev);
49f55c1538SÁlvaro Fernández Rojas const struct bcm6368_usbh_hw *hw = priv->hw;
50f55c1538SÁlvaro Fernández Rojas
51f55c1538SÁlvaro Fernández Rojas /* configure to work in native cpu endian */
52f55c1538SÁlvaro Fernández Rojas clrsetbits_be32(priv->regs + USBH_SWAP_REG,
53f55c1538SÁlvaro Fernández Rojas USBH_SWAP_EHCI_ENDIAN | USBH_SWAP_OHCI_ENDIAN,
54f55c1538SÁlvaro Fernández Rojas USBH_SWAP_EHCI_DATA | USBH_SWAP_OHCI_DATA);
55f55c1538SÁlvaro Fernández Rojas
56f55c1538SÁlvaro Fernández Rojas /* setup config */
57f55c1538SÁlvaro Fernández Rojas if (hw->setup_clr)
58f55c1538SÁlvaro Fernández Rojas clrbits_be32(priv->regs + USBH_SETUP_REG, hw->setup_clr);
59f55c1538SÁlvaro Fernández Rojas
60f55c1538SÁlvaro Fernández Rojas setbits_be32(priv->regs + USBH_SETUP_REG, USBH_SETUP_IOC);
61f55c1538SÁlvaro Fernández Rojas
62f55c1538SÁlvaro Fernández Rojas /* enable pll control */
63f55c1538SÁlvaro Fernández Rojas if (hw->pll_clr)
64f55c1538SÁlvaro Fernández Rojas clrbits_be32(priv->regs + USBH_PLL_REG, hw->pll_clr);
65f55c1538SÁlvaro Fernández Rojas
66f55c1538SÁlvaro Fernández Rojas return 0;
67f55c1538SÁlvaro Fernández Rojas }
68f55c1538SÁlvaro Fernández Rojas
69f55c1538SÁlvaro Fernández Rojas static struct phy_ops bcm6368_usbh_ops = {
70f55c1538SÁlvaro Fernández Rojas .init = bcm6368_usbh_init,
71f55c1538SÁlvaro Fernández Rojas };
72f55c1538SÁlvaro Fernández Rojas
73f55c1538SÁlvaro Fernández Rojas static const struct bcm6368_usbh_hw bcm6328_hw = {
74f55c1538SÁlvaro Fernández Rojas .pll_clr = USBH_PLL_IDDQ_PWRDN | USBH_PLL_PWRDN_DELAY,
75f55c1538SÁlvaro Fernández Rojas .setup_clr = 0,
76f55c1538SÁlvaro Fernández Rojas };
77f55c1538SÁlvaro Fernández Rojas
78f55c1538SÁlvaro Fernández Rojas static const struct bcm6368_usbh_hw bcm6362_hw = {
79f55c1538SÁlvaro Fernández Rojas .pll_clr = 0,
80f55c1538SÁlvaro Fernández Rojas .setup_clr = 0,
81f55c1538SÁlvaro Fernández Rojas };
82f55c1538SÁlvaro Fernández Rojas
83f55c1538SÁlvaro Fernández Rojas static const struct bcm6368_usbh_hw bcm6368_hw = {
84f55c1538SÁlvaro Fernández Rojas .pll_clr = 0,
85f55c1538SÁlvaro Fernández Rojas .setup_clr = 0,
86f55c1538SÁlvaro Fernández Rojas };
87f55c1538SÁlvaro Fernández Rojas
88f55c1538SÁlvaro Fernández Rojas static const struct bcm6368_usbh_hw bcm63268_hw = {
89f55c1538SÁlvaro Fernández Rojas .pll_clr = USBH_PLL_IDDQ_PWRDN | USBH_PLL_PWRDN_DELAY,
90f55c1538SÁlvaro Fernández Rojas .setup_clr = USBH_SETUP_IPP,
91f55c1538SÁlvaro Fernández Rojas };
92f55c1538SÁlvaro Fernández Rojas
93f55c1538SÁlvaro Fernández Rojas static const struct udevice_id bcm6368_usbh_ids[] = {
94f55c1538SÁlvaro Fernández Rojas {
95f55c1538SÁlvaro Fernández Rojas .compatible = "brcm,bcm6328-usbh",
96f55c1538SÁlvaro Fernández Rojas .data = (ulong)&bcm6328_hw,
97f55c1538SÁlvaro Fernández Rojas }, {
98f55c1538SÁlvaro Fernández Rojas .compatible = "brcm,bcm6362-usbh",
99f55c1538SÁlvaro Fernández Rojas .data = (ulong)&bcm6362_hw,
100f55c1538SÁlvaro Fernández Rojas }, {
101f55c1538SÁlvaro Fernández Rojas .compatible = "brcm,bcm6368-usbh",
102f55c1538SÁlvaro Fernández Rojas .data = (ulong)&bcm6368_hw,
103f55c1538SÁlvaro Fernández Rojas }, {
104f55c1538SÁlvaro Fernández Rojas .compatible = "brcm,bcm63268-usbh",
105f55c1538SÁlvaro Fernández Rojas .data = (ulong)&bcm63268_hw,
106f55c1538SÁlvaro Fernández Rojas }, { /* sentinel */ }
107f55c1538SÁlvaro Fernández Rojas };
108f55c1538SÁlvaro Fernández Rojas
bcm6368_usbh_probe(struct udevice * dev)109f55c1538SÁlvaro Fernández Rojas static int bcm6368_usbh_probe(struct udevice *dev)
110f55c1538SÁlvaro Fernández Rojas {
111f55c1538SÁlvaro Fernández Rojas struct bcm6368_usbh_priv *priv = dev_get_priv(dev);
112f55c1538SÁlvaro Fernández Rojas const struct bcm6368_usbh_hw *hw =
113f55c1538SÁlvaro Fernández Rojas (const struct bcm6368_usbh_hw *)dev_get_driver_data(dev);
114f55c1538SÁlvaro Fernández Rojas #if defined(CONFIG_POWER_DOMAIN)
115f55c1538SÁlvaro Fernández Rojas struct power_domain pwr_dom;
116f55c1538SÁlvaro Fernández Rojas #endif
117f55c1538SÁlvaro Fernández Rojas struct reset_ctl rst_ctl;
118f55c1538SÁlvaro Fernández Rojas struct clk clk;
119f55c1538SÁlvaro Fernández Rojas int ret;
120f55c1538SÁlvaro Fernández Rojas
121*25d8380fSÁlvaro Fernández Rojas priv->regs = dev_remap_addr(dev);
122*25d8380fSÁlvaro Fernández Rojas if (!priv->regs)
123f55c1538SÁlvaro Fernández Rojas return -EINVAL;
124f55c1538SÁlvaro Fernández Rojas
125f55c1538SÁlvaro Fernández Rojas priv->hw = hw;
126f55c1538SÁlvaro Fernández Rojas
127f55c1538SÁlvaro Fernández Rojas /* enable usbh clock */
128f55c1538SÁlvaro Fernández Rojas ret = clk_get_by_name(dev, "usbh", &clk);
129f55c1538SÁlvaro Fernández Rojas if (ret < 0)
130f55c1538SÁlvaro Fernández Rojas return ret;
131f55c1538SÁlvaro Fernández Rojas
132f55c1538SÁlvaro Fernández Rojas ret = clk_enable(&clk);
133f55c1538SÁlvaro Fernández Rojas if (ret < 0)
134f55c1538SÁlvaro Fernández Rojas return ret;
135f55c1538SÁlvaro Fernández Rojas
136f55c1538SÁlvaro Fernández Rojas ret = clk_free(&clk);
137f55c1538SÁlvaro Fernández Rojas if (ret < 0)
138f55c1538SÁlvaro Fernández Rojas return ret;
139f55c1538SÁlvaro Fernández Rojas
140f55c1538SÁlvaro Fernández Rojas #if defined(CONFIG_POWER_DOMAIN)
141f55c1538SÁlvaro Fernández Rojas /* enable power domain */
142f55c1538SÁlvaro Fernández Rojas ret = power_domain_get(dev, &pwr_dom);
143f55c1538SÁlvaro Fernández Rojas if (ret < 0)
144f55c1538SÁlvaro Fernández Rojas return ret;
145f55c1538SÁlvaro Fernández Rojas
146f55c1538SÁlvaro Fernández Rojas ret = power_domain_on(&pwr_dom);
147f55c1538SÁlvaro Fernández Rojas if (ret < 0)
148f55c1538SÁlvaro Fernández Rojas return ret;
149f55c1538SÁlvaro Fernández Rojas
150f55c1538SÁlvaro Fernández Rojas ret = power_domain_free(&pwr_dom);
151f55c1538SÁlvaro Fernández Rojas if (ret < 0)
152f55c1538SÁlvaro Fernández Rojas return ret;
153f55c1538SÁlvaro Fernández Rojas #endif
154f55c1538SÁlvaro Fernández Rojas
155f55c1538SÁlvaro Fernández Rojas /* perform reset */
156f55c1538SÁlvaro Fernández Rojas ret = reset_get_by_index(dev, 0, &rst_ctl);
157f55c1538SÁlvaro Fernández Rojas if (ret < 0)
158f55c1538SÁlvaro Fernández Rojas return ret;
159f55c1538SÁlvaro Fernández Rojas
160f55c1538SÁlvaro Fernández Rojas ret = reset_deassert(&rst_ctl);
161f55c1538SÁlvaro Fernández Rojas if (ret < 0)
162f55c1538SÁlvaro Fernández Rojas return ret;
163f55c1538SÁlvaro Fernández Rojas
164f55c1538SÁlvaro Fernández Rojas ret = reset_free(&rst_ctl);
165f55c1538SÁlvaro Fernández Rojas if (ret < 0)
166f55c1538SÁlvaro Fernández Rojas return ret;
167f55c1538SÁlvaro Fernández Rojas
168f55c1538SÁlvaro Fernández Rojas /* enable usb_ref clock */
169f55c1538SÁlvaro Fernández Rojas ret = clk_get_by_name(dev, "usb_ref", &clk);
170f55c1538SÁlvaro Fernández Rojas if (!ret) {
171f55c1538SÁlvaro Fernández Rojas ret = clk_enable(&clk);
172f55c1538SÁlvaro Fernández Rojas if (ret < 0)
173f55c1538SÁlvaro Fernández Rojas return ret;
174f55c1538SÁlvaro Fernández Rojas
175f55c1538SÁlvaro Fernández Rojas ret = clk_free(&clk);
176f55c1538SÁlvaro Fernández Rojas if (ret < 0)
177f55c1538SÁlvaro Fernández Rojas return ret;
178f55c1538SÁlvaro Fernández Rojas }
179f55c1538SÁlvaro Fernández Rojas
180f55c1538SÁlvaro Fernández Rojas mdelay(100);
181f55c1538SÁlvaro Fernández Rojas
182f55c1538SÁlvaro Fernández Rojas return 0;
183f55c1538SÁlvaro Fernández Rojas }
184f55c1538SÁlvaro Fernández Rojas
185f55c1538SÁlvaro Fernández Rojas U_BOOT_DRIVER(bcm6368_usbh) = {
186f55c1538SÁlvaro Fernández Rojas .name = "bcm6368-usbh",
187f55c1538SÁlvaro Fernández Rojas .id = UCLASS_PHY,
188f55c1538SÁlvaro Fernández Rojas .of_match = bcm6368_usbh_ids,
189f55c1538SÁlvaro Fernández Rojas .ops = &bcm6368_usbh_ops,
190f55c1538SÁlvaro Fernández Rojas .priv_auto_alloc_size = sizeof(struct bcm6368_usbh_priv),
191f55c1538SÁlvaro Fernández Rojas .probe = bcm6368_usbh_probe,
192f55c1538SÁlvaro Fernández Rojas };
193