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