summaryrefslogtreecommitdiff
path: root/drivers/soc/ti
diff options
context:
space:
mode:
authorDave Gerlach <d-gerlach@ti.com>2022-05-01 20:32:12 -0700
committerNishanth Menon <nm@ti.com>2022-05-03 08:02:09 -0500
commit2a21f9e6d9a408dbd09a01caf5fff42c2f70fa82 (patch)
treeb1b5e937801d73c59e0c3811adb38d5e35d87d04 /drivers/soc/ti
parentea082040fe071d2ba1f8f73792743d7ca9fb218e (diff)
downloadlinux-2a21f9e6d9a408dbd09a01caf5fff42c2f70fa82.tar.gz
soc: ti: wkup_m3_ipc: Add debug option to halt m3 in suspend
Add a debugfs option to allow configurable halting of the wkup_m3 during suspend at the last possible point before low power mode entry. This condition can only be resolved through JTAG and advancing beyond the while loop in a8_lp_ds0_handler [1]. Although this hangs the system it forces the system to remain active once it has been entirely configured for low power mode entry, allowing for register inspection through JTAG to help in debugging transition errors. Halt mode can be set using the enable_off_mode entry under wkup_m3_ipc in the debugfs. [1] https://git.ti.com/cgit/processor-firmware/ti-amx3-cm3-pm-firmware/tree/src/pm_services/pm_handlers.c?h=08.02.00.006#n141 Suggested-by: Brad Griffis <bgriffis@ti.com> Signed-off-by: Dave Gerlach <d-gerlach@ti.com> [dfustini: add link for a8_lp_ds0_handler() in ti-amx3-cm3-pm-firmware] Signed-off-by: Drew Fustini <dfustini@baylibre.com> Signed-off-by: Nishanth Menon <nm@ti.com> Link: https://lore.kernel.org/r/20220502033211.1383158-1-dfustini@baylibre.com
Diffstat (limited to 'drivers/soc/ti')
-rw-r--r--drivers/soc/ti/wkup_m3_ipc.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c
index 84e9534056f8..0076d467ff6b 100644
--- a/drivers/soc/ti/wkup_m3_ipc.c
+++ b/drivers/soc/ti/wkup_m3_ipc.c
@@ -7,6 +7,7 @@
* Dave Gerlach <d-gerlach@ti.com>
*/
+#include <linux/debugfs.h>
#include <linux/err.h>
#include <linux/firmware.h>
#include <linux/kernel.h>
@@ -50,6 +51,9 @@
#define IPC_IO_ISOLATION_STAT_SHIFT (10)
#define IPC_IO_ISOLATION_STAT_MASK (0x1 << 10)
+#define IPC_DBG_HALT_SHIFT (11)
+#define IPC_DBG_HALT_MASK (0x1 << 11)
+
#define M3_STATE_UNKNOWN 0
#define M3_STATE_RESET 1
#define M3_STATE_INITED 2
@@ -157,6 +161,73 @@ static int wkup_m3_init_scale_data(struct wkup_m3_ipc *m3_ipc,
return ret;
}
+#ifdef CONFIG_DEBUG_FS
+static void wkup_m3_set_halt_late(bool enabled)
+{
+ if (enabled)
+ m3_ipc_state->halt = (1 << IPC_DBG_HALT_SHIFT);
+ else
+ m3_ipc_state->halt = 0;
+}
+
+static int option_get(void *data, u64 *val)
+{
+ u32 *option = data;
+
+ *val = *option;
+
+ return 0;
+}
+
+static int option_set(void *data, u64 val)
+{
+ u32 *option = data;
+
+ *option = val;
+
+ if (option == &m3_ipc_state->halt) {
+ if (val)
+ wkup_m3_set_halt_late(true);
+ else
+ wkup_m3_set_halt_late(false);
+ }
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(wkup_m3_ipc_option_fops, option_get, option_set,
+ "%llu\n");
+
+static int wkup_m3_ipc_dbg_init(struct wkup_m3_ipc *m3_ipc)
+{
+ m3_ipc->dbg_path = debugfs_create_dir("wkup_m3_ipc", NULL);
+
+ if (!m3_ipc->dbg_path)
+ return -EINVAL;
+
+ (void)debugfs_create_file("enable_late_halt", 0644,
+ m3_ipc->dbg_path,
+ &m3_ipc->halt,
+ &wkup_m3_ipc_option_fops);
+
+ return 0;
+}
+
+static inline void wkup_m3_ipc_dbg_destroy(struct wkup_m3_ipc *m3_ipc)
+{
+ debugfs_remove_recursive(m3_ipc->dbg_path);
+}
+#else
+static inline int wkup_m3_ipc_dbg_init(struct wkup_m3_ipc *m3_ipc)
+{
+ return 0;
+}
+
+static inline void wkup_m3_ipc_dbg_destroy(struct wkup_m3_ipc *m3_ipc)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
static void am33xx_txev_eoi(struct wkup_m3_ipc *m3_ipc)
{
writel(AM33XX_M3_TXEV_ACK,
@@ -402,7 +473,9 @@ static int wkup_m3_prepare_low_power(struct wkup_m3_ipc *m3_ipc, int state)
wkup_m3_ctrl_ipc_write(m3_ipc, m3_power_state, 1);
wkup_m3_ctrl_ipc_write(m3_ipc, m3_ipc->mem_type |
m3_ipc->vtt_conf |
- m3_ipc->isolation_conf, 4);
+ m3_ipc->isolation_conf |
+ m3_ipc->halt, 4);
+
wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 2);
wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 3);
wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 6);
@@ -631,6 +704,8 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
goto err_put_rproc;
}
+ wkup_m3_ipc_dbg_init(m3_ipc);
+
return 0;
err_put_rproc:
@@ -642,6 +717,8 @@ err_free_mbox:
static int wkup_m3_ipc_remove(struct platform_device *pdev)
{
+ wkup_m3_ipc_dbg_destroy(m3_ipc_state);
+
mbox_free_channel(m3_ipc_state->mbox);
rproc_shutdown(m3_ipc_state->rproc);