@@ -428,6 +428,7 @@ static int k3_r5_rproc_request_mbox(struct rproc *rproc)
428428 * private to each core. Only Core0 needs to be unhalted for running the
429429 * cluster in this mode. The function uses the same reset logic as LockStep
430430 * mode for this (though the behavior is agnostic of the reset release order).
431+ * This callback is invoked only in remoteproc mode.
431432 */
432433static int k3_r5_rproc_prepare (struct rproc * rproc )
433434{
@@ -493,7 +494,8 @@ static int k3_r5_rproc_prepare(struct rproc *rproc)
493494 * both cores. The access is made possible only with releasing the resets for
494495 * both cores, but with only Core0 unhalted. This function re-uses the same
495496 * reset assert logic as LockStep mode for this mode (though the behavior is
496- * agnostic of the reset assert order).
497+ * agnostic of the reset assert order). This callback is invoked only in
498+ * remoteproc mode.
497499 */
498500static int k3_r5_rproc_unprepare (struct rproc * rproc )
499501{
@@ -527,7 +529,8 @@ static int k3_r5_rproc_unprepare(struct rproc *rproc)
527529 *
528530 * The Single-CPU mode on applicable SoCs (eg: AM64x) only uses Core0 to execute
529531 * code, so only Core0 needs to be unhalted. The function uses the same logic
530- * flow as Split-mode for this.
532+ * flow as Split-mode for this. This callback is invoked only in remoteproc
533+ * mode.
531534 */
532535static int k3_r5_rproc_start (struct rproc * rproc )
533536{
@@ -598,7 +601,8 @@ static int k3_r5_rproc_start(struct rproc *rproc)
598601 * be done here, but is preferred to be done in the .unprepare() ops - this
599602 * maintains the symmetric behavior between the .start(), .stop(), .prepare()
600603 * and .unprepare() ops, and also balances them well between sysfs 'state'
601- * flow and device bind/unbind or module removal.
604+ * flow and device bind/unbind or module removal. This callback is invoked
605+ * only in remoteproc mode.
602606 */
603607static int k3_r5_rproc_stop (struct rproc * rproc )
604608{
@@ -635,6 +639,78 @@ static int k3_r5_rproc_stop(struct rproc *rproc)
635639 return ret ;
636640}
637641
642+ /*
643+ * Attach to a running R5F remote processor (IPC-only mode)
644+ *
645+ * The R5F attach callback only needs to request the mailbox, the remote
646+ * processor is already booted, so there is no need to issue any TI-SCI
647+ * commands to boot the R5F cores in IPC-only mode. This callback is invoked
648+ * only in IPC-only mode.
649+ */
650+ static int k3_r5_rproc_attach (struct rproc * rproc )
651+ {
652+ struct k3_r5_rproc * kproc = rproc -> priv ;
653+ struct device * dev = kproc -> dev ;
654+ int ret ;
655+
656+ ret = k3_r5_rproc_request_mbox (rproc );
657+ if (ret )
658+ return ret ;
659+
660+ dev_info (dev , "R5F core initialized in IPC-only mode\n" );
661+ return 0 ;
662+ }
663+
664+ /*
665+ * Detach from a running R5F remote processor (IPC-only mode)
666+ *
667+ * The R5F detach callback performs the opposite operation to attach callback
668+ * and only needs to release the mailbox, the R5F cores are not stopped and
669+ * will be left in booted state in IPC-only mode. This callback is invoked
670+ * only in IPC-only mode.
671+ */
672+ static int k3_r5_rproc_detach (struct rproc * rproc )
673+ {
674+ struct k3_r5_rproc * kproc = rproc -> priv ;
675+ struct device * dev = kproc -> dev ;
676+
677+ mbox_free_channel (kproc -> mbox );
678+ dev_info (dev , "R5F core deinitialized in IPC-only mode\n" );
679+ return 0 ;
680+ }
681+
682+ /*
683+ * This function implements the .get_loaded_rsc_table() callback and is used
684+ * to provide the resource table for the booted R5F in IPC-only mode. The K3 R5F
685+ * firmwares follow a design-by-contract approach and are expected to have the
686+ * resource table at the base of the DDR region reserved for firmware usage.
687+ * This provides flexibility for the remote processor to be booted by different
688+ * bootloaders that may or may not have the ability to publish the resource table
689+ * address and size through a DT property. This callback is invoked only in
690+ * IPC-only mode.
691+ */
692+ static struct resource_table * k3_r5_get_loaded_rsc_table (struct rproc * rproc ,
693+ size_t * rsc_table_sz )
694+ {
695+ struct k3_r5_rproc * kproc = rproc -> priv ;
696+ struct device * dev = kproc -> dev ;
697+
698+ if (!kproc -> rmem [0 ].cpu_addr ) {
699+ dev_err (dev , "memory-region #1 does not exist, loaded rsc table can't be found" );
700+ return ERR_PTR (- ENOMEM );
701+ }
702+
703+ /*
704+ * NOTE: The resource table size is currently hard-coded to a maximum
705+ * of 256 bytes. The most common resource table usage for K3 firmwares
706+ * is to only have the vdev resource entry and an optional trace entry.
707+ * The exact size could be computed based on resource table address, but
708+ * the hard-coded value suffices to support the IPC-only mode.
709+ */
710+ * rsc_table_sz = 256 ;
711+ return (struct resource_table * )kproc -> rmem [0 ].cpu_addr ;
712+ }
713+
638714/*
639715 * Internal Memory translation helper
640716 *
@@ -1014,6 +1090,116 @@ static void k3_r5_adjust_tcm_sizes(struct k3_r5_rproc *kproc)
10141090 }
10151091}
10161092
1093+ /*
1094+ * This function checks and configures a R5F core for IPC-only or remoteproc
1095+ * mode. The driver is configured to be in IPC-only mode for a R5F core when
1096+ * the core has been loaded and started by a bootloader. The IPC-only mode is
1097+ * detected by querying the System Firmware for reset, power on and halt status
1098+ * and ensuring that the core is running. Any incomplete steps at bootloader
1099+ * are validated and errored out.
1100+ *
1101+ * In IPC-only mode, the driver state flags for ATCM, BTCM and LOCZRAMA settings
1102+ * and cluster mode parsed originally from kernel DT are updated to reflect the
1103+ * actual values configured by bootloader. The driver internal device memory
1104+ * addresses for TCMs are also updated.
1105+ */
1106+ static int k3_r5_rproc_configure_mode (struct k3_r5_rproc * kproc )
1107+ {
1108+ struct k3_r5_cluster * cluster = kproc -> cluster ;
1109+ struct k3_r5_core * core = kproc -> core ;
1110+ struct device * cdev = core -> dev ;
1111+ bool r_state = false, c_state = false;
1112+ u32 ctrl = 0 , cfg = 0 , stat = 0 , halted = 0 ;
1113+ u64 boot_vec = 0 ;
1114+ u32 atcm_enable , btcm_enable , loczrama ;
1115+ struct k3_r5_core * core0 ;
1116+ enum cluster_mode mode ;
1117+ int ret ;
1118+
1119+ core0 = list_first_entry (& cluster -> cores , struct k3_r5_core , elem );
1120+
1121+ ret = core -> ti_sci -> ops .dev_ops .is_on (core -> ti_sci , core -> ti_sci_id ,
1122+ & r_state , & c_state );
1123+ if (ret ) {
1124+ dev_err (cdev , "failed to get initial state, mode cannot be determined, ret = %d\n" ,
1125+ ret );
1126+ return ret ;
1127+ }
1128+ if (r_state != c_state ) {
1129+ dev_warn (cdev , "R5F core may have been powered on by a different host, programmed state (%d) != actual state (%d)\n" ,
1130+ r_state , c_state );
1131+ }
1132+
1133+ ret = reset_control_status (core -> reset );
1134+ if (ret < 0 ) {
1135+ dev_err (cdev , "failed to get initial local reset status, ret = %d\n" ,
1136+ ret );
1137+ return ret ;
1138+ }
1139+
1140+ ret = ti_sci_proc_get_status (core -> tsp , & boot_vec , & cfg , & ctrl ,
1141+ & stat );
1142+ if (ret < 0 ) {
1143+ dev_err (cdev , "failed to get initial processor status, ret = %d\n" ,
1144+ ret );
1145+ return ret ;
1146+ }
1147+ atcm_enable = cfg & PROC_BOOT_CFG_FLAG_R5_ATCM_EN ? 1 : 0 ;
1148+ btcm_enable = cfg & PROC_BOOT_CFG_FLAG_R5_BTCM_EN ? 1 : 0 ;
1149+ loczrama = cfg & PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE ? 1 : 0 ;
1150+ if (cluster -> soc_data -> single_cpu_mode ) {
1151+ mode = cfg & PROC_BOOT_CFG_FLAG_R5_SINGLE_CORE ?
1152+ CLUSTER_MODE_SINGLECPU : CLUSTER_MODE_SPLIT ;
1153+ } else {
1154+ mode = cfg & PROC_BOOT_CFG_FLAG_R5_LOCKSTEP ?
1155+ CLUSTER_MODE_LOCKSTEP : CLUSTER_MODE_SPLIT ;
1156+ }
1157+ halted = ctrl & PROC_BOOT_CTRL_FLAG_R5_CORE_HALT ;
1158+
1159+ /*
1160+ * IPC-only mode detection requires both local and module resets to
1161+ * be deasserted and R5F core to be unhalted. Local reset status is
1162+ * irrelevant if module reset is asserted (POR value has local reset
1163+ * deasserted), and is deemed as remoteproc mode
1164+ */
1165+ if (c_state && !ret && !halted ) {
1166+ dev_info (cdev , "configured R5F for IPC-only mode\n" );
1167+ kproc -> rproc -> state = RPROC_DETACHED ;
1168+ ret = 1 ;
1169+ /* override rproc ops with only required IPC-only mode ops */
1170+ kproc -> rproc -> ops -> prepare = NULL ;
1171+ kproc -> rproc -> ops -> unprepare = NULL ;
1172+ kproc -> rproc -> ops -> start = NULL ;
1173+ kproc -> rproc -> ops -> stop = NULL ;
1174+ kproc -> rproc -> ops -> attach = k3_r5_rproc_attach ;
1175+ kproc -> rproc -> ops -> detach = k3_r5_rproc_detach ;
1176+ kproc -> rproc -> ops -> get_loaded_rsc_table =
1177+ k3_r5_get_loaded_rsc_table ;
1178+ } else if (!c_state ) {
1179+ dev_info (cdev , "configured R5F for remoteproc mode\n" );
1180+ ret = 0 ;
1181+ } else {
1182+ dev_err (cdev , "mismatched mode: local_reset = %s, module_reset = %s, core_state = %s\n" ,
1183+ !ret ? "deasserted" : "asserted" ,
1184+ c_state ? "deasserted" : "asserted" ,
1185+ halted ? "halted" : "unhalted" );
1186+ ret = - EINVAL ;
1187+ }
1188+
1189+ /* fixup TCMs, cluster & core flags to actual values in IPC-only mode */
1190+ if (ret > 0 ) {
1191+ if (core == core0 )
1192+ cluster -> mode = mode ;
1193+ core -> atcm_enable = atcm_enable ;
1194+ core -> btcm_enable = btcm_enable ;
1195+ core -> loczrama = loczrama ;
1196+ core -> mem [0 ].dev_addr = loczrama ? 0 : K3_R5_TCM_DEV_ADDR ;
1197+ core -> mem [1 ].dev_addr = loczrama ? K3_R5_TCM_DEV_ADDR : 0 ;
1198+ }
1199+
1200+ return ret ;
1201+ }
1202+
10171203static int k3_r5_cluster_rproc_init (struct platform_device * pdev )
10181204{
10191205 struct k3_r5_cluster * cluster = platform_get_drvdata (pdev );
@@ -1023,7 +1209,7 @@ static int k3_r5_cluster_rproc_init(struct platform_device *pdev)
10231209 struct device * cdev ;
10241210 const char * fw_name ;
10251211 struct rproc * rproc ;
1026- int ret ;
1212+ int ret , ret1 ;
10271213
10281214 core1 = list_last_entry (& cluster -> cores , struct k3_r5_core , elem );
10291215 list_for_each_entry (core , & cluster -> cores , elem ) {
@@ -1054,13 +1240,20 @@ static int k3_r5_cluster_rproc_init(struct platform_device *pdev)
10541240 kproc -> rproc = rproc ;
10551241 core -> rproc = rproc ;
10561242
1243+ ret = k3_r5_rproc_configure_mode (kproc );
1244+ if (ret < 0 )
1245+ goto err_config ;
1246+ if (ret )
1247+ goto init_rmem ;
1248+
10571249 ret = k3_r5_rproc_configure (kproc );
10581250 if (ret ) {
10591251 dev_err (dev , "initial configure failed, ret = %d\n" ,
10601252 ret );
10611253 goto err_config ;
10621254 }
10631255
1256+ init_rmem :
10641257 k3_r5_adjust_tcm_sizes (kproc );
10651258
10661259 ret = k3_r5_reserved_mem_init (kproc );
@@ -1085,6 +1278,15 @@ static int k3_r5_cluster_rproc_init(struct platform_device *pdev)
10851278 return 0 ;
10861279
10871280err_split :
1281+ if (rproc -> state == RPROC_ATTACHED ) {
1282+ ret1 = rproc_detach (rproc );
1283+ if (ret1 ) {
1284+ dev_err (kproc -> dev , "failed to detach rproc, ret = %d\n" ,
1285+ ret1 );
1286+ return ret1 ;
1287+ }
1288+ }
1289+
10881290 rproc_del (rproc );
10891291err_add :
10901292 k3_r5_reserved_mem_exit (kproc );
@@ -1108,6 +1310,7 @@ static void k3_r5_cluster_rproc_exit(void *data)
11081310 struct k3_r5_rproc * kproc ;
11091311 struct k3_r5_core * core ;
11101312 struct rproc * rproc ;
1313+ int ret ;
11111314
11121315 /*
11131316 * lockstep mode and single-cpu modes have only one rproc associated
@@ -1123,6 +1326,14 @@ static void k3_r5_cluster_rproc_exit(void *data)
11231326 rproc = core -> rproc ;
11241327 kproc = rproc -> priv ;
11251328
1329+ if (rproc -> state == RPROC_ATTACHED ) {
1330+ ret = rproc_detach (rproc );
1331+ if (ret ) {
1332+ dev_err (kproc -> dev , "failed to detach rproc, ret = %d\n" , ret );
1333+ return ;
1334+ }
1335+ }
1336+
11261337 rproc_del (rproc );
11271338
11281339 k3_r5_reserved_mem_exit (kproc );
0 commit comments