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 #ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER
26 static struct adsp_debug_slot_shell *dw_slot;
27 #endif
28 
29 struct adsp_debug_slot_shell {
30 	uint8_t rx_window[RX_WINDOW_SIZE];
31 	uint8_t tx_window[ADSP_DW_SLOT_SIZE - RX_WINDOW_SIZE];
32 } __packed;
33 
timer_handler(struct k_timer * timer)34 static void timer_handler(struct k_timer *timer)
35 {
36 	const struct shell_adsp_memory_window *sh_adsp_mw = k_timer_user_data_get(timer);
37 
38 	__ASSERT_NO_MSG(sh_adsp_mw->shell_handler && sh_adsp_mw->shell_context);
39 
40 	sh_adsp_mw->shell_handler(SHELL_TRANSPORT_EVT_RX_RDY,
41 				    sh_adsp_mw->shell_context);
42 }
43 
init(const struct shell_transport * transport,const void * config,shell_transport_handler_t evt_handler,void * context)44 static int init(const struct shell_transport *transport,
45 		const void *config,
46 		shell_transport_handler_t evt_handler,
47 		void *context)
48 {
49 	struct shell_adsp_memory_window *sh_adsp_mw =
50 		(struct shell_adsp_memory_window *)transport->ctx;
51 
52 #ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER
53 	struct adsp_dw_desc slot_desc = { .type = ADSP_DW_SLOT_SHELL, };
54 
55 	dw_slot = (struct adsp_debug_slot_shell *)adsp_dw_request_slot(&slot_desc, NULL);
56 	if (!dw_slot) {
57 		return -ENOTSUP;
58 	}
59 #else
60 	struct adsp_debug_slot_shell *dw_slot;
61 
62 	if (ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type &&
63 	    (ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type !=
64 		    ADSP_DW_SLOT_SHELL)) {
65 		LOG_WRN("Possible conflict with debug window slot for shell, key %#x\n",
66 			ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type);
67 	}
68 
69 	ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type = ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type;
70 
71 	dw_slot = (struct adsp_debug_slot_shell *)ADSP_DW->slots[ADSP_DW_SLOT_NUM_SHELL];
72 #endif
73 
74 	sh_adsp_mw->shell_handler = evt_handler;
75 	sh_adsp_mw->shell_context = context;
76 
77 
78 	sh_adsp_mw->ws_rx = sys_winstream_init(&dw_slot->rx_window[0], sizeof(dw_slot->rx_window));
79 	sh_adsp_mw->ws_tx = sys_winstream_init(&dw_slot->tx_window[0], sizeof(dw_slot->tx_window));
80 
81 	LOG_DBG("shell with ADSP debug window rx/tx %u/%u\n",
82 		sizeof(dw_slot->rx_window), sizeof(dw_slot->tx_window));
83 
84 	k_timer_init(&sh_adsp_mw->timer, timer_handler, NULL);
85 	k_timer_user_data_set(&sh_adsp_mw->timer, (void *)sh_adsp_mw);
86 	k_timer_start(&sh_adsp_mw->timer, POLL_INTERVAL, POLL_INTERVAL);
87 
88 	return 0;
89 }
90 
uninit(const struct shell_transport * transport)91 static int uninit(const struct shell_transport *transport)
92 {
93 	struct shell_adsp_memory_window *sh_adsp_mw =
94 		(struct shell_adsp_memory_window *)transport->ctx;
95 
96 	k_timer_stop(&sh_adsp_mw->timer);
97 
98 #ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER
99 	adsp_dw_release_slot(ADSP_DW_SLOT_SHELL);
100 	dw_slot = NULL;
101 #endif
102 
103 	return 0;
104 }
105 
enable(const struct shell_transport * transport,bool blocking)106 static int enable(const struct shell_transport *transport, bool blocking)
107 {
108 	return 0;
109 }
110 
write(const struct shell_transport * transport,const void * data,size_t length,size_t * cnt)111 static int write(const struct shell_transport *transport,
112 		 const void *data, size_t length, size_t *cnt)
113 {
114 	struct shell_adsp_memory_window *sh_adsp_mw =
115 		(struct shell_adsp_memory_window *)transport->ctx;
116 
117 	sys_winstream_write(sh_adsp_mw->ws_tx, data, length);
118 	*cnt = length;
119 
120 	return 0;
121 }
122 
read(const struct shell_transport * transport,void * data,size_t length,size_t * cnt)123 static int read(const struct shell_transport *transport,
124 		void *data, size_t length, size_t *cnt)
125 {
126 	struct shell_adsp_memory_window *sh_adsp_mw =
127 		(struct shell_adsp_memory_window *)transport->ctx;
128 	uint32_t res;
129 
130 	res = sys_winstream_read(sh_adsp_mw->ws_rx, &sh_adsp_mw->read_seqno, data, length);
131 	*cnt = res;
132 
133 	return 0;
134 }
135 
136 const struct shell_transport_api shell_adsp_memory_window_transport_api = {
137 	.init = init,
138 	.uninit = uninit,
139 	.enable = enable,
140 	.write = write,
141 	.read = read
142 };
143 
enable_shell_adsp_memory_window(void)144 static int enable_shell_adsp_memory_window(void)
145 {
146 	bool log_backend = true;
147 	uint32_t level = CONFIG_LOG_MAX_LEVEL;
148 	static const struct shell_backend_config_flags cfg_flags =
149 		SHELL_DEFAULT_BACKEND_CONFIG_FLAGS;
150 
151 	shell_init(&shell_adsp_memory_window, NULL, cfg_flags, log_backend, level);
152 
153 	return 0;
154 }
155 SYS_INIT(enable_shell_adsp_memory_window, POST_KERNEL, 0);
156 
shell_backend_adsp_memory_window_get_ptr(void)157 const struct shell *shell_backend_adsp_memory_window_get_ptr(void)
158 {
159 	return &shell_adsp_memory_window;
160 }
161