1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 2015 IBM Corp.
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/slab.h>
10 #include <linux/of_address.h>
11 #include <linux/of_platform.h>
16 static const __be32
*read_prop_string(const struct device_node
*np
,
17 const char *prop_name
)
21 prop
= of_get_property(np
, prop_name
, NULL
);
22 if (cxl_verbose
&& prop
)
23 pr_info("%s: %s\n", prop_name
, (char *) prop
);
27 static const __be32
*read_prop_dword(const struct device_node
*np
,
28 const char *prop_name
, u32
*val
)
32 prop
= of_get_property(np
, prop_name
, NULL
);
34 *val
= be32_to_cpu(prop
[0]);
35 if (cxl_verbose
&& prop
)
36 pr_info("%s: %#x (%u)\n", prop_name
, *val
, *val
);
40 static const __be64
*read_prop64_dword(const struct device_node
*np
,
41 const char *prop_name
, u64
*val
)
45 prop
= of_get_property(np
, prop_name
, NULL
);
47 *val
= be64_to_cpu(prop
[0]);
48 if (cxl_verbose
&& prop
)
49 pr_info("%s: %#llx (%llu)\n", prop_name
, *val
, *val
);
54 static int read_handle(struct device_node
*np
, u64
*handle
)
59 /* Get address and size of the node */
60 prop
= of_get_address(np
, 0, &size
, NULL
);
64 /* Helper to read a big number; size is in cells (not bytes) */
65 *handle
= of_read_number(prop
, of_n_addr_cells(np
));
69 static int read_phys_addr(struct device_node
*np
, char *prop_name
,
72 int i
, len
, entry_size
, naddr
, nsize
, type
;
76 naddr
= of_n_addr_cells(np
);
77 nsize
= of_n_size_cells(np
);
79 prop
= of_get_property(np
, prop_name
, &len
);
81 entry_size
= naddr
+ nsize
;
82 for (i
= 0; i
< (len
/ 4); i
+= entry_size
, prop
+= entry_size
) {
83 type
= be32_to_cpu(prop
[0]);
84 addr
= of_read_number(prop
, naddr
);
85 size
= of_read_number(&prop
[naddr
], nsize
);
87 case 0: /* unit address */
88 afu
->guest
->handle
= addr
;
91 afu
->guest
->p2n_phys
+= addr
;
92 afu
->guest
->p2n_size
= size
;
94 case 2: /* problem state area */
95 afu
->psn_phys
+= addr
;
96 afu
->adapter
->ps_size
= size
;
99 pr_err("Invalid address type %d found in %s property of AFU\n",
104 pr_info("%s: %#x %#llx (size %#llx)\n",
105 prop_name
, type
, addr
, size
);
111 static int read_vpd(struct cxl
*adapter
, struct cxl_afu
*afu
)
115 size_t len
= sizeof(vpd
);
120 rc
= cxl_guest_read_adapter_vpd(adapter
, vpd
, len
);
122 rc
= cxl_guest_read_afu_vpd(afu
, vpd
, len
);
125 cxl_dump_debug_buffer(vpd
, rc
);
131 int cxl_of_read_afu_handle(struct cxl_afu
*afu
, struct device_node
*afu_np
)
133 if (read_handle(afu_np
, &afu
->guest
->handle
))
135 pr_devel("AFU handle: 0x%.16llx\n", afu
->guest
->handle
);
140 int cxl_of_read_afu_properties(struct cxl_afu
*afu
, struct device_node
*np
)
145 u16 device_id
, vendor_id
;
146 u32 val
= 0, class_code
;
148 /* Properties are read in the same order as listed in PAPR */
151 pr_info("Dump of the 'ibm,coherent-platform-function' node properties:\n");
153 prop
= of_get_property(np
, "compatible", &len
);
156 p
= (char *) prop
+ i
;
157 pr_info("compatible: %s\n", p
);
160 read_prop_string(np
, "name");
163 rc
= read_phys_addr(np
, "reg", afu
);
167 rc
= read_phys_addr(np
, "assigned-addresses", afu
);
171 if (afu
->psn_phys
== 0)
177 read_prop_string(np
, "ibm,loc-code");
178 read_prop_string(np
, "device_type");
181 read_prop_dword(np
, "ibm,#processes", &afu
->max_procs_virtualised
);
184 read_prop_dword(np
, "ibm,scratchpad-size", &val
);
185 read_prop_dword(np
, "ibm,programmable", &val
);
186 read_prop_string(np
, "ibm,phandle");
190 read_prop_dword(np
, "ibm,max-ints-per-process", &afu
->guest
->max_ints
);
191 afu
->irqs_max
= afu
->guest
->max_ints
;
193 prop
= read_prop_dword(np
, "ibm,min-ints-per-process", &afu
->pp_irqs
);
195 /* One extra interrupt for the PSL interrupt is already
196 * included. Remove it now to keep only AFU interrupts and
197 * match the native case.
203 read_prop_dword(np
, "ibm,max-ints", &val
);
204 read_prop_dword(np
, "ibm,vpd-size", &val
);
207 read_prop64_dword(np
, "ibm,error-buffer-size", &afu
->eb_len
);
211 read_prop_dword(np
, "ibm,config-record-type", &val
);
213 read_prop64_dword(np
, "ibm,config-record-size", &afu
->crs_len
);
216 read_prop_dword(np
, "ibm,#config-records", &afu
->crs_num
);
219 for (i
= 0; i
< afu
->crs_num
; i
++) {
220 rc
= cxl_ops
->afu_cr_read16(afu
, i
, PCI_DEVICE_ID
,
223 pr_info("record %d - device-id: %#x\n",
225 rc
= cxl_ops
->afu_cr_read16(afu
, i
, PCI_VENDOR_ID
,
228 pr_info("record %d - vendor-id: %#x\n",
230 rc
= cxl_ops
->afu_cr_read32(afu
, i
, PCI_CLASS_REVISION
,
234 pr_info("record %d - class-code: %#x\n",
239 read_prop_dword(np
, "ibm,function-number", &val
);
240 read_prop_dword(np
, "ibm,privileged-function", &val
);
241 read_prop_dword(np
, "vendor-id", &val
);
242 read_prop_dword(np
, "device-id", &val
);
243 read_prop_dword(np
, "revision-id", &val
);
244 read_prop_dword(np
, "class-code", &val
);
245 read_prop_dword(np
, "subsystem-vendor-id", &val
);
246 read_prop_dword(np
, "subsystem-id", &val
);
249 * if "ibm,process-mmio" doesn't exist then per-process mmio is
253 prop
= read_prop_dword(np
, "ibm,process-mmio", &val
);
254 if (prop
&& val
== 1)
260 read_prop_dword(np
, "ibm,supports-aur", &val
);
261 read_prop_dword(np
, "ibm,supports-csrp", &val
);
262 read_prop_dword(np
, "ibm,supports-prr", &val
);
265 prop
= read_prop_dword(np
, "ibm,function-error-interrupt", &val
);
267 afu
->serr_hwirq
= val
;
269 pr_devel("AFU handle: %#llx\n", afu
->guest
->handle
);
270 pr_devel("p2n_phys: %#llx (size %#llx)\n",
271 afu
->guest
->p2n_phys
, afu
->guest
->p2n_size
);
272 pr_devel("psn_phys: %#llx (size %#llx)\n",
273 afu
->psn_phys
, afu
->adapter
->ps_size
);
274 pr_devel("Max number of processes virtualised=%i\n",
275 afu
->max_procs_virtualised
);
276 pr_devel("Per-process irqs min=%i, max=%i\n", afu
->pp_irqs
,
278 pr_devel("Slice error interrupt=%#lx\n", afu
->serr_hwirq
);
283 static int read_adapter_irq_config(struct cxl
*adapter
, struct device_node
*np
)
285 const __be32
*ranges
;
287 struct irq_avail
*cur
;
289 ranges
= of_get_property(np
, "interrupt-ranges", &len
);
290 if (ranges
== NULL
|| len
< (2 * sizeof(int)))
294 * encoded array of two cells per entry, each cell encoded as
297 nranges
= len
/ (2 * sizeof(int));
298 if (nranges
== 0 || (nranges
* 2 * sizeof(int)) != len
)
301 adapter
->guest
->irq_avail
= kcalloc(nranges
, sizeof(struct irq_avail
),
303 if (adapter
->guest
->irq_avail
== NULL
)
306 adapter
->guest
->irq_base_offset
= be32_to_cpu(ranges
[0]);
307 for (i
= 0; i
< nranges
; i
++) {
308 cur
= &adapter
->guest
->irq_avail
[i
];
309 cur
->offset
= be32_to_cpu(ranges
[i
* 2]);
310 cur
->range
= be32_to_cpu(ranges
[i
* 2 + 1]);
311 cur
->bitmap
= kcalloc(BITS_TO_LONGS(cur
->range
),
312 sizeof(*cur
->bitmap
), GFP_KERNEL
);
313 if (cur
->bitmap
== NULL
)
315 if (cur
->offset
< adapter
->guest
->irq_base_offset
)
316 adapter
->guest
->irq_base_offset
= cur
->offset
;
318 pr_info("available IRQ range: %#lx-%#lx (%lu)\n",
319 cur
->offset
, cur
->offset
+ cur
->range
- 1,
322 adapter
->guest
->irq_nranges
= nranges
;
323 spin_lock_init(&adapter
->guest
->irq_alloc_lock
);
327 for (i
--; i
>= 0; i
--) {
328 cur
= &adapter
->guest
->irq_avail
[i
];
331 kfree(adapter
->guest
->irq_avail
);
332 adapter
->guest
->irq_avail
= NULL
;
336 int cxl_of_read_adapter_handle(struct cxl
*adapter
, struct device_node
*np
)
338 if (read_handle(np
, &adapter
->guest
->handle
))
340 pr_devel("Adapter handle: 0x%.16llx\n", adapter
->guest
->handle
);
345 int cxl_of_read_adapter_properties(struct cxl
*adapter
, struct device_node
*np
)
347 int rc
, len
, naddr
, i
;
352 /* Properties are read in the same order as listed in PAPR */
354 naddr
= of_n_addr_cells(np
);
357 pr_info("Dump of the 'ibm,coherent-platform-facility' node properties:\n");
359 read_prop_dword(np
, "#address-cells", &val
);
360 read_prop_dword(np
, "#size-cells", &val
);
362 prop
= of_get_property(np
, "compatible", &len
);
365 p
= (char *) prop
+ i
;
366 pr_info("compatible: %s\n", p
);
369 read_prop_string(np
, "name");
370 read_prop_string(np
, "model");
372 prop
= of_get_property(np
, "reg", NULL
);
374 pr_info("reg: addr:%#llx size:%#x\n",
375 of_read_number(prop
, naddr
),
376 be32_to_cpu(prop
[naddr
]));
379 read_prop_string(np
, "ibm,loc-code");
382 if ((rc
= read_adapter_irq_config(adapter
, np
)))
386 read_prop_string(np
, "device_type");
387 read_prop_string(np
, "ibm,phandle");
390 prop
= read_prop_dword(np
, "ibm,caia-version", &val
);
392 adapter
->caia_major
= (val
& 0xFF00) >> 8;
393 adapter
->caia_minor
= val
& 0xFF;
396 prop
= read_prop_dword(np
, "ibm,psl-revision", &val
);
398 adapter
->psl_rev
= val
;
400 prop
= read_prop_string(np
, "status");
402 adapter
->guest
->status
= kasprintf(GFP_KERNEL
, "%s", (char *) prop
);
403 if (adapter
->guest
->status
== NULL
)
407 prop
= read_prop_dword(np
, "vendor-id", &val
);
409 adapter
->guest
->vendor
= val
;
411 prop
= read_prop_dword(np
, "device-id", &val
);
413 adapter
->guest
->device
= val
;
416 read_prop_dword(np
, "ibm,privileged-facility", &val
);
417 read_prop_dword(np
, "revision-id", &val
);
418 read_prop_dword(np
, "class-code", &val
);
421 prop
= read_prop_dword(np
, "subsystem-vendor-id", &val
);
423 adapter
->guest
->subsystem_vendor
= val
;
425 prop
= read_prop_dword(np
, "subsystem-id", &val
);
427 adapter
->guest
->subsystem
= val
;
430 read_vpd(adapter
, NULL
);
435 static int cxl_of_remove(struct platform_device
*pdev
)
440 adapter
= dev_get_drvdata(&pdev
->dev
);
441 for (afu
= 0; afu
< adapter
->slices
; afu
++)
442 cxl_guest_remove_afu(adapter
->afu
[afu
]);
444 cxl_guest_remove_adapter(adapter
);
448 static void cxl_of_shutdown(struct platform_device
*pdev
)
453 int cxl_of_probe(struct platform_device
*pdev
)
455 struct device_node
*np
= NULL
;
456 struct device_node
*afu_np
= NULL
;
457 struct cxl
*adapter
= NULL
;
459 int slice
= 0, slice_ok
= 0;
461 pr_devel("in %s\n", __func__
);
463 np
= pdev
->dev
.of_node
;
468 adapter
= cxl_guest_init_adapter(np
, pdev
);
469 if (IS_ERR(adapter
)) {
470 dev_err(&pdev
->dev
, "guest_init_adapter failed: %li\n", PTR_ERR(adapter
));
471 return PTR_ERR(adapter
);
475 for_each_child_of_node(np
, afu_np
) {
476 if ((ret
= cxl_guest_init_afu(adapter
, slice
, afu_np
)))
477 dev_err(&pdev
->dev
, "AFU %i failed to initialise: %i\n",
485 dev_info(&pdev
->dev
, "No active AFU");
492 static const struct of_device_id cxl_of_match
[] = {
493 { .compatible
= "ibm,coherent-platform-facility",},
496 MODULE_DEVICE_TABLE(of
, cxl_of_match
);
498 struct platform_driver cxl_of_driver
= {
501 .of_match_table
= cxl_of_match
,
504 .probe
= cxl_of_probe
,
505 .remove
= cxl_of_remove
,
506 .shutdown
= cxl_of_shutdown
,