1 /* 2 * Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <clk.h> 9 #include <dm/ofnode.h> 10 #include <generic-phy.h> 11 #include <reset.h> 12 #include <asm/io.h> 13 #include <dm.h> 14 #include "ehci.h" 15 16 /* 17 * Even though here we don't explicitly use "struct ehci_ctrl" 18 * ehci_register() expects it to be the first thing that resides in 19 * device's private data. 20 */ 21 struct generic_ehci { 22 struct ehci_ctrl ctrl; 23 struct clk *clocks; 24 struct reset_ctl *resets; 25 struct phy phy; 26 int clock_count; 27 int reset_count; 28 }; 29 30 static int ehci_setup_phy(struct udevice *dev, int index) 31 { 32 struct generic_ehci *priv = dev_get_priv(dev); 33 int ret; 34 35 ret = generic_phy_get_by_index(dev, index, &priv->phy); 36 if (ret) { 37 if (ret != -ENOENT) { 38 dev_err(dev, "failed to get usb phy\n"); 39 return ret; 40 } 41 } else { 42 ret = generic_phy_init(&priv->phy); 43 if (ret) { 44 dev_err(dev, "failed to init usb phy\n"); 45 return ret; 46 } 47 48 ret = generic_phy_power_on(&priv->phy); 49 if (ret) { 50 dev_err(dev, "failed to power on usb phy\n"); 51 return generic_phy_exit(&priv->phy); 52 } 53 } 54 55 return 0; 56 } 57 58 static int ehci_shutdown_phy(struct udevice *dev) 59 { 60 struct generic_ehci *priv = dev_get_priv(dev); 61 int ret = 0; 62 63 if (generic_phy_valid(&priv->phy)) { 64 ret = generic_phy_power_off(&priv->phy); 65 if (ret) { 66 dev_err(dev, "failed to power off usb phy\n"); 67 return ret; 68 } 69 70 ret = generic_phy_exit(&priv->phy); 71 if (ret) { 72 dev_err(dev, "failed to power off usb phy\n"); 73 return ret; 74 } 75 } 76 77 return 0; 78 } 79 80 static int ehci_usb_probe(struct udevice *dev) 81 { 82 struct generic_ehci *priv = dev_get_priv(dev); 83 struct ehci_hccr *hccr; 84 struct ehci_hcor *hcor; 85 int i, err, ret, clock_nb, reset_nb; 86 87 err = 0; 88 priv->clock_count = 0; 89 clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks", 90 "#clock-cells"); 91 if (clock_nb > 0) { 92 priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), 93 GFP_KERNEL); 94 if (!priv->clocks) 95 return -ENOMEM; 96 97 for (i = 0; i < clock_nb; i++) { 98 err = clk_get_by_index(dev, i, &priv->clocks[i]); 99 100 if (err < 0) 101 break; 102 err = clk_enable(&priv->clocks[i]); 103 if (err) { 104 dev_err(dev, "failed to enable clock %d\n", i); 105 clk_free(&priv->clocks[i]); 106 goto clk_err; 107 } 108 priv->clock_count++; 109 } 110 } else { 111 if (clock_nb != -ENOENT) { 112 dev_err(dev, "failed to get clock phandle(%d)\n", 113 clock_nb); 114 return clock_nb; 115 } 116 } 117 118 priv->reset_count = 0; 119 reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets", 120 "#reset-cells"); 121 if (reset_nb > 0) { 122 priv->resets = devm_kcalloc(dev, reset_nb, 123 sizeof(struct reset_ctl), 124 GFP_KERNEL); 125 if (!priv->resets) 126 return -ENOMEM; 127 128 for (i = 0; i < reset_nb; i++) { 129 err = reset_get_by_index(dev, i, &priv->resets[i]); 130 if (err < 0) 131 break; 132 133 if (reset_deassert(&priv->resets[i])) { 134 dev_err(dev, "failed to deassert reset %d\n", 135 i); 136 reset_free(&priv->resets[i]); 137 goto reset_err; 138 } 139 priv->reset_count++; 140 } 141 } else { 142 if (reset_nb != -ENOENT) { 143 dev_err(dev, "failed to get reset phandle(%d)\n", 144 reset_nb); 145 goto clk_err; 146 } 147 } 148 149 err = ehci_setup_phy(dev, 0); 150 if (err) 151 goto reset_err; 152 153 hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE); 154 hcor = (struct ehci_hcor *)((uintptr_t)hccr + 155 HC_LENGTH(ehci_readl(&hccr->cr_capbase))); 156 157 err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); 158 if (err) 159 goto phy_err; 160 161 return 0; 162 163 phy_err: 164 ret = ehci_shutdown_phy(dev); 165 if (ret) 166 dev_err(dev, "failed to shutdown usb phy\n"); 167 168 reset_err: 169 ret = reset_release_all(priv->resets, priv->reset_count); 170 if (ret) 171 dev_err(dev, "failed to assert all resets\n"); 172 clk_err: 173 ret = clk_release_all(priv->clocks, priv->clock_count); 174 if (ret) 175 dev_err(dev, "failed to disable all clocks\n"); 176 177 return err; 178 } 179 180 static int ehci_usb_remove(struct udevice *dev) 181 { 182 struct generic_ehci *priv = dev_get_priv(dev); 183 int ret; 184 185 ret = ehci_deregister(dev); 186 if (ret) 187 return ret; 188 189 ret = ehci_shutdown_phy(dev); 190 if (ret) 191 return ret; 192 193 ret = reset_release_all(priv->resets, priv->reset_count); 194 if (ret) 195 return ret; 196 197 return clk_release_all(priv->clocks, priv->clock_count); 198 } 199 200 static const struct udevice_id ehci_usb_ids[] = { 201 { .compatible = "generic-ehci" }, 202 { } 203 }; 204 205 U_BOOT_DRIVER(ehci_generic) = { 206 .name = "ehci_generic", 207 .id = UCLASS_USB, 208 .of_match = ehci_usb_ids, 209 .probe = ehci_usb_probe, 210 .remove = ehci_usb_remove, 211 .ops = &ehci_usb_ops, 212 .priv_auto_alloc_size = sizeof(struct generic_ehci), 213 .flags = DM_FLAG_ALLOC_PRIV_DMA, 214 }; 215