gen_defines: generate ranges defines for PCIe I/O and memory regions
As described in IEEE Std 1275-1994, the PCIe bindings uses the ranges property to describe the PCI I/O and memory regions. Write _RANGES_ defines that will be used to determines the I/O and memory regions from PCIe Controller drivers. Also exclude "ranges" & "dma-ranges" property's length generation alogn "reg" and "interrupt". Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
This commit is contained in:
parent
2f4a6646cf
commit
1e8f0f3bd1
1 changed files with 49 additions and 3 deletions
|
@ -355,6 +355,7 @@ def write_special_props(node):
|
||||||
# Macros that are special to the devicetree specification
|
# Macros that are special to the devicetree specification
|
||||||
out_comment("Macros for properties that are special in the specification:")
|
out_comment("Macros for properties that are special in the specification:")
|
||||||
write_regs(node)
|
write_regs(node)
|
||||||
|
write_ranges(node)
|
||||||
write_interrupts(node)
|
write_interrupts(node)
|
||||||
write_compatibles(node)
|
write_compatibles(node)
|
||||||
write_status(node)
|
write_status(node)
|
||||||
|
@ -364,6 +365,49 @@ def write_special_props(node):
|
||||||
write_pinctrls(node)
|
write_pinctrls(node)
|
||||||
write_fixed_partitions(node)
|
write_fixed_partitions(node)
|
||||||
|
|
||||||
|
def write_ranges(node):
|
||||||
|
# ranges property: edtlib knows the right #address-cells and
|
||||||
|
# #size-cells of parent and child, and can therefore pack the
|
||||||
|
# child & parent addresses and sizes correctly
|
||||||
|
|
||||||
|
idx_vals = []
|
||||||
|
path_id = node.z_path_id
|
||||||
|
|
||||||
|
if node.ranges is not None:
|
||||||
|
idx_vals.append((f"{path_id}_RANGES_NUM", len(node.ranges)))
|
||||||
|
|
||||||
|
for i,range in enumerate(node.ranges):
|
||||||
|
idx_vals.append((f"{path_id}_RANGES_IDX_{i}_EXISTS", 1))
|
||||||
|
|
||||||
|
if node.bus == "pcie":
|
||||||
|
idx_vals.append((f"{path_id}_RANGES_IDX_{i}_VAL_CHILD_BUS_FLAGS_EXISTS", 1))
|
||||||
|
idx_macro = f"{path_id}_RANGES_IDX_{i}_VAL_CHILD_BUS_FLAGS"
|
||||||
|
idx_value = range.child_bus_addr >> ((range.child_bus_cells - 1) * 32)
|
||||||
|
idx_vals.append((idx_macro,
|
||||||
|
f"{idx_value} /* {hex(idx_value)} */"))
|
||||||
|
if range.child_bus_addr is not None:
|
||||||
|
idx_macro = f"{path_id}_RANGES_IDX_{i}_VAL_CHILD_BUS_ADDRESS"
|
||||||
|
if node.bus == "pcie":
|
||||||
|
idx_value = range.child_bus_addr & ((1 << (range.child_bus_cells - 1) * 32) - 1)
|
||||||
|
else:
|
||||||
|
idx_value = range.child_bus_addr
|
||||||
|
idx_vals.append((idx_macro,
|
||||||
|
f"{idx_value} /* {hex(idx_value)} */"))
|
||||||
|
if range.parent_bus_addr is not None:
|
||||||
|
idx_macro = f"{path_id}_RANGES_IDX_{i}_VAL_PARENT_BUS_ADDRESS"
|
||||||
|
idx_vals.append((idx_macro,
|
||||||
|
f"{range.parent_bus_addr} /* {hex(range.parent_bus_addr)} */"))
|
||||||
|
if range.length is not None:
|
||||||
|
idx_macro = f"{path_id}_RANGES_IDX_{i}_VAL_LENGTH"
|
||||||
|
idx_vals.append((idx_macro,
|
||||||
|
f"{range.length} /* {hex(range.length)} */"))
|
||||||
|
|
||||||
|
for macro, val in idx_vals:
|
||||||
|
out_dt_define(macro, val)
|
||||||
|
|
||||||
|
out_dt_define(f"{path_id}_FOREACH_RANGE(fn)",
|
||||||
|
" ".join(f"fn(DT_{path_id}, {i})" for i,range in enumerate(node.ranges)))
|
||||||
|
|
||||||
def write_regs(node):
|
def write_regs(node):
|
||||||
# reg property: edtlib knows the right #address-cells and
|
# reg property: edtlib knows the right #address-cells and
|
||||||
# #size-cells, and can therefore pack the register base addresses
|
# #size-cells, and can therefore pack the register base addresses
|
||||||
|
@ -682,10 +726,12 @@ def prop_len(prop):
|
||||||
# Returns the property's length if and only if we should generate
|
# Returns the property's length if and only if we should generate
|
||||||
# a _LEN macro for the property. Otherwise, returns None.
|
# a _LEN macro for the property. Otherwise, returns None.
|
||||||
#
|
#
|
||||||
# This deliberately excludes reg and interrupts.
|
# This deliberately excludes ranges, dma-ranges, reg and interrupts.
|
||||||
# While they have array type, their lengths as arrays are
|
# While they have array type, their lengths as arrays are
|
||||||
# basically nonsense semantically due to #address-cells and
|
# basically nonsense semantically due to #address-cells and
|
||||||
# #size-cells for "reg" and #interrupt-cells for "interrupts".
|
# #size-cells for "reg", #interrupt-cells for "interrupts"
|
||||||
|
# and #address-cells, #size-cells and the #address-cells from the
|
||||||
|
# parent node for "ranges" and "dma-ranges".
|
||||||
#
|
#
|
||||||
# We have special purpose macros for the number of register blocks
|
# We have special purpose macros for the number of register blocks
|
||||||
# / interrupt specifiers. Excluding them from this list means
|
# / interrupt specifiers. Excluding them from this list means
|
||||||
|
@ -698,7 +744,7 @@ def prop_len(prop):
|
||||||
|
|
||||||
if (prop.type in ["array", "uint8-array", "string-array",
|
if (prop.type in ["array", "uint8-array", "string-array",
|
||||||
"phandles", "phandle-array"] and
|
"phandles", "phandle-array"] and
|
||||||
prop.name not in ["reg", "interrupts"]):
|
prop.name not in ["ranges", "dma-ranges", "reg", "interrupts"]):
|
||||||
return len(prop.val)
|
return len(prop.val)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue