@@ -855,7 +855,8 @@ static void scp_remove_rpmsg_subdev(struct mtk_scp *scp)
855855}
856856
857857static struct mtk_scp * scp_rproc_init (struct platform_device * pdev ,
858- struct mtk_scp_of_cluster * scp_cluster )
858+ struct mtk_scp_of_cluster * scp_cluster ,
859+ const struct mtk_scp_of_data * of_data )
859860{
860861 struct device * dev = & pdev -> dev ;
861862 struct device_node * np = dev -> of_node ;
@@ -878,7 +879,7 @@ static struct mtk_scp *scp_rproc_init(struct platform_device *pdev,
878879 scp = rproc -> priv ;
879880 scp -> rproc = rproc ;
880881 scp -> dev = dev ;
881- scp -> data = of_device_get_match_data ( dev ) ;
882+ scp -> data = of_data ;
882883 scp -> cluster = scp_cluster ;
883884 platform_set_drvdata (pdev , scp );
884885
@@ -951,15 +952,15 @@ static void scp_free(struct mtk_scp *scp)
951952 mutex_destroy (& scp -> send_lock );
952953}
953954
954- static int scp_cluster_init (struct platform_device * pdev ,
955- struct mtk_scp_of_cluster * scp_cluster )
955+ static int scp_add_single_core (struct platform_device * pdev ,
956+ struct mtk_scp_of_cluster * scp_cluster )
956957{
957958 struct device * dev = & pdev -> dev ;
958959 struct list_head * scp_list = & scp_cluster -> mtk_scp_list ;
959960 struct mtk_scp * scp ;
960961 int ret ;
961962
962- scp = scp_rproc_init (pdev , scp_cluster );
963+ scp = scp_rproc_init (pdev , scp_cluster , of_device_get_match_data ( dev ) );
963964 if (IS_ERR (scp ))
964965 return PTR_ERR (scp );
965966
@@ -975,6 +976,108 @@ static int scp_cluster_init(struct platform_device *pdev,
975976 return 0 ;
976977}
977978
979+ static int scp_add_multi_core (struct platform_device * pdev ,
980+ struct mtk_scp_of_cluster * scp_cluster )
981+ {
982+ struct device * dev = & pdev -> dev ;
983+ struct device_node * np = dev_of_node (dev );
984+ struct platform_device * cpdev ;
985+ struct device_node * child ;
986+ struct list_head * scp_list = & scp_cluster -> mtk_scp_list ;
987+ const struct mtk_scp_of_data * * cluster_of_data ;
988+ struct mtk_scp * scp , * temp ;
989+ int core_id = 0 ;
990+ int ret ;
991+
992+ cluster_of_data = (const struct mtk_scp_of_data * * )of_device_get_match_data (dev );
993+
994+ for_each_available_child_of_node (np , child ) {
995+ if (!cluster_of_data [core_id ]) {
996+ ret = - EINVAL ;
997+ dev_err (dev , "Not support core %d\n" , core_id );
998+ of_node_put (child );
999+ goto init_fail ;
1000+ }
1001+
1002+ cpdev = of_find_device_by_node (child );
1003+ if (!cpdev ) {
1004+ ret = - ENODEV ;
1005+ dev_err (dev , "Not found platform device for core %d\n" , core_id );
1006+ of_node_put (child );
1007+ goto init_fail ;
1008+ }
1009+
1010+ scp = scp_rproc_init (cpdev , scp_cluster , cluster_of_data [core_id ]);
1011+ put_device (& cpdev -> dev );
1012+ if (IS_ERR (scp )) {
1013+ ret = PTR_ERR (scp );
1014+ dev_err (dev , "Failed to initialize core %d rproc\n" , core_id );
1015+ of_node_put (child );
1016+ goto init_fail ;
1017+ }
1018+
1019+ ret = rproc_add (scp -> rproc );
1020+ if (ret ) {
1021+ dev_err (dev , "Failed to add rproc of core %d\n" , core_id );
1022+ of_node_put (child );
1023+ scp_free (scp );
1024+ goto init_fail ;
1025+ }
1026+
1027+ list_add_tail (& scp -> elem , scp_list );
1028+ core_id ++ ;
1029+ }
1030+
1031+ /*
1032+ * Here we are setting the platform device for @pdev to the last @scp that was
1033+ * created, which is needed because (1) scp_rproc_init() is calling
1034+ * platform_set_drvdata() on the child platform devices and (2) we need a handle to
1035+ * the cluster list in scp_remove().
1036+ */
1037+ platform_set_drvdata (pdev , scp );
1038+
1039+ return 0 ;
1040+
1041+ init_fail :
1042+ list_for_each_entry_safe_reverse (scp , temp , scp_list , elem ) {
1043+ list_del (& scp -> elem );
1044+ rproc_del (scp -> rproc );
1045+ scp_free (scp );
1046+ }
1047+
1048+ return ret ;
1049+ }
1050+
1051+ static int scp_is_single_core (struct platform_device * pdev )
1052+ {
1053+ struct device * dev = & pdev -> dev ;
1054+ struct device_node * np = dev_of_node (dev );
1055+ struct device_node * child ;
1056+
1057+ child = of_get_next_available_child (np , NULL );
1058+ if (!child )
1059+ return dev_err_probe (dev , - ENODEV , "No child node\n" );
1060+
1061+ of_node_put (child );
1062+ return of_node_name_eq (child , "cros-ec-rpmsg" );
1063+ }
1064+
1065+ static int scp_cluster_init (struct platform_device * pdev , struct mtk_scp_of_cluster * scp_cluster )
1066+ {
1067+ int ret ;
1068+
1069+ ret = scp_is_single_core (pdev );
1070+ if (ret < 0 )
1071+ return ret ;
1072+
1073+ if (ret )
1074+ ret = scp_add_single_core (pdev , scp_cluster );
1075+ else
1076+ ret = scp_add_multi_core (pdev , scp_cluster );
1077+
1078+ return ret ;
1079+ }
1080+
9781081static int scp_probe (struct platform_device * pdev )
9791082{
9801083 struct device * dev = & pdev -> dev ;
@@ -1007,6 +1110,10 @@ static int scp_probe(struct platform_device *pdev)
10071110
10081111 INIT_LIST_HEAD (& scp_cluster -> mtk_scp_list );
10091112
1113+ ret = devm_of_platform_populate (dev );
1114+ if (ret )
1115+ return dev_err_probe (dev , ret , "Failed to populate platform devices\n" );
1116+
10101117 ret = scp_cluster_init (pdev , scp_cluster );
10111118 if (ret )
10121119 return ret ;
@@ -1101,12 +1208,19 @@ static const struct mtk_scp_of_data mt8195_of_data_c1 = {
11011208 .host_to_scp_int_bit = MT8195_CORE1_HOST_IPC_INT_BIT ,
11021209};
11031210
1211+ static const struct mtk_scp_of_data * mt8195_of_data_cores [] = {
1212+ & mt8195_of_data ,
1213+ & mt8195_of_data_c1 ,
1214+ NULL
1215+ };
1216+
11041217static const struct of_device_id mtk_scp_of_match [] = {
11051218 { .compatible = "mediatek,mt8183-scp" , .data = & mt8183_of_data },
11061219 { .compatible = "mediatek,mt8186-scp" , .data = & mt8186_of_data },
11071220 { .compatible = "mediatek,mt8188-scp" , .data = & mt8188_of_data },
11081221 { .compatible = "mediatek,mt8192-scp" , .data = & mt8192_of_data },
11091222 { .compatible = "mediatek,mt8195-scp" , .data = & mt8195_of_data },
1223+ { .compatible = "mediatek,mt8195-scp-dual" , .data = & mt8195_of_data_cores },
11101224 {},
11111225};
11121226MODULE_DEVICE_TABLE (of , mtk_scp_of_match );
0 commit comments