88#include <sof/lib/agent.h>
99#include <sof/lib/mailbox.h>
1010#include <sof/lib/notifier.h>
11+ #include <sof/lib/uuid.h>
1112#include <sof/schedule/ll_schedule_domain.h>
1213#include <sof/schedule/ll_schedule.h>
1314#include <sof/schedule/edf_schedule.h>
@@ -19,144 +20,177 @@ void mtk_dai_init(struct sof *sof);
1920#define MBOX0 DEVICE_DT_GET(DT_INST(0, mediatek_mbox))
2021#define MBOX1 DEVICE_DT_GET(DT_INST(1, mediatek_mbox))
2122
22- static void mtk_ipc_send (const void * msg , size_t sz )
23+ /* This is silly: the kernel mt8196 driver changes the protocol to
24+ * swap the device used for replies. It used to be that mbox0 was
25+ * used to send commands in both directions and mbox1 to send the
26+ * replies. Now mbox0 is for commands to and replies from the host,
27+ * and mbox1 for commands from the host and replies from us. Arguably
28+ * the new style is a cleaner scheme, but doing this without a
29+ * protocol rev? Come on!
30+ */
31+ #ifdef CONFIG_SOC_MT8196
32+ #define MBOX_CMD_TO_HOST MBOX0
33+ #define MBOX_RPL_TO_HOST MBOX1
34+ #define MBOX_CMD_TO_DSP MBOX1
35+ #define MBOX_RPL_TO_DSP MBOX0
36+ #else
37+ #define MBOX_CMD_TO_HOST MBOX0
38+ #define MBOX_RPL_TO_HOST MBOX1
39+ #define MBOX_CMD_TO_DSP MBOX0
40+ #define MBOX_RPL_TO_DSP MBOX1
41+ #endif
42+
43+ /* Use the same UUID as in "ipc-zephyr.c", which is actually an Intel driver */
44+ SOF_DEFINE_REG_UUID (zipc_task );
45+
46+ static void mbox_cmd_fn (const struct device * mbox , void * arg )
2347{
24- mailbox_dspbox_write (0 , msg , sz );
25- mtk_adsp_mbox_signal (MBOX0 , 0 );
48+ /* We're in ISR context. This unblocks the IPC task thread,
49+ * which calls ipc_do_cmd(), which calls back into
50+ * ipc_platform_do_cmd() below, which then calls ipc_cmd().
51+ */
52+ ipc_schedule_process (ipc_get ());
2653}
2754
28- static void mbox0_fn ( const struct device * mbox , void * arg )
55+ enum task_state ipc_platform_do_cmd ( struct ipc * ipc )
2956{
30- printk ("ANDY %s:%d\n" , __func__ , __LINE__ );
31- ipc_schedule_process (ipc_get ());
57+ /* mailbox_validate() checks the command length (that's all it
58+ * vaildates) and copies the incoming command from the host
59+ * window to the comp_data buffer in the IPC object.
60+ */
61+ struct ipc_cmd_hdr * hdr = mailbox_validate ();
62+
63+ if (hdr )
64+ ipc_cmd (hdr );
65+ return SOF_TASK_STATE_COMPLETED ;
3266}
3367
34- static void mbox1_fn ( const struct device * mbox , void * arg )
68+ void ipc_platform_complete_cmd ( struct ipc * ipc )
3569{
36- printk ("ANDY %s:%d\n" , __func__ , __LINE__ );
37- ipc_get ()-> is_notification_pending = false;
70+ mtk_adsp_mbox_signal (MBOX_RPL_TO_HOST , 1 );
3871}
3972
40- int platform_ipc_init ( struct ipc * ipc )
73+ static void mtk_ipc_send ( const void * msg , size_t sz )
4174{
42- printk ( "ANDY %s:%d\n" , __func__ , __LINE__ );
43- mtk_adsp_mbox_set_handler ( MBOX0 , 1 , mbox0_fn , NULL );
44- mtk_adsp_mbox_set_handler ( MBOX1 , 1 , mbox1_fn , NULL );
75+ mailbox_dspbox_write ( 0 , msg , sz );
76+ mtk_adsp_mbox_signal ( MBOX_CMD_TO_HOST , 0 );
77+ }
4578
46- return 0 ;
79+ int ipc_platform_send_msg (const struct ipc_msg * msg )
80+ {
81+ struct ipc * ipc = ipc_get ();
82+
83+ if (ipc -> is_notification_pending )
84+ return - EBUSY ;
85+
86+ ipc -> is_notification_pending = true;
87+ mtk_ipc_send (msg -> tx_data , msg -> tx_size );
88+ return 0 ;
4789}
4890
49- void ipc_platform_complete_cmd ( struct ipc * ipc )
91+ static void mbox_reply_fn ( const struct device * mbox , void * arg )
5092{
51- mtk_adsp_mbox_signal ( MBOX1 , 1 ) ;
93+ ipc_get () -> is_notification_pending = false ;
5294}
5395
54- int ipc_platform_send_msg (const struct ipc_msg * msg )
96+ /* Called out of ipc_init(), which is called out of platform_init() below */
97+ int platform_ipc_init (struct ipc * ipc )
5598{
56- printk ( "ANDY %s:%d\n" , __func__ , __LINE__ );
57- struct ipc * ipc = ipc_get ( );
99+ schedule_task_init_edf ( & ipc -> ipc_task , SOF_UUID ( zipc_task_uuid ),
100+ & ipc_task_ops , ipc , 0 , 0 );
58101
59- if (ipc -> is_notification_pending )
60- return - EBUSY ;
102+ mtk_adsp_mbox_set_handler (MBOX_CMD_TO_DSP , 1 , mbox_cmd_fn , NULL );
103+ mtk_adsp_mbox_set_handler (MBOX_RPL_TO_DSP , 1 , mbox_reply_fn , NULL );
104+ return 0 ;
105+ }
61106
62- ipc -> is_notification_pending = true;
63- mtk_ipc_send ( msg -> tx_data , msg -> tx_size );
64- return 0 ;
107+ int platform_context_save ( struct sof * sof )
108+ {
109+ return 0 ;
65110}
66111
67112static int set_cpuclk (int clock , int hz )
68113{
69- return clock == 0 && hz == CONFIG_XTENSA_CCOUNT_HZ ? 0 : - EINVAL ;
114+ return clock == 0 && hz == CONFIG_XTENSA_CCOUNT_HZ ? 0 : - EINVAL ;
70115}
71116
117+ /* Dummy CPU clock driver that supports one known frequency. This
118+ * hardware has clock scaling support, but it hasn't historically been
119+ * exercised so we have nothing to test against.
120+ */
72121void clocks_init (struct sof * sof )
73122{
74- // Dummy CPU clock driver that supports one known frequency.
75- // This hardware has clock scaling support, but it hasn't
76- // historically been exercised so we have nothing to test
77- // against.
78- static struct freq_table freqs [] = {
79- { .freq = CONFIG_XTENSA_CCOUNT_HZ ,
80- .ticks_per_msec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000 , }
81- };
82- static struct clock_info clks [] = {
83- { .freqs_num = ARRAY_SIZE (freqs ),
84- .freqs = freqs ,
85- .notification_id = NOTIFIER_ID_CPU_FREQ ,
86- .notification_mask = NOTIFIER_TARGET_CORE_MASK (0 ),
87- .set_freq = set_cpuclk , },
88- };
89- sof -> clocks = clks ;
123+ static const struct freq_table freqs [] = {
124+ { .freq = CONFIG_XTENSA_CCOUNT_HZ ,
125+ .ticks_per_msec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000 , }
126+ };
127+ static struct clock_info clks [] = {
128+ { .freqs_num = ARRAY_SIZE (freqs ),
129+ .freqs = freqs ,
130+ .notification_id = NOTIFIER_ID_CPU_FREQ ,
131+ .notification_mask = NOTIFIER_TARGET_CORE_MASK (0 ),
132+ .set_freq = set_cpuclk , },
133+ };
134+ sof -> clocks = clks ;
90135}
91136
92137int platform_init (struct sof * sof )
93138{
94- int ret ;
95- printk ("ANDY %s:%d\n" , __func__ , __LINE__ );
96-
97- clocks_init (sof );
98-
99- sof -> platform_timer_domain = zephyr_domain_init (PLATFORM_DEFAULT_CLOCK );
100-
101- ipc_init (sof );
102-
103- mtk_dai_init (sof );
104-
105- scheduler_init_edf ();
106- scheduler_init_ll (sof -> platform_timer_domain );
107-
108- sa_init (sof , CONFIG_SYSTICK_PERIOD ); // watchdoggy thingy
109-
139+ clocks_init (sof );
140+ sof -> platform_timer_domain = zephyr_domain_init (PLATFORM_DEFAULT_CLOCK );
141+ ipc_init (sof );
142+ mtk_dai_init (sof );
143+ scheduler_init_edf ();
144+ scheduler_init_ll (sof -> platform_timer_domain );
145+ sa_init (sof , CONFIG_SYSTICK_PERIOD );
110146 return 0 ;
111147}
112148
113149int platform_boot_complete (uint32_t boot_message )
114150{
115- printk ("ANDY %s:%d\n" , __func__ , __LINE__ );
116- static const struct sof_ipc_fw_ready fw_ready_cmd = {
117- .hdr .cmd = SOF_IPC_FW_READY ,
118- .hdr .size = sizeof (struct sof_ipc_fw_ready ),
119- .version = {
120- .hdr .size = sizeof (struct sof_ipc_fw_version ),
121- .micro = SOF_MICRO ,
122- .minor = SOF_MINOR ,
123- .major = SOF_MAJOR ,
124- .tag = SOF_TAG ,
125- .abi_version = SOF_ABI_VERSION ,
126- .src_hash = SOF_SRC_HASH ,
127- },
128- .flags = DEBUG_SET_FW_READY_FLAGS ,
129- };
130-
131- mtk_ipc_send (& fw_ready_cmd , sizeof (fw_ready_cmd ));
151+ static const struct sof_ipc_fw_ready fw_ready_cmd = {
152+ .hdr .cmd = SOF_IPC_FW_READY ,
153+ .hdr .size = sizeof (struct sof_ipc_fw_ready ),
154+ .version = {
155+ .hdr .size = sizeof (struct sof_ipc_fw_version ),
156+ .micro = SOF_MICRO ,
157+ .minor = SOF_MINOR ,
158+ .major = SOF_MAJOR ,
159+ .tag = SOF_TAG ,
160+ .abi_version = SOF_ABI_VERSION ,
161+ .src_hash = SOF_SRC_HASH ,
162+ },
163+ .flags = DEBUG_SET_FW_READY_FLAGS ,
164+ };
165+
166+ mtk_ipc_send (& fw_ready_cmd , sizeof (fw_ready_cmd ));
132167 return 0 ;
133168}
134169
135- // Extended manifest window record. Note the alignment attribute is
136- // critical as rimage demands allocation in units of 16 bytes, yet the
137- // C struct records emitted into the section are not in general padded
138- // and will pack tighter than that! (Really this is an rimage bug, it
139- // should separately validate each symbol in the section and re-pack
140- // the array instead of relying on the poor linker to do it).
141-
170+ /* Extended manifest window record. Note the alignment attribute is
171+ * critical as rimage demands allocation in units of 16 bytes, yet the
172+ * C struct records emitted into the section are not in general padded
173+ * and will pack tighter than that! (Really this is an rimage bug, it
174+ * should separately validate each symbol in the section and re-pack
175+ * the array instead of relying on the poor linker to do it).
176+ */
142177#define WINDOW (region ) \
143178 { .type = SOF_IPC_REGION_##region, \
144179 .size = MTK_IPC_WIN_SIZE(region), \
145- .offset = MTK_IPC_WIN_OFF(region), }
146-
180+ . offset = MTK_IPC_WIN_OFF(region), }
147181struct ext_man_windows mtk_man_win __section (".fw_metadata" ) __aligned (EXT_MAN_ALIGN ) = {
148- .hdr = {
149- .type = EXT_MAN_ELEM_WINDOW ,
150- .elem_size = ROUND_UP (sizeof (struct ext_man_windows ), EXT_MAN_ALIGN )
151- },
182+ .hdr = {
183+ .type = EXT_MAN_ELEM_WINDOW ,
184+ .elem_size = ROUND_UP (sizeof (struct ext_man_windows ), EXT_MAN_ALIGN )
185+ },
152186 .window = {
153187 .ext_hdr = {
154- .hdr .cmd = SOF_IPC_FW_READY ,
155- .hdr .size = sizeof (struct sof_ipc_window ),
156- .type = SOF_IPC_EXT_WINDOW ,
157- },
158- .num_windows = 6 ,
159- .window = {
188+ .hdr .cmd = SOF_IPC_FW_READY ,
189+ .hdr .size = sizeof (struct sof_ipc_window ),
190+ .type = SOF_IPC_EXT_WINDOW ,
191+ },
192+ .num_windows = 6 ,
193+ .window = {
160194 // Order doesn't match memory layout for historical
161195 // reasons. Shouldn't matter, but don't rock the boat...
162196 WINDOW (UPBOX ),
0 commit comments