1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/types.h>
4 #include <linux/kernel.h>
6 #include <asm/mips-boards/bonito64.h>
10 #define PCI_ACCESS_READ 0
11 #define PCI_ACCESS_WRITE 1
13 #define HT1LO_PCICFG_BASE 0x1a000000
14 #define HT1LO_PCICFG_BASE_TP1 0x1b000000
16 static int loongson3_pci_config_access(unsigned char access_type,
17 struct pci_bus *bus, unsigned int devfn,
20 unsigned char busnum = bus->number;
21 int function = PCI_FUNC(devfn);
22 int device = PCI_SLOT(devfn);
27 if (where < PCI_CFG_SPACE_SIZE) { /* standard config */
28 addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
31 return PCIBIOS_DEVICE_NOT_FOUND;
32 addrp = (void *)TO_UNCAC(HT1LO_PCICFG_BASE | addr);
34 addrp = (void *)TO_UNCAC(HT1LO_PCICFG_BASE_TP1 | addr);
36 } else if (where < PCI_CFG_SPACE_EXP_SIZE) { /* extended config */
37 struct pci_dev *rootdev;
39 rootdev = pci_get_domain_bus_and_slot(0, 0, 0);
41 return PCIBIOS_DEVICE_NOT_FOUND;
43 addr = pci_resource_start(rootdev, 3);
45 return PCIBIOS_DEVICE_NOT_FOUND;
47 addr |= busnum << 20 | device << 15 | function << 12 | reg;
48 addrp = (void *)TO_UNCAC(addr);
50 return PCIBIOS_DEVICE_NOT_FOUND;
53 if (access_type == PCI_ACCESS_WRITE)
57 if (*data == 0xffffffff) {
59 return PCIBIOS_DEVICE_NOT_FOUND;
62 return PCIBIOS_SUCCESSFUL;
65 static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
66 int where, int size, u32 *val)
69 int ret = loongson3_pci_config_access(PCI_ACCESS_READ,
70 bus, devfn, where, &data);
72 if (ret != PCIBIOS_SUCCESSFUL)
76 *val = (data >> ((where & 3) << 3)) & 0xff;
78 *val = (data >> ((where & 3) << 3)) & 0xffff;
82 return PCIBIOS_SUCCESSFUL;
85 static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
86 int where, int size, u32 val)
94 ret = loongson3_pci_config_access(PCI_ACCESS_READ,
95 bus, devfn, where, &data);
96 if (ret != PCIBIOS_SUCCESSFUL)
100 data = (data & ~(0xff << ((where & 3) << 3))) |
101 (val << ((where & 3) << 3));
103 data = (data & ~(0xffff << ((where & 3) << 3))) |
104 (val << ((where & 3) << 3));
107 ret = loongson3_pci_config_access(PCI_ACCESS_WRITE,
108 bus, devfn, where, &data);
113 struct pci_ops loongson_pci_ops = {
114 .read = loongson3_pci_pcibios_read,
115 .write = loongson3_pci_pcibios_write