1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
8 #include <linux/of_irq.h>
9 #include <linux/bitfield.h>
10 #include <linux/bits.h>
13 #define OF_PCI_ADDRESS_CELLS 3
14 #define OF_PCI_SIZE_CELLS 2
15 #define OF_PCI_MAX_INT_PIN 4
17 struct of_pci_addr_pair
{
18 u32 phys_addr
[OF_PCI_ADDRESS_CELLS
];
19 u32 size
[OF_PCI_SIZE_CELLS
];
23 * Each entry in the ranges table is a tuple containing the child address,
24 * the parent address, and the size of the region in the child address space.
25 * Thus, for PCI, in each entry parent address is an address on the primary
26 * side and the child address is the corresponding address on the secondary
30 u32 child_addr
[OF_PCI_ADDRESS_CELLS
];
31 u32 parent_addr
[OF_PCI_ADDRESS_CELLS
];
32 u32 size
[OF_PCI_SIZE_CELLS
];
35 #define OF_PCI_ADDR_SPACE_IO 0x1
36 #define OF_PCI_ADDR_SPACE_MEM32 0x2
37 #define OF_PCI_ADDR_SPACE_MEM64 0x3
39 #define OF_PCI_ADDR_FIELD_NONRELOC BIT(31)
40 #define OF_PCI_ADDR_FIELD_SS GENMASK(25, 24)
41 #define OF_PCI_ADDR_FIELD_PREFETCH BIT(30)
42 #define OF_PCI_ADDR_FIELD_BUS GENMASK(23, 16)
43 #define OF_PCI_ADDR_FIELD_DEV GENMASK(15, 11)
44 #define OF_PCI_ADDR_FIELD_FUNC GENMASK(10, 8)
45 #define OF_PCI_ADDR_FIELD_REG GENMASK(7, 0)
47 enum of_pci_prop_compatible
{
48 PROP_COMPAT_PCI_VVVV_DDDD
,
49 PROP_COMPAT_PCICLASS_CCSSPP
,
50 PROP_COMPAT_PCICLASS_CCSS
,
54 static void of_pci_set_address(struct pci_dev
*pdev
, u32
*prop
, u64 addr
,
55 u32 reg_num
, u32 flags
, bool reloc
)
57 prop
[0] = FIELD_PREP(OF_PCI_ADDR_FIELD_BUS
, pdev
->bus
->number
) |
58 FIELD_PREP(OF_PCI_ADDR_FIELD_DEV
, PCI_SLOT(pdev
->devfn
)) |
59 FIELD_PREP(OF_PCI_ADDR_FIELD_FUNC
, PCI_FUNC(pdev
->devfn
));
60 prop
[0] |= flags
| reg_num
;
62 prop
[0] |= OF_PCI_ADDR_FIELD_NONRELOC
;
63 prop
[1] = upper_32_bits(addr
);
64 prop
[2] = lower_32_bits(addr
);
68 static int of_pci_get_addr_flags(struct resource
*res
, u32
*flags
)
72 if (res
->flags
& IORESOURCE_IO
)
73 ss
= OF_PCI_ADDR_SPACE_IO
;
74 else if (res
->flags
& IORESOURCE_MEM_64
)
75 ss
= OF_PCI_ADDR_SPACE_MEM64
;
76 else if (res
->flags
& IORESOURCE_MEM
)
77 ss
= OF_PCI_ADDR_SPACE_MEM32
;
82 if (res
->flags
& IORESOURCE_PREFETCH
)
83 *flags
|= OF_PCI_ADDR_FIELD_PREFETCH
;
85 *flags
|= FIELD_PREP(OF_PCI_ADDR_FIELD_SS
, ss
);
90 static int of_pci_prop_bus_range(struct pci_dev
*pdev
,
91 struct of_changeset
*ocs
,
92 struct device_node
*np
)
94 u32 bus_range
[] = { pdev
->subordinate
->busn_res
.start
,
95 pdev
->subordinate
->busn_res
.end
};
97 return of_changeset_add_prop_u32_array(ocs
, np
, "bus-range", bus_range
,
98 ARRAY_SIZE(bus_range
));
101 static int of_pci_prop_ranges(struct pci_dev
*pdev
, struct of_changeset
*ocs
,
102 struct device_node
*np
)
104 struct of_pci_range
*rp
;
105 struct resource
*res
;
110 if (pci_is_bridge(pdev
)) {
111 num
= PCI_BRIDGE_RESOURCE_NUM
;
112 res
= &pdev
->resource
[PCI_BRIDGE_RESOURCES
];
114 num
= PCI_STD_NUM_BARS
;
115 res
= &pdev
->resource
[PCI_STD_RESOURCES
];
118 rp
= kcalloc(num
, sizeof(*rp
), GFP_KERNEL
);
122 for (i
= 0, j
= 0; j
< num
; j
++) {
123 if (!resource_size(&res
[j
]))
126 if (of_pci_get_addr_flags(&res
[j
], &flags
))
129 val64
= pci_bus_address(pdev
, &res
[j
] - pdev
->resource
);
130 of_pci_set_address(pdev
, rp
[i
].parent_addr
, val64
, 0, flags
,
132 if (pci_is_bridge(pdev
)) {
133 memcpy(rp
[i
].child_addr
, rp
[i
].parent_addr
,
134 sizeof(rp
[i
].child_addr
));
137 * For endpoint device, the lower 64-bits of child
138 * address is always zero.
140 rp
[i
].child_addr
[0] = j
;
143 val64
= resource_size(&res
[j
]);
144 rp
[i
].size
[0] = upper_32_bits(val64
);
145 rp
[i
].size
[1] = lower_32_bits(val64
);
150 ret
= of_changeset_add_prop_u32_array(ocs
, np
, "ranges", (u32
*)rp
,
151 i
* sizeof(*rp
) / sizeof(u32
));
157 static int of_pci_prop_reg(struct pci_dev
*pdev
, struct of_changeset
*ocs
,
158 struct device_node
*np
)
160 struct of_pci_addr_pair reg
= { 0 };
162 /* configuration space */
163 of_pci_set_address(pdev
, reg
.phys_addr
, 0, 0, 0, true);
165 return of_changeset_add_prop_u32_array(ocs
, np
, "reg", (u32
*)®
,
166 sizeof(reg
) / sizeof(u32
));
169 static int of_pci_prop_interrupts(struct pci_dev
*pdev
,
170 struct of_changeset
*ocs
,
171 struct device_node
*np
)
176 ret
= pci_read_config_byte(pdev
, PCI_INTERRUPT_PIN
, &pin
);
183 return of_changeset_add_prop_u32(ocs
, np
, "interrupts", (u32
)pin
);
186 static int of_pci_prop_intr_ctrl(struct pci_dev
*pdev
, struct of_changeset
*ocs
,
187 struct device_node
*np
)
192 ret
= pci_read_config_byte(pdev
, PCI_INTERRUPT_PIN
, &pin
);
199 ret
= of_changeset_add_prop_u32(ocs
, np
, "#interrupt-cells", 1);
203 return of_changeset_add_prop_bool(ocs
, np
, "interrupt-controller");
206 static int of_pci_prop_intr_map(struct pci_dev
*pdev
, struct of_changeset
*ocs
,
207 struct device_node
*np
)
209 u32 i
, addr_sz
[OF_PCI_MAX_INT_PIN
] = { 0 }, map_sz
= 0;
210 struct of_phandle_args out_irq
[OF_PCI_MAX_INT_PIN
];
211 __be32 laddr
[OF_PCI_ADDRESS_CELLS
] = { 0 };
212 u32 int_map_mask
[] = { 0xffff00, 0, 0, 7 };
213 struct device_node
*pnode
;
214 struct pci_dev
*child
;
219 pnode
= pci_device_to_OF_node(pdev
->bus
->self
);
221 pnode
= pci_bus_to_OF_node(pdev
->bus
);
224 pci_err(pdev
, "failed to get parent device node");
228 laddr
[0] = cpu_to_be32((pdev
->bus
->number
<< 16) | (pdev
->devfn
<< 8));
229 for (pin
= 1; pin
<= OF_PCI_MAX_INT_PIN
; pin
++) {
231 out_irq
[i
].np
= pnode
;
232 out_irq
[i
].args_count
= 1;
233 out_irq
[i
].args
[0] = pin
;
234 ret
= of_irq_parse_raw(laddr
, &out_irq
[i
]);
236 out_irq
[i
].np
= NULL
;
237 pci_dbg(pdev
, "parse irq %d failed, ret %d", pin
, ret
);
240 of_property_read_u32(out_irq
[i
].np
, "#address-cells",
244 list_for_each_entry(child
, &pdev
->subordinate
->devices
, bus_list
) {
245 for (pin
= 1; pin
<= OF_PCI_MAX_INT_PIN
; pin
++) {
246 i
= pci_swizzle_interrupt_pin(child
, pin
) - 1;
249 map_sz
+= 5 + addr_sz
[i
] + out_irq
[i
].args_count
;
254 * Parsing interrupt failed for all pins. In this case, it does not
255 * need to generate interrupt-map property.
260 int_map
= kcalloc(map_sz
, sizeof(u32
), GFP_KERNEL
);
265 list_for_each_entry(child
, &pdev
->subordinate
->devices
, bus_list
) {
266 for (pin
= 1; pin
<= OF_PCI_MAX_INT_PIN
; pin
++) {
267 i
= pci_swizzle_interrupt_pin(child
, pin
) - 1;
271 *mapp
= (child
->bus
->number
<< 16) |
273 mapp
+= OF_PCI_ADDRESS_CELLS
;
276 *mapp
= out_irq
[i
].np
->phandle
;
279 ret
= of_property_read_u32_array(out_irq
[i
].np
,
286 memcpy(mapp
, out_irq
[i
].args
,
287 out_irq
[i
].args_count
* sizeof(u32
));
288 mapp
+= out_irq
[i
].args_count
;
292 ret
= of_changeset_add_prop_u32_array(ocs
, np
, "interrupt-map", int_map
,
297 ret
= of_changeset_add_prop_u32(ocs
, np
, "#interrupt-cells", 1);
301 ret
= of_changeset_add_prop_u32_array(ocs
, np
, "interrupt-map-mask",
303 ARRAY_SIZE(int_map_mask
));
315 static int of_pci_prop_compatible(struct pci_dev
*pdev
,
316 struct of_changeset
*ocs
,
317 struct device_node
*np
)
319 const char *compat_strs
[PROP_COMPAT_NUM
] = { 0 };
322 compat_strs
[PROP_COMPAT_PCI_VVVV_DDDD
] =
323 kasprintf(GFP_KERNEL
, "pci%x,%x", pdev
->vendor
, pdev
->device
);
324 compat_strs
[PROP_COMPAT_PCICLASS_CCSSPP
] =
325 kasprintf(GFP_KERNEL
, "pciclass,%06x", pdev
->class);
326 compat_strs
[PROP_COMPAT_PCICLASS_CCSS
] =
327 kasprintf(GFP_KERNEL
, "pciclass,%04x", pdev
->class >> 8);
329 ret
= of_changeset_add_prop_string_array(ocs
, np
, "compatible",
330 compat_strs
, PROP_COMPAT_NUM
);
331 for (i
= 0; i
< PROP_COMPAT_NUM
; i
++)
332 kfree(compat_strs
[i
]);
337 int of_pci_add_properties(struct pci_dev
*pdev
, struct of_changeset
*ocs
,
338 struct device_node
*np
)
343 * The added properties will be released when the
344 * changeset is destroyed.
346 if (pci_is_bridge(pdev
)) {
347 ret
= of_changeset_add_prop_string(ocs
, np
, "device_type",
352 ret
= of_pci_prop_bus_range(pdev
, ocs
, np
);
356 ret
= of_pci_prop_intr_map(pdev
, ocs
, np
);
360 ret
= of_pci_prop_intr_ctrl(pdev
, ocs
, np
);
365 ret
= of_pci_prop_ranges(pdev
, ocs
, np
);
369 ret
= of_changeset_add_prop_u32(ocs
, np
, "#address-cells",
370 OF_PCI_ADDRESS_CELLS
);
374 ret
= of_changeset_add_prop_u32(ocs
, np
, "#size-cells",
379 ret
= of_pci_prop_reg(pdev
, ocs
, np
);
383 ret
= of_pci_prop_compatible(pdev
, ocs
, np
);
387 ret
= of_pci_prop_interrupts(pdev
, ocs
, np
);