1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2016 Broadcom
4*4882a593Smuzhiyun * Author: Jayachandran C <jchandra@broadcom.com>
5*4882a593Smuzhiyun * Copyright (C) 2016 Semihalf
6*4882a593Smuzhiyun * Author: Tomasz Nowicki <tn@semihalf.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #define pr_fmt(fmt) "ACPI: " fmt
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/pci.h>
13*4882a593Smuzhiyun #include <linux/pci-acpi.h>
14*4882a593Smuzhiyun #include <linux/pci-ecam.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun /* Structure to hold entries from the MCFG table */
17*4882a593Smuzhiyun struct mcfg_entry {
18*4882a593Smuzhiyun struct list_head list;
19*4882a593Smuzhiyun phys_addr_t addr;
20*4882a593Smuzhiyun u16 segment;
21*4882a593Smuzhiyun u8 bus_start;
22*4882a593Smuzhiyun u8 bus_end;
23*4882a593Smuzhiyun };
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #ifdef CONFIG_PCI_QUIRKS
26*4882a593Smuzhiyun struct mcfg_fixup {
27*4882a593Smuzhiyun char oem_id[ACPI_OEM_ID_SIZE + 1];
28*4882a593Smuzhiyun char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
29*4882a593Smuzhiyun u32 oem_revision;
30*4882a593Smuzhiyun u16 segment;
31*4882a593Smuzhiyun struct resource bus_range;
32*4882a593Smuzhiyun const struct pci_ecam_ops *ops;
33*4882a593Smuzhiyun struct resource cfgres;
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define MCFG_BUS_RANGE(start, end) DEFINE_RES_NAMED((start), \
37*4882a593Smuzhiyun ((end) - (start) + 1), \
38*4882a593Smuzhiyun NULL, IORESOURCE_BUS)
39*4882a593Smuzhiyun #define MCFG_BUS_ANY MCFG_BUS_RANGE(0x0, 0xff)
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun static struct mcfg_fixup mcfg_quirks[] = {
42*4882a593Smuzhiyun /* { OEM_ID, OEM_TABLE_ID, REV, SEGMENT, BUS_RANGE, ops, cfgres }, */
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #ifdef CONFIG_ARM64
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define AL_ECAM(table_id, rev, seg, ops) \
47*4882a593Smuzhiyun { "AMAZON", table_id, rev, seg, MCFG_BUS_ANY, ops }
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun AL_ECAM("GRAVITON", 0, 0, &al_pcie_ops),
50*4882a593Smuzhiyun AL_ECAM("GRAVITON", 0, 1, &al_pcie_ops),
51*4882a593Smuzhiyun AL_ECAM("GRAVITON", 0, 2, &al_pcie_ops),
52*4882a593Smuzhiyun AL_ECAM("GRAVITON", 0, 3, &al_pcie_ops),
53*4882a593Smuzhiyun AL_ECAM("GRAVITON", 0, 4, &al_pcie_ops),
54*4882a593Smuzhiyun AL_ECAM("GRAVITON", 0, 5, &al_pcie_ops),
55*4882a593Smuzhiyun AL_ECAM("GRAVITON", 0, 6, &al_pcie_ops),
56*4882a593Smuzhiyun AL_ECAM("GRAVITON", 0, 7, &al_pcie_ops),
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #define QCOM_ECAM32(seg) \
59*4882a593Smuzhiyun { "QCOM ", "QDF2432 ", 1, seg, MCFG_BUS_ANY, &pci_32b_ops }
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun QCOM_ECAM32(0),
62*4882a593Smuzhiyun QCOM_ECAM32(1),
63*4882a593Smuzhiyun QCOM_ECAM32(2),
64*4882a593Smuzhiyun QCOM_ECAM32(3),
65*4882a593Smuzhiyun QCOM_ECAM32(4),
66*4882a593Smuzhiyun QCOM_ECAM32(5),
67*4882a593Smuzhiyun QCOM_ECAM32(6),
68*4882a593Smuzhiyun QCOM_ECAM32(7),
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun #define RKCP_ECAM(seg, table_id, ops) \
71*4882a593Smuzhiyun { "RKCP ", table_id, 0x0000, seg, MCFG_BUS_ANY, ops }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun RKCP_ECAM(0, "RK3588 ", &rk_pcie_ecam_ops), /* pcie3x4: Name (_SEG, Zero) */
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #define HISI_QUAD_DOM(table_id, seg, ops) \
76*4882a593Smuzhiyun { "HISI ", table_id, 0, (seg) + 0, MCFG_BUS_ANY, ops }, \
77*4882a593Smuzhiyun { "HISI ", table_id, 0, (seg) + 1, MCFG_BUS_ANY, ops }, \
78*4882a593Smuzhiyun { "HISI ", table_id, 0, (seg) + 2, MCFG_BUS_ANY, ops }, \
79*4882a593Smuzhiyun { "HISI ", table_id, 0, (seg) + 3, MCFG_BUS_ANY, ops }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun HISI_QUAD_DOM("HIP05 ", 0, &hisi_pcie_ops),
82*4882a593Smuzhiyun HISI_QUAD_DOM("HIP06 ", 0, &hisi_pcie_ops),
83*4882a593Smuzhiyun HISI_QUAD_DOM("HIP07 ", 0, &hisi_pcie_ops),
84*4882a593Smuzhiyun HISI_QUAD_DOM("HIP07 ", 4, &hisi_pcie_ops),
85*4882a593Smuzhiyun HISI_QUAD_DOM("HIP07 ", 8, &hisi_pcie_ops),
86*4882a593Smuzhiyun HISI_QUAD_DOM("HIP07 ", 12, &hisi_pcie_ops),
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun #define THUNDER_PEM_RES(addr, node) \
89*4882a593Smuzhiyun DEFINE_RES_MEM((addr) + ((u64) (node) << 44), 0x39 * SZ_16M)
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun #define THUNDER_PEM_QUIRK(rev, node) \
92*4882a593Smuzhiyun { "CAVIUM", "THUNDERX", rev, 4 + (10 * (node)), MCFG_BUS_ANY, \
93*4882a593Smuzhiyun &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88001f000000UL, node) }, \
94*4882a593Smuzhiyun { "CAVIUM", "THUNDERX", rev, 5 + (10 * (node)), MCFG_BUS_ANY, \
95*4882a593Smuzhiyun &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x884057000000UL, node) }, \
96*4882a593Smuzhiyun { "CAVIUM", "THUNDERX", rev, 6 + (10 * (node)), MCFG_BUS_ANY, \
97*4882a593Smuzhiyun &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88808f000000UL, node) }, \
98*4882a593Smuzhiyun { "CAVIUM", "THUNDERX", rev, 7 + (10 * (node)), MCFG_BUS_ANY, \
99*4882a593Smuzhiyun &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89001f000000UL, node) }, \
100*4882a593Smuzhiyun { "CAVIUM", "THUNDERX", rev, 8 + (10 * (node)), MCFG_BUS_ANY, \
101*4882a593Smuzhiyun &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x894057000000UL, node) }, \
102*4882a593Smuzhiyun { "CAVIUM", "THUNDERX", rev, 9 + (10 * (node)), MCFG_BUS_ANY, \
103*4882a593Smuzhiyun &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89808f000000UL, node) }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun #define THUNDER_ECAM_QUIRK(rev, seg) \
106*4882a593Smuzhiyun { "CAVIUM", "THUNDERX", rev, seg, MCFG_BUS_ANY, \
107*4882a593Smuzhiyun &pci_thunder_ecam_ops }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* SoC pass2.x */
110*4882a593Smuzhiyun THUNDER_PEM_QUIRK(1, 0),
111*4882a593Smuzhiyun THUNDER_PEM_QUIRK(1, 1),
112*4882a593Smuzhiyun THUNDER_ECAM_QUIRK(1, 10),
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /* SoC pass1.x */
115*4882a593Smuzhiyun THUNDER_PEM_QUIRK(2, 0), /* off-chip devices */
116*4882a593Smuzhiyun THUNDER_PEM_QUIRK(2, 1), /* off-chip devices */
117*4882a593Smuzhiyun THUNDER_ECAM_QUIRK(2, 0),
118*4882a593Smuzhiyun THUNDER_ECAM_QUIRK(2, 1),
119*4882a593Smuzhiyun THUNDER_ECAM_QUIRK(2, 2),
120*4882a593Smuzhiyun THUNDER_ECAM_QUIRK(2, 3),
121*4882a593Smuzhiyun THUNDER_ECAM_QUIRK(2, 10),
122*4882a593Smuzhiyun THUNDER_ECAM_QUIRK(2, 11),
123*4882a593Smuzhiyun THUNDER_ECAM_QUIRK(2, 12),
124*4882a593Smuzhiyun THUNDER_ECAM_QUIRK(2, 13),
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun #define XGENE_V1_ECAM_MCFG(rev, seg) \
127*4882a593Smuzhiyun {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \
128*4882a593Smuzhiyun &xgene_v1_pcie_ecam_ops }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun #define XGENE_V2_ECAM_MCFG(rev, seg) \
131*4882a593Smuzhiyun {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \
132*4882a593Smuzhiyun &xgene_v2_pcie_ecam_ops }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /* X-Gene SoC with v1 PCIe controller */
135*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(1, 0),
136*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(1, 1),
137*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(1, 2),
138*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(1, 3),
139*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(1, 4),
140*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(2, 0),
141*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(2, 1),
142*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(2, 2),
143*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(2, 3),
144*4882a593Smuzhiyun XGENE_V1_ECAM_MCFG(2, 4),
145*4882a593Smuzhiyun /* X-Gene SoC with v2.1 PCIe controller */
146*4882a593Smuzhiyun XGENE_V2_ECAM_MCFG(3, 0),
147*4882a593Smuzhiyun XGENE_V2_ECAM_MCFG(3, 1),
148*4882a593Smuzhiyun /* X-Gene SoC with v2.2 PCIe controller */
149*4882a593Smuzhiyun XGENE_V2_ECAM_MCFG(4, 0),
150*4882a593Smuzhiyun XGENE_V2_ECAM_MCFG(4, 1),
151*4882a593Smuzhiyun XGENE_V2_ECAM_MCFG(4, 2),
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun #define ALTRA_ECAM_QUIRK(rev, seg) \
154*4882a593Smuzhiyun { "Ampere", "Altra ", rev, seg, MCFG_BUS_ANY, &pci_32b_read_ops }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 0),
157*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 1),
158*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 2),
159*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 3),
160*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 4),
161*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 5),
162*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 6),
163*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 7),
164*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 8),
165*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 9),
166*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 10),
167*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 11),
168*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 12),
169*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 13),
170*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 14),
171*4882a593Smuzhiyun ALTRA_ECAM_QUIRK(1, 15),
172*4882a593Smuzhiyun #endif /* ARM64 */
173*4882a593Smuzhiyun };
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
176*4882a593Smuzhiyun static char mcfg_oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
177*4882a593Smuzhiyun static u32 mcfg_oem_revision;
178*4882a593Smuzhiyun
pci_mcfg_quirk_matches(struct mcfg_fixup * f,u16 segment,struct resource * bus_range)179*4882a593Smuzhiyun static int pci_mcfg_quirk_matches(struct mcfg_fixup *f, u16 segment,
180*4882a593Smuzhiyun struct resource *bus_range)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun if (!memcmp(f->oem_id, mcfg_oem_id, ACPI_OEM_ID_SIZE) &&
183*4882a593Smuzhiyun !memcmp(f->oem_table_id, mcfg_oem_table_id,
184*4882a593Smuzhiyun ACPI_OEM_TABLE_ID_SIZE) &&
185*4882a593Smuzhiyun f->oem_revision == mcfg_oem_revision &&
186*4882a593Smuzhiyun f->segment == segment &&
187*4882a593Smuzhiyun resource_contains(&f->bus_range, bus_range))
188*4882a593Smuzhiyun return 1;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return 0;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun #endif
193*4882a593Smuzhiyun
pci_mcfg_apply_quirks(struct acpi_pci_root * root,struct resource * cfgres,const struct pci_ecam_ops ** ecam_ops)194*4882a593Smuzhiyun static void pci_mcfg_apply_quirks(struct acpi_pci_root *root,
195*4882a593Smuzhiyun struct resource *cfgres,
196*4882a593Smuzhiyun const struct pci_ecam_ops **ecam_ops)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun #ifdef CONFIG_PCI_QUIRKS
199*4882a593Smuzhiyun u16 segment = root->segment;
200*4882a593Smuzhiyun struct resource *bus_range = &root->secondary;
201*4882a593Smuzhiyun struct mcfg_fixup *f;
202*4882a593Smuzhiyun int i;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun for (i = 0, f = mcfg_quirks; i < ARRAY_SIZE(mcfg_quirks); i++, f++) {
205*4882a593Smuzhiyun if (pci_mcfg_quirk_matches(f, segment, bus_range)) {
206*4882a593Smuzhiyun if (f->cfgres.start)
207*4882a593Smuzhiyun *cfgres = f->cfgres;
208*4882a593Smuzhiyun if (f->ops)
209*4882a593Smuzhiyun *ecam_ops = f->ops;
210*4882a593Smuzhiyun dev_info(&root->device->dev, "MCFG quirk: ECAM at %pR for %pR with %ps\n",
211*4882a593Smuzhiyun cfgres, bus_range, *ecam_ops);
212*4882a593Smuzhiyun return;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun #endif
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun /* List to save MCFG entries */
219*4882a593Smuzhiyun static LIST_HEAD(pci_mcfg_list);
220*4882a593Smuzhiyun
pci_mcfg_lookup(struct acpi_pci_root * root,struct resource * cfgres,const struct pci_ecam_ops ** ecam_ops)221*4882a593Smuzhiyun int pci_mcfg_lookup(struct acpi_pci_root *root, struct resource *cfgres,
222*4882a593Smuzhiyun const struct pci_ecam_ops **ecam_ops)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun const struct pci_ecam_ops *ops = &pci_generic_ecam_ops;
225*4882a593Smuzhiyun struct resource *bus_res = &root->secondary;
226*4882a593Smuzhiyun u16 seg = root->segment;
227*4882a593Smuzhiyun struct mcfg_entry *e;
228*4882a593Smuzhiyun struct resource res;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /* Use address from _CBA if present, otherwise lookup MCFG */
231*4882a593Smuzhiyun if (root->mcfg_addr)
232*4882a593Smuzhiyun goto skip_lookup;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun /*
235*4882a593Smuzhiyun * We expect the range in bus_res in the coverage of MCFG bus range.
236*4882a593Smuzhiyun */
237*4882a593Smuzhiyun list_for_each_entry(e, &pci_mcfg_list, list) {
238*4882a593Smuzhiyun if (e->segment == seg && e->bus_start <= bus_res->start &&
239*4882a593Smuzhiyun e->bus_end >= bus_res->end) {
240*4882a593Smuzhiyun root->mcfg_addr = e->addr;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun skip_lookup:
246*4882a593Smuzhiyun memset(&res, 0, sizeof(res));
247*4882a593Smuzhiyun if (root->mcfg_addr) {
248*4882a593Smuzhiyun res.start = root->mcfg_addr + (bus_res->start << 20);
249*4882a593Smuzhiyun res.end = res.start + (resource_size(bus_res) << 20) - 1;
250*4882a593Smuzhiyun res.flags = IORESOURCE_MEM;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /*
254*4882a593Smuzhiyun * Allow quirks to override default ECAM ops and CFG resource
255*4882a593Smuzhiyun * range. This may even fabricate a CFG resource range in case
256*4882a593Smuzhiyun * MCFG does not have it. Invalid CFG start address means MCFG
257*4882a593Smuzhiyun * firmware bug or we need another quirk in array.
258*4882a593Smuzhiyun */
259*4882a593Smuzhiyun pci_mcfg_apply_quirks(root, &res, &ops);
260*4882a593Smuzhiyun if (!res.start)
261*4882a593Smuzhiyun return -ENXIO;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun *cfgres = res;
264*4882a593Smuzhiyun *ecam_ops = ops;
265*4882a593Smuzhiyun return 0;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
pci_mcfg_parse(struct acpi_table_header * header)268*4882a593Smuzhiyun static __init int pci_mcfg_parse(struct acpi_table_header *header)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun struct acpi_table_mcfg *mcfg;
271*4882a593Smuzhiyun struct acpi_mcfg_allocation *mptr;
272*4882a593Smuzhiyun struct mcfg_entry *e, *arr;
273*4882a593Smuzhiyun int i, n;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun if (header->length < sizeof(struct acpi_table_mcfg))
276*4882a593Smuzhiyun return -EINVAL;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun n = (header->length - sizeof(struct acpi_table_mcfg)) /
279*4882a593Smuzhiyun sizeof(struct acpi_mcfg_allocation);
280*4882a593Smuzhiyun mcfg = (struct acpi_table_mcfg *)header;
281*4882a593Smuzhiyun mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
284*4882a593Smuzhiyun if (!arr)
285*4882a593Smuzhiyun return -ENOMEM;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun for (i = 0, e = arr; i < n; i++, mptr++, e++) {
288*4882a593Smuzhiyun e->segment = mptr->pci_segment;
289*4882a593Smuzhiyun e->addr = mptr->address;
290*4882a593Smuzhiyun e->bus_start = mptr->start_bus_number;
291*4882a593Smuzhiyun e->bus_end = mptr->end_bus_number;
292*4882a593Smuzhiyun list_add(&e->list, &pci_mcfg_list);
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun #ifdef CONFIG_PCI_QUIRKS
296*4882a593Smuzhiyun /* Save MCFG IDs and revision for quirks matching */
297*4882a593Smuzhiyun memcpy(mcfg_oem_id, header->oem_id, ACPI_OEM_ID_SIZE);
298*4882a593Smuzhiyun memcpy(mcfg_oem_table_id, header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
299*4882a593Smuzhiyun mcfg_oem_revision = header->oem_revision;
300*4882a593Smuzhiyun #endif
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun pr_info("MCFG table detected, %d entries\n", n);
303*4882a593Smuzhiyun return 0;
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /* Interface called by ACPI - parse and save MCFG table */
pci_mmcfg_late_init(void)307*4882a593Smuzhiyun void __init pci_mmcfg_late_init(void)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
310*4882a593Smuzhiyun if (err)
311*4882a593Smuzhiyun pr_debug("Failed to parse MCFG (%d)\n", err);
312*4882a593Smuzhiyun }
313