@@ -1499,9 +1499,8 @@ def _init_prop(self, prop_spec: PropertySpec,
1499
1499
"is different from the 'const' value specified in "
1500
1500
f"{ self .binding_path } ({ const !r} )" )
1501
1501
1502
- # Skip properties that start with '#', like '#size-cells', and mapping
1503
- # properties like 'gpio-map'/'interrupt-map'
1504
- if name [0 ] == "#" or name .endswith ("-map" ):
1502
+ # Skip properties that start with '#', like '#size-cells'
1503
+ if name [0 ] == "#" :
1505
1504
return
1506
1505
1507
1506
self .props [name ] = Property (prop_spec , val , self )
@@ -1598,7 +1597,10 @@ def _prop_val(
1598
1597
f"with '{ name } = < &foo ... &bar 1 ... &baz 2 3 >' "
1599
1598
f"(a mix of phandles and numbers), not '{ prop } '" )
1600
1599
1601
- return self ._standard_phandle_val_list (prop , specifier_space )
1600
+ if prop .name .endswith ("-map" ):
1601
+ return self ._map_phandle_val_list (prop , specifier_space )
1602
+ else :
1603
+ return self ._standard_phandle_val_list (prop , specifier_space )
1602
1604
1603
1605
if prop_type == "path" :
1604
1606
return self .edt ._node2enode [prop .to_path ()]
@@ -1773,6 +1775,105 @@ def _init_interrupts(self) -> None:
1773
1775
1774
1776
_add_names (node , "interrupt" , self .interrupts )
1775
1777
1778
+ def _map_phandle_val_list (
1779
+ self , prop : dtlib_Property , specifier_space : Optional [str ]
1780
+ ) -> list [Optional [ControllerAndData ]]:
1781
+ if not specifier_space :
1782
+ specifier_space = prop .name [:- 4 ] # Strip '-map'
1783
+
1784
+ res : list [Optional [ControllerAndData ]] = []
1785
+
1786
+ raw = prop .value
1787
+ while raw :
1788
+ if len (raw ) < 4 :
1789
+ # Not enough room for phandle
1790
+ _err ("bad value for " + repr (prop ))
1791
+
1792
+ def count_cells_num (node : dtlib_Node , specifier : str ) -> int :
1793
+ """
1794
+ Calculate the number of cells in the node.
1795
+ When calculating the number of interrupt cells,
1796
+ add up the values of the address and size cells.
1797
+ """
1798
+
1799
+ if not node :
1800
+ _err ("node is None." )
1801
+
1802
+ num = node .props [f"#{ specifier } -cells" ].to_num ()
1803
+
1804
+ if specifier == "interrupt" :
1805
+ parent_props = None
1806
+ if node .parent :
1807
+ parent_props = node .parent .props
1808
+
1809
+ if "#address-cells" in node .props :
1810
+ num = num + node .props ["#address-cells" ].to_num ()
1811
+ elif parent_props and "#address-cells" in parent_props :
1812
+ num = num + parent_props ["#address-cells" ].to_num ()
1813
+ else :
1814
+ _err ("Neither the node nor its parent has `#address-cells` property" )
1815
+
1816
+ if "#size-cells" in node .props :
1817
+ num = num + node .props ["#size-cells" ].to_num ()
1818
+ elif parent_props and "#address-cells" in parent_props :
1819
+ num = num + parent_props ["#size-cells" ].to_num ()
1820
+ else :
1821
+ _err ("Neither the node nor its parent has `#size-cells` property" )
1822
+
1823
+ return num
1824
+
1825
+ child_specifier_num = count_cells_num (prop .node , specifier_space )
1826
+
1827
+ child_specifiers = to_nums (raw [: 4 * child_specifier_num ])
1828
+ raw = raw [4 * child_specifier_num :]
1829
+ phandle = to_num (raw [:4 ])
1830
+ raw = raw [4 :]
1831
+
1832
+ controller_node : dtlib_Node = prop .node .dt .phandle2node .get (phandle )
1833
+ if not controller_node :
1834
+ _err (f"controller node cannot be found from phandle:{ phandle } " )
1835
+
1836
+ parent_specifier_num = count_cells_num (controller_node , specifier_space )
1837
+ parent_specifiers = to_nums (raw [: 4 * parent_specifier_num ])
1838
+ raw = raw [4 * parent_specifier_num :]
1839
+
1840
+ # Although this is rare, if a cell-name is specified for the map node,
1841
+ # it will be reflected.
1842
+ # If not specified, the name of child_specifier_[i] will be set.
1843
+ values : dict [str , int ] = {}
1844
+ for i , v in enumerate (child_specifiers ):
1845
+ cell_name = f"child_specifier_{ i } "
1846
+ if specifier_space in self ._binding .specifier2cells and (
1847
+ i < len (self ._binding .specifier2cells )
1848
+ ):
1849
+ cell_name = self ._bindings .specifier2cells [i ]
1850
+
1851
+ values [cell_name ] = v
1852
+
1853
+ # The cell name for parent_specifier cannot be determined.
1854
+ # For convenience, we assign it the name parent_specifier_[i].
1855
+ for i , v in enumerate (parent_specifiers ):
1856
+ values [f"parent_specifier_{ i } " ] = v
1857
+
1858
+ controller : Node = self .edt ._node2enode [controller_node ]
1859
+ if not controller :
1860
+ _err ("controller cannot be found from: " + repr (controller_node ))
1861
+
1862
+ res .append (
1863
+ ControllerAndData (
1864
+ node = self ,
1865
+ controller = controller ,
1866
+ data = values ,
1867
+ name = None ,
1868
+ basename = specifier_space ,
1869
+ )
1870
+ )
1871
+
1872
+ if len (raw ) != 0 :
1873
+ _err (f"unexpected prop.value remainings: { raw } " )
1874
+
1875
+ return res
1876
+
1776
1877
def _standard_phandle_val_list (
1777
1878
self ,
1778
1879
prop : dtlib_Property ,
@@ -2717,9 +2818,10 @@ def _check_prop_by_type(prop_name: str,
2717
2818
2718
2819
if (prop_type == "phandle-array"
2719
2820
and not prop_name .endswith ("s" )
2821
+ and not prop_name .endswith ("-map" )
2720
2822
and "specifier-space" not in options ):
2721
2823
_err (f"'{ prop_name } ' in 'properties:' in { binding_path } "
2722
- f"has type 'phandle-array' and its name does not end in 's', "
2824
+ f"has type 'phandle-array' and its name does not end in 's' or '-map' , "
2723
2825
f"but no 'specifier-space' was provided." )
2724
2826
2725
2827
# If you change const_types, be sure to update the type annotation
0 commit comments