1 /*
2  * Copyright (c) 2024 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/shell/shell_adsp_memory_window.h>
8 #include <zephyr/sys/winstream.h>
9 #include <zephyr/logging/log.h>
10 
11 #include <adsp_memory.h>
12 #include <adsp_debug_window.h>
13 
14 SHELL_ADSP_MEMORY_WINDOW_DEFINE(shell_transport_adsp_memory_window);
15 SHELL_DEFINE(shell_adsp_memory_window, CONFIG_SHELL_BACKEND_ADSP_MEMORY_WINDOW_PROMPT,
16 	     &shell_transport_adsp_memory_window, 256, 0, SHELL_FLAG_OLF_CRLF);
17 
18 LOG_MODULE_REGISTER(shell_adsp_memory_window);
19 
20 #define RX_WINDOW_SIZE		256
21 #define POLL_INTERVAL		K_MSEC(CONFIG_SHELL_BACKEND_ADSP_MEMORY_WINDOW_POLL_INTERVAL)
22 
23 BUILD_ASSERT(RX_WINDOW_SIZE < ADSP_DW_SLOT_SIZE);
24 
25 struct adsp_debug_slot_shell {
26 	uint8_t rx_window[RX_WINDOW_SIZE];
27 	uint8_t tx_window[ADSP_DW_SLOT_SIZE - RX_WINDOW_SIZE];
28 } __packed;
29 
timer_handler(struct k_timer * timer)30 static void timer_handler(struct k_timer *timer)
31 {
32 	const struct shell_adsp_memory_window *sh_adsp_mw = k_timer_user_data_get(timer);
33 
34 	__ASSERT_NO_MSG(sh_adsp_mw->shell_handler && sh_adsp_mw->shell_context);
35 
36 	sh_adsp_mw->shell_handler(SHELL_TRANSPORT_EVT_RX_RDY,
37 				    sh_adsp_mw->shell_context);
38 }
39 
init(const struct shell_transport * transport,const void * config,shell_transport_handler_t evt_handler,void * context)40 static int init(const struct shell_transport *transport,
41 		const void *config,
42 		shell_transport_handler_t evt_handler,
43 		void *context)
44 {
45 	struct shell_adsp_memory_window *sh_adsp_mw =
46 		(struct shell_adsp_memory_window *)transport->ctx;
47 	struct adsp_debug_slot_shell *dw_slot;
48 
49 	if (ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type &&
50 	    (ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type !=
51 		    ADSP_DW_SLOT_SHELL)) {
52 		LOG_WRN("Possible conflict with debug window slot for shell, key %#x\n",
53 			ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type);
54 	}
55 
56 	ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type = ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type;
57 
58 	sh_adsp_mw->shell_handler = evt_handler;
59 	sh_adsp_mw->shell_context = context;
60 
61 	dw_slot = (struct adsp_debug_slot_shell *)ADSP_DW->slots[ADSP_DW_SLOT_NUM_SHELL];
62 
63 	sh_adsp_mw->ws_rx = sys_winstream_init(&dw_slot->rx_window[0], sizeof(dw_slot->rx_window));
64 	sh_adsp_mw->ws_tx = sys_winstream_init(&dw_slot->tx_window[0], sizeof(dw_slot->tx_window));
65 
66 	LOG_DBG("shell with ADSP debug window rx/tx %u/%u\n",
67 		sizeof(dw_slot->rx_window), sizeof(dw_slot->tx_window));
68 
69 	k_timer_init(&sh_adsp_mw->timer, timer_handler, NULL);
70 	k_timer_user_data_set(&sh_adsp_mw->timer, (void *)sh_adsp_mw);
71 	k_timer_start(&sh_adsp_mw->timer, POLL_INTERVAL, POLL_INTERVAL);
72 
73 	return 0;
74 }
75 
uninit(const struct shell_transport * transport)76 static int uninit(const struct shell_transport *transport)
77 {
78 	struct shell_adsp_memory_window *sh_adsp_mw =
79 		(struct shell_adsp_memory_window *)transport->ctx;
80 
81 	k_timer_stop(&sh_adsp_mw->timer);
82 
83 	return 0;
84 }
85 
enable(const struct shell_transport * transport,bool blocking)86 static int enable(const struct shell_transport *transport, bool blocking)
87 {
88 	return 0;
89 }
90 
write(const struct shell_transport * transport,const void * data,size_t length,size_t * cnt)91 static int write(const struct shell_transport *transport,
92 		 const void *data, size_t length, size_t *cnt)
93 {
94 	struct shell_adsp_memory_window *sh_adsp_mw =
95 		(struct shell_adsp_memory_window *)transport->ctx;
96 
97 	sys_winstream_write(sh_adsp_mw->ws_tx, data, length);
98 	*cnt = length;
99 
100 	return 0;
101 }
102 
read(const struct shell_transport * transport,void * data,size_t length,size_t * cnt)103 static int read(const struct shell_transport *transport,
104 		void *data, size_t length, size_t *cnt)
105 {
106 	struct shell_adsp_memory_window *sh_adsp_mw =
107 		(struct shell_adsp_memory_window *)transport->ctx;
108 	uint32_t res;
109 
110 	res = sys_winstream_read(sh_adsp_mw->ws_rx, &sh_adsp_mw->read_seqno, data, length);
111 	*cnt = res;
112 
113 	return 0;
114 }
115 
116 const struct shell_transport_api shell_adsp_memory_window_transport_api = {
117 	.init = init,
118 	.uninit = uninit,
119 	.enable = enable,
120 	.write = write,
121 	.read = read
122 };
123 
enable_shell_adsp_memory_window(void)124 static int enable_shell_adsp_memory_window(void)
125 {
126 	bool log_backend = true;
127 	uint32_t level = CONFIG_LOG_MAX_LEVEL;
128 	static const struct shell_backend_config_flags cfg_flags =
129 		SHELL_DEFAULT_BACKEND_CONFIG_FLAGS;
130 
131 	shell_init(&shell_adsp_memory_window, NULL, cfg_flags, log_backend, level);
132 
133 	return 0;
134 }
135 SYS_INIT(enable_shell_adsp_memory_window, POST_KERNEL, 0);
136 
shell_backend_adsp_memory_window_get_ptr(void)137 const struct shell *shell_backend_adsp_memory_window_get_ptr(void)
138 {
139 	return &shell_adsp_memory_window;
140 }
141