1/* 2 * Copyright 2001 MontaVista Software Inc. 3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 * 5 * arch/mips/ddb5xxx/ddb5476/pci_ops.c 6 * Define the pci_ops for DB5477. 7 * 8 * Much of the code is derived from the original DDB5074 port by 9 * Geert Uytterhoeven <geert@sonycom.com> 10 * 11 * This program is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License as published by the 13 * Free Software Foundation; either version 2 of the License, or (at your 14 * option) any later version. 15 * 16 */ 17 18#include <linux/config.h> 19#include <linux/pci.h> 20#include <linux/kernel.h> 21#include <linux/types.h> 22 23#include <asm/addrspace.h> 24#include <asm/debug.h> 25 26#include <asm/ddb5xxx/ddb5xxx.h> 27 28/* 29 * config_swap structure records what set of pdar/pmr are used 30 * to access pci config space. It also provides a place hold the 31 * original values for future restoring. 32 */ 33struct pci_config_swap { 34 u32 pdar; 35 u32 pmr; 36 u32 config_base; 37 u32 config_size; 38 u32 pdar_backup; 39 u32 pmr_backup; 40}; 41 42/* 43 * On DDB5476, we have one set of swap registers 44 */ 45struct pci_config_swap ext_pci_swap = { 46 DDB_PCIW0, 47 DDB_PCIINIT0, 48 DDB_PCI_CONFIG_BASE, 49 DDB_PCI_CONFIG_SIZE 50}; 51 52static int pci_config_workaround=1; 53 54/* 55 * access config space 56 */ 57static inline u32 ddb_access_config_base(struct pci_config_swap *swap, 58 u32 bus,/* 0 means top level bus */ 59 u32 slot_num) 60{ 61 u32 pci_addr = 0; 62 u32 pciinit_offset = 0; 63 u32 virt_addr = swap->config_base; 64 u32 option; 65 66 if (pci_config_workaround) { 67 /* [jsun] work around Vrc5476 controller itself, returnning 68 * slot 0 essentially makes vrc5476 invisible 69 */ 70 if (slot_num == 12) slot_num = 0; 71 72 73 } else { 74 /* now we have to be hornest, returning the true 75 * PCI config headers for vrc5476 76 */ 77 if (slot_num == 12) { 78 swap->pdar_backup = ddb_in32(swap->pdar); 79 swap->pmr_backup = ddb_in32(swap->pmr); 80 return DDB_BASE + DDB_PCI_BASE; 81 } 82 } 83 84 /* minimum pdar (window) size is 2MB */ 85 db_assert(swap->config_size >= (2 << 20)); 86 87 db_assert(slot_num < (1 << 5)); 88 db_assert(bus < (1 << 8)); 89 90 /* backup registers */ 91 swap->pdar_backup = ddb_in32(swap->pdar); 92 swap->pmr_backup = ddb_in32(swap->pmr); 93 94 /* set the pdar (pci window) register */ 95 ddb_set_pdar(swap->pdar, 96 swap->config_base, 97 swap->config_size, 98 32, /* 32 bit wide */ 99 0, /* not on local memory bus */ 100 0); /* not visible from PCI bus (N/A) */ 101 102 /* 103 * calcuate the absolute pci config addr; 104 * according to the spec, we start scanning from adr:11 (0x800) 105 */ 106 if (bus == 0) { 107 /* type 0 config */ 108 pci_addr = 0x800 << slot_num; 109 } else { 110 /* type 1 config */ 111 pci_addr = (bus << 16) | (slot_num << 11); 112 /* panic("ddb_access_config_base: we don't support type 1 config Yet"); */ 113 } 114 115 /* 116 * if pci_addr is less than pci config window size, we set 117 * pciinit_offset to 0 and adjust the virt_address. 118 * Otherwise we will try to adjust pciinit_offset. 119 */ 120 if (pci_addr < swap->config_size) { 121 virt_addr = KSEG1ADDR(swap->config_base + pci_addr); 122 pciinit_offset = 0; 123 } else { 124 db_assert( (pci_addr & (swap->config_size - 1)) == 0); 125 virt_addr = KSEG1ADDR(swap->config_base); 126 pciinit_offset = pci_addr; 127 } 128 129 /* set the pmr register */ 130 option = DDB_PCI_ACCESS_32; 131 if (bus != 0) option |= DDB_PCI_CFGTYPE1; 132 ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); 133 134 return virt_addr; 135} 136 137static inline void ddb_close_config_base(struct pci_config_swap *swap) 138{ 139 ddb_out32(swap->pdar, swap->pdar_backup); 140 ddb_out32(swap->pmr, swap->pmr_backup); 141} 142 143static int read_config_dword(struct pci_config_swap *swap, 144 struct pci_dev *dev, 145 u32 where, 146 u32 *val) 147{ 148 u32 bus, slot_num, func_num; 149 u32 base; 150 151 db_assert((where & 3) == 0); 152 db_assert(where < (1 << 8)); 153 154 /* check if the bus is top-level */ 155 if (dev->bus->parent != NULL) { 156 bus = dev->bus->number; 157 db_assert(bus != 0); 158 } else { 159 bus = 0; 160 } 161 162 slot_num = PCI_SLOT(dev->devfn); 163 func_num = PCI_FUNC(dev->devfn); 164 base = ddb_access_config_base(swap, bus, slot_num); 165 *val = *(volatile u32*) (base + (func_num << 8) + where); 166 ddb_close_config_base(swap); 167 return PCIBIOS_SUCCESSFUL; 168} 169 170static int read_config_word(struct pci_config_swap *swap, 171 struct pci_dev *dev, 172 u32 where, 173 u16 *val) 174{ 175 int status; 176 u32 result; 177 178 db_assert((where & 1) == 0); 179 180 status = read_config_dword(swap, dev, where & ~3, &result); 181 if (where & 2) result >>= 16; 182 *val = result & 0xffff; 183 return status; 184} 185 186static int read_config_byte(struct pci_config_swap *swap, 187 struct pci_dev *dev, 188 u32 where, 189 u8 *val) 190{ 191 int status; 192 u32 result; 193 194 status = read_config_dword(swap, dev, where & ~3, &result); 195 if (where & 1) result >>= 8; 196 if (where & 2) result >>= 16; 197 *val = result & 0xff; 198 return status; 199} 200 201static int write_config_dword(struct pci_config_swap *swap, 202 struct pci_dev *dev, 203 u32 where, 204 u32 val) 205{ 206 u32 bus, slot_num, func_num; 207 u32 base; 208 209 db_assert((where & 3) == 0); 210 db_assert(where < (1 << 8)); 211 212 /* check if the bus is top-level */ 213 if (dev->bus->parent != NULL) { 214 bus = dev->bus->number; 215 db_assert(bus != 0); 216 } else { 217 bus = 0; 218 } 219 220 slot_num = PCI_SLOT(dev->devfn); 221 func_num = PCI_FUNC(dev->devfn); 222 base = ddb_access_config_base(swap, bus, slot_num); 223 *(volatile u32*) (base + (func_num << 8) + where) = val; 224 ddb_close_config_base(swap); 225 return PCIBIOS_SUCCESSFUL; 226} 227 228static int write_config_word(struct pci_config_swap *swap, 229 struct pci_dev *dev, 230 u32 where, 231 u16 val) 232{ 233 int status, shift=0; 234 u32 result; 235 236 db_assert((where & 1) == 0); 237 238 status = read_config_dword(swap, dev, where & ~3, &result); 239 if (status != PCIBIOS_SUCCESSFUL) return status; 240 241 if (where & 2) 242 shift += 16; 243 result &= ~(0xffff << shift); 244 result |= val << shift; 245 return write_config_dword(swap, dev, where & ~3, result); 246} 247 248static int write_config_byte(struct pci_config_swap *swap, 249 struct pci_dev *dev, 250 u32 where, 251 u8 val) 252{ 253 int status, shift=0; 254 u32 result; 255 256 status = read_config_dword(swap, dev, where & ~3, &result); 257 if (status != PCIBIOS_SUCCESSFUL) return status; 258 259 if (where & 2) 260 shift += 16; 261 if (where & 1) 262 shift += 8; 263 result &= ~(0xff << shift); 264 result |= val << shift; 265 return write_config_dword(swap, dev, where & ~3, result); 266} 267 268#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ 269static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \ 270{ \ 271 return rw##_config_##unitname(pciswap, \ 272 dev, \ 273 where, \ 274 val); \ 275} 276 277MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap) 278MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap) 279MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap) 280 281MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap) 282MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap) 283MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap) 284 285struct pci_ops ddb5476_ext_pci_ops ={ 286 extpci_read_config_byte, 287 extpci_read_config_word, 288 extpci_read_config_dword, 289 extpci_write_config_byte, 290 extpci_write_config_word, 291 extpci_write_config_dword 292}; 293 294 295#if defined(CONFIG_DEBUG) 296void jsun_scan_pci_bus(void) 297{ 298 struct pci_bus bus; 299 struct pci_dev dev; 300 unsigned int devfn; 301 int j; 302 303 pci_config_workaround = 0; 304 305 bus.parent = NULL; /* we scan the top level only */ 306 dev.bus = &bus; 307 dev.sysdata = NULL; 308 309 /* scan ext pci bus and io pci bus*/ 310 for (j=0; j< 1; j++) { 311 printk(KERN_INFO "scan ddb5476 external PCI bus:\n"); 312 bus.ops = &ddb5476_ext_pci_ops; 313 314 for (devfn = 0; devfn < 0x100; devfn += 8) { 315 u32 temp; 316 u16 temp16; 317 u8 temp8; 318 int i; 319 320 dev.devfn = devfn; 321 db_verify(pci_read_config_dword(&dev, 0, &temp), 322 == PCIBIOS_SUCCESSFUL); 323 if (temp == 0xffffffff) continue; 324 325 printk(KERN_INFO "slot %d: (addr %d) \n", devfn/8, 326 11+devfn/8); 327 328 /* verify read word and byte */ 329 db_verify(pci_read_config_word(&dev, 2, &temp16), 330 == PCIBIOS_SUCCESSFUL); 331 db_assert(temp16 == (temp >> 16)); 332 db_verify(pci_read_config_byte(&dev, 3, &temp8), 333 == PCIBIOS_SUCCESSFUL); 334 db_assert(temp8 == (temp >> 24)); 335 db_verify(pci_read_config_byte(&dev, 1, &temp8), 336 == PCIBIOS_SUCCESSFUL); 337 db_assert(temp8 == ((temp >> 8) & 0xff)); 338 339 for (i=0; i < 16; i++) { 340 if ((i%4) == 0) 341 printk(KERN_INFO); 342 db_verify(pci_read_config_dword(&dev, i*4, &temp), 343 == PCIBIOS_SUCCESSFUL); 344 printk("\t%08X", temp); 345 if ((i%4) == 3) 346 printk("\n"); 347 } 348 } 349 } 350 351 pci_config_workaround = 1; 352} 353#endif 354