1 /* 2 * Copyright (C) 2015 Marvell International Ltd. 3 * 4 * MVEBU USB HOST xHCI Controller 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <dm.h> 11 #include <fdtdec.h> 12 #include <usb.h> 13 #include <power/regulator.h> 14 #include <asm/gpio.h> 15 16 #include "xhci.h" 17 18 DECLARE_GLOBAL_DATA_PTR; 19 20 struct mvebu_xhci_platdata { 21 fdt_addr_t hcd_base; 22 }; 23 24 /** 25 * Contains pointers to register base addresses 26 * for the usb controller. 27 */ 28 struct mvebu_xhci { 29 struct xhci_ctrl ctrl; /* Needs to come first in this struct! */ 30 struct usb_platdata usb_plat; 31 struct xhci_hccr *hcd; 32 }; 33 34 /* 35 * Dummy implementation that can be overwritten by a board 36 * specific function 37 */ 38 __weak int board_xhci_enable(fdt_addr_t base) 39 { 40 return 0; 41 } 42 43 static int xhci_usb_probe(struct udevice *dev) 44 { 45 struct mvebu_xhci_platdata *plat = dev_get_platdata(dev); 46 struct mvebu_xhci *ctx = dev_get_priv(dev); 47 struct xhci_hcor *hcor; 48 int len, ret; 49 struct udevice *regulator; 50 51 ctx->hcd = (struct xhci_hccr *)plat->hcd_base; 52 len = HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase)); 53 hcor = (struct xhci_hcor *)((uintptr_t)ctx->hcd + len); 54 55 ret = device_get_supply_regulator(dev, "vbus-supply", ®ulator); 56 if (!ret) { 57 ret = regulator_set_enable(regulator, true); 58 if (ret) { 59 printf("Failed to turn ON the VBUS regulator\n"); 60 return ret; 61 } 62 } 63 64 /* Enable USB xHCI (VBUS, reset etc) in board specific code */ 65 board_xhci_enable(devfdt_get_addr_index(dev, 1)); 66 67 return xhci_register(dev, ctx->hcd, hcor); 68 } 69 70 static int xhci_usb_ofdata_to_platdata(struct udevice *dev) 71 { 72 struct mvebu_xhci_platdata *plat = dev_get_platdata(dev); 73 74 /* 75 * Get the base address for XHCI controller from the device node 76 */ 77 plat->hcd_base = devfdt_get_addr(dev); 78 if (plat->hcd_base == FDT_ADDR_T_NONE) { 79 debug("Can't get the XHCI register base address\n"); 80 return -ENXIO; 81 } 82 83 return 0; 84 } 85 86 static const struct udevice_id xhci_usb_ids[] = { 87 { .compatible = "marvell,armada3700-xhci" }, 88 { .compatible = "marvell,armada-380-xhci" }, 89 { .compatible = "marvell,armada-8k-xhci" }, 90 { } 91 }; 92 93 U_BOOT_DRIVER(usb_xhci) = { 94 .name = "xhci_mvebu", 95 .id = UCLASS_USB, 96 .of_match = xhci_usb_ids, 97 .ofdata_to_platdata = xhci_usb_ofdata_to_platdata, 98 .probe = xhci_usb_probe, 99 .remove = xhci_deregister, 100 .ops = &xhci_usb_ops, 101 .platdata_auto_alloc_size = sizeof(struct mvebu_xhci_platdata), 102 .priv_auto_alloc_size = sizeof(struct mvebu_xhci), 103 .flags = DM_FLAG_ALLOC_PRIV_DMA, 104 }; 105