Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / mips / pci / ops-loongson3.c
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
15 static 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
50 static 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
70 static 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
98 struct pci_ops loongson_pci_ops = {
99         .read = loongson3_pci_pcibios_read,
100         .write = loongson3_pci_pcibios_write
101 };