1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Faraday FTPCI100 PCI Bridge Controller Device Driver Implementation 4 * 5 * Copyright (C) 2011 Andes Technology Corporation 6 * Gavin Guo, Andes Technology Corporation <gavinguo@andestech.com> 7 * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> 8 */ 9 #include <common.h> 10 #include <malloc.h> 11 #include <pci.h> 12 13 #include <faraday/ftpci100.h> 14 15 #include <asm/io.h> 16 #include <asm/types.h> /* u32, u16.... used by pci.h */ 17 18 struct ftpci100_data { 19 unsigned int reg_base; 20 unsigned int io_base; 21 unsigned int mem_base; 22 unsigned int mmio_base; 23 unsigned int ndevs; 24 }; 25 26 static struct pci_config devs[FTPCI100_MAX_FUNCTIONS]; 27 static struct pci_controller local_hose; 28 29 static void setup_pci_bar(unsigned int bus, unsigned int dev, unsigned func, 30 unsigned char header, struct ftpci100_data *priv) 31 { 32 struct pci_controller *hose = (struct pci_controller *)&local_hose; 33 unsigned int i, tmp32, bar_no, iovsmem = 1; 34 pci_dev_t dev_nu; 35 36 /* A device is present, add an entry to the array */ 37 devs[priv->ndevs].bus = bus; 38 devs[priv->ndevs].dev = dev; 39 devs[priv->ndevs].func = func; 40 41 dev_nu = PCI_BDF(bus, dev, func); 42 43 if ((header & 0x7f) == 0x01) 44 /* PCI-PCI Bridge */ 45 bar_no = 2; 46 else 47 bar_no = 6; 48 49 /* Allocate address spaces by configuring BARs */ 50 for (i = 0; i < bar_no; i++) { 51 pci_hose_write_config_dword(hose, dev_nu, 52 PCI_BASE_ADDRESS_0 + i * 4, 0xffffffff); 53 pci_hose_read_config_dword(hose, dev_nu, 54 PCI_BASE_ADDRESS_0 + i * 4, &tmp32); 55 56 if (tmp32 == 0x0) 57 continue; 58 59 /* IO space */ 60 if (tmp32 & 0x1) { 61 iovsmem = 0; 62 unsigned int size_mask = ~(tmp32 & 0xfffffffc); 63 64 if (priv->io_base & size_mask) 65 priv->io_base = (priv->io_base & ~size_mask) + \ 66 size_mask + 1; 67 68 devs[priv->ndevs].bar[i].addr = priv->io_base; 69 devs[priv->ndevs].bar[i].size = size_mask + 1; 70 71 pci_hose_write_config_dword(hose, dev_nu, 72 PCI_BASE_ADDRESS_0 + i * 4, 73 priv->io_base); 74 75 debug("Allocated IO address 0x%X-" \ 76 "0x%X for Bus %d, Device %d, Function %d\n", 77 priv->io_base, 78 priv->io_base + size_mask, bus, dev, func); 79 80 priv->io_base += size_mask + 1; 81 } else { 82 /* Memory space */ 83 unsigned int is_64bit = ((tmp32 & 0x6) == 0x4); 84 unsigned int is_pref = tmp32 & 0x8; 85 unsigned int size_mask = ~(tmp32 & 0xfffffff0); 86 unsigned int alloc_base; 87 unsigned int *addr_mem_base; 88 89 if (is_pref) 90 addr_mem_base = &priv->mem_base; 91 else 92 addr_mem_base = &priv->mmio_base; 93 94 alloc_base = *addr_mem_base; 95 96 if (alloc_base & size_mask) 97 alloc_base = (alloc_base & ~size_mask) \ 98 + size_mask + 1; 99 100 pci_hose_write_config_dword(hose, dev_nu, 101 PCI_BASE_ADDRESS_0 + i * 4, alloc_base); 102 103 debug("Allocated %s address 0x%X-" \ 104 "0x%X for Bus %d, Device %d, Function %d\n", 105 is_pref ? "MEM" : "MMIO", alloc_base, 106 alloc_base + size_mask, bus, dev, func); 107 108 devs[priv->ndevs].bar[i].addr = alloc_base; 109 devs[priv->ndevs].bar[i].size = size_mask + 1; 110 111 debug("BAR address BAR size\n"); 112 debug("%010x %08d\n", 113 devs[priv->ndevs].bar[0].addr, 114 devs[priv->ndevs].bar[0].size); 115 116 alloc_base += size_mask + 1; 117 *addr_mem_base = alloc_base; 118 119 if (is_64bit) { 120 i++; 121 pci_hose_write_config_dword(hose, dev_nu, 122 PCI_BASE_ADDRESS_0 + i * 4, 0x0); 123 } 124 } 125 } 126 127 /* Enable Bus Master, Memory Space, and IO Space */ 128 pci_hose_read_config_dword(hose, dev_nu, PCI_CACHE_LINE_SIZE, &tmp32); 129 pci_hose_write_config_dword(hose, dev_nu, PCI_CACHE_LINE_SIZE, 0x08); 130 pci_hose_read_config_dword(hose, dev_nu, PCI_CACHE_LINE_SIZE, &tmp32); 131 132 pci_hose_read_config_dword(hose, dev_nu, PCI_COMMAND, &tmp32); 133 134 tmp32 &= 0xffff; 135 136 if (iovsmem == 0) 137 tmp32 |= 0x5; 138 else 139 tmp32 |= 0x6; 140 141 pci_hose_write_config_dword(hose, dev_nu, PCI_COMMAND, tmp32); 142 } 143 144 static void pci_bus_scan(struct ftpci100_data *priv) 145 { 146 struct pci_controller *hose = (struct pci_controller *)&local_hose; 147 unsigned int bus, dev, func; 148 pci_dev_t dev_nu; 149 unsigned int data32; 150 unsigned int tmp; 151 unsigned char header; 152 unsigned char int_pin; 153 unsigned int niobars; 154 unsigned int nmbars; 155 156 priv->ndevs = 1; 157 158 nmbars = 0; 159 niobars = 0; 160 161 for (bus = 0; bus < MAX_BUS_NUM; bus++) 162 for (dev = 0; dev < MAX_DEV_NUM; dev++) 163 for (func = 0; func < MAX_FUN_NUM; func++) { 164 dev_nu = PCI_BDF(bus, dev, func); 165 pci_hose_read_config_dword(hose, dev_nu, 166 PCI_VENDOR_ID, &data32); 167 168 /* 169 * some broken boards return 0 or ~0, 170 * if a slot is empty. 171 */ 172 if (data32 == 0xffffffff || 173 data32 == 0x00000000 || 174 data32 == 0x0000ffff || 175 data32 == 0xffff0000) 176 continue; 177 178 pci_hose_read_config_dword(hose, dev_nu, 179 PCI_HEADER_TYPE, &tmp); 180 header = (unsigned char)tmp; 181 setup_pci_bar(bus, dev, func, header, priv); 182 183 devs[priv->ndevs].v_id = (u16)(data32 & \ 184 0x0000ffff); 185 186 devs[priv->ndevs].d_id = (u16)((data32 & \ 187 0xffff0000) >> 16); 188 189 /* Figure out what INTX# line the card uses */ 190 pci_hose_read_config_byte(hose, dev_nu, 191 PCI_INTERRUPT_PIN, &int_pin); 192 193 /* assign the appropriate irq line */ 194 if (int_pin > PCI_IRQ_LINES) { 195 printf("more irq lines than expect\n"); 196 } else if (int_pin != 0) { 197 /* This device uses an interrupt line */ 198 devs[priv->ndevs].pin = int_pin; 199 } 200 201 pci_hose_read_config_dword(hose, dev_nu, 202 PCI_CLASS_DEVICE, &data32); 203 204 debug("%06d %03d %03d " \ 205 "%04d %08x %08x " \ 206 "%03d %08x %06d %08x\n", 207 priv->ndevs, devs[priv->ndevs].bus, 208 devs[priv->ndevs].dev, 209 devs[priv->ndevs].func, 210 devs[priv->ndevs].d_id, 211 devs[priv->ndevs].v_id, 212 devs[priv->ndevs].pin, 213 devs[priv->ndevs].bar[0].addr, 214 devs[priv->ndevs].bar[0].size, 215 data32 >> 8); 216 217 priv->ndevs++; 218 } 219 } 220 221 static void ftpci_preinit(struct ftpci100_data *priv) 222 { 223 struct ftpci100_ahbc *ftpci100; 224 struct pci_controller *hose = (struct pci_controller *)&local_hose; 225 u32 pci_config_addr; 226 u32 pci_config_data; 227 228 priv->reg_base = CONFIG_FTPCI100_BASE; 229 priv->io_base = CONFIG_FTPCI100_BASE + CONFIG_FTPCI100_IO_SIZE; 230 priv->mmio_base = CONFIG_FTPCI100_MEM_BASE; 231 priv->mem_base = CONFIG_FTPCI100_MEM_BASE + CONFIG_FTPCI100_MEM_SIZE; 232 233 ftpci100 = (struct ftpci100_ahbc *)priv->reg_base; 234 235 pci_config_addr = (u32) &ftpci100->conf; 236 pci_config_data = (u32) &ftpci100->data; 237 238 /* print device name */ 239 printf("FTPCI100\n"); 240 241 /* dump basic configuration */ 242 debug("%s: Config addr is %08X, data port is %08X\n", 243 __func__, pci_config_addr, pci_config_data); 244 245 /* PCI memory space */ 246 pci_set_region(hose->regions + 0, 247 CONFIG_PCI_MEM_BUS, 248 CONFIG_PCI_MEM_PHYS, 249 CONFIG_PCI_MEM_SIZE, 250 PCI_REGION_MEM); 251 hose->region_count++; 252 253 /* PCI IO space */ 254 pci_set_region(hose->regions + 1, 255 CONFIG_PCI_IO_BUS, 256 CONFIG_PCI_IO_PHYS, 257 CONFIG_PCI_IO_SIZE, 258 PCI_REGION_IO); 259 hose->region_count++; 260 261 #if defined(CONFIG_PCI_SYS_BUS) 262 /* PCI System Memory space */ 263 pci_set_region(hose->regions + 2, 264 CONFIG_PCI_SYS_BUS, 265 CONFIG_PCI_SYS_PHYS, 266 CONFIG_PCI_SYS_SIZE, 267 PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 268 hose->region_count++; 269 #endif 270 271 /* setup indirect read/write function */ 272 pci_setup_indirect(hose, pci_config_addr, pci_config_data); 273 274 /* register hose */ 275 pci_register_hose(hose); 276 } 277 278 void pci_ftpci_init(void) 279 { 280 struct ftpci100_data *priv = NULL; 281 struct pci_controller *hose = (struct pci_controller *)&local_hose; 282 pci_dev_t bridge_num; 283 284 struct pci_device_id bridge_ids[] = { 285 {FTPCI100_BRIDGE_VENDORID, FTPCI100_BRIDGE_DEVICEID}, 286 {0, 0} 287 }; 288 289 priv = malloc(sizeof(struct ftpci100_data)); 290 291 if (!priv) { 292 printf("%s(): failed to malloc priv\n", __func__); 293 return; 294 } 295 296 memset(priv, 0, sizeof(struct ftpci100_data)); 297 298 ftpci_preinit(priv); 299 300 debug("Device bus dev func deviceID vendorID pin address" \ 301 " size class\n"); 302 303 pci_bus_scan(priv); 304 305 /* 306 * Setup the PCI Bridge Window to 1GB, 307 * it will cause USB OHCI Host controller Unrecoverable Error 308 * if it is not set. 309 */ 310 bridge_num = pci_find_devices(bridge_ids, 0); 311 if (bridge_num == -1) { 312 printf("PCI Bridge not found\n"); 313 return; 314 } 315 pci_hose_write_config_dword(hose, bridge_num, PCI_MEM_BASE_SIZE1, 316 FTPCI100_BASE_ADR_SIZE(1024)); 317 } 318