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