@@ -428,6 +428,7 @@ static int k3_r5_rproc_request_mbox(struct rproc *rproc)
428
428
* private to each core. Only Core0 needs to be unhalted for running the
429
429
* cluster in this mode. The function uses the same reset logic as LockStep
430
430
* mode for this (though the behavior is agnostic of the reset release order).
431
+ * This callback is invoked only in remoteproc mode.
431
432
*/
432
433
static int k3_r5_rproc_prepare (struct rproc * rproc )
433
434
{
@@ -493,7 +494,8 @@ static int k3_r5_rproc_prepare(struct rproc *rproc)
493
494
* both cores. The access is made possible only with releasing the resets for
494
495
* both cores, but with only Core0 unhalted. This function re-uses the same
495
496
* 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.
497
499
*/
498
500
static int k3_r5_rproc_unprepare (struct rproc * rproc )
499
501
{
@@ -527,7 +529,8 @@ static int k3_r5_rproc_unprepare(struct rproc *rproc)
527
529
*
528
530
* The Single-CPU mode on applicable SoCs (eg: AM64x) only uses Core0 to execute
529
531
* 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.
531
534
*/
532
535
static int k3_r5_rproc_start (struct rproc * rproc )
533
536
{
@@ -598,7 +601,8 @@ static int k3_r5_rproc_start(struct rproc *rproc)
598
601
* be done here, but is preferred to be done in the .unprepare() ops - this
599
602
* maintains the symmetric behavior between the .start(), .stop(), .prepare()
600
603
* 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.
602
606
*/
603
607
static int k3_r5_rproc_stop (struct rproc * rproc )
604
608
{
@@ -635,6 +639,78 @@ static int k3_r5_rproc_stop(struct rproc *rproc)
635
639
return ret ;
636
640
}
637
641
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
+
638
714
/*
639
715
* Internal Memory translation helper
640
716
*
@@ -1014,6 +1090,116 @@ static void k3_r5_adjust_tcm_sizes(struct k3_r5_rproc *kproc)
1014
1090
}
1015
1091
}
1016
1092
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
+
1017
1203
static int k3_r5_cluster_rproc_init (struct platform_device * pdev )
1018
1204
{
1019
1205
struct k3_r5_cluster * cluster = platform_get_drvdata (pdev );
@@ -1023,7 +1209,7 @@ static int k3_r5_cluster_rproc_init(struct platform_device *pdev)
1023
1209
struct device * cdev ;
1024
1210
const char * fw_name ;
1025
1211
struct rproc * rproc ;
1026
- int ret ;
1212
+ int ret , ret1 ;
1027
1213
1028
1214
core1 = list_last_entry (& cluster -> cores , struct k3_r5_core , elem );
1029
1215
list_for_each_entry (core , & cluster -> cores , elem ) {
@@ -1054,13 +1240,20 @@ static int k3_r5_cluster_rproc_init(struct platform_device *pdev)
1054
1240
kproc -> rproc = rproc ;
1055
1241
core -> rproc = rproc ;
1056
1242
1243
+ ret = k3_r5_rproc_configure_mode (kproc );
1244
+ if (ret < 0 )
1245
+ goto err_config ;
1246
+ if (ret )
1247
+ goto init_rmem ;
1248
+
1057
1249
ret = k3_r5_rproc_configure (kproc );
1058
1250
if (ret ) {
1059
1251
dev_err (dev , "initial configure failed, ret = %d\n" ,
1060
1252
ret );
1061
1253
goto err_config ;
1062
1254
}
1063
1255
1256
+ init_rmem :
1064
1257
k3_r5_adjust_tcm_sizes (kproc );
1065
1258
1066
1259
ret = k3_r5_reserved_mem_init (kproc );
@@ -1085,6 +1278,15 @@ static int k3_r5_cluster_rproc_init(struct platform_device *pdev)
1085
1278
return 0 ;
1086
1279
1087
1280
err_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
+
1088
1290
rproc_del (rproc );
1089
1291
err_add :
1090
1292
k3_r5_reserved_mem_exit (kproc );
@@ -1108,6 +1310,7 @@ static void k3_r5_cluster_rproc_exit(void *data)
1108
1310
struct k3_r5_rproc * kproc ;
1109
1311
struct k3_r5_core * core ;
1110
1312
struct rproc * rproc ;
1313
+ int ret ;
1111
1314
1112
1315
/*
1113
1316
* lockstep mode and single-cpu modes have only one rproc associated
@@ -1123,6 +1326,14 @@ static void k3_r5_cluster_rproc_exit(void *data)
1123
1326
rproc = core -> rproc ;
1124
1327
kproc = rproc -> priv ;
1125
1328
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
+
1126
1337
rproc_del (rproc );
1127
1338
1128
1339
k3_r5_reserved_mem_exit (kproc );
0 commit comments