blob: d50a3dc2d8db127e225df7bfd24dd435500526cc [file] [log] [blame]
David Daney7b6e7ba2016-03-04 14:31:48 -08001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2015, 2016 Cavium, Inc.
7 */
8
9#include <linux/kernel.h>
Paul Gortmakerd0c6fd72016-07-02 19:13:32 -040010#include <linux/init.h>
David Daney7b6e7ba2016-03-04 14:31:48 -080011#include <linux/ioport.h>
12#include <linux/of_pci.h>
13#include <linux/of.h>
Jayachandran C80955f92016-06-10 21:55:09 +020014#include <linux/pci-ecam.h>
David Daney7b6e7ba2016-03-04 14:31:48 -080015#include <linux/platform_device.h>
16
David Daney7b6e7ba2016-03-04 14:31:48 -080017static void set_val(u32 v, int where, int size, u32 *val)
18{
19 int shift = (where & 3) * 8;
20
21 pr_debug("set_val %04x: %08x\n", (unsigned)(where & ~3), v);
22 v >>= shift;
23 if (size == 1)
24 v &= 0xff;
25 else if (size == 2)
26 v &= 0xffff;
27 *val = v;
28}
29
30static int handle_ea_bar(u32 e0, int bar, struct pci_bus *bus,
31 unsigned int devfn, int where, int size, u32 *val)
32{
33 void __iomem *addr;
34 u32 v;
35
36 /* Entries are 16-byte aligned; bits[2,3] select word in entry */
37 int where_a = where & 0xc;
38
39 if (where_a == 0) {
40 set_val(e0, where, size, val);
41 return PCIBIOS_SUCCESSFUL;
42 }
43 if (where_a == 0x4) {
44 addr = bus->ops->map_bus(bus, devfn, bar); /* BAR 0 */
45 if (!addr) {
46 *val = ~0;
47 return PCIBIOS_DEVICE_NOT_FOUND;
48 }
49 v = readl(addr);
50 v &= ~0xf;
51 v |= 2; /* EA entry-1. Base-L */
52 set_val(v, where, size, val);
53 return PCIBIOS_SUCCESSFUL;
54 }
55 if (where_a == 0x8) {
56 u32 barl_orig;
57 u32 barl_rb;
58
59 addr = bus->ops->map_bus(bus, devfn, bar); /* BAR 0 */
60 if (!addr) {
61 *val = ~0;
62 return PCIBIOS_DEVICE_NOT_FOUND;
63 }
64 barl_orig = readl(addr + 0);
65 writel(0xffffffff, addr + 0);
66 barl_rb = readl(addr + 0);
67 writel(barl_orig, addr + 0);
68 /* zeros in unsettable bits */
69 v = ~barl_rb & ~3;
70 v |= 0xc; /* EA entry-2. Offset-L */
71 set_val(v, where, size, val);
72 return PCIBIOS_SUCCESSFUL;
73 }
74 if (where_a == 0xc) {
75 addr = bus->ops->map_bus(bus, devfn, bar + 4); /* BAR 1 */
76 if (!addr) {
77 *val = ~0;
78 return PCIBIOS_DEVICE_NOT_FOUND;
79 }
80 v = readl(addr); /* EA entry-3. Base-H */
81 set_val(v, where, size, val);
82 return PCIBIOS_SUCCESSFUL;
83 }
84 return PCIBIOS_DEVICE_NOT_FOUND;
85}
86
87static int thunder_ecam_p2_config_read(struct pci_bus *bus, unsigned int devfn,
88 int where, int size, u32 *val)
89{
Jayachandran C1958e712016-05-11 17:34:46 -050090 struct pci_config_window *cfg = bus->sysdata;
David Daney7b6e7ba2016-03-04 14:31:48 -080091 int where_a = where & ~3;
92 void __iomem *addr;
93 u32 node_bits;
94 u32 v;
95
96 /* EA Base[63:32] may be missing some bits ... */
97 switch (where_a) {
98 case 0xa8:
99 case 0xbc:
100 case 0xd0:
101 case 0xe4:
102 break;
103 default:
104 return pci_generic_config_read(bus, devfn, where, size, val);
105 }
106
107 addr = bus->ops->map_bus(bus, devfn, where_a);
108 if (!addr) {
109 *val = ~0;
110 return PCIBIOS_DEVICE_NOT_FOUND;
111 }
112
113 v = readl(addr);
114
115 /*
116 * Bit 44 of the 64-bit Base must match the same bit in
117 * the config space access window. Since we are working with
118 * the high-order 32 bits, shift everything down by 32 bits.
119 */
Jayachandran C1958e712016-05-11 17:34:46 -0500120 node_bits = (cfg->res.start >> 32) & (1 << 12);
David Daney7b6e7ba2016-03-04 14:31:48 -0800121
122 v |= node_bits;
123 set_val(v, where, size, val);
124
125 return PCIBIOS_SUCCESSFUL;
126}
127
128static int thunder_ecam_config_read(struct pci_bus *bus, unsigned int devfn,
129 int where, int size, u32 *val)
130{
131 u32 v;
132 u32 vendor_device;
133 u32 class_rev;
134 void __iomem *addr;
135 int cfg_type;
136 int where_a = where & ~3;
137
138 addr = bus->ops->map_bus(bus, devfn, 0xc);
139 if (!addr) {
140 *val = ~0;
141 return PCIBIOS_DEVICE_NOT_FOUND;
142 }
143
144 v = readl(addr);
145
146 /* Check for non type-00 header */
147 cfg_type = (v >> 16) & 0x7f;
148
149 addr = bus->ops->map_bus(bus, devfn, 8);
150 if (!addr) {
151 *val = ~0;
152 return PCIBIOS_DEVICE_NOT_FOUND;
153 }
154
155 class_rev = readl(addr);
156 if (class_rev == 0xffffffff)
157 goto no_emulation;
158
159 if ((class_rev & 0xff) >= 8) {
160 /* Pass-2 handling */
161 if (cfg_type)
162 goto no_emulation;
163 return thunder_ecam_p2_config_read(bus, devfn, where,
164 size, val);
165 }
166
167 /*
168 * All BARs have fixed addresses specified by the EA
169 * capability; they must return zero on read.
170 */
171 if (cfg_type == 0 &&
172 ((where >= 0x10 && where < 0x2c) ||
173 (where >= 0x1a4 && where < 0x1bc))) {
174 /* BAR or SR-IOV BAR */
175 *val = 0;
176 return PCIBIOS_SUCCESSFUL;
177 }
178
179 addr = bus->ops->map_bus(bus, devfn, 0);
180 if (!addr) {
181 *val = ~0;
182 return PCIBIOS_DEVICE_NOT_FOUND;
183 }
184
185 vendor_device = readl(addr);
186 if (vendor_device == 0xffffffff)
187 goto no_emulation;
188
189 pr_debug("%04x:%04x - Fix pass#: %08x, where: %03x, devfn: %03x\n",
190 vendor_device & 0xffff, vendor_device >> 16, class_rev,
191 (unsigned) where, devfn);
192
193 /* Check for non type-00 header */
194 if (cfg_type == 0) {
195 bool has_msix;
196 bool is_nic = (vendor_device == 0xa01e177d);
197 bool is_tns = (vendor_device == 0xa01f177d);
198
199 addr = bus->ops->map_bus(bus, devfn, 0x70);
200 if (!addr) {
201 *val = ~0;
202 return PCIBIOS_DEVICE_NOT_FOUND;
203 }
204 /* E_CAP */
205 v = readl(addr);
206 has_msix = (v & 0xff00) != 0;
207
208 if (!has_msix && where_a == 0x70) {
209 v |= 0xbc00; /* next capability is EA at 0xbc */
210 set_val(v, where, size, val);
211 return PCIBIOS_SUCCESSFUL;
212 }
213 if (where_a == 0xb0) {
214 addr = bus->ops->map_bus(bus, devfn, where_a);
215 if (!addr) {
216 *val = ~0;
217 return PCIBIOS_DEVICE_NOT_FOUND;
218 }
219 v = readl(addr);
220 if (v & 0xff00)
221 pr_err("Bad MSIX cap header: %08x\n", v);
222 v |= 0xbc00; /* next capability is EA at 0xbc */
223 set_val(v, where, size, val);
224 return PCIBIOS_SUCCESSFUL;
225 }
226 if (where_a == 0xbc) {
227 if (is_nic)
228 v = 0x40014; /* EA last in chain, 4 entries */
229 else if (is_tns)
230 v = 0x30014; /* EA last in chain, 3 entries */
231 else if (has_msix)
232 v = 0x20014; /* EA last in chain, 2 entries */
233 else
234 v = 0x10014; /* EA last in chain, 1 entry */
235 set_val(v, where, size, val);
236 return PCIBIOS_SUCCESSFUL;
237 }
238 if (where_a >= 0xc0 && where_a < 0xd0)
239 /* EA entry-0. PP=0, BAR0 Size:3 */
240 return handle_ea_bar(0x80ff0003,
241 0x10, bus, devfn, where,
242 size, val);
243 if (where_a >= 0xd0 && where_a < 0xe0 && has_msix)
244 /* EA entry-1. PP=0, BAR4 Size:3 */
245 return handle_ea_bar(0x80ff0043,
246 0x20, bus, devfn, where,
247 size, val);
248 if (where_a >= 0xe0 && where_a < 0xf0 && is_tns)
249 /* EA entry-2. PP=0, BAR2, Size:3 */
250 return handle_ea_bar(0x80ff0023,
251 0x18, bus, devfn, where,
252 size, val);
253 if (where_a >= 0xe0 && where_a < 0xf0 && is_nic)
254 /* EA entry-2. PP=4, VF_BAR0 (9), Size:3 */
255 return handle_ea_bar(0x80ff0493,
256 0x1a4, bus, devfn, where,
257 size, val);
258 if (where_a >= 0xf0 && where_a < 0x100 && is_nic)
259 /* EA entry-3. PP=4, VF_BAR4 (d), Size:3 */
260 return handle_ea_bar(0x80ff04d3,
261 0x1b4, bus, devfn, where,
262 size, val);
263 } else if (cfg_type == 1) {
264 bool is_rsl_bridge = devfn == 0x08;
265 bool is_rad_bridge = devfn == 0xa0;
266 bool is_zip_bridge = devfn == 0xa8;
267 bool is_dfa_bridge = devfn == 0xb0;
268 bool is_nic_bridge = devfn == 0x10;
269
270 if (where_a == 0x70) {
271 addr = bus->ops->map_bus(bus, devfn, where_a);
272 if (!addr) {
273 *val = ~0;
274 return PCIBIOS_DEVICE_NOT_FOUND;
275 }
276 v = readl(addr);
277 if (v & 0xff00)
278 pr_err("Bad PCIe cap header: %08x\n", v);
279 v |= 0xbc00; /* next capability is EA at 0xbc */
280 set_val(v, where, size, val);
281 return PCIBIOS_SUCCESSFUL;
282 }
283 if (where_a == 0xbc) {
284 if (is_nic_bridge)
285 v = 0x10014; /* EA last in chain, 1 entry */
286 else
287 v = 0x00014; /* EA last in chain, no entries */
288 set_val(v, where, size, val);
289 return PCIBIOS_SUCCESSFUL;
290 }
291 if (where_a == 0xc0) {
292 if (is_rsl_bridge || is_nic_bridge)
293 v = 0x0101; /* subordinate:secondary = 1:1 */
294 else if (is_rad_bridge)
295 v = 0x0202; /* subordinate:secondary = 2:2 */
296 else if (is_zip_bridge)
297 v = 0x0303; /* subordinate:secondary = 3:3 */
298 else if (is_dfa_bridge)
299 v = 0x0404; /* subordinate:secondary = 4:4 */
300 set_val(v, where, size, val);
301 return PCIBIOS_SUCCESSFUL;
302 }
303 if (where_a == 0xc4 && is_nic_bridge) {
304 /* Enabled, not-Write, SP=ff, PP=05, BEI=6, ES=4 */
305 v = 0x80ff0564;
306 set_val(v, where, size, val);
307 return PCIBIOS_SUCCESSFUL;
308 }
309 if (where_a == 0xc8 && is_nic_bridge) {
310 v = 0x00000002; /* Base-L 64-bit */
311 set_val(v, where, size, val);
312 return PCIBIOS_SUCCESSFUL;
313 }
314 if (where_a == 0xcc && is_nic_bridge) {
315 v = 0xfffffffe; /* MaxOffset-L 64-bit */
316 set_val(v, where, size, val);
317 return PCIBIOS_SUCCESSFUL;
318 }
319 if (where_a == 0xd0 && is_nic_bridge) {
320 v = 0x00008430; /* NIC Base-H */
321 set_val(v, where, size, val);
322 return PCIBIOS_SUCCESSFUL;
323 }
324 if (where_a == 0xd4 && is_nic_bridge) {
325 v = 0x0000000f; /* MaxOffset-H */
326 set_val(v, where, size, val);
327 return PCIBIOS_SUCCESSFUL;
328 }
329 }
330no_emulation:
331 return pci_generic_config_read(bus, devfn, where, size, val);
332}
333
334static int thunder_ecam_config_write(struct pci_bus *bus, unsigned int devfn,
335 int where, int size, u32 val)
336{
337 /*
338 * All BARs have fixed addresses; ignore BAR writes so they
339 * don't get corrupted.
340 */
341 if ((where >= 0x10 && where < 0x2c) ||
342 (where >= 0x1a4 && where < 0x1bc))
343 /* BAR or SR-IOV BAR */
344 return PCIBIOS_SUCCESSFUL;
345
346 return pci_generic_config_write(bus, devfn, where, size, val);
347}
348
Jayachandran C1958e712016-05-11 17:34:46 -0500349static struct pci_ecam_ops pci_thunder_ecam_ops = {
David Daney7b6e7ba2016-03-04 14:31:48 -0800350 .bus_shift = 20,
Jayachandran C1958e712016-05-11 17:34:46 -0500351 .pci_ops = {
352 .map_bus = pci_ecam_map_bus,
David Daney7b6e7ba2016-03-04 14:31:48 -0800353 .read = thunder_ecam_config_read,
354 .write = thunder_ecam_config_write,
355 }
356};
357
358static const struct of_device_id thunder_ecam_of_match[] = {
Jayachandran C1958e712016-05-11 17:34:46 -0500359 { .compatible = "cavium,pci-host-thunder-ecam" },
David Daney7b6e7ba2016-03-04 14:31:48 -0800360 { },
361};
David Daney7b6e7ba2016-03-04 14:31:48 -0800362
363static int thunder_ecam_probe(struct platform_device *pdev)
364{
Jayachandran C1958e712016-05-11 17:34:46 -0500365 return pci_host_common_probe(pdev, &pci_thunder_ecam_ops);
David Daney7b6e7ba2016-03-04 14:31:48 -0800366}
367
368static struct platform_driver thunder_ecam_driver = {
369 .driver = {
370 .name = KBUILD_MODNAME,
371 .of_match_table = thunder_ecam_of_match,
372 },
373 .probe = thunder_ecam_probe,
374};
Paul Gortmakerd0c6fd72016-07-02 19:13:32 -0400375builtin_platform_driver(thunder_ecam_driver);