11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4SLinus Torvalds * for more details. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (C) 2000, 2001 Keith M Wesolowski 71da177e4SLinus Torvalds */ 81da177e4SLinus Torvalds #include <linux/kernel.h> 91da177e4SLinus Torvalds #include <linux/init.h> 101da177e4SLinus Torvalds #include <linux/pci.h> 111da177e4SLinus Torvalds #include <linux/types.h> 121da177e4SLinus Torvalds #include <asm/pci.h> 131da177e4SLinus Torvalds #include <asm/ip32/mace.h> 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds #if 0 161da177e4SLinus Torvalds # define DPRINTK(args...) printk(args); 171da177e4SLinus Torvalds #else 181da177e4SLinus Torvalds # define DPRINTK(args...) 191da177e4SLinus Torvalds #endif 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds /* 221da177e4SLinus Torvalds * O2 has up to 5 PCI devices connected into the MACE bridge. The device 231da177e4SLinus Torvalds * map looks like this: 241da177e4SLinus Torvalds * 251da177e4SLinus Torvalds * 0 aic7xxx 0 261da177e4SLinus Torvalds * 1 aic7xxx 1 271da177e4SLinus Torvalds * 2 expansion slot 281da177e4SLinus Torvalds * 3 N/C 291da177e4SLinus Torvalds * 4 N/C 301da177e4SLinus Torvalds */ 311da177e4SLinus Torvalds 328cfaf453SGiuseppe Sacco static inline int mkaddr(struct pci_bus *bus, unsigned int devfn, 338cfaf453SGiuseppe Sacco unsigned int reg) 348cfaf453SGiuseppe Sacco { 358cfaf453SGiuseppe Sacco return ((bus->number & 0xff) << 16) | 36378a5459SGiuseppe Sacco ((devfn & 0xff) << 8) | 378cfaf453SGiuseppe Sacco (reg & 0xfc); 388cfaf453SGiuseppe Sacco } 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds static int 421da177e4SLinus Torvalds mace_pci_read_config(struct pci_bus *bus, unsigned int devfn, 431da177e4SLinus Torvalds int reg, int size, u32 *val) 441da177e4SLinus Torvalds { 45c990081bSThomas Bogendoerfer u32 control = mace->pci.control; 46c990081bSThomas Bogendoerfer 47c990081bSThomas Bogendoerfer /* disable master aborts interrupts during config read */ 48c990081bSThomas Bogendoerfer mace->pci.control = control & ~MACEPCI_CONTROL_MAR_INT; 498cfaf453SGiuseppe Sacco mace->pci.config_addr = mkaddr(bus, devfn, reg); 501da177e4SLinus Torvalds switch (size) { 511da177e4SLinus Torvalds case 1: 521da177e4SLinus Torvalds *val = mace->pci.config_data.b[(reg & 3) ^ 3]; 531da177e4SLinus Torvalds break; 541da177e4SLinus Torvalds case 2: 551da177e4SLinus Torvalds *val = mace->pci.config_data.w[((reg >> 1) & 1) ^ 1]; 561da177e4SLinus Torvalds break; 571da177e4SLinus Torvalds case 4: 581da177e4SLinus Torvalds *val = mace->pci.config_data.l; 591da177e4SLinus Torvalds break; 601da177e4SLinus Torvalds } 61c990081bSThomas Bogendoerfer /* ack possible master abort */ 62c990081bSThomas Bogendoerfer mace->pci.error &= ~MACEPCI_ERROR_MASTER_ABORT; 63c990081bSThomas Bogendoerfer mace->pci.control = control; 64*8736595bSThomas Bogendoerfer /* 65*8736595bSThomas Bogendoerfer * someone forgot to set the ultra bit for the onboard 66*8736595bSThomas Bogendoerfer * scsi chips; we fake it here 67*8736595bSThomas Bogendoerfer */ 68*8736595bSThomas Bogendoerfer if (bus->number == 0 && reg == 0x40 && size == 4 && 69*8736595bSThomas Bogendoerfer (devfn == (1 << 3) || devfn == (2 << 3))) 70*8736595bSThomas Bogendoerfer *val |= 0x1000; 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds DPRINTK("read%d: reg=%08x,val=%02x\n", size * 8, reg, *val); 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds return PCIBIOS_SUCCESSFUL; 751da177e4SLinus Torvalds } 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds static int 781da177e4SLinus Torvalds mace_pci_write_config(struct pci_bus *bus, unsigned int devfn, 791da177e4SLinus Torvalds int reg, int size, u32 val) 801da177e4SLinus Torvalds { 818cfaf453SGiuseppe Sacco mace->pci.config_addr = mkaddr(bus, devfn, reg); 821da177e4SLinus Torvalds switch (size) { 831da177e4SLinus Torvalds case 1: 841da177e4SLinus Torvalds mace->pci.config_data.b[(reg & 3) ^ 3] = val; 851da177e4SLinus Torvalds break; 861da177e4SLinus Torvalds case 2: 871da177e4SLinus Torvalds mace->pci.config_data.w[((reg >> 1) & 1) ^ 1] = val; 881da177e4SLinus Torvalds break; 891da177e4SLinus Torvalds case 4: 901da177e4SLinus Torvalds mace->pci.config_data.l = val; 911da177e4SLinus Torvalds break; 921da177e4SLinus Torvalds } 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds DPRINTK("write%d: reg=%08x,val=%02x\n", size * 8, reg, val); 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds return PCIBIOS_SUCCESSFUL; 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds struct pci_ops mace_pci_ops = { 1001da177e4SLinus Torvalds .read = mace_pci_read_config, 1011da177e4SLinus Torvalds .write = mace_pci_write_config, 1021da177e4SLinus Torvalds }; 103