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