@@ -114,8 +114,21 @@ class Binding:
114114 path:
115115 The absolute path to the file defining the binding.
116116
117+ title:
118+ The free-form title of the binding (optional).
119+
120+ When the content in the 'description:' is too long, the 'title:' can
121+ be used as a heading for the extended description. Typically, it serves
122+ as a description of the hardware model. For example:
123+
124+ title: Nordic GPIO
125+
126+ description: |
127+ Descriptions and example nodes related to GPIO.
128+ ...
129+
117130 description:
118- The free-form description of the binding, or None .
131+ The free-form description of the binding.
119132
120133 compatible:
121134 The compatible string the binding matches.
@@ -173,7 +186,7 @@ class Binding:
173186
174187 def __init__ (self , path : Optional [str ], fname2path : dict [str , str ],
175188 raw : Any = None , require_compatible : bool = True ,
176- require_description : bool = True ):
189+ require_description : bool = True , require_title : bool = False ):
177190 """
178191 Binding constructor.
179192
@@ -201,6 +214,12 @@ def __init__(self, path: Optional[str], fname2path: dict[str, str],
201214 "description:" line. If False, a missing "description:" is
202215 not an error. Either way, "description:" must be a string
203216 if it is present in the binding.
217+
218+ require_title:
219+ If True, it is an error if the binding does not contain a
220+ "title:" line. If False, a missing "title:" is not an error.
221+ Either way, "title:" must be a string if it is present in
222+ the binding.
204223 """
205224 self .path : Optional [str ] = path
206225 self ._fname2path : dict [str , str ] = fname2path
@@ -217,8 +236,8 @@ def __init__(self, path: Optional[str], fname2path: dict[str, str],
217236 self .raw : dict = self ._merge_includes (raw , self .path )
218237
219238 # Recursively initialize any child bindings. These don't
220- # require a 'compatible' or 'description ' to be well defined,
221- # but they must be dicts.
239+ # require a 'compatible', 'description' or 'title ' to be well
240+ # defined, but they must be dicts.
222241 if "child-binding" in raw :
223242 if not isinstance (raw ["child-binding" ], dict ):
224243 _err (f"malformed 'child-binding:' in { self .path } , "
@@ -232,7 +251,7 @@ def __init__(self, path: Optional[str], fname2path: dict[str, str],
232251 self .child_binding = None
233252
234253 # Make sure this is a well defined object.
235- self ._check (require_compatible , require_description )
254+ self ._check (require_compatible , require_description , require_title )
236255
237256 # Initialize look up tables.
238257 self .prop2specs : dict [str , PropertySpec ] = {}
@@ -251,6 +270,11 @@ def __repr__(self) -> str:
251270 basename = os .path .basename (self .path or "" )
252271 return f"<Binding { basename } " + compat + ">"
253272
273+ @property
274+ def title (self ) -> Optional [str ]:
275+ "See the class docstring"
276+ return self .raw .get ('title' )
277+
254278 @property
255279 def description (self ) -> Optional [str ]:
256280 "See the class docstring"
@@ -364,7 +388,8 @@ def _load_raw(self, fname: str) -> dict:
364388
365389 return self ._merge_includes (contents , path )
366390
367- def _check (self , require_compatible : bool , require_description : bool ):
391+ def _check (self , require_compatible : bool , require_description : bool ,
392+ require_title : bool ):
368393 # Does sanity checking on the binding.
369394
370395 raw = self .raw
@@ -378,6 +403,13 @@ def _check(self, require_compatible: bool, require_description: bool):
378403 elif require_compatible :
379404 _err (f"missing 'compatible' in { self .path } " )
380405
406+ if "title" in raw :
407+ title = raw ["title" ]
408+ if not isinstance (title , str ) or not title :
409+ _err (f"malformed or empty 'title' in { self .path } " )
410+ elif require_title :
411+ _err (f"missing 'title' in { self .path } " )
412+
381413 if "description" in raw :
382414 description = raw ["description" ]
383415 if not isinstance (description , str ) or not description :
@@ -387,8 +419,8 @@ def _check(self, require_compatible: bool, require_description: bool):
387419
388420 # Allowed top-level keys. The 'include' key should have been
389421 # removed by _load_raw() already.
390- ok_top = {"description " , "compatible " , "bus " , "on- bus" ,
391- "properties" , "child-binding" }
422+ ok_top = {"title " , "description " , "compatible " , "bus" ,
423+ "on-bus" , " properties" , "child-binding" }
392424
393425 # Descriptive errors for legacy bindings.
394426 legacy_errors = {
@@ -398,7 +430,6 @@ def _check(self, require_compatible: bool, require_description: bool):
398430 "parent" : "use 'on-bus: <bus>' instead" ,
399431 "parent-bus" : "use 'on-bus: <bus>' instead" ,
400432 "sub-node" : "use 'child-binding' instead" ,
401- "title" : "use 'description' instead" ,
402433 }
403434
404435 for key in raw :
@@ -3328,7 +3359,8 @@ def _raw_default_property_for(
33283359 for name in _DEFAULT_PROP_TYPES
33293360 },
33303361 },
3331- require_compatible = False , require_description = False ,
3362+ require_compatible = False ,
3363+ require_description = False ,
33323364)
33333365
33343366_DEFAULT_PROP_SPECS : dict [str , PropertySpec ] = {
0 commit comments