File Index
Files and directories
Sign in
FILE

pci-thunder-pem.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pci/controller/pci-thunder-pem.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2015 - 2016 Cavium, Inc.
  4 */
  5
  6#include <linux/bitfield.h>
  7#include <linux/kernel.h>
  8#include <linux/init.h>
  9#include <linux/pci.h>
 10#include <linux/of_address.h>
 11#include <linux/of_pci.h>
 12#include <linux/pci-acpi.h>
 13#include <linux/pci-ecam.h>
 14#include <linux/platform_device.h>
 15#include <linux/io-64-nonatomic-lo-hi.h>
 16#include "../pci.h"
 17#include "pci-host-common.h"
 18
 19#if defined(CONFIG_PCI_HOST_THUNDER_PEM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))
 20
 21#define PEM_CFG_WR 0x28
 22#define PEM_CFG_RD 0x30
 23
 24/*
 25 * Enhanced Configuration Access Mechanism (ECAM)
 26 *
 27 * N.B. This is a non-standard platform-specific ECAM bus shift value.  For
 28 * standard values defined in the PCI Express Base Specification see
 29 * include/linux/pci-ecam.h.
 30 */
 31#define THUNDER_PCIE_ECAM_BUS_SHIFT	24
 32
 33struct thunder_pem_pci {
 34	u32		ea_entry[3];
 35	void __iomem	*pem_reg_base;
 36};
 37
 38static int thunder_pem_bridge_read(struct pci_bus *bus, unsigned int devfn,
 39				   int where, int size, u32 *val)
 40{
 41	u64 read_val, tmp_val;
 42	struct pci_config_window *cfg = bus->sysdata;
 43	struct thunder_pem_pci *pem_pci = (struct thunder_pem_pci *)cfg->priv;
 44
 45	if (devfn != 0 || where >= 2048)
 46		return PCIBIOS_DEVICE_NOT_FOUND;
 47
 48	/*
 49	 * 32-bit accesses only.  Write the address to the low order
 50	 * bits of PEM_CFG_RD, then trigger the read by reading back.
 51	 * The config data lands in the upper 32-bits of PEM_CFG_RD.
 52	 */
 53	read_val = where & ~3ull;
 54	writeq(read_val, pem_pci->pem_reg_base + PEM_CFG_RD);
 55	read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
 56	read_val >>= 32;
 57
 58	/*
 59	 * The config space contains some garbage, fix it up.  Also
 60	 * synthesize an EA capability for the BAR used by MSI-X.
 61	 */
 62	switch (where & ~3) {
 63	case 0x40:
 64		read_val &= 0xffff00ff;
 65		read_val |= 0x00007000; /* Skip MSI CAP */
 66		break;
 67	case 0x70: /* Express Cap */
 68		/*
 69		 * Change PME interrupt to vector 2 on T88 where it
 70		 * reads as 0, else leave it alone.
 71		 */
 72		if (!(read_val & (0x1f << 25)))
 73			read_val |= (2u << 25);
 74		break;
 75	case 0xb0: /* MSI-X Cap */
 76		/* TableSize=2 or 4, Next Cap is EA */
 77		read_val &= 0xc00000ff;
 78		/*
 79		 * If Express Cap(0x70) raw PME vector reads as 0 we are on
 80		 * T88 and TableSize is reported as 4, else TableSize
 81		 * is 2.
 82		 */
 83		writeq(0x70, pem_pci->pem_reg_base + PEM_CFG_RD);
 84		tmp_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
 85		tmp_val >>= 32;
 86		if (!(tmp_val & (0x1f << 25)))
 87			read_val |= 0x0003bc00;
 88		else
 89			read_val |= 0x0001bc00;
 90		break;
 91	case 0xb4:
 92		/* Table offset=0, BIR=0 */
 93		read_val = 0x00000000;
 94		break;
 95	case 0xb8:
 96		/* BPA offset=0xf0000, BIR=0 */
 97		read_val = 0x000f0000;
 98		break;
 99	case 0xbc:
100		/* EA, 1 entry, no next Cap */
101		read_val = 0x00010014;
102		break;
103	case 0xc0:
104		/* DW2 for type-1 */
105		read_val = 0x00000000;
106		break;
107	case 0xc4:
108		/* Entry BEI=0, PP=0x00, SP=0xff, ES=3 */
109		read_val = 0x80ff0003;
110		break;
111	case 0xc8:
112		read_val = pem_pci->ea_entry[0];
113		break;
114	case 0xcc:
115		read_val = pem_pci->ea_entry[1];
116		break;
117	case 0xd0:
118		read_val = pem_pci->ea_entry[2];
119		break;
120	default:
121		break;
122	}
123	read_val >>= (8 * (where & 3));
124	switch (size) {
125	case 1:
126		read_val &= 0xff;
127		break;
128	case 2:
129		read_val &= 0xffff;
130		break;
131	default:
132		break;
133	}
134	*val = read_val;
135	return PCIBIOS_SUCCESSFUL;
136}
137
138static int thunder_pem_config_read(struct pci_bus *bus, unsigned int devfn,
139				   int where, int size, u32 *val)
140{
141	struct pci_config_window *cfg = bus->sysdata;
142
143	if (bus->number < cfg->busr.start ||
144	    bus->number > cfg->busr.end)
145		return PCIBIOS_DEVICE_NOT_FOUND;
146
147	/*
148	 * The first device on the bus is the PEM PCIe bridge.
149	 * Special case its config access.
150	 */
151	if (bus->number == cfg->busr.start)
152		return thunder_pem_bridge_read(bus, devfn, where, size, val);
153
154	return pci_generic_config_read(bus, devfn, where, size, val);
155}
156
157/*
158 * Some of the w1c_bits below also include read-only or non-writable
159 * reserved bits, this makes the code simpler and is OK as the bits
160 * are not affected by writing zeros to them.
161 */
162static u32 thunder_pem_bridge_w1c_bits(u64 where_aligned)
163{
164	u32 w1c_bits = 0;
165
166	switch (where_aligned) {
167	case 0x04: /* Command/Status */
168	case 0x1c: /* Base and I/O Limit/Secondary Status */
169		w1c_bits = 0xff000000;
170		break;
171	case 0x44: /* Power Management Control and Status */
172		w1c_bits = 0xfffffe00;
173		break;
174	case 0x78: /* Device Control/Device Status */
175	case 0x80: /* Link Control/Link Status */
176	case 0x88: /* Slot Control/Slot Status */
177	case 0x90: /* Root Status */
178	case 0xa0: /* Link Control 2 Registers/Link Status 2 */
179		w1c_bits = 0xffff0000;
180		break;
181	case 0x104: /* Uncorrectable Error Status */
182	case 0x110: /* Correctable Error Status */
183	case 0x130: /* Error Status */
184	case 0x160: /* Link Control 4 */
185		w1c_bits = 0xffffffff;
186		break;
187	default:
188		break;
189	}
190	return w1c_bits;
191}
192
193/* Some bits must be written to one so they appear to be read-only. */
194static u32 thunder_pem_bridge_w1_bits(u64 where_aligned)
195{
196	u32 w1_bits;
197
198	switch (where_aligned) {
199	case 0x1c: /* I/O Base / I/O Limit, Secondary Status */
200		/* Force 32-bit I/O addressing. */
201		w1_bits = 0x0101;
202		break;
203	case 0x24: /* Prefetchable Memory Base / Prefetchable Memory Limit */
204		/* Force 64-bit addressing */
205		w1_bits = 0x00010001;
206		break;
207	default:
208		w1_bits = 0;
209		break;
210	}
211	return w1_bits;
212}
213
214static int thunder_pem_bridge_write(struct pci_bus *bus, unsigned int devfn,
215				    int where, int size, u32 val)
216{
217	struct pci_config_window *cfg = bus->sysdata;
218	struct thunder_pem_pci *pem_pci = (struct thunder_pem_pci *)cfg->priv;
219	u64 write_val, read_val;
220	u64 where_aligned = where & ~3ull;
221	u32 mask = 0;
222
223
224	if (devfn != 0 || where >= 2048)
225		return PCIBIOS_DEVICE_NOT_FOUND;
226
227	/*
228	 * 32-bit accesses only.  If the write is for a size smaller
229	 * than 32-bits, we must first read the 32-bit value and merge
230	 * in the desired bits and then write the whole 32-bits back
231	 * out.
232	 */
233	switch (size) {
234	case 1:
235		writeq(where_aligned, pem_pci->pem_reg_base + PEM_CFG_RD);
236		read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
237		read_val >>= 32;
238		mask = ~(0xff << (8 * (where & 3)));
239		read_val &= mask;
240		val = (val & 0xff) << (8 * (where & 3));
241		val |= (u32)read_val;
242		break;
243	case 2:
244		writeq(where_aligned, pem_pci->pem_reg_base + PEM_CFG_RD);
245		read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
246		read_val >>= 32;
247		mask = ~(0xffff << (8 * (where & 3)));
248		read_val &= mask;
249		val = (val & 0xffff) << (8 * (where & 3));
250		val |= (u32)read_val;
251		break;
252	default:
253		break;
254	}
255
256	/*
257	 * By expanding the write width to 32 bits, we may
258	 * inadvertently hit some W1C bits that were not intended to
259	 * be written.  Calculate the mask that must be applied to the
260	 * data to be written to avoid these cases.
261	 */
262	if (mask) {
263		u32 w1c_bits = thunder_pem_bridge_w1c_bits(where);
264
265		if (w1c_bits) {
266			mask &= w1c_bits;
267			val &= ~mask;
268		}
269	}
270
271	/*
272	 * Some bits must be read-only with value of one.  Since the
273	 * access method allows these to be cleared if a zero is
274	 * written, force them to one before writing.
275	 */
276	val |= thunder_pem_bridge_w1_bits(where_aligned);
277
278	/*
279	 * Low order bits are the config address, the high order 32
280	 * bits are the data to be written.
281	 */
282	write_val = (((u64)val) << 32) | where_aligned;
283	writeq(write_val, pem_pci->pem_reg_base + PEM_CFG_WR);
284	return PCIBIOS_SUCCESSFUL;
285}
286
287static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
288				    int where, int size, u32 val)
289{
290	struct pci_config_window *cfg = bus->sysdata;
291
292	if (bus->number < cfg->busr.start ||
293	    bus->number > cfg->busr.end)
294		return PCIBIOS_DEVICE_NOT_FOUND;
295	/*
296	 * The first device on the bus is the PEM PCIe bridge.
297	 * Special case its config access.
298	 */
299	if (bus->number == cfg->busr.start)
300		return thunder_pem_bridge_write(bus, devfn, where, size, val);
301
302
303	return pci_generic_config_write(bus, devfn, where, size, val);
304}
305
306static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg,
307			    struct resource *res_pem)
308{
309	struct thunder_pem_pci *pem_pci;
310	resource_size_t bar4_start;
311
312	pem_pci = devm_kzalloc(dev, sizeof(*pem_pci), GFP_KERNEL);
313	if (!pem_pci)
314		return -ENOMEM;
315
316	pem_pci->pem_reg_base = devm_ioremap(dev, res_pem->start, 0x10000);
317	if (!pem_pci->pem_reg_base)
318		return -ENOMEM;
319
320	/*
321	 * The MSI-X BAR for the PEM and AER interrupts is located at
322	 * a fixed offset from the PEM register base.  Generate a
323	 * fragment of the synthesized Enhanced Allocation capability
324	 * structure here for the BAR.
325	 */
326	bar4_start = res_pem->start + 0xf00000;
327	pem_pci->ea_entry[0] = lower_32_bits(bar4_start) | 2;
328	pem_pci->ea_entry[1] = lower_32_bits(res_pem->end - bar4_start) & ~3u;
329	pem_pci->ea_entry[2] = upper_32_bits(bar4_start);
330
331	cfg->priv = pem_pci;
332	return 0;
333}
334
335#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
336
337#define PEM_RES_BASE		0x87e0c0000000ULL
338#define PEM_NODE_MASK		GENMASK_ULL(45, 44)
339#define PEM_INDX_MASK		GENMASK_ULL(26, 24)
340#define PEM_MIN_DOM_IN_NODE	4
341#define PEM_MAX_DOM_IN_NODE	10
342
343static void thunder_pem_reserve_range(struct device *dev, int seg,
344				      struct resource *r)
345{
346	resource_size_t start = r->start, end = r->end;
347	struct resource *res;
348	const char *regionid;
349
350	regionid = kasprintf(GFP_KERNEL, "PEM RC:%d", seg);
351	if (!regionid)
352		return;
353
354	res = request_mem_region(start, end - start + 1, regionid);
355	if (res)
356		res->flags &= ~IORESOURCE_BUSY;
357	else
358		kfree(regionid);
359
360	dev_info(dev, "%pR %s reserved\n", r,
361		 res ? "has been" : "could not be");
362}
363
364static void thunder_pem_legacy_fw(struct acpi_pci_root *root,
365				 struct resource *res_pem)
366{
367	int node = acpi_get_node(root->device->handle);
368	int index;
369
370	if (node == NUMA_NO_NODE)
371		node = 0;
372
373	index = root->segment - PEM_MIN_DOM_IN_NODE;
374	index -= node * PEM_MAX_DOM_IN_NODE;
375	res_pem->start = PEM_RES_BASE | FIELD_PREP(PEM_NODE_MASK, node) |
376					FIELD_PREP(PEM_INDX_MASK, index);
377	res_pem->flags = IORESOURCE_MEM;
378}
379
380static int thunder_pem_acpi_init(struct pci_config_window *cfg)
381{
382	struct device *dev = cfg->parent;
383	struct acpi_device *adev = to_acpi_device(dev);
384	struct acpi_pci_root *root = acpi_driver_data(adev);
385	struct resource *res_pem;
386	int ret;
387
388	res_pem = devm_kzalloc(&adev->dev, sizeof(*res_pem), GFP_KERNEL);
389	if (!res_pem)
390		return -ENOMEM;
391
392	ret = acpi_get_rc_resources(dev, "CAVA02B", root->segment, res_pem);
393
394	/*
395	 * If we fail to gather resources it means that we run with old
396	 * FW where we need to calculate PEM-specific resources manually.
397	 */
398	if (ret) {
399		thunder_pem_legacy_fw(root, res_pem);
400		/*
401		 * Reserve 64K size PEM specific resources. The full 16M range
402		 * size is required for thunder_pem_init() call.
403		 */
404		resource_set_size(res_pem, SZ_64K);
405		thunder_pem_reserve_range(dev, root->segment, res_pem);
406		resource_set_size(res_pem, SZ_16M);
407
408		/* Reserve PCI configuration space as well. */
409		thunder_pem_reserve_range(dev, root->segment, &cfg->res);
410	}
411
412	return thunder_pem_init(dev, cfg, res_pem);
413}
414
415const struct pci_ecam_ops thunder_pem_ecam_ops = {
416	.bus_shift	= THUNDER_PCIE_ECAM_BUS_SHIFT,
417	.init		= thunder_pem_acpi_init,
418	.pci_ops	= {
419		.map_bus	= pci_ecam_map_bus,
420		.read		= thunder_pem_config_read,
421		.write		= thunder_pem_config_write,
422	}
423};
424
425#endif
426
427#ifdef CONFIG_PCI_HOST_THUNDER_PEM
428
429static int thunder_pem_platform_init(struct pci_config_window *cfg)
430{
431	struct device *dev = cfg->parent;
432	struct platform_device *pdev = to_platform_device(dev);
433	struct resource *res_pem;
434
435	if (!dev->of_node)
436		return -EINVAL;
437
438	/*
439	 * The second register range is the PEM bridge to the PCIe
440	 * bus.  It has a different config access method than those
441	 * devices behind the bridge.
442	 */
443	res_pem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
444	if (!res_pem) {
445		dev_err(dev, "missing \"reg[1]\"property\n");
446		return -EINVAL;
447	}
448
449	return thunder_pem_init(dev, cfg, res_pem);
450}
451
452static const struct pci_ecam_ops pci_thunder_pem_ops = {
453	.bus_shift	= THUNDER_PCIE_ECAM_BUS_SHIFT,
454	.init		= thunder_pem_platform_init,
455	.pci_ops	= {
456		.map_bus	= pci_ecam_map_bus,
457		.read		= thunder_pem_config_read,
458		.write		= thunder_pem_config_write,
459	}
460};
461
462static const struct of_device_id thunder_pem_of_match[] = {
463	{
464		.compatible = "cavium,pci-host-thunder-pem",
465		.data = &pci_thunder_pem_ops,
466	},
467	{ },
468};
469
470static struct platform_driver thunder_pem_driver = {
471	.driver = {
472		.name = KBUILD_MODNAME,
473		.of_match_table = thunder_pem_of_match,
474		.suppress_bind_attrs = true,
475	},
476	.probe = pci_host_common_probe,
477};
478builtin_platform_driver(thunder_pem_driver);
479
480#endif
481#endif
~/ Read-only file preview.