blob: 46ed541a3ec7e2bcc0c1f4a58e18f4596c96b39d [file] [log] [blame]
Kyle Swenson8d8f6542021-03-15 11:02:55 -06001#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};