1#include <linux/types.h> 2#include <linux/pci.h> 3#include <linux/kernel.h> 4 5#include <asm/mips-boards/bonito64.h> 6 7#include <loongson.h> 8 9#define PCI_ACCESS_READ 0 10#define PCI_ACCESS_WRITE 1 11 12#define HT1LO_PCICFG_BASE 0x1a000000 13#define HT1LO_PCICFG_BASE_TP1 0x1b000000 14 15static int loongson3_pci_config_access(unsigned char access_type, 16 struct pci_bus *bus, unsigned int devfn, 17 int where, u32 *data) 18{ 19 unsigned char busnum = bus->number; 20 u_int64_t addr, type; 21 void *addrp; 22 int device = PCI_SLOT(devfn); 23 int function = PCI_FUNC(devfn); 24 int reg = where & ~3; 25 26 addr = (busnum << 16) | (device << 11) | (function << 8) | reg; 27 if (busnum == 0) { 28 if (device > 31) 29 return PCIBIOS_DEVICE_NOT_FOUND; 30 addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE) | (addr & 0xffff)); 31 type = 0; 32 33 } else { 34 addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE_TP1) | (addr)); 35 type = 0x10000; 36 } 37 38 if (access_type == PCI_ACCESS_WRITE) 39 writel(*data, addrp); 40 else { 41 *data = readl(addrp); 42 if (*data == 0xffffffff) { 43 *data = -1; 44 return PCIBIOS_DEVICE_NOT_FOUND; 45 } 46 } 47 return PCIBIOS_SUCCESSFUL; 48} 49 50static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn, 51 int where, int size, u32 *val) 52{ 53 u32 data = 0; 54 int ret = loongson3_pci_config_access(PCI_ACCESS_READ, 55 bus, devfn, where, &data); 56 57 if (ret != PCIBIOS_SUCCESSFUL) 58 return ret; 59 60 if (size == 1) 61 *val = (data >> ((where & 3) << 3)) & 0xff; 62 else if (size == 2) 63 *val = (data >> ((where & 3) << 3)) & 0xffff; 64 else 65 *val = data; 66 67 return PCIBIOS_SUCCESSFUL; 68} 69 70static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn, 71 int where, int size, u32 val) 72{ 73 u32 data = 0; 74 int ret; 75 76 if (size == 4) 77 data = val; 78 else { 79 ret = loongson3_pci_config_access(PCI_ACCESS_READ, 80 bus, devfn, where, &data); 81 if (ret != PCIBIOS_SUCCESSFUL) 82 return ret; 83 84 if (size == 1) 85 data = (data & ~(0xff << ((where & 3) << 3))) | 86 (val << ((where & 3) << 3)); 87 else if (size == 2) 88 data = (data & ~(0xffff << ((where & 3) << 3))) | 89 (val << ((where & 3) << 3)); 90 } 91 92 ret = loongson3_pci_config_access(PCI_ACCESS_WRITE, 93 bus, devfn, where, &data); 94 95 return ret; 96} 97 98struct pci_ops loongson_pci_ops = { 99 .read = loongson3_pci_pcibios_read, 100 .write = loongson3_pci_pcibios_write 101}; 102