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