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
6 * Copyright (C) 2015, 2016 Cavium, Inc.
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/ioport.h>
12 #include <linux/of_pci.h>
14 #include <linux/pci-ecam.h>
15 #include <linux/platform_device.h>
17 static void set_val(u32 v
, int where
, int size
, u32
*val
)
19 int shift
= (where
& 3) * 8;
21 pr_debug("set_val %04x: %08x\n", (unsigned)(where
& ~3), v
);
30 static int handle_ea_bar(u32 e0
, int bar
, struct pci_bus
*bus
,
31 unsigned int devfn
, int where
, int size
, u32
*val
)
36 /* Entries are 16-byte aligned; bits[2,3] select word in entry */
37 int where_a
= where
& 0xc;
40 set_val(e0
, where
, size
, val
);
41 return PCIBIOS_SUCCESSFUL
;
44 addr
= bus
->ops
->map_bus(bus
, devfn
, bar
); /* BAR 0 */
47 return PCIBIOS_DEVICE_NOT_FOUND
;
51 v
|= 2; /* EA entry-1. Base-L */
52 set_val(v
, where
, size
, val
);
53 return PCIBIOS_SUCCESSFUL
;
59 addr
= bus
->ops
->map_bus(bus
, devfn
, bar
); /* BAR 0 */
62 return PCIBIOS_DEVICE_NOT_FOUND
;
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 */
70 v
|= 0xc; /* EA entry-2. Offset-L */
71 set_val(v
, where
, size
, val
);
72 return PCIBIOS_SUCCESSFUL
;
75 addr
= bus
->ops
->map_bus(bus
, devfn
, bar
+ 4); /* BAR 1 */
78 return PCIBIOS_DEVICE_NOT_FOUND
;
80 v
= readl(addr
); /* EA entry-3. Base-H */
81 set_val(v
, where
, size
, val
);
82 return PCIBIOS_SUCCESSFUL
;
84 return PCIBIOS_DEVICE_NOT_FOUND
;
87 static int thunder_ecam_p2_config_read(struct pci_bus
*bus
, unsigned int devfn
,
88 int where
, int size
, u32
*val
)
90 struct pci_config_window
*cfg
= bus
->sysdata
;
91 int where_a
= where
& ~3;
96 /* EA Base[63:32] may be missing some bits ... */
104 return pci_generic_config_read(bus
, devfn
, where
, size
, val
);
107 addr
= bus
->ops
->map_bus(bus
, devfn
, where_a
);
110 return PCIBIOS_DEVICE_NOT_FOUND
;
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.
120 node_bits
= (cfg
->res
.start
>> 32) & (1 << 12);
123 set_val(v
, where
, size
, val
);
125 return PCIBIOS_SUCCESSFUL
;
128 static int thunder_ecam_config_read(struct pci_bus
*bus
, unsigned int devfn
,
129 int where
, int size
, u32
*val
)
136 int where_a
= where
& ~3;
138 addr
= bus
->ops
->map_bus(bus
, devfn
, 0xc);
141 return PCIBIOS_DEVICE_NOT_FOUND
;
146 /* Check for non type-00 header */
147 cfg_type
= (v
>> 16) & 0x7f;
149 addr
= bus
->ops
->map_bus(bus
, devfn
, 8);
152 return PCIBIOS_DEVICE_NOT_FOUND
;
155 class_rev
= readl(addr
);
156 if (class_rev
== 0xffffffff)
159 if ((class_rev
& 0xff) >= 8) {
160 /* Pass-2 handling */
163 return thunder_ecam_p2_config_read(bus
, devfn
, where
,
168 * All BARs have fixed addresses specified by the EA
169 * capability; they must return zero on read.
172 ((where
>= 0x10 && where
< 0x2c) ||
173 (where
>= 0x1a4 && where
< 0x1bc))) {
174 /* BAR or SR-IOV BAR */
176 return PCIBIOS_SUCCESSFUL
;
179 addr
= bus
->ops
->map_bus(bus
, devfn
, 0);
182 return PCIBIOS_DEVICE_NOT_FOUND
;
185 vendor_device
= readl(addr
);
186 if (vendor_device
== 0xffffffff)
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
);
193 /* Check for non type-00 header */
196 bool is_nic
= (vendor_device
== 0xa01e177d);
197 bool is_tns
= (vendor_device
== 0xa01f177d);
199 addr
= bus
->ops
->map_bus(bus
, devfn
, 0x70);
202 return PCIBIOS_DEVICE_NOT_FOUND
;
206 has_msix
= (v
& 0xff00) != 0;
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
;
213 if (where_a
== 0xb0) {
214 addr
= bus
->ops
->map_bus(bus
, devfn
, where_a
);
217 return PCIBIOS_DEVICE_NOT_FOUND
;
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
;
226 if (where_a
== 0xbc) {
228 v
= 0x40014; /* EA last in chain, 4 entries */
230 v
= 0x30014; /* EA last in chain, 3 entries */
232 v
= 0x20014; /* EA last in chain, 2 entries */
234 v
= 0x10014; /* EA last in chain, 1 entry */
235 set_val(v
, where
, size
, val
);
236 return PCIBIOS_SUCCESSFUL
;
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
,
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
,
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
,
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
,
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
,
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;
270 if (where_a
== 0x70) {
271 addr
= bus
->ops
->map_bus(bus
, devfn
, where_a
);
274 return PCIBIOS_DEVICE_NOT_FOUND
;
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
;
283 if (where_a
== 0xbc) {
285 v
= 0x10014; /* EA last in chain, 1 entry */
287 v
= 0x00014; /* EA last in chain, no entries */
288 set_val(v
, where
, size
, val
);
289 return PCIBIOS_SUCCESSFUL
;
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
;
303 if (where_a
== 0xc4 && is_nic_bridge
) {
304 /* Enabled, not-Write, SP=ff, PP=05, BEI=6, ES=4 */
306 set_val(v
, where
, size
, val
);
307 return PCIBIOS_SUCCESSFUL
;
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
;
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
;
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
;
324 if (where_a
== 0xd4 && is_nic_bridge
) {
325 v
= 0x0000000f; /* MaxOffset-H */
326 set_val(v
, where
, size
, val
);
327 return PCIBIOS_SUCCESSFUL
;
331 return pci_generic_config_read(bus
, devfn
, where
, size
, val
);
334 static int thunder_ecam_config_write(struct pci_bus
*bus
, unsigned int devfn
,
335 int where
, int size
, u32 val
)
338 * All BARs have fixed addresses; ignore BAR writes so they
339 * don't get corrupted.
341 if ((where
>= 0x10 && where
< 0x2c) ||
342 (where
>= 0x1a4 && where
< 0x1bc))
343 /* BAR or SR-IOV BAR */
344 return PCIBIOS_SUCCESSFUL
;
346 return pci_generic_config_write(bus
, devfn
, where
, size
, val
);
349 static struct pci_ecam_ops pci_thunder_ecam_ops
= {
352 .map_bus
= pci_ecam_map_bus
,
353 .read
= thunder_ecam_config_read
,
354 .write
= thunder_ecam_config_write
,
358 static const struct of_device_id thunder_ecam_of_match
[] = {
359 { .compatible
= "cavium,pci-host-thunder-ecam" },
363 static int thunder_ecam_probe(struct platform_device
*pdev
)
365 return pci_host_common_probe(pdev
, &pci_thunder_ecam_ops
);
368 static struct platform_driver thunder_ecam_driver
= {
370 .name
= KBUILD_MODNAME
,
371 .of_match_table
= thunder_ecam_of_match
,
373 .probe
= thunder_ecam_probe
,
375 builtin_platform_driver(thunder_ecam_driver
);