Skip to content

Commit 2a21f9e

Browse files
dgerlachnmenon
authored andcommitted
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
1 parent ea08204 commit 2a21f9e

2 files changed

Lines changed: 80 additions & 1 deletion

File tree

drivers/soc/ti/wkup_m3_ipc.c

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* Dave Gerlach <d-gerlach@ti.com>
88
*/
99

10+
#include <linux/debugfs.h>
1011
#include <linux/err.h>
1112
#include <linux/firmware.h>
1213
#include <linux/kernel.h>
@@ -50,6 +51,9 @@
5051
#define IPC_IO_ISOLATION_STAT_SHIFT (10)
5152
#define IPC_IO_ISOLATION_STAT_MASK (0x1 << 10)
5253

54+
#define IPC_DBG_HALT_SHIFT (11)
55+
#define IPC_DBG_HALT_MASK (0x1 << 11)
56+
5357
#define M3_STATE_UNKNOWN 0
5458
#define M3_STATE_RESET 1
5559
#define M3_STATE_INITED 2
@@ -157,6 +161,73 @@ static int wkup_m3_init_scale_data(struct wkup_m3_ipc *m3_ipc,
157161
return ret;
158162
}
159163

164+
#ifdef CONFIG_DEBUG_FS
165+
static void wkup_m3_set_halt_late(bool enabled)
166+
{
167+
if (enabled)
168+
m3_ipc_state->halt = (1 << IPC_DBG_HALT_SHIFT);
169+
else
170+
m3_ipc_state->halt = 0;
171+
}
172+
173+
static int option_get(void *data, u64 *val)
174+
{
175+
u32 *option = data;
176+
177+
*val = *option;
178+
179+
return 0;
180+
}
181+
182+
static int option_set(void *data, u64 val)
183+
{
184+
u32 *option = data;
185+
186+
*option = val;
187+
188+
if (option == &m3_ipc_state->halt) {
189+
if (val)
190+
wkup_m3_set_halt_late(true);
191+
else
192+
wkup_m3_set_halt_late(false);
193+
}
194+
195+
return 0;
196+
}
197+
198+
DEFINE_SIMPLE_ATTRIBUTE(wkup_m3_ipc_option_fops, option_get, option_set,
199+
"%llu\n");
200+
201+
static int wkup_m3_ipc_dbg_init(struct wkup_m3_ipc *m3_ipc)
202+
{
203+
m3_ipc->dbg_path = debugfs_create_dir("wkup_m3_ipc", NULL);
204+
205+
if (!m3_ipc->dbg_path)
206+
return -EINVAL;
207+
208+
(void)debugfs_create_file("enable_late_halt", 0644,
209+
m3_ipc->dbg_path,
210+
&m3_ipc->halt,
211+
&wkup_m3_ipc_option_fops);
212+
213+
return 0;
214+
}
215+
216+
static inline void wkup_m3_ipc_dbg_destroy(struct wkup_m3_ipc *m3_ipc)
217+
{
218+
debugfs_remove_recursive(m3_ipc->dbg_path);
219+
}
220+
#else
221+
static inline int wkup_m3_ipc_dbg_init(struct wkup_m3_ipc *m3_ipc)
222+
{
223+
return 0;
224+
}
225+
226+
static inline void wkup_m3_ipc_dbg_destroy(struct wkup_m3_ipc *m3_ipc)
227+
{
228+
}
229+
#endif /* CONFIG_DEBUG_FS */
230+
160231
static void am33xx_txev_eoi(struct wkup_m3_ipc *m3_ipc)
161232
{
162233
writel(AM33XX_M3_TXEV_ACK,
@@ -402,7 +473,9 @@ static int wkup_m3_prepare_low_power(struct wkup_m3_ipc *m3_ipc, int state)
402473
wkup_m3_ctrl_ipc_write(m3_ipc, m3_power_state, 1);
403474
wkup_m3_ctrl_ipc_write(m3_ipc, m3_ipc->mem_type |
404475
m3_ipc->vtt_conf |
405-
m3_ipc->isolation_conf, 4);
476+
m3_ipc->isolation_conf |
477+
m3_ipc->halt, 4);
478+
406479
wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 2);
407480
wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 3);
408481
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)
631704
goto err_put_rproc;
632705
}
633706

707+
wkup_m3_ipc_dbg_init(m3_ipc);
708+
634709
return 0;
635710

636711
err_put_rproc:
@@ -642,6 +717,8 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
642717

643718
static int wkup_m3_ipc_remove(struct platform_device *pdev)
644719
{
720+
wkup_m3_ipc_dbg_destroy(m3_ipc_state);
721+
645722
mbox_free_channel(m3_ipc_state->mbox);
646723

647724
rproc_shutdown(m3_ipc_state->rproc);

include/linux/wkup_m3_ipc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct wkup_m3_ipc {
3636
int vtt_conf;
3737
int isolation_conf;
3838
int state;
39+
u32 halt;
3940

4041
unsigned long volt_scale_offsets;
4142
const char *sd_fw_name;
@@ -46,6 +47,7 @@ struct wkup_m3_ipc {
4647

4748
struct wkup_m3_ipc_ops *ops;
4849
int is_rtc_only;
50+
struct dentry *dbg_path;
4951
};
5052

5153
struct wkup_m3_wakeup_src {

0 commit comments

Comments
 (0)