devicetree: generate extern's for devicetree struct devices

Generate a header (device_extern.h) that handles extern of possible
device structs that would come from devicetree.  This removes the need
for DEVICE_DT_DECLARE and DEVICE_DT_INST_DECLARE which we can remove.

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py
index 3dd6138..2fd6ba1 100755
--- a/scripts/dts/gen_defines.py
+++ b/scripts/dts/gen_defines.py
@@ -110,9 +110,35 @@
         write_chosen(edt)
         write_global_compat_info(edt)
 
+        write_device_extern_header(args.device_header_out, edt)
+
     if args.edt_pickle_out:
         write_pickled_edt(edt, args.edt_pickle_out)
 
+
+def write_device_extern_header(device_header_out, edt):
+    # Generate header that will extern devicetree struct device's
+
+    with open(device_header_out, "w", encoding="utf-8") as dev_header_file:
+        print("#ifndef DEVICE_EXTERN_GEN_H", file=dev_header_file)
+        print("#define DEVICE_EXTERN_GEN_H", file=dev_header_file)
+        print("", file=dev_header_file)
+        print("#ifdef __cplusplus", file=dev_header_file)
+        print('extern "C" {', file=dev_header_file)
+        print("#endif", file=dev_header_file)
+        print("", file=dev_header_file)
+
+        for node in sorted(edt.nodes, key=lambda node: node.dep_ordinal):
+            print(f"extern const struct device DEVICE_DT_NAME_GET(DT_{node.z_path_id});", file=dev_header_file)
+
+        print("", file=dev_header_file)
+        print("#ifdef __cplusplus", file=dev_header_file)
+        print("}", file=dev_header_file)
+        print("#endif", file=dev_header_file)
+        print("", file=dev_header_file)
+        print("#endif /* DEVICE_EXTERN_GEN_H */", file=dev_header_file)
+
+
 def setup_edtlib_logging():
     # The edtlib module emits logs using the standard 'logging' module.
     # Configure it so that warnings and above are printed to stderr,
@@ -159,6 +185,8 @@
     parser.add_argument("--dts-out", required=True,
                         help="path to write merged DTS source code to (e.g. "
                              "as a debugging aid)")
+    parser.add_argument("--device-header-out", required=True,
+                        help="path to write device struct extern header to")
     parser.add_argument("--edt-pickle-out",
                         help="path to write pickled edtlib.EDT object to")