@@ -74,8 +74,8 @@ struct mbox_info {
74
74
};
75
75
76
76
/*
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.
79
79
*/
80
80
static const struct mem_bank_data zynqmp_tcm_banks_split [] = {
81
81
{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)
761
761
return ERR_PTR (ret );
762
762
}
763
763
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
+
764
861
/**
765
862
* zynqmp_r5_get_tcm_node()
766
863
* 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,
839
936
struct zynqmp_r5_core * r5_core ;
840
937
int ret , i ;
841
938
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 );
845
949
return ret ;
846
950
}
847
951
@@ -906,16 +1010,25 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
906
1010
* fail driver probe if either of that is not set in dts.
907
1011
*/
908
1012
if (cluster_mode == LOCKSTEP_MODE ) {
909
- tcm_mode = PM_RPU_TCM_COMB ;
910
1013
fw_reg_val = PM_RPU_MODE_LOCKSTEP ;
911
1014
} else if (cluster_mode == SPLIT_MODE ) {
912
- tcm_mode = PM_RPU_TCM_SPLIT ;
913
1015
fw_reg_val = PM_RPU_MODE_SPLIT ;
914
1016
} else {
915
1017
dev_err (dev , "driver does not support cluster mode %d\n" , cluster_mode );
916
1018
return - EINVAL ;
917
1019
}
918
1020
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
+
919
1032
/*
920
1033
* Number of cores is decided by number of child nodes of
921
1034
* r5f subsystem node in dts. If Split mode is used in dts
0 commit comments