1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/pci.h>
4 #include <linux/spinlock.h>
5 #include <asm/bootinfo.h>
6 
7 #include <asm/nile4.h>
8 #include <asm/lasat/lasat.h>
9 
10 #define PCI_ACCESS_READ  0
11 #define PCI_ACCESS_WRITE 1
12 
13 #define LO(reg) (reg / 4)
14 #define HI(reg) (reg / 4 + 1)
15 
16 static volatile unsigned long * const vrc_pciregs = (void *)Vrc5074_BASE;
17 
18 static spinlock_t nile4_pci_lock;
19 
nile4_pcibios_config_access(unsigned char access_type,struct pci_dev * dev,unsigned char reg,u32 * data)20 static int nile4_pcibios_config_access(unsigned char access_type,
21        struct pci_dev *dev, unsigned char reg, u32 *data)
22 {
23 	unsigned char bus = dev->bus->number;
24 	unsigned char dev_fn = dev->devfn;
25 	u32 adr, mask, err;
26 
27 	if ((bus == 0) && (PCI_SLOT(dev_fn) > 8))
28 		/* The addressing scheme chosen leaves room for just
29 		 * 8 devices on the first bus (besides the PCI
30 		 * controller itself) */
31 		return PCIBIOS_DEVICE_NOT_FOUND;
32 
33 	if ((bus == 0) && (dev_fn == PCI_DEVFN(0,0))) {
34 		/* Access controller registers directly */
35 		if (access_type == PCI_ACCESS_WRITE) {
36 			vrc_pciregs[(0x200+reg) >> 2] = *data;
37 		} else {
38 			*data = vrc_pciregs[(0x200+reg) >> 2];
39 		}
40 	        return PCIBIOS_SUCCESSFUL;
41 	}
42 
43 	/* Temporarily map PCI Window 1 to config space */
44 	mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
45 	vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (bus ? 0x200 : 0);
46 
47 	/* Clear PCI Error register. This also clears the Error Type
48 	 * bits in the Control register */
49 	vrc_pciregs[LO(NILE4_PCIERR)] = 0;
50 	vrc_pciregs[HI(NILE4_PCIERR)] = 0;
51 
52 	/* Setup address */
53 	if (bus == 0)
54 		adr = KSEG1ADDR(PCI_WINDOW1) +
55 		      ((1 << (PCI_SLOT(dev_fn) + 15)) |
56 		       (PCI_FUNC(dev_fn) << 8) | (reg & ~3));
57 	else
58 		adr = KSEG1ADDR(PCI_WINDOW1) | (bus << 16) | (dev_fn << 8) |
59 		      (reg & ~3);
60 
61 	if (access_type == PCI_ACCESS_WRITE)
62 		*(u32 *)adr = *data;
63 	else
64 		*data = *(u32 *)adr;
65 
66 	/* Check for master or target abort */
67 	err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
68 
69 	/* Restore PCI Window 1 */
70 	vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
71 
72 	if (err)
73 		return PCIBIOS_DEVICE_NOT_FOUND;
74 
75 	return PCIBIOS_SUCCESSFUL;
76 }
77 
78 /*
79  * We can't address 8 and 16 bit words directly.  Instead we have to
80  * read/write a 32bit word and mask/modify the data we actually want.
81  */
nile4_pcibios_read_config_byte(struct pci_dev * dev,int reg,u8 * val)82 static int nile4_pcibios_read_config_byte(struct pci_dev *dev, int reg, u8 *val)
83 {
84 	unsigned long flags;
85         u32 data = 0;
86 	int err;
87 
88 	spin_lock_irqsave(&nile4_pci_lock, flags);
89 	err = nile4_pcibios_config_access(PCI_ACCESS_READ, dev, reg, &data);
90 	spin_unlock_irqrestore(&nile4_pci_lock, flags);
91 
92 	if (err)
93 		return err;
94 
95 	*val = (data >> ((reg & 3) << 3)) & 0xff;
96 
97 	return PCIBIOS_SUCCESSFUL;
98 }
99 
nile4_pcibios_read_config_word(struct pci_dev * dev,int reg,u16 * val)100 static int nile4_pcibios_read_config_word(struct pci_dev *dev, int reg, u16 *val)
101 {
102 	unsigned long flags;
103         u32 data = 0;
104 	int err;
105 
106 	if (reg & 1)
107 		return PCIBIOS_BAD_REGISTER_NUMBER;
108 
109 	spin_lock_irqsave(&nile4_pci_lock, flags);
110 	err = nile4_pcibios_config_access(PCI_ACCESS_READ, dev, reg, &data);
111 	spin_unlock_irqrestore(&nile4_pci_lock, flags);
112 
113 	if (err)
114 		return err;
115 
116 	*val = (data >> ((reg & 3) << 3)) & 0xffff;
117 
118 	return PCIBIOS_SUCCESSFUL;
119 }
120 
nile4_pcibios_read_config_dword(struct pci_dev * dev,int reg,u32 * val)121 static int nile4_pcibios_read_config_dword(struct pci_dev *dev, int reg, u32 *val)
122 {
123 	unsigned long flags;
124         u32 data = 0;
125 	int err;
126 
127 	if (reg & 3)
128 		return PCIBIOS_BAD_REGISTER_NUMBER;
129 
130 	spin_lock_irqsave(&nile4_pci_lock, flags);
131 	err = nile4_pcibios_config_access(PCI_ACCESS_READ, dev, reg, &data);
132 	spin_unlock_irqrestore(&nile4_pci_lock, flags);
133 
134 	if (err)
135 		return err;
136 
137 	*val = data;
138 
139 	return PCIBIOS_SUCCESSFUL;
140 }
141 
142 
nile4_pcibios_write_config_byte(struct pci_dev * dev,int reg,u8 val)143 static int nile4_pcibios_write_config_byte(struct pci_dev *dev, int reg, u8 val)
144 {
145 	unsigned long flags;
146         u32 data = 0;
147 	int err;
148 
149 	spin_lock_irqsave(&nile4_pci_lock, flags);
150         err = nile4_pcibios_config_access(PCI_ACCESS_READ, dev, reg, &data);
151         if (err)
152 		goto out;
153 
154 	data = (data & ~(0xff << ((reg & 3) << 3))) | (val << ((reg & 3) << 3));
155 	err = nile4_pcibios_config_access(PCI_ACCESS_WRITE, dev, reg, &data);
156 
157 out:
158 	spin_unlock_irqrestore(&nile4_pci_lock, flags);
159 	return err;
160 }
161 
nile4_pcibios_write_config_word(struct pci_dev * dev,int reg,u16 val)162 static int nile4_pcibios_write_config_word(struct pci_dev *dev, int reg, u16 val)
163 {
164 	unsigned long flags;
165         u32 data = 0;
166 	int err;
167 
168 	if (reg & 1)
169 		return PCIBIOS_BAD_REGISTER_NUMBER;
170 
171 	spin_lock_irqsave(&nile4_pci_lock, flags);
172         err = nile4_pcibios_config_access(PCI_ACCESS_READ, dev, reg, &data);
173         if (err)
174 	       goto out;
175 
176 	data = (data & ~(0xffff << ((reg & 3) << 3))) | (val << ((reg&3) << 3));
177 	err = nile4_pcibios_config_access(PCI_ACCESS_WRITE, dev, reg, &data);
178 
179 out:
180 	spin_unlock_irqrestore(&nile4_pci_lock, flags);
181 	return err;
182 }
183 
nile4_pcibios_write_config_dword(struct pci_dev * dev,int reg,u32 val)184 static int nile4_pcibios_write_config_dword(struct pci_dev *dev, int reg, u32 val)
185 {
186 	unsigned long flags;
187         u32 data = 0;
188 	int err;
189 
190 	if (reg & 3)
191 		return PCIBIOS_BAD_REGISTER_NUMBER;
192 
193 	spin_lock_irqsave(&nile4_pci_lock, flags);
194 	err = nile4_pcibios_config_access(PCI_ACCESS_WRITE, dev, reg, &val);
195 	spin_unlock_irqrestore(&nile4_pci_lock, flags);
196 
197 	if (err)
198 		return -1;
199 	else
200 		return PCIBIOS_SUCCESSFUL;
201 out:
202 	return err;
203 }
204 
205 struct pci_ops nile4_pci_ops = {
206 	nile4_pcibios_read_config_byte,
207 	nile4_pcibios_read_config_word,
208 	nile4_pcibios_read_config_dword,
209 	nile4_pcibios_write_config_byte,
210 	nile4_pcibios_write_config_word,
211 	nile4_pcibios_write_config_dword
212 };
213