From d9c1cfb1d7d9a09248d56e71da0d761b18bff2e4 Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Fri, 20 Dec 2024 07:58:46 -0800 Subject: [PATCH] openamp: xlnx: Enable gen_domain to invoke openamp processing For gen_domain_dts.py plugin, if the openamp domains are present then have this processing occur at the start. Additionally if the openamp processing ocurred then keep TCM nodes. For OpenAMP to enable this do the following: 1. If OpenAMP processing occurs then at the end remove the OpenAMP nodes 2. Only output the OpenAMP Configuration header for non-Linux targets 3. Add some OpenAMP lookup tables to aid the gen_domain_dts.py in OpenAMP info lookup This way the following use cases are still preserved 1. Non-Linux OpenAMP runs 2. If a user keeps the OpenAMP plugin args in a Linux domain Lopper run Signed-off-by: Ben Levinsky --- lopper/assists/gen_domain_dts.py | 13 ++++- lopper/assists/openamp.py | 2 +- lopper/assists/openamp_xlnx.py | 69 ++++++++++++++++++++------- lopper/assists/openamp_xlnx_common.py | 13 +++++ 4 files changed, 78 insertions(+), 19 deletions(-) diff --git a/lopper/assists/gen_domain_dts.py b/lopper/assists/gen_domain_dts.py index 1b1883cf..8db51985 100644 --- a/lopper/assists/gen_domain_dts.py +++ b/lopper/assists/gen_domain_dts.py @@ -22,6 +22,8 @@ from common_utils import to_cmakelist import common_utils as utils from domain_access import update_mem_node +from openamp_xlnx import xlnx_openamp_find_channels, xlnx_openamp_parse +from openamp_xlnx_common import openamp_linux_hosts, openamp_roles def delete_unused_props( node, driver_proplist , delete_child_nodes): if delete_child_nodes: @@ -91,6 +93,15 @@ def xlnx_generate_domain_dts(tgt_node, sdt, options): except IndexError: pass + openamp_present = xlnx_openamp_find_channels(sdt) + + if openamp_present and linux_dt == 1 and machine in openamp_linux_hosts: + # Currently this plugin is only invoked for Linux. So for now just consider linux case + xlnx_options = { "openamp_host": openamp_roles[machine], + "openamp_remote": openamp_roles[machine], + "openamp_role": "host" } + xlnx_openamp_parse(sdt, options, xlnx_options, verbose = 0 ) + # Delete other CPU Cluster nodes cpunode_list = sdt.tree.nodes('/cpu.*@.*', strict=True) clustercpu_nodes = [] @@ -117,7 +128,7 @@ def xlnx_generate_domain_dts(tgt_node, sdt, options): if linux_dt: if node.name == "memory@fffc0000" or node.name == "memory@bbf00000": sdt.tree.delete(node) - if keep_tcms == None and 'tcm' in node.name: + if (keep_tcms == None and not openamp_present) and 'tcm' in node.name: sdt.tree.delete(node) if node.propval('memory_type', list) == ['linear_flash']: sdt.tree.delete(node) diff --git a/lopper/assists/openamp.py b/lopper/assists/openamp.py index f2238b4d..f9551fad 100644 --- a/lopper/assists/openamp.py +++ b/lopper/assists/openamp.py @@ -187,7 +187,7 @@ def openamp_parse(root_node, tree, options ): for i in root_node["compatible"].value: if "xlnx" in i: - return xlnx_openamp_parse(tree, options, verbose) + return xlnx_openamp_parse(tree, options, None, verbose) return False diff --git a/lopper/assists/openamp_xlnx.py b/lopper/assists/openamp_xlnx.py index 6ec2aed7..a3b84eb6 100644 --- a/lopper/assists/openamp_xlnx.py +++ b/lopper/assists/openamp_xlnx.py @@ -870,7 +870,7 @@ def xlnx_rpmsg_parse_generate_native_amba_node(tree): return amba_node -def xlnx_rpmsg_parse(tree, node, openamp_channel_info, options, verbose = 0 ): +def xlnx_rpmsg_parse(tree, node, openamp_channel_info, options, xlnx_options = None, verbose = 0 ): # Xilinx OpenAMP subroutine to collect RPMsg information from RPMsg # relation amba_node = None @@ -951,17 +951,22 @@ def xlnx_rpmsg_parse(tree, node, openamp_channel_info, options, verbose = 0 ): role = None arg_host = None arg_remote = None - for o,a in opts: - if o in ('-l', "--openamp_role"): - role = a - elif o in ('-m', "--openamp_host"): - arg_host = a - elif o in ('-n', "--openamp_remote"): - arg_remote = a - elif o in ("--openamp_output_filename"): - output_file = a - else: - print("Argument: ",o, " is not recognized. Erroring out.") + if xlnx_options != None: + role = xlnx_options["openamp_role"] + arg_host = xlnx_options["openamp_host"] + arg_remote = xlnx_options["openamp_remote"] + else: + for o,a in opts: + if o in ('-l', "--openamp_role"): + role = a + elif o in ('-m', "--openamp_host"): + arg_host = a + elif o in ('-n', "--openamp_remote"): + arg_remote = a + elif o in ("--openamp_output_filename"): + output_file = a + else: + print("Argument: ",o, " is not recognized. Erroring out.") if role not in ['host', 'remote']: print('ERROR: Role value is not proper. Expect either "host" or "remote". Got: ', role) @@ -986,9 +991,13 @@ def xlnx_rpmsg_parse(tree, node, openamp_channel_info, options, verbose = 0 ): return False # Generate Text file to configure OpenAMP Application - ret = xlnx_openamp_gen_outputs(openamp_channel_info, chan_id, role, verbose) - if not ret: - return ret + # Only do this for remote firmware configuration + if role == 'remote': + ret = xlnx_openamp_gen_outputs(openamp_channel_info, chan_id, role, verbose) + if not ret: + return ret + + xlnx_openamp_remove_channels(tree) # remove definitions defn_node = tree["/definitions"] @@ -1577,8 +1586,34 @@ def xlnx_remoteproc_parse(tree, node, openamp_channel_info, verbose = 0 ): return True +def xlnx_openamp_remove_channels(tree, verbose = 0): + for n in tree["/domains"].subnodes(): + node_compat = n.props("compatible") + if node_compat != []: + node_compat = node_compat[0].value + if node_compat in [REMOTEPROC_D_TO_D_v2, REMOTEPROC_D_TO_D]: + tree - n + if node_compat == RPMSG_D_TO_D: + tree - n + +def xlnx_openamp_find_channels(sdt, verbose = 0): + # Xilinx OpenAMP subroutine to parse OpenAMP Channel + # information and generate Device Tree information. + tree = sdt.tree + + for n in tree["/domains"].subnodes(): + node_compat = n.props("compatible") + if node_compat != []: + node_compat = node_compat[0].value + + if node_compat in [REMOTEPROC_D_TO_D_v2, REMOTEPROC_D_TO_D]: + return True + if node_compat == RPMSG_D_TO_D: + return True + + return False -def xlnx_openamp_parse(sdt, options, verbose = 0 ): +def xlnx_openamp_parse(sdt, options, xlnx_options = None, verbose = 0 ): # Xilinx OpenAMP subroutine to parse OpenAMP Channel # information and generate Device Tree information. tree = sdt.tree @@ -1594,7 +1629,7 @@ def xlnx_openamp_parse(sdt, options, verbose = 0 ): openamp_channel_info[REMOTEPROC_D_TO_D_v2] = (node_compat == REMOTEPROC_D_TO_D_v2) ret = xlnx_remoteproc_parse(tree, n, openamp_channel_info, verbose) elif node_compat == RPMSG_D_TO_D: - ret = xlnx_rpmsg_parse(tree, n, openamp_channel_info, options, verbose) + ret = xlnx_rpmsg_parse(tree, n, openamp_channel_info, options, xlnx_options, verbose) if ret == False: return ret diff --git a/lopper/assists/openamp_xlnx_common.py b/lopper/assists/openamp_xlnx_common.py index c8cceb34..34bf51d8 100644 --- a/lopper/assists/openamp_xlnx_common.py +++ b/lopper/assists/openamp_xlnx_common.py @@ -30,6 +30,19 @@ 0xFF380000 : 67, } +openamp_linux_hosts = [ "psv_cortexa72_0", "psx_cortexa78_0", "psu_cortexa53_0" ] +openamp_roles = { openamp_linux_hosts[0] : "a72_0", + openamp_linux_hosts[1] : "a78_0", + openamp_linux_hosts[2] : "a53_0", + "psx_cortexr52_0" : "r52_0", + "psx_cortexr52_1" : "r52_1", + "psx_cortexr52_2" : "r52_2", + "psx_cortexr52_3" : "r52_3", + "psu_cortexr5_0" : "r5_0", + "psu_cortexr5_1" : "r5_1", + "psv_cortexr5_1" : "r5_1", + "psv_cortexr5_0" : "r5_0" } + class SOC_TYPE: UNINITIALIZED = -1 VERSAL = 0