summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/hab.txt41
-rw-r--r--drivers/soc/qcom/hab/hab.c9
-rw-r--r--drivers/soc/qcom/hab/hab_parser.c98
3 files changed, 144 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/soc/qcom/hab.txt b/Documentation/devicetree/bindings/soc/qcom/hab.txt
new file mode 100644
index 000000000000..32f79e7ff498
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/hab.txt
@@ -0,0 +1,41 @@
+* HAB
+
+HAB(Hypervisor ABstraction) is meant to be a cross-platform abstraction layer
+for utilizing the underlying hypervisor system. This API can be accessed from
+both user and kernel sides.
+The intended users of this are primarily the multimedia drivers who want to
+communicate with the host OS to use the multimedia hardware.
+
+Required properties:
+- compatible: Must be "qcom,hab"
+- vmid: the local VM's ID
+ It should be unique in a system, and host's ID should be 0. Here is an
+ example for a system as qvm host + agl gvm + android gvm, and such below
+ setting is proper,
+ qvm host's vmid: 0
+ agl gvm's vmid: 1
+ android gvm's vmid: 2
+- mmid group properties:
+ - grp-start-id: mmid group starting ID, eg, 100 is for MM_AUD_1~4
+ - role: the local role of this group, and must be "fe" or "be"
+ - remote-vmids: When the local role is "fe", this is to tell which VM is the
+ relevant BE. When it is "be", this is to tell which VMs it will support as
+ BE.
+
+Example:
+ qcom,hab {
+ compatible = "qcom,hab";
+ vmid = <2>;
+
+ mmid100: mmid-grp@100 {
+ grp-start-id = <100>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmid200: mmid-grp@200 {
+ grp-start-id = <200>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+ }
diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c
index 040730d63a83..a48636dc9dbe 100644
--- a/drivers/soc/qcom/hab/hab.c
+++ b/drivers/soc/qcom/hab/hab.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -687,9 +687,12 @@ int do_hab_parse(void)
memset(&hab_driver.settings, HABCFG_VMID_INVALID,
sizeof(hab_driver.settings));
- pr_debug("prepare default gvm 2 settings...\n");
- fill_default_gvm_settings(&hab_driver.settings, 2,
+ result = hab_parse(&hab_driver.settings);
+ if (result) {
+ pr_warn("hab_parse failed and use the default settings\n");
+ fill_default_gvm_settings(&hab_driver.settings, 2,
MM_AUD_START, MM_ID_MAX);
+ }
/* now generate hab pchan list */
result = hab_generate_pchan_list(&hab_driver.settings);
diff --git a/drivers/soc/qcom/hab/hab_parser.c b/drivers/soc/qcom/hab/hab_parser.c
index a38d9bcf26b9..da0a4a3830a7 100644
--- a/drivers/soc/qcom/hab/hab_parser.c
+++ b/drivers/soc/qcom/hab/hab_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,6 +12,7 @@
*/
#include "hab.h"
+#include <linux/of.h>
/*
* set valid mmid value in tbl to show this is valid entry. All inputs here are
@@ -63,3 +64,98 @@ int fill_default_gvm_settings(struct local_vmid *settings, int vmid_local,
return fill_vmid_mmid_tbl(settings->vmid_mmid_list, 0, 1,
mmid_start/100, (mmid_end-mmid_start)/100+1, HABCFG_BE_FALSE);
}
+
+static int hab_parse_dt(struct local_vmid *settings)
+{
+ int result, i;
+ struct device_node *hab_node = NULL;
+ struct device_node *mmid_grp_node = NULL;
+ const char *role = NULL;
+ int tmp = -1, vmids_num;
+ u32 vmids[16];
+ int32_t grp_start_id, be;
+
+ /* parse device tree*/
+ pr_debug("parsing hab node in device tree...\n");
+ hab_node = of_find_compatible_node(NULL, NULL, "qcom,hab");
+ if (!hab_node) {
+ pr_err("no hab device tree node\n");
+ return -ENODEV;
+ }
+
+ /* read the local vmid of this VM, like 0 for host, 1 for AGL GVM */
+ result = of_property_read_u32(hab_node, "vmid", &tmp);
+ if (result) {
+ pr_err("failed to read local vmid, result = %d\n", result);
+ return result;
+ }
+
+ pr_debug("local vmid = %d\n", tmp);
+ settings->self = tmp;
+
+ for_each_child_of_node(hab_node, mmid_grp_node) {
+ /* read the group starting id */
+ result = of_property_read_u32(mmid_grp_node,
+ "grp-start-id", &tmp);
+ if (result) {
+ pr_err("failed to read grp-start-id, result = %d\n",
+ result);
+ return result;
+ }
+
+ pr_debug("grp-start-id = %d\n", tmp);
+ grp_start_id = tmp;
+
+ /* read the role(fe/be) of these pchans in this mmid group */
+ result = of_property_read_string(mmid_grp_node, "role", &role);
+ if (result) {
+ pr_err("failed to get role, result = %d\n", result);
+ return result;
+ }
+
+ pr_debug("local role of this mmid group is %s\n", role);
+ if (!strcmp(role, "be"))
+ be = 1;
+ else
+ be = 0;
+
+ /* read the remote vmids for these pchans in this mmid group */
+ vmids_num = of_property_count_elems_of_size(mmid_grp_node,
+ "remote-vmids", sizeof(u32));
+
+ result = of_property_read_u32_array(mmid_grp_node,
+ "remote-vmids", vmids, vmids_num);
+ if (result) {
+ pr_err("failed to read remote-vmids, result = %d\n",
+ result);
+ return result;
+ }
+
+ for (i = 0; i < vmids_num; i++) {
+ pr_debug("vmids_num = %d, vmids[%d] = %d\n",
+ vmids_num, i, vmids[i]);
+
+ result = fill_vmid_mmid_tbl(
+ settings->vmid_mmid_list,
+ vmids[i], 1,
+ grp_start_id/100, 1, be);
+ if (result) {
+ pr_err("fill_vmid_mmid_tbl failed\n");
+ return result;
+ }
+ }
+
+ }
+
+ dump_settings(settings);
+ return 0;
+}
+
+int hab_parse(struct local_vmid *settings)
+{
+ int ret;
+
+ ret = hab_parse_dt(settings);
+
+ return ret;
+}