1/* 2 * linux/arch/alpha/kernel/core_t2.c 3 * 4 * Written by Jay A Estabrook (jestabro@amt.tay1.dec.com). 5 * December 1996. 6 * 7 * based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com) 8 * 9 * Code common to all T2 core logic chips. 10 */ 11 12#include <linux/kernel.h> 13#include <linux/types.h> 14#include <linux/pci.h> 15#include <linux/sched.h> 16#include <linux/init.h> 17 18#include <asm/ptrace.h> 19#include <asm/system.h> 20 21#define __EXTERN_INLINE 22#include <asm/io.h> 23#include <asm/core_t2.h> 24#undef __EXTERN_INLINE 25 26#include "proto.h" 27#include "pci_impl.h" 28 29 30/* 31 * NOTE: Herein lie back-to-back mb instructions. They are magic. 32 * One plausible explanation is that the i/o controller does not properly 33 * handle the system transaction. Another involves timing. Ho hum. 34 */ 35 36/* 37 * BIOS32-style PCI interface: 38 */ 39 40#define DEBUG_CONFIG 0 41 42#if DEBUG_CONFIG 43# define DBG(args) printk args 44#else 45# define DBG(args) 46#endif 47 48 49/* 50 * Given a bus, device, and function number, compute resulting 51 * configuration space address and setup the T2_HAXR2 register 52 * accordingly. It is therefore not safe to have concurrent 53 * invocations to configuration space access routines, but there 54 * really shouldn't be any need for this. 55 * 56 * Type 0: 57 * 58 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 59 * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 61 * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| 62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 63 * 64 * 31:11 Device select bit. 65 * 10:8 Function number 66 * 7:2 Register number 67 * 68 * Type 1: 69 * 70 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 71 * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 73 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| 74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 75 * 76 * 31:24 reserved 77 * 23:16 bus number (8 bits = 128 possible buses) 78 * 15:11 Device number (5 bits) 79 * 10:8 function number 80 * 7:2 register number 81 * 82 * Notes: 83 * The function number selects which function of a multi-function device 84 * (e.g., SCSI and Ethernet). 85 * 86 * The register selects a DWORD (32 bit) register offset. Hence it 87 * doesn't get shifted by 2 bits as we want to "drop" the bottom two 88 * bits. 89 */ 90 91static int 92mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, 93 unsigned char *type1) 94{ 95 unsigned long addr; 96 u8 bus = dev->bus->number; 97 u8 device_fn = dev->devfn; 98 99 DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x," 100 " addr=0x%lx, type1=0x%x)\n", 101 bus, device_fn, where, pci_addr, type1)); 102 103 if (bus == 0) { 104 int device = device_fn >> 3; 105 106 /* Type 0 configuration cycle. */ 107 108 if (device > 8) { 109 DBG(("mk_conf_addr: device (%d)>20, returning -1\n", 110 device)); 111 return -1; 112 } 113 114 *type1 = 0; 115 addr = (0x0800L << device) | ((device_fn & 7) << 8) | (where); 116 } else { 117 /* Type 1 configuration cycle. */ 118 *type1 = 1; 119 addr = (bus << 16) | (device_fn << 8) | (where); 120 } 121 *pci_addr = addr; 122 DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); 123 return 0; 124} 125 126static unsigned int 127conf_read(unsigned long addr, unsigned char type1) 128{ 129 unsigned long flags; 130 unsigned int value, cpu; 131 unsigned long t2_cfg = 0; 132 133 cpu = smp_processor_id(); 134 135 __save_and_cli(flags); /* avoid getting hit by machine check */ 136 137 DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); 138 139 140 /* If Type1 access, must set T2 CFG. */ 141 if (type1) { 142 t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL; 143 *(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg; 144 mb(); 145 DBG(("conf_read: TYPE1 access\n")); 146 } 147 mb(); 148 draina(); 149 150 mcheck_expected(cpu) = 1; 151 mcheck_taken(cpu) = 0; 152 mb(); 153 154 /* Access configuration space. */ 155 value = *(vuip)addr; 156 mb(); 157 mb(); /* magic */ 158 159 if (mcheck_taken(cpu)) { 160 mcheck_taken(cpu) = 0; 161 value = 0xffffffffU; 162 mb(); 163 } 164 mcheck_expected(cpu) = 0; 165 mb(); 166 167 /* If Type1 access, must reset T2 CFG so normal IO space ops work. */ 168 if (type1) { 169 *(vulp)T2_HAE_3 = t2_cfg; 170 mb(); 171 } 172 DBG(("conf_read(): finished\n")); 173 174 __restore_flags(flags); 175 return value; 176} 177 178static void 179conf_write(unsigned long addr, unsigned int value, unsigned char type1) 180{ 181 unsigned long flags; 182 unsigned int cpu; 183 unsigned long t2_cfg = 0; 184 185 cpu = smp_processor_id(); 186 187 __save_and_cli(flags); /* avoid getting hit by machine check */ 188 189 190 /* If Type1 access, must set T2 CFG. */ 191 if (type1) { 192 t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL; 193 *(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL; 194 mb(); 195 DBG(("conf_write: TYPE1 access\n")); 196 } 197 mb(); 198 draina(); 199 200 mcheck_expected(cpu) = 1; 201 mb(); 202 203 /* Access configuration space. */ 204 *(vuip)addr = value; 205 mb(); 206 mb(); /* magic */ 207 208 mcheck_expected(cpu) = 0; 209 mb(); 210 211 /* If Type1 access, must reset T2 CFG so normal IO space ops work. */ 212 if (type1) { 213 *(vulp)T2_HAE_3 = t2_cfg; 214 mb(); 215 } 216 DBG(("conf_write(): finished\n")); 217 __restore_flags(flags); 218} 219 220static int 221t2_read_config_byte(struct pci_dev *dev, int where, u8 *value) 222{ 223 unsigned long addr, pci_addr; 224 unsigned char type1; 225 226 if (mk_conf_addr(dev, where, &pci_addr, &type1)) 227 return PCIBIOS_DEVICE_NOT_FOUND; 228 229 addr = (pci_addr << 5) + 0x00 + T2_CONF; 230 *value = conf_read(addr, type1) >> ((where & 3) * 8); 231 return PCIBIOS_SUCCESSFUL; 232} 233 234static int 235t2_read_config_word(struct pci_dev *dev, int where, u16 *value) 236{ 237 unsigned long addr, pci_addr; 238 unsigned char type1; 239 240 if (mk_conf_addr(dev, where, &pci_addr, &type1)) 241 return PCIBIOS_DEVICE_NOT_FOUND; 242 243 addr = (pci_addr << 5) + 0x08 + T2_CONF; 244 *value = conf_read(addr, type1) >> ((where & 3) * 8); 245 return PCIBIOS_SUCCESSFUL; 246} 247 248static int 249t2_read_config_dword(struct pci_dev *dev, int where, u32 *value) 250{ 251 unsigned long addr, pci_addr; 252 unsigned char type1; 253 254 if (mk_conf_addr(dev, where, &pci_addr, &type1)) 255 return PCIBIOS_DEVICE_NOT_FOUND; 256 257 addr = (pci_addr << 5) + 0x18 + T2_CONF; 258 *value = conf_read(addr, type1); 259 return PCIBIOS_SUCCESSFUL; 260} 261 262static int 263t2_write_config(struct pci_dev *dev, int where, u32 value, long mask) 264{ 265 unsigned long addr, pci_addr; 266 unsigned char type1; 267 268 if (mk_conf_addr(dev, where, &pci_addr, &type1)) 269 return PCIBIOS_DEVICE_NOT_FOUND; 270 271 addr = (pci_addr << 5) + mask + T2_CONF; 272 conf_write(addr, value << ((where & 3) * 8), type1); 273 return PCIBIOS_SUCCESSFUL; 274} 275 276static int 277t2_write_config_byte(struct pci_dev *dev, int where, u8 value) 278{ 279 return t2_write_config(dev, where, value, 0x00); 280} 281 282static int 283t2_write_config_word(struct pci_dev *dev, int where, u16 value) 284{ 285 return t2_write_config(dev, where, value, 0x08); 286} 287 288static int 289t2_write_config_dword(struct pci_dev *dev, int where, u32 value) 290{ 291 return t2_write_config(dev, where, value, 0x18); 292} 293 294struct pci_ops t2_pci_ops = 295{ 296 read_byte: t2_read_config_byte, 297 read_word: t2_read_config_word, 298 read_dword: t2_read_config_dword, 299 write_byte: t2_write_config_byte, 300 write_word: t2_write_config_word, 301 write_dword: t2_write_config_dword 302}; 303 304void __init 305t2_init_arch(void) 306{ 307 struct pci_controller *hose; 308 unsigned int i; 309 310 for (i = 0; i < NR_CPUS; i++) { 311 mcheck_expected(i) = 0; 312 mcheck_taken(i) = 0; 313 } 314 315 316 printk("t2_init: HBASE was 0x%lx\n", *(vulp)T2_HBASE); 317 318 /* 319 * Set up the PCI->physical memory translation windows. 320 * For now, window 2 is disabled. In the future, we may 321 * want to use it to do scatter/gather DMA. 322 * 323 * Window 1 goes at 1 GB and is 1 GB large. 324 */ 325 326 /* WARNING!! must correspond to the DMA_WIN params!!! */ 327 *(vulp)T2_WBASE1 = 0x400807ffU; 328 *(vulp)T2_WMASK1 = 0x3ff00000U; 329 *(vulp)T2_TBASE1 = 0; 330 331 *(vulp)T2_WBASE2 = 0x0; 332 *(vulp)T2_HBASE = 0x0; 333 334 /* Zero HAE. */ 335 *(vulp)T2_HAE_1 = 0; mb(); 336 *(vulp)T2_HAE_2 = 0; mb(); 337 *(vulp)T2_HAE_3 = 0; mb(); 338 339 /* 340 * Create our single hose. 341 */ 342 343 pci_isa_hose = hose = alloc_pci_controller(); 344 hose->io_space = &ioport_resource; 345 hose->mem_space = &iomem_resource; 346 hose->index = 0; 347 348 hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR; 349 hose->dense_mem_base = T2_DENSE_MEM - IDENT_ADDR; 350 hose->sparse_io_base = T2_IO - IDENT_ADDR; 351 hose->dense_io_base = 0; 352 353 hose->sg_isa = hose->sg_pci = NULL; 354 __direct_map_base = 0x40000000; 355 __direct_map_size = 0x40000000; 356} 357 358#define SIC_SEIC (1UL << 33) /* System Event Clear */ 359 360static void 361t2_clear_errors(int cpu) 362{ 363 struct sable_cpu_csr *cpu_regs; 364 365 cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE; 366 if (cpu == 1) 367 cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE; 368 if (cpu == 2) 369 cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE; 370 if (cpu == 3) 371 cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE; 372 373 cpu_regs->sic &= ~SIC_SEIC; 374 375 /* Clear CPU errors. */ 376 cpu_regs->bcce |= cpu_regs->bcce; 377 cpu_regs->cbe |= cpu_regs->cbe; 378 cpu_regs->bcue |= cpu_regs->bcue; 379 cpu_regs->dter |= cpu_regs->dter; 380 381 *(vulp)T2_CERR1 |= *(vulp)T2_CERR1; 382 *(vulp)T2_PERR1 |= *(vulp)T2_PERR1; 383 384 mb(); 385 mb(); /* magic */ 386} 387 388void 389t2_machine_check(unsigned long vector, unsigned long la_ptr, 390 struct pt_regs * regs) 391{ 392 int cpu = smp_processor_id(); 393 394 /* Clear the error before any reporting. */ 395 mb(); 396 mb(); /* magic */ 397 draina(); 398 t2_clear_errors(cpu); 399 wrmces(rdmces()|1); /* ??? */ 400 mb(); 401 402 process_mcheck_info(vector, la_ptr, regs, "T2", mcheck_expected(cpu)); 403} 404