Skip to content

Commit 72c350c

Browse files
tnmyshmathieupoirier
authored andcommitted
remoteproc: zynqmp: parse TCM from device tree
ZynqMP TCM information was fixed in driver. Now ZynqMP TCM information is available in device-tree. Parse TCM information in driver as per new bindings. Signed-off-by: Tanmay Shah <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mathieu Poirier <[email protected]>
1 parent 9e1b2a0 commit 72c350c

File tree

1 file changed

+120
-7
lines changed

1 file changed

+120
-7
lines changed

drivers/remoteproc/xlnx_r5_remoteproc.c

Lines changed: 120 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ struct mbox_info {
7474
};
7575

7676
/*
77-
* Hardcoded TCM bank values. This will be removed once TCM bindings are
78-
* accepted for system-dt specifications and upstreamed in linux kernel
77+
* Hardcoded TCM bank values. This will stay in driver to maintain backward
78+
* compatibility with device-tree that does not have TCM information.
7979
*/
8080
static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
8181
{0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
@@ -761,6 +761,103 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
761761
return ERR_PTR(ret);
762762
}
763763

764+
static int zynqmp_r5_get_tcm_node_from_dt(struct zynqmp_r5_cluster *cluster)
765+
{
766+
int i, j, tcm_bank_count, ret, tcm_pd_idx, pd_count;
767+
struct of_phandle_args out_args;
768+
struct zynqmp_r5_core *r5_core;
769+
struct platform_device *cpdev;
770+
struct mem_bank_data *tcm;
771+
struct device_node *np;
772+
struct resource *res;
773+
u64 abs_addr, size;
774+
struct device *dev;
775+
776+
for (i = 0; i < cluster->core_count; i++) {
777+
r5_core = cluster->r5_cores[i];
778+
dev = r5_core->dev;
779+
np = r5_core->np;
780+
781+
pd_count = of_count_phandle_with_args(np, "power-domains",
782+
"#power-domain-cells");
783+
784+
if (pd_count <= 0) {
785+
dev_err(dev, "invalid power-domains property, %d\n", pd_count);
786+
return -EINVAL;
787+
}
788+
789+
/* First entry in power-domains list is for r5 core, rest for TCM. */
790+
tcm_bank_count = pd_count - 1;
791+
792+
if (tcm_bank_count <= 0) {
793+
dev_err(dev, "invalid TCM count %d\n", tcm_bank_count);
794+
return -EINVAL;
795+
}
796+
797+
r5_core->tcm_banks = devm_kcalloc(dev, tcm_bank_count,
798+
sizeof(struct mem_bank_data *),
799+
GFP_KERNEL);
800+
if (!r5_core->tcm_banks)
801+
return -ENOMEM;
802+
803+
r5_core->tcm_bank_count = tcm_bank_count;
804+
for (j = 0, tcm_pd_idx = 1; j < tcm_bank_count; j++, tcm_pd_idx++) {
805+
tcm = devm_kzalloc(dev, sizeof(struct mem_bank_data),
806+
GFP_KERNEL);
807+
if (!tcm)
808+
return -ENOMEM;
809+
810+
r5_core->tcm_banks[j] = tcm;
811+
812+
/* Get power-domains id of TCM. */
813+
ret = of_parse_phandle_with_args(np, "power-domains",
814+
"#power-domain-cells",
815+
tcm_pd_idx, &out_args);
816+
if (ret) {
817+
dev_err(r5_core->dev,
818+
"failed to get tcm %d pm domain, ret %d\n",
819+
tcm_pd_idx, ret);
820+
return ret;
821+
}
822+
tcm->pm_domain_id = out_args.args[0];
823+
of_node_put(out_args.np);
824+
825+
/* Get TCM address without translation. */
826+
ret = of_property_read_reg(np, j, &abs_addr, &size);
827+
if (ret) {
828+
dev_err(dev, "failed to get reg property\n");
829+
return ret;
830+
}
831+
832+
/*
833+
* Remote processor can address only 32 bits
834+
* so convert 64-bits into 32-bits. This will discard
835+
* any unwanted upper 32-bits.
836+
*/
837+
tcm->da = (u32)abs_addr;
838+
tcm->size = (u32)size;
839+
840+
cpdev = to_platform_device(dev);
841+
res = platform_get_resource(cpdev, IORESOURCE_MEM, j);
842+
if (!res) {
843+
dev_err(dev, "failed to get tcm resource\n");
844+
return -EINVAL;
845+
}
846+
847+
tcm->addr = (u32)res->start;
848+
tcm->bank_name = (char *)res->name;
849+
res = devm_request_mem_region(dev, tcm->addr, tcm->size,
850+
tcm->bank_name);
851+
if (!res) {
852+
dev_err(dev, "failed to request tcm resource\n");
853+
return -EINVAL;
854+
}
855+
}
856+
}
857+
858+
return 0;
859+
}
860+
764861
/**
765862
* zynqmp_r5_get_tcm_node()
766863
* Ideally this function should parse tcm node and store information
@@ -839,9 +936,16 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
839936
struct zynqmp_r5_core *r5_core;
840937
int ret, i;
841938

842-
ret = zynqmp_r5_get_tcm_node(cluster);
843-
if (ret < 0) {
844-
dev_err(dev, "can't get tcm node, err %d\n", ret);
939+
r5_core = cluster->r5_cores[0];
940+
941+
/* Maintain backward compatibility for zynqmp by using hardcode TCM address. */
942+
if (of_find_property(r5_core->np, "reg", NULL))
943+
ret = zynqmp_r5_get_tcm_node_from_dt(cluster);
944+
else
945+
ret = zynqmp_r5_get_tcm_node(cluster);
946+
947+
if (ret) {
948+
dev_err(dev, "can't get tcm, err %d\n", ret);
845949
return ret;
846950
}
847951

@@ -906,16 +1010,25 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
9061010
* fail driver probe if either of that is not set in dts.
9071011
*/
9081012
if (cluster_mode == LOCKSTEP_MODE) {
909-
tcm_mode = PM_RPU_TCM_COMB;
9101013
fw_reg_val = PM_RPU_MODE_LOCKSTEP;
9111014
} else if (cluster_mode == SPLIT_MODE) {
912-
tcm_mode = PM_RPU_TCM_SPLIT;
9131015
fw_reg_val = PM_RPU_MODE_SPLIT;
9141016
} else {
9151017
dev_err(dev, "driver does not support cluster mode %d\n", cluster_mode);
9161018
return -EINVAL;
9171019
}
9181020

1021+
if (of_find_property(dev_node, "xlnx,tcm-mode", NULL)) {
1022+
ret = of_property_read_u32(dev_node, "xlnx,tcm-mode", (u32 *)&tcm_mode);
1023+
if (ret)
1024+
return ret;
1025+
} else {
1026+
if (cluster_mode == LOCKSTEP_MODE)
1027+
tcm_mode = PM_RPU_TCM_COMB;
1028+
else
1029+
tcm_mode = PM_RPU_TCM_SPLIT;
1030+
}
1031+
9191032
/*
9201033
* Number of cores is decided by number of child nodes of
9211034
* r5f subsystem node in dts. If Split mode is used in dts

0 commit comments

Comments
 (0)