• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
loongson3_pci_config_access(unsigned char access_type,struct pci_bus * bus,unsigned int devfn,int where,u32 * data)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 
loongson3_pci_pcibios_read(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 * val)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 
loongson3_pci_pcibios_write(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 val)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 };
102