1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2f55c1538SÁlvaro Fernández Rojas /* 3f55c1538SÁ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 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 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 fdt_addr_t addr; 120f55c1538SÁlvaro Fernández Rojas fdt_size_t size; 121f55c1538SÁlvaro Fernández Rojas int ret; 122f55c1538SÁlvaro Fernández Rojas 123f55c1538SÁlvaro Fernández Rojas addr = devfdt_get_addr_size_index(dev, 0, &size); 124f55c1538SÁlvaro Fernández Rojas if (addr == FDT_ADDR_T_NONE) 125f55c1538SÁlvaro Fernández Rojas return -EINVAL; 126f55c1538SÁlvaro Fernández Rojas 127f55c1538SÁlvaro Fernández Rojas priv->regs = ioremap(addr, size); 128f55c1538SÁlvaro Fernández Rojas priv->hw = hw; 129f55c1538SÁlvaro Fernández Rojas 130f55c1538SÁlvaro Fernández Rojas /* enable usbh clock */ 131f55c1538SÁlvaro Fernández Rojas ret = clk_get_by_name(dev, "usbh", &clk); 132f55c1538SÁlvaro Fernández Rojas if (ret < 0) 133f55c1538SÁlvaro Fernández Rojas return ret; 134f55c1538SÁlvaro Fernández Rojas 135f55c1538SÁlvaro Fernández Rojas ret = clk_enable(&clk); 136f55c1538SÁlvaro Fernández Rojas if (ret < 0) 137f55c1538SÁlvaro Fernández Rojas return ret; 138f55c1538SÁlvaro Fernández Rojas 139f55c1538SÁlvaro Fernández Rojas ret = clk_free(&clk); 140f55c1538SÁlvaro Fernández Rojas if (ret < 0) 141f55c1538SÁlvaro Fernández Rojas return ret; 142f55c1538SÁlvaro Fernández Rojas 143f55c1538SÁlvaro Fernández Rojas #if defined(CONFIG_POWER_DOMAIN) 144f55c1538SÁlvaro Fernández Rojas /* enable power domain */ 145f55c1538SÁlvaro Fernández Rojas ret = power_domain_get(dev, &pwr_dom); 146f55c1538SÁlvaro Fernández Rojas if (ret < 0) 147f55c1538SÁlvaro Fernández Rojas return ret; 148f55c1538SÁlvaro Fernández Rojas 149f55c1538SÁlvaro Fernández Rojas ret = power_domain_on(&pwr_dom); 150f55c1538SÁlvaro Fernández Rojas if (ret < 0) 151f55c1538SÁlvaro Fernández Rojas return ret; 152f55c1538SÁlvaro Fernández Rojas 153f55c1538SÁlvaro Fernández Rojas ret = power_domain_free(&pwr_dom); 154f55c1538SÁlvaro Fernández Rojas if (ret < 0) 155f55c1538SÁlvaro Fernández Rojas return ret; 156f55c1538SÁlvaro Fernández Rojas #endif 157f55c1538SÁlvaro Fernández Rojas 158f55c1538SÁlvaro Fernández Rojas /* perform reset */ 159f55c1538SÁlvaro Fernández Rojas ret = reset_get_by_index(dev, 0, &rst_ctl); 160f55c1538SÁlvaro Fernández Rojas if (ret < 0) 161f55c1538SÁlvaro Fernández Rojas return ret; 162f55c1538SÁlvaro Fernández Rojas 163f55c1538SÁlvaro Fernández Rojas ret = reset_deassert(&rst_ctl); 164f55c1538SÁlvaro Fernández Rojas if (ret < 0) 165f55c1538SÁlvaro Fernández Rojas return ret; 166f55c1538SÁlvaro Fernández Rojas 167f55c1538SÁlvaro Fernández Rojas ret = reset_free(&rst_ctl); 168f55c1538SÁlvaro Fernández Rojas if (ret < 0) 169f55c1538SÁlvaro Fernández Rojas return ret; 170f55c1538SÁlvaro Fernández Rojas 171f55c1538SÁlvaro Fernández Rojas /* enable usb_ref clock */ 172f55c1538SÁlvaro Fernández Rojas ret = clk_get_by_name(dev, "usb_ref", &clk); 173f55c1538SÁlvaro Fernández Rojas if (!ret) { 174f55c1538SÁlvaro Fernández Rojas ret = clk_enable(&clk); 175f55c1538SÁlvaro Fernández Rojas if (ret < 0) 176f55c1538SÁlvaro Fernández Rojas return ret; 177f55c1538SÁlvaro Fernández Rojas 178f55c1538SÁlvaro Fernández Rojas ret = clk_free(&clk); 179f55c1538SÁlvaro Fernández Rojas if (ret < 0) 180f55c1538SÁlvaro Fernández Rojas return ret; 181f55c1538SÁlvaro Fernández Rojas } 182f55c1538SÁlvaro Fernández Rojas 183f55c1538SÁlvaro Fernández Rojas mdelay(100); 184f55c1538SÁlvaro Fernández Rojas 185f55c1538SÁlvaro Fernández Rojas return 0; 186f55c1538SÁlvaro Fernández Rojas } 187f55c1538SÁlvaro Fernández Rojas 188f55c1538SÁlvaro Fernández Rojas U_BOOT_DRIVER(bcm6368_usbh) = { 189f55c1538SÁlvaro Fernández Rojas .name = "bcm6368-usbh", 190f55c1538SÁlvaro Fernández Rojas .id = UCLASS_PHY, 191f55c1538SÁlvaro Fernández Rojas .of_match = bcm6368_usbh_ids, 192f55c1538SÁlvaro Fernández Rojas .ops = &bcm6368_usbh_ops, 193f55c1538SÁlvaro Fernández Rojas .priv_auto_alloc_size = sizeof(struct bcm6368_usbh_priv), 194f55c1538SÁlvaro Fernández Rojas .probe = bcm6368_usbh_probe, 195f55c1538SÁlvaro Fernández Rojas }; 196