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