1 /* 2 * Sunxi ehci glue 3 * 4 * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com> 5 * Copyright (C) 2014 Roman Byshko <rbyshko@gmail.com> 6 * 7 * Based on code from 8 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> 9 * 10 * SPDX-License-Identifier: GPL-2.0+ 11 */ 12 13 #include <common.h> 14 #include <asm/arch/clock.h> 15 #include <asm/arch/usb_phy.h> 16 #include <asm/io.h> 17 #include <dm.h> 18 #include "ehci.h" 19 20 struct ehci_sunxi_priv { 21 struct ehci_ctrl ehci; 22 int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ 23 int phy_index; /* Index of the usb-phy attached to this hcd */ 24 }; 25 26 static int ehci_usb_probe(struct udevice *dev) 27 { 28 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 29 struct usb_platdata *plat = dev_get_platdata(dev); 30 struct ehci_sunxi_priv *priv = dev_get_priv(dev); 31 struct ehci_hccr *hccr = (struct ehci_hccr *)dev_get_addr(dev); 32 struct ehci_hcor *hcor; 33 34 /* 35 * This should go away once we've moved to the driver model for 36 * clocks resp. phys. 37 */ 38 if (hccr == (void *)SUNXI_USB1_BASE) { 39 priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0; 40 priv->phy_index = 1; 41 } else { 42 priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI1; 43 priv->phy_index = 2; 44 } 45 46 setbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask); 47 #ifdef CONFIG_SUNXI_GEN_SUN6I 48 setbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); 49 #endif 50 51 sunxi_usb_phy_init(priv->phy_index); 52 sunxi_usb_phy_power_on(priv->phy_index); 53 54 hcor = (struct ehci_hcor *)((uint32_t)hccr + 55 HC_LENGTH(ehci_readl(&hccr->cr_capbase))); 56 57 return ehci_register(dev, hccr, hcor, NULL, 0, plat->init_type); 58 } 59 60 static int ehci_usb_remove(struct udevice *dev) 61 { 62 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 63 struct ehci_sunxi_priv *priv = dev_get_priv(dev); 64 int ret; 65 66 ret = ehci_deregister(dev); 67 if (ret) 68 return ret; 69 70 sunxi_usb_phy_exit(priv->phy_index); 71 72 #ifdef CONFIG_SUNXI_GEN_SUN6I 73 clrbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); 74 #endif 75 clrbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask); 76 77 return 0; 78 } 79 80 static const struct udevice_id ehci_usb_ids[] = { 81 { .compatible = "allwinner,sun4i-a10-ehci", }, 82 { .compatible = "allwinner,sun5i-a13-ehci", }, 83 { .compatible = "allwinner,sun6i-a31-ehci", }, 84 { .compatible = "allwinner,sun7i-a20-ehci", }, 85 { .compatible = "allwinner,sun8i-a23-ehci", }, 86 { .compatible = "allwinner,sun9i-a80-ehci", }, 87 { } 88 }; 89 90 U_BOOT_DRIVER(usb_ehci) = { 91 .name = "ehci_sunxi", 92 .id = UCLASS_USB, 93 .of_match = ehci_usb_ids, 94 .probe = ehci_usb_probe, 95 .remove = ehci_usb_remove, 96 .ops = &ehci_usb_ops, 97 .platdata_auto_alloc_size = sizeof(struct usb_platdata), 98 .priv_auto_alloc_size = sizeof(struct ehci_sunxi_priv), 99 .flags = DM_FLAG_ALLOC_PRIV_DMA, 100 }; 101