1#!/usr/bin/env python3 2# 3# Copyright (c) 2022 Kumar Gala <galak@kernel.org> 4# 5# SPDX-License-Identifier: Apache-2.0 6 7import argparse 8import os 9import sys 10import re 11 12import yaml 13try: 14 # Use the C LibYAML parser if available, rather than the Python parser. 15 from yaml import CSafeLoader as SafeLoader 16except ImportError: 17 from yaml import SafeLoader # type: ignore 18 19sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'python-devicetree', 20 'src')) 21 22def binding_paths(bindings_dirs): 23 # Returns a list with the paths to all bindings (.yaml files) in 24 # 'bindings_dirs' 25 26 binding_paths = [] 27 28 for bindings_dir in bindings_dirs: 29 for root, _, filenames in os.walk(bindings_dir): 30 for filename in filenames: 31 if filename.endswith(".yaml") or filename.endswith(".yml"): 32 binding_paths.append(os.path.join(root, filename)) 33 34 return binding_paths 35 36def parse_args(): 37 # Returns parsed command-line arguments 38 39 parser = argparse.ArgumentParser(allow_abbrev=False) 40 parser.add_argument("--kconfig-out", required=True, 41 help="path to write the Kconfig file") 42 parser.add_argument("--bindings-dirs", nargs='+', required=True, 43 help="directory with bindings in YAML format, " 44 "we allow multiple") 45 46 return parser.parse_args() 47 48def printfile(s): 49 print(s, file=kconfig_file) 50 51def str2ident(s): 52 # Converts 's' to a form suitable for (part of) an identifier 53 54 return re.sub('[-,.@/+]', '_', s.upper()) 55 56def compat2kconfig(compat): 57 compat_ident = str2ident(compat) 58 59 printfile(f'') 60 printfile(f'DT_COMPAT_{compat_ident} := {compat}') 61 printfile(f'') 62 printfile(f'config DT_HAS_{compat_ident}_ENABLED') 63 printfile(f'\tdef_bool $(dt_compat_enabled,$(DT_COMPAT_{compat_ident}))') 64 65def main(): 66 global kconfig_file 67 args = parse_args() 68 69 compat_list = [] 70 71 for binding_path in binding_paths(args.bindings_dirs): 72 with open(binding_path, encoding="utf-8") as f: 73 contents = f.read() 74 75 try: 76 # Parsed PyYAML output (Python lists/dictionaries/strings/etc., 77 # representing the file) 78 raw = yaml.load(contents, Loader=SafeLoader) 79 except yaml.YAMLError as e: 80 print(f"WARNING: '{binding_path}' appears in binding " 81 f"directories but isn't valid YAML: {e}") 82 continue 83 if raw is None or 'compatible' not in raw: 84 continue 85 86 compat_list.append(raw['compatible']) 87 88 # Remove any duplicates and sort the list 89 compat_list = sorted(set(compat_list)) 90 91 with open(args.kconfig_out, "w", encoding="utf-8") as kconfig_file: 92 printfile(f'# Generated devicetree Kconfig') 93 printfile(f'#') 94 printfile(f'# SPDX-License-Identifier: Apache-2.0') 95 96 for c in compat_list: 97 compat2kconfig(c) 98 99 100if __name__ == "__main__": 101 main() 102