1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * UniPhier Specific Glue Layer for DWC3 4 * 5 * Copyright (C) 2016-2017 Socionext Inc. 6 * Author: Masahiro Yamada <yamada.masahiro@socionext.com> 7 */ 8 9 #include <dm.h> 10 #include <linux/bitops.h> 11 #include <linux/errno.h> 12 #include <linux/io.h> 13 #include <linux/sizes.h> 14 15 #define UNIPHIER_PRO4_DWC3_RESET 0x40 16 #define UNIPHIER_PRO4_DWC3_RESET_XIOMMU BIT(5) 17 #define UNIPHIER_PRO4_DWC3_RESET_XLINK BIT(4) 18 #define UNIPHIER_PRO4_DWC3_RESET_PHY_SS BIT(2) 19 20 #define UNIPHIER_PRO5_DWC3_RESET 0x00 21 #define UNIPHIER_PRO5_DWC3_RESET_PHY_S1 BIT(17) 22 #define UNIPHIER_PRO5_DWC3_RESET_PHY_S0 BIT(16) 23 #define UNIPHIER_PRO5_DWC3_RESET_XLINK BIT(15) 24 #define UNIPHIER_PRO5_DWC3_RESET_XIOMMU BIT(14) 25 26 #define UNIPHIER_PXS2_DWC3_RESET 0x00 27 #define UNIPHIER_PXS2_DWC3_RESET_XLINK BIT(15) 28 29 static int uniphier_pro4_dwc3_init(void __iomem *regs) 30 { 31 u32 tmp; 32 33 tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET); 34 tmp &= ~UNIPHIER_PRO4_DWC3_RESET_PHY_SS; 35 tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK; 36 writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET); 37 38 return 0; 39 } 40 41 static int uniphier_pro5_dwc3_init(void __iomem *regs) 42 { 43 u32 tmp; 44 45 tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET); 46 tmp &= ~(UNIPHIER_PRO5_DWC3_RESET_PHY_S1 | 47 UNIPHIER_PRO5_DWC3_RESET_PHY_S0); 48 tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU; 49 writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET); 50 51 return 0; 52 } 53 54 static int uniphier_pxs2_dwc3_init(void __iomem *regs) 55 { 56 u32 tmp; 57 58 tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET); 59 tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK; 60 writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET); 61 62 return 0; 63 } 64 65 static int uniphier_dwc3_probe(struct udevice *dev) 66 { 67 fdt_addr_t base; 68 void __iomem *regs; 69 int (*init)(void __iomem *regs); 70 int ret; 71 72 base = devfdt_get_addr(dev); 73 if (base == FDT_ADDR_T_NONE) 74 return -EINVAL; 75 76 regs = ioremap(base, SZ_32K); 77 if (!regs) 78 return -ENOMEM; 79 80 init = (typeof(init))dev_get_driver_data(dev); 81 ret = init(regs); 82 if (ret) 83 dev_err(dev, "failed to init glue layer\n"); 84 85 iounmap(regs); 86 87 return ret; 88 } 89 90 static const struct udevice_id uniphier_dwc3_match[] = { 91 { 92 .compatible = "socionext,uniphier-pro4-dwc3", 93 .data = (ulong)uniphier_pro4_dwc3_init, 94 }, 95 { 96 .compatible = "socionext,uniphier-pro5-dwc3", 97 .data = (ulong)uniphier_pro5_dwc3_init, 98 }, 99 { 100 .compatible = "socionext,uniphier-pxs2-dwc3", 101 .data = (ulong)uniphier_pxs2_dwc3_init, 102 }, 103 { 104 .compatible = "socionext,uniphier-ld20-dwc3", 105 .data = (ulong)uniphier_pxs2_dwc3_init, 106 }, 107 { 108 .compatible = "socionext,uniphier-pxs3-dwc3", 109 .data = (ulong)uniphier_pxs2_dwc3_init, 110 }, 111 { /* sentinel */ } 112 }; 113 114 U_BOOT_DRIVER(usb_xhci) = { 115 .name = "uniphier-dwc3", 116 .id = UCLASS_SIMPLE_BUS, 117 .of_match = uniphier_dwc3_match, 118 .probe = uniphier_dwc3_probe, 119 }; 120