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 <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 int clock_count; 25 int reset_count; 26 }; 27 28 static int ehci_usb_probe(struct udevice *dev) 29 { 30 struct generic_ehci *priv = dev_get_priv(dev); 31 struct ehci_hccr *hccr; 32 struct ehci_hcor *hcor; 33 int i, err, ret, clock_nb, reset_nb; 34 35 err = 0; 36 priv->clock_count = 0; 37 clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks", 38 "#clock-cells"); 39 if (clock_nb > 0) { 40 priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), 41 GFP_KERNEL); 42 if (!priv->clocks) 43 return -ENOMEM; 44 45 for (i = 0; i < clock_nb; i++) { 46 err = clk_get_by_index(dev, i, &priv->clocks[i]); 47 48 if (err < 0) 49 break; 50 err = clk_enable(&priv->clocks[i]); 51 if (err) { 52 error("failed to enable clock %d\n", i); 53 clk_free(&priv->clocks[i]); 54 goto clk_err; 55 } 56 priv->clock_count++; 57 } 58 } else { 59 if (clock_nb != -ENOENT) { 60 error("failed to get clock phandle(%d)\n", clock_nb); 61 return clock_nb; 62 } 63 } 64 65 priv->reset_count = 0; 66 reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets", 67 "#reset-cells"); 68 if (reset_nb > 0) { 69 priv->resets = devm_kcalloc(dev, reset_nb, 70 sizeof(struct reset_ctl), 71 GFP_KERNEL); 72 if (!priv->resets) 73 return -ENOMEM; 74 75 for (i = 0; i < reset_nb; i++) { 76 err = reset_get_by_index(dev, i, &priv->resets[i]); 77 if (err < 0) 78 break; 79 80 if (reset_deassert(&priv->resets[i])) { 81 error("failed to deassert reset %d\n", i); 82 reset_free(&priv->resets[i]); 83 goto reset_err; 84 } 85 priv->reset_count++; 86 } 87 } else { 88 if (reset_nb != -ENOENT) { 89 error("failed to get reset phandle(%d)\n", reset_nb); 90 goto clk_err; 91 } 92 } 93 94 hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE); 95 hcor = (struct ehci_hcor *)((uintptr_t)hccr + 96 HC_LENGTH(ehci_readl(&hccr->cr_capbase))); 97 98 err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); 99 if (err) 100 goto reset_err; 101 102 return 0; 103 104 reset_err: 105 ret = reset_release_all(priv->resets, priv->reset_count); 106 if (ret) 107 error("failed to assert all resets\n"); 108 clk_err: 109 ret = clk_release_all(priv->clocks, priv->clock_count); 110 if (ret) 111 error("failed to disable all clocks\n"); 112 113 return err; 114 } 115 116 static int ehci_usb_remove(struct udevice *dev) 117 { 118 struct generic_ehci *priv = dev_get_priv(dev); 119 int ret; 120 121 ret = ehci_deregister(dev); 122 if (ret) 123 return ret; 124 125 ret = reset_release_all(priv->resets, priv->reset_count); 126 if (ret) 127 return ret; 128 129 return clk_release_all(priv->clocks, priv->clock_count); 130 } 131 132 static const struct udevice_id ehci_usb_ids[] = { 133 { .compatible = "generic-ehci" }, 134 { } 135 }; 136 137 U_BOOT_DRIVER(ehci_generic) = { 138 .name = "ehci_generic", 139 .id = UCLASS_USB, 140 .of_match = ehci_usb_ids, 141 .probe = ehci_usb_probe, 142 .remove = ehci_usb_remove, 143 .ops = &ehci_usb_ops, 144 .priv_auto_alloc_size = sizeof(struct generic_ehci), 145 .flags = DM_FLAG_ALLOC_PRIV_DMA, 146 }; 147