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