1 // SPDX-License-Identifier: GPL-2.0+ 2 #include <common.h> 3 #include <dm.h> 4 #include <reset.h> 5 #include <fdtdec.h> 6 #include <pci.h> 7 #include <asm/io.h> 8 #include <asm/arch/h2x_ast2600.h> 9 #include <asm/arch/ahbc_aspeed.h> 10 11 DECLARE_GLOBAL_DATA_PTR; 12 13 /* PCI Host Controller registers */ 14 15 #define ASPEED_PCIE_CLASS_CODE 0x04 16 #define ASPEED_PCIE_GLOBAL 0x30 17 #define ASPEED_PCIE_CFG_DIN 0x50 18 #define ASPEED_PCIE_CFG3 0x58 19 #define ASPEED_PCIE_LOCK 0x7C 20 #define ASPEED_PCIE_LINK 0xC0 21 #define ASPEED_PCIE_INT 0xC4 22 #define ASPEED_PCIE_LINK_STS 0xD0 23 24 /* AST_PCIE_CFG2 0x04 */ 25 #define PCIE_CFG_CLASS_CODE(x) (x << 8) 26 #define PCIE_CFG_REV_ID(x) (x) 27 28 /* AST_PCIE_GLOBAL 0x30 */ 29 #define ROOT_COMPLEX_ID(x) (x << 4) 30 31 /* AST_PCIE_LOCK 0x7C */ 32 #define PCIE_UNLOCK 0xa8 33 34 /* AST_PCIE_LINK 0xC0 */ 35 #define PCIE_LINK_STS BIT(5) 36 37 /* ASPEED_PCIE_LINK_STS 0xD0 */ 38 #define PCIE_LINK_5G BIT(17) 39 #define PCIE_LINK_2_5G BIT(16) 40 41 struct pcie_aspeed { 42 void *ctrl_base; 43 void *h2x_pt; 44 void *cfg_base; 45 fdt_size_t cfg_size; 46 int link_sts; 47 int first_busno; 48 }; 49 50 static int pcie_aspeed_read_config(struct udevice *bus, pci_dev_t bdf, 51 uint offset, ulong *valuep, 52 enum pci_size_t size) 53 { 54 struct pcie_aspeed *pcie = dev_get_priv(bus); 55 56 debug("PCIE CFG read: (b,d,f)=(%2d,%2d,%2d) \n", 57 PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); 58 59 /* Only allow one other device besides the local one on the local bus */ 60 if (PCI_BUS(bdf) == 1 && PCI_DEV(bdf) != 0) { 61 debug("- out of range\n"); 62 /* 63 * If local dev is 0, the first other dev can 64 * only be 1 65 */ 66 *valuep = pci_get_ff(size); 67 return 0; 68 } 69 70 if (PCI_BUS(bdf) == 1 && (!pcie->link_sts)) { 71 *valuep = pci_get_ff(size); 72 return 0; 73 } 74 75 aspeed_pcie_cfg_read(pcie->h2x_pt, bdf, offset, valuep); 76 77 debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, *valuep); 78 *valuep = pci_conv_32_to_size(*valuep, offset, size); 79 80 return 0; 81 } 82 83 static int pcie_aspeed_write_config(struct udevice *bus, pci_dev_t bdf, 84 uint offset, ulong value, 85 enum pci_size_t size) 86 { 87 struct pcie_aspeed *pcie = dev_get_priv(bus); 88 89 debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ", 90 PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); 91 debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); 92 93 aspeed_pcie_cfg_write(pcie->h2x_pt, bdf, offset, value, size); 94 95 return 0; 96 } 97 98 static int pcie_aspeed_probe(struct udevice *dev) 99 { 100 void *fdt = (void *)gd->fdt_blob; 101 102 struct reset_ctl reset_ctl0, reset_ctl1; 103 struct pcie_aspeed *pcie = dev_get_priv(dev); 104 // struct udevice *ctrl = pci_get_controller(dev); 105 // struct pci_controller *host = dev_get_uclass_priv(ctrl); 106 struct udevice *ahbc_dev; 107 int h2x_of_handle; 108 int ret = 0; 109 110 ret = reset_get_by_index(dev, 0, &reset_ctl0); 111 if (ret) { 112 printf("%s(): Failed to get reset signal\n", __func__); 113 return ret; 114 } 115 116 ret = reset_get_by_index(dev, 0, &reset_ctl1); 117 if (ret) { 118 printf("%s(): Failed to get reset signal\n", __func__); 119 return ret; 120 } 121 122 reset_assert(&reset_ctl0); 123 reset_assert(&reset_ctl1); 124 mdelay(100); 125 reset_deassert(&reset_ctl0); 126 127 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(aspeed_ahbc), 128 &ahbc_dev); 129 if (ret) { 130 debug("ahbc device not defined\n"); 131 return ret; 132 } 133 134 h2x_of_handle = fdtdec_lookup_phandle(fdt, dev_of_offset(dev), "cfg-handle"); 135 if (h2x_of_handle > 0) { 136 pcie->h2x_pt = (void *)fdtdec_get_addr(fdt, h2x_of_handle, "reg"); 137 debug("h2x cfg addr %x \n", (u32)pcie->h2x_pt); 138 } else { 139 debug("h2x device not defined\n"); 140 return h2x_of_handle; 141 } 142 143 aspeed_ahbc_remap_enable(devfdt_get_addr_ptr(ahbc_dev)); 144 145 //plda enable 146 writel(PCIE_UNLOCK, pcie->ctrl_base + ASPEED_PCIE_LOCK); 147 writel(ROOT_COMPLEX_ID(0x3), pcie->ctrl_base + ASPEED_PCIE_GLOBAL); 148 149 pcie->first_busno = dev->seq; 150 mdelay(100); 151 152 /* Don't register host if link is down */ 153 if (readl(pcie->ctrl_base + ASPEED_PCIE_LINK) & PCIE_LINK_STS) { 154 printf("PCIE-%d: Link up - ", dev->seq); 155 if(readl(pcie->ctrl_base + ASPEED_PCIE_LINK_STS) & PCIE_LINK_5G) 156 printf("5G \n"); 157 if(readl(pcie->ctrl_base + ASPEED_PCIE_LINK_STS) & PCIE_LINK_2_5G) 158 printf("2.5G \n"); 159 pcie->link_sts = 1; 160 } else { 161 printf("PCIE-%d: Link down\n", dev->seq); 162 pcie->link_sts = 0; 163 } 164 aspeed_h2x_rc_enable(pcie->h2x_pt); 165 if(pcie->link_sts) 166 aspeed_pcie_workaround(pcie->h2x_pt); 167 168 return 0; 169 } 170 171 static int pcie_aspeed_ofdata_to_platdata(struct udevice *dev) 172 { 173 struct pcie_aspeed *pcie = dev_get_priv(dev); 174 175 /* Get the controller base address */ 176 pcie->ctrl_base = (void *)devfdt_get_addr_index(dev, 0); 177 178 /* Get the config space base address and size */ 179 pcie->cfg_base = (void *)devfdt_get_addr_size_index(dev, 1, 180 &pcie->cfg_size); 181 182 return 0; 183 } 184 185 static const struct dm_pci_ops pcie_aspeed_ops = { 186 .read_config = pcie_aspeed_read_config, 187 .write_config = pcie_aspeed_write_config, 188 }; 189 190 static const struct udevice_id pcie_aspeed_ids[] = { 191 { .compatible = "aspeed,ast2600-pcie" }, 192 { } 193 }; 194 195 U_BOOT_DRIVER(pcie_aspeed) = { 196 .name = "pcie_aspeed", 197 .id = UCLASS_PCI, 198 .of_match = pcie_aspeed_ids, 199 .ops = &pcie_aspeed_ops, 200 .ofdata_to_platdata = pcie_aspeed_ofdata_to_platdata, 201 .probe = pcie_aspeed_probe, 202 .priv_auto_alloc_size = sizeof(struct pcie_aspeed), 203 }; 204