@@ -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 */
8080static 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