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 && err != -ENOSYS) { 104 pr_err("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 pr_err("failed to get clock phandle(%d)\n", clock_nb); 113 return clock_nb; 114 } 115 } 116 117 priv->reset_count = 0; 118 reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets", 119 "#reset-cells"); 120 if (reset_nb > 0) { 121 priv->resets = devm_kcalloc(dev, reset_nb, 122 sizeof(struct reset_ctl), 123 GFP_KERNEL); 124 if (!priv->resets) 125 return -ENOMEM; 126 127 for (i = 0; i < reset_nb; i++) { 128 err = reset_get_by_index(dev, i, &priv->resets[i]); 129 if (err < 0) 130 break; 131 132 if (reset_deassert(&priv->resets[i])) { 133 pr_err("failed to deassert reset %d\n", i); 134 reset_free(&priv->resets[i]); 135 goto reset_err; 136 } 137 priv->reset_count++; 138 } 139 } else { 140 if (reset_nb != -ENOENT) { 141 pr_err("failed to get reset phandle(%d)\n", reset_nb); 142 goto clk_err; 143 } 144 } 145 146 err = ehci_setup_phy(dev, 0); 147 if (err) 148 149 goto reset_err; 150 151 hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE); 152 hcor = (struct ehci_hcor *)((uintptr_t)hccr + 153 HC_LENGTH(ehci_readl(&hccr->cr_capbase))); 154 155 err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); 156 if (err) 157 goto phy_err; 158 159 return 0; 160 161 phy_err: 162 ret = ehci_shutdown_phy(dev); 163 if (ret) 164 dev_err(dev, "failed to shutdown usb phy\n"); 165 166 reset_err: 167 ret = reset_release_all(priv->resets, priv->reset_count); 168 if (ret) 169 pr_err("failed to assert all resets\n"); 170 clk_err: 171 ret = clk_release_all(priv->clocks, priv->clock_count); 172 if (ret) 173 pr_err("failed to disable all clocks\n"); 174 175 return err; 176 } 177 178 static int ehci_usb_remove(struct udevice *dev) 179 { 180 struct generic_ehci *priv = dev_get_priv(dev); 181 int ret; 182 183 ret = ehci_deregister(dev); 184 if (ret) 185 return ret; 186 187 ret = ehci_shutdown_phy(dev); 188 if (ret) 189 return ret; 190 191 ret = reset_release_all(priv->resets, priv->reset_count); 192 if (ret) 193 return ret; 194 195 return clk_release_all(priv->clocks, priv->clock_count); 196 } 197 198 static const struct udevice_id ehci_usb_ids[] = { 199 { .compatible = "generic-ehci" }, 200 { } 201 }; 202 203 U_BOOT_DRIVER(ehci_generic) = { 204 .name = "ehci_generic", 205 .id = UCLASS_USB, 206 .of_match = ehci_usb_ids, 207 .probe = ehci_usb_probe, 208 .remove = ehci_usb_remove, 209 .ops = &ehci_usb_ops, 210 .priv_auto_alloc_size = sizeof(struct generic_ehci), 211 .flags = DM_FLAG_ALLOC_PRIV_DMA, 212 }; 213