xref: /openbmc/linux/drivers/misc/cxl/vphb.c (revision 6f7f0b3df6d49316c6f27390bb5ec250255be548)
1*6f7f0b3dSMichael Neuling /*
2*6f7f0b3dSMichael Neuling  * Copyright 2014 IBM Corp.
3*6f7f0b3dSMichael Neuling  *
4*6f7f0b3dSMichael Neuling  * This program is free software; you can redistribute it and/or
5*6f7f0b3dSMichael Neuling  * modify it under the terms of the GNU General Public License
6*6f7f0b3dSMichael Neuling  * as published by the Free Software Foundation; either version
7*6f7f0b3dSMichael Neuling  * 2 of the License, or (at your option) any later version.
8*6f7f0b3dSMichael Neuling  */
9*6f7f0b3dSMichael Neuling 
10*6f7f0b3dSMichael Neuling #include <linux/pci.h>
11*6f7f0b3dSMichael Neuling #include <misc/cxl.h>
12*6f7f0b3dSMichael Neuling #include "cxl.h"
13*6f7f0b3dSMichael Neuling 
14*6f7f0b3dSMichael Neuling static int cxl_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
15*6f7f0b3dSMichael Neuling {
16*6f7f0b3dSMichael Neuling 	if (dma_mask < DMA_BIT_MASK(64)) {
17*6f7f0b3dSMichael Neuling 		pr_info("%s only 64bit DMA supported on CXL", __func__);
18*6f7f0b3dSMichael Neuling 		return -EIO;
19*6f7f0b3dSMichael Neuling 	}
20*6f7f0b3dSMichael Neuling 
21*6f7f0b3dSMichael Neuling 	*(pdev->dev.dma_mask) = dma_mask;
22*6f7f0b3dSMichael Neuling 	return 0;
23*6f7f0b3dSMichael Neuling }
24*6f7f0b3dSMichael Neuling 
25*6f7f0b3dSMichael Neuling static int cxl_pci_probe_mode(struct pci_bus *bus)
26*6f7f0b3dSMichael Neuling {
27*6f7f0b3dSMichael Neuling 	return PCI_PROBE_NORMAL;
28*6f7f0b3dSMichael Neuling }
29*6f7f0b3dSMichael Neuling 
30*6f7f0b3dSMichael Neuling static int cxl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
31*6f7f0b3dSMichael Neuling {
32*6f7f0b3dSMichael Neuling 	return -ENODEV;
33*6f7f0b3dSMichael Neuling }
34*6f7f0b3dSMichael Neuling 
35*6f7f0b3dSMichael Neuling static void cxl_teardown_msi_irqs(struct pci_dev *pdev)
36*6f7f0b3dSMichael Neuling {
37*6f7f0b3dSMichael Neuling 	/*
38*6f7f0b3dSMichael Neuling 	 * MSI should never be set but need still need to provide this call
39*6f7f0b3dSMichael Neuling 	 * back.
40*6f7f0b3dSMichael Neuling 	 */
41*6f7f0b3dSMichael Neuling }
42*6f7f0b3dSMichael Neuling 
43*6f7f0b3dSMichael Neuling static bool cxl_pci_enable_device_hook(struct pci_dev *dev)
44*6f7f0b3dSMichael Neuling {
45*6f7f0b3dSMichael Neuling 	struct pci_controller *phb;
46*6f7f0b3dSMichael Neuling 	struct cxl_afu *afu;
47*6f7f0b3dSMichael Neuling 	struct cxl_context *ctx;
48*6f7f0b3dSMichael Neuling 
49*6f7f0b3dSMichael Neuling 	phb = pci_bus_to_host(dev->bus);
50*6f7f0b3dSMichael Neuling 	afu = (struct cxl_afu *)phb->private_data;
51*6f7f0b3dSMichael Neuling 	set_dma_ops(&dev->dev, &dma_direct_ops);
52*6f7f0b3dSMichael Neuling 	set_dma_offset(&dev->dev, PAGE_OFFSET);
53*6f7f0b3dSMichael Neuling 
54*6f7f0b3dSMichael Neuling 	/*
55*6f7f0b3dSMichael Neuling 	 * Allocate a context to do cxl things too.  If we eventually do real
56*6f7f0b3dSMichael Neuling 	 * DMA ops, we'll need a default context to attach them to
57*6f7f0b3dSMichael Neuling 	 */
58*6f7f0b3dSMichael Neuling 	ctx = cxl_dev_context_init(dev);
59*6f7f0b3dSMichael Neuling 	if (!ctx)
60*6f7f0b3dSMichael Neuling 		return false;
61*6f7f0b3dSMichael Neuling 	dev->dev.archdata.cxl_ctx = ctx;
62*6f7f0b3dSMichael Neuling 
63*6f7f0b3dSMichael Neuling 	return (cxl_afu_check_and_enable(afu) == 0);
64*6f7f0b3dSMichael Neuling }
65*6f7f0b3dSMichael Neuling 
66*6f7f0b3dSMichael Neuling static void cxl_pci_disable_device(struct pci_dev *dev)
67*6f7f0b3dSMichael Neuling {
68*6f7f0b3dSMichael Neuling 	struct cxl_context *ctx = cxl_get_context(dev);
69*6f7f0b3dSMichael Neuling 
70*6f7f0b3dSMichael Neuling 	if (ctx) {
71*6f7f0b3dSMichael Neuling 		if (ctx->status == STARTED) {
72*6f7f0b3dSMichael Neuling 			dev_err(&dev->dev, "Default context started\n");
73*6f7f0b3dSMichael Neuling 			return;
74*6f7f0b3dSMichael Neuling 		}
75*6f7f0b3dSMichael Neuling 		cxl_release_context(ctx);
76*6f7f0b3dSMichael Neuling 	}
77*6f7f0b3dSMichael Neuling }
78*6f7f0b3dSMichael Neuling 
79*6f7f0b3dSMichael Neuling static resource_size_t cxl_pci_window_alignment(struct pci_bus *bus,
80*6f7f0b3dSMichael Neuling 						unsigned long type)
81*6f7f0b3dSMichael Neuling {
82*6f7f0b3dSMichael Neuling 	return 1;
83*6f7f0b3dSMichael Neuling }
84*6f7f0b3dSMichael Neuling 
85*6f7f0b3dSMichael Neuling static void cxl_pci_reset_secondary_bus(struct pci_dev *dev)
86*6f7f0b3dSMichael Neuling {
87*6f7f0b3dSMichael Neuling 	/* Should we do an AFU reset here ? */
88*6f7f0b3dSMichael Neuling }
89*6f7f0b3dSMichael Neuling 
90*6f7f0b3dSMichael Neuling static int cxl_pcie_cfg_record(u8 bus, u8 devfn)
91*6f7f0b3dSMichael Neuling {
92*6f7f0b3dSMichael Neuling 	return (bus << 8) + devfn;
93*6f7f0b3dSMichael Neuling }
94*6f7f0b3dSMichael Neuling 
95*6f7f0b3dSMichael Neuling static unsigned long cxl_pcie_cfg_addr(struct pci_controller* phb,
96*6f7f0b3dSMichael Neuling 				       u8 bus, u8 devfn, int offset)
97*6f7f0b3dSMichael Neuling {
98*6f7f0b3dSMichael Neuling 	int record = cxl_pcie_cfg_record(bus, devfn);
99*6f7f0b3dSMichael Neuling 
100*6f7f0b3dSMichael Neuling 	return (unsigned long)phb->cfg_addr + ((unsigned long)phb->cfg_data * record) + offset;
101*6f7f0b3dSMichael Neuling }
102*6f7f0b3dSMichael Neuling 
103*6f7f0b3dSMichael Neuling 
104*6f7f0b3dSMichael Neuling static int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn,
105*6f7f0b3dSMichael Neuling 				int offset, int len,
106*6f7f0b3dSMichael Neuling 				volatile void __iomem **ioaddr,
107*6f7f0b3dSMichael Neuling 				u32 *mask, int *shift)
108*6f7f0b3dSMichael Neuling {
109*6f7f0b3dSMichael Neuling 	struct pci_controller *phb;
110*6f7f0b3dSMichael Neuling 	struct cxl_afu *afu;
111*6f7f0b3dSMichael Neuling 	unsigned long addr;
112*6f7f0b3dSMichael Neuling 
113*6f7f0b3dSMichael Neuling 	phb = pci_bus_to_host(bus);
114*6f7f0b3dSMichael Neuling 	afu = (struct cxl_afu *)phb->private_data;
115*6f7f0b3dSMichael Neuling 	if (phb == NULL)
116*6f7f0b3dSMichael Neuling 		return PCIBIOS_DEVICE_NOT_FOUND;
117*6f7f0b3dSMichael Neuling 	if (cxl_pcie_cfg_record(bus->number, devfn) > afu->crs_num)
118*6f7f0b3dSMichael Neuling 		return PCIBIOS_DEVICE_NOT_FOUND;
119*6f7f0b3dSMichael Neuling 	if (offset >= (unsigned long)phb->cfg_data)
120*6f7f0b3dSMichael Neuling 		return PCIBIOS_BAD_REGISTER_NUMBER;
121*6f7f0b3dSMichael Neuling 	addr = cxl_pcie_cfg_addr(phb, bus->number, devfn, offset);
122*6f7f0b3dSMichael Neuling 
123*6f7f0b3dSMichael Neuling 	*ioaddr = (void *)(addr & ~0x3ULL);
124*6f7f0b3dSMichael Neuling 	*shift = ((addr & 0x3) * 8);
125*6f7f0b3dSMichael Neuling 	switch (len) {
126*6f7f0b3dSMichael Neuling 	case 1:
127*6f7f0b3dSMichael Neuling 		*mask = 0xff;
128*6f7f0b3dSMichael Neuling 		break;
129*6f7f0b3dSMichael Neuling 	case 2:
130*6f7f0b3dSMichael Neuling 		*mask = 0xffff;
131*6f7f0b3dSMichael Neuling 		break;
132*6f7f0b3dSMichael Neuling 	default:
133*6f7f0b3dSMichael Neuling 		*mask = 0xffffffff;
134*6f7f0b3dSMichael Neuling 		break;
135*6f7f0b3dSMichael Neuling 	}
136*6f7f0b3dSMichael Neuling 	return 0;
137*6f7f0b3dSMichael Neuling }
138*6f7f0b3dSMichael Neuling 
139*6f7f0b3dSMichael Neuling static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
140*6f7f0b3dSMichael Neuling 				int offset, int len, u32 *val)
141*6f7f0b3dSMichael Neuling {
142*6f7f0b3dSMichael Neuling 	volatile void __iomem *ioaddr;
143*6f7f0b3dSMichael Neuling 	int shift, rc;
144*6f7f0b3dSMichael Neuling 	u32 mask;
145*6f7f0b3dSMichael Neuling 
146*6f7f0b3dSMichael Neuling 	rc = cxl_pcie_config_info(bus, devfn, offset, len, &ioaddr,
147*6f7f0b3dSMichael Neuling 				  &mask, &shift);
148*6f7f0b3dSMichael Neuling 	if (rc)
149*6f7f0b3dSMichael Neuling 		return rc;
150*6f7f0b3dSMichael Neuling 
151*6f7f0b3dSMichael Neuling 	/* Can only read 32 bits */
152*6f7f0b3dSMichael Neuling 	*val = (in_le32(ioaddr) >> shift) & mask;
153*6f7f0b3dSMichael Neuling 	return PCIBIOS_SUCCESSFUL;
154*6f7f0b3dSMichael Neuling }
155*6f7f0b3dSMichael Neuling 
156*6f7f0b3dSMichael Neuling static int cxl_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
157*6f7f0b3dSMichael Neuling 				 int offset, int len, u32 val)
158*6f7f0b3dSMichael Neuling {
159*6f7f0b3dSMichael Neuling 	volatile void __iomem *ioaddr;
160*6f7f0b3dSMichael Neuling 	u32 v, mask;
161*6f7f0b3dSMichael Neuling 	int shift, rc;
162*6f7f0b3dSMichael Neuling 
163*6f7f0b3dSMichael Neuling 	rc = cxl_pcie_config_info(bus, devfn, offset, len, &ioaddr,
164*6f7f0b3dSMichael Neuling 				  &mask, &shift);
165*6f7f0b3dSMichael Neuling 	if (rc)
166*6f7f0b3dSMichael Neuling 		return rc;
167*6f7f0b3dSMichael Neuling 
168*6f7f0b3dSMichael Neuling 	/* Can only write 32 bits so do read-modify-write */
169*6f7f0b3dSMichael Neuling 	mask <<= shift;
170*6f7f0b3dSMichael Neuling 	val <<= shift;
171*6f7f0b3dSMichael Neuling 
172*6f7f0b3dSMichael Neuling 	v = (in_le32(ioaddr) & ~mask) || (val & mask);
173*6f7f0b3dSMichael Neuling 
174*6f7f0b3dSMichael Neuling 	out_le32(ioaddr, v);
175*6f7f0b3dSMichael Neuling 	return PCIBIOS_SUCCESSFUL;
176*6f7f0b3dSMichael Neuling }
177*6f7f0b3dSMichael Neuling 
178*6f7f0b3dSMichael Neuling static struct pci_ops cxl_pcie_pci_ops =
179*6f7f0b3dSMichael Neuling {
180*6f7f0b3dSMichael Neuling 	.read = cxl_pcie_read_config,
181*6f7f0b3dSMichael Neuling 	.write = cxl_pcie_write_config,
182*6f7f0b3dSMichael Neuling };
183*6f7f0b3dSMichael Neuling 
184*6f7f0b3dSMichael Neuling 
185*6f7f0b3dSMichael Neuling static struct pci_controller_ops cxl_pci_controller_ops =
186*6f7f0b3dSMichael Neuling {
187*6f7f0b3dSMichael Neuling 	.probe_mode = cxl_pci_probe_mode,
188*6f7f0b3dSMichael Neuling 	.enable_device_hook = cxl_pci_enable_device_hook,
189*6f7f0b3dSMichael Neuling 	.disable_device = cxl_pci_disable_device,
190*6f7f0b3dSMichael Neuling 	.release_device = cxl_pci_disable_device,
191*6f7f0b3dSMichael Neuling 	.window_alignment = cxl_pci_window_alignment,
192*6f7f0b3dSMichael Neuling 	.reset_secondary_bus = cxl_pci_reset_secondary_bus,
193*6f7f0b3dSMichael Neuling 	.setup_msi_irqs = cxl_setup_msi_irqs,
194*6f7f0b3dSMichael Neuling 	.teardown_msi_irqs = cxl_teardown_msi_irqs,
195*6f7f0b3dSMichael Neuling 	.dma_set_mask = cxl_dma_set_mask,
196*6f7f0b3dSMichael Neuling };
197*6f7f0b3dSMichael Neuling 
198*6f7f0b3dSMichael Neuling int cxl_pci_vphb_add(struct cxl_afu *afu)
199*6f7f0b3dSMichael Neuling {
200*6f7f0b3dSMichael Neuling 	struct pci_dev *phys_dev;
201*6f7f0b3dSMichael Neuling 	struct pci_controller *phb, *phys_phb;
202*6f7f0b3dSMichael Neuling 
203*6f7f0b3dSMichael Neuling 	phys_dev = to_pci_dev(afu->adapter->dev.parent);
204*6f7f0b3dSMichael Neuling 	phys_phb = pci_bus_to_host(phys_dev->bus);
205*6f7f0b3dSMichael Neuling 
206*6f7f0b3dSMichael Neuling 	/* Alloc and setup PHB data structure */
207*6f7f0b3dSMichael Neuling 	phb = pcibios_alloc_controller(phys_phb->dn);
208*6f7f0b3dSMichael Neuling 
209*6f7f0b3dSMichael Neuling 	if (!phb)
210*6f7f0b3dSMichael Neuling 		return -ENODEV;
211*6f7f0b3dSMichael Neuling 
212*6f7f0b3dSMichael Neuling 	/* Setup parent in sysfs */
213*6f7f0b3dSMichael Neuling 	phb->parent = &phys_dev->dev;
214*6f7f0b3dSMichael Neuling 
215*6f7f0b3dSMichael Neuling 	/* Setup the PHB using arch provided callback */
216*6f7f0b3dSMichael Neuling 	phb->ops = &cxl_pcie_pci_ops;
217*6f7f0b3dSMichael Neuling 	phb->cfg_addr = afu->afu_desc_mmio + afu->crs_offset;
218*6f7f0b3dSMichael Neuling 	phb->cfg_data = (void *)(u64)afu->crs_len;
219*6f7f0b3dSMichael Neuling 	phb->private_data = afu;
220*6f7f0b3dSMichael Neuling 	phb->controller_ops = cxl_pci_controller_ops;
221*6f7f0b3dSMichael Neuling 
222*6f7f0b3dSMichael Neuling 	/* Scan the bus */
223*6f7f0b3dSMichael Neuling 	pcibios_scan_phb(phb);
224*6f7f0b3dSMichael Neuling 	if (phb->bus == NULL)
225*6f7f0b3dSMichael Neuling 		return -ENXIO;
226*6f7f0b3dSMichael Neuling 
227*6f7f0b3dSMichael Neuling 	/* Claim resources. This might need some rework as well depending
228*6f7f0b3dSMichael Neuling 	 * whether we are doing probe-only or not, like assigning unassigned
229*6f7f0b3dSMichael Neuling 	 * resources etc...
230*6f7f0b3dSMichael Neuling 	 */
231*6f7f0b3dSMichael Neuling 	pcibios_claim_one_bus(phb->bus);
232*6f7f0b3dSMichael Neuling 
233*6f7f0b3dSMichael Neuling 	/* Add probed PCI devices to the device model */
234*6f7f0b3dSMichael Neuling 	pci_bus_add_devices(phb->bus);
235*6f7f0b3dSMichael Neuling 
236*6f7f0b3dSMichael Neuling 	afu->phb = phb;
237*6f7f0b3dSMichael Neuling 
238*6f7f0b3dSMichael Neuling 	return 0;
239*6f7f0b3dSMichael Neuling }
240*6f7f0b3dSMichael Neuling 
241*6f7f0b3dSMichael Neuling 
242*6f7f0b3dSMichael Neuling void cxl_pci_vphb_remove(struct cxl_afu *afu)
243*6f7f0b3dSMichael Neuling {
244*6f7f0b3dSMichael Neuling 	struct pci_controller *phb;
245*6f7f0b3dSMichael Neuling 
246*6f7f0b3dSMichael Neuling 	/* If there is no configuration record we won't have one of these */
247*6f7f0b3dSMichael Neuling 	if (!afu || !afu->phb)
248*6f7f0b3dSMichael Neuling 		return;
249*6f7f0b3dSMichael Neuling 
250*6f7f0b3dSMichael Neuling 	phb = afu->phb;
251*6f7f0b3dSMichael Neuling 
252*6f7f0b3dSMichael Neuling 	pci_remove_root_bus(phb->bus);
253*6f7f0b3dSMichael Neuling }
254*6f7f0b3dSMichael Neuling 
255*6f7f0b3dSMichael Neuling struct cxl_afu *cxl_pci_to_afu(struct pci_dev *dev)
256*6f7f0b3dSMichael Neuling {
257*6f7f0b3dSMichael Neuling 	struct pci_controller *phb;
258*6f7f0b3dSMichael Neuling 
259*6f7f0b3dSMichael Neuling 	phb = pci_bus_to_host(dev->bus);
260*6f7f0b3dSMichael Neuling 
261*6f7f0b3dSMichael Neuling 	return (struct cxl_afu *)phb->private_data;
262*6f7f0b3dSMichael Neuling }
263*6f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_pci_to_afu);
264*6f7f0b3dSMichael Neuling 
265*6f7f0b3dSMichael Neuling unsigned int cxl_pci_to_cfg_record(struct pci_dev *dev)
266*6f7f0b3dSMichael Neuling {
267*6f7f0b3dSMichael Neuling 	return cxl_pcie_cfg_record(dev->bus->number, dev->devfn);
268*6f7f0b3dSMichael Neuling }
269*6f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_pci_to_cfg_record);
270