1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2016 Intel Corporation. All rights reserved.
4 *
5 * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
6 * Keyon Jie <yang.jie@linux.intel.com>
7 */
8
9 #ifndef __SOF_IPC_COMMON_H__
10 #define __SOF_IPC_COMMON_H__
11
12 #include <rtos/bit.h>
13 #include <rtos/alloc.h>
14 #include <sof/list.h>
15 #include <rtos/task.h>
16 #include <rtos/spinlock.h>
17 #include <rtos/sof.h>
18 #include <user/trace.h>
19 #include <ipc/header.h>
20 #include <ipc/stream.h>
21
22 #include <stdbool.h>
23 #include <stdint.h>
24
25 struct dma_sg_elem_array;
26 struct ipc_msg;
27
28 /* validates internal non tail structures within IPC command structure */
29 #define IPC_IS_SIZE_INVALID(object) \
30 (object).hdr.size == sizeof(object) ? 0 : 1
31
32 /* ipc trace context, used by multiple units */
33 extern struct tr_ctx ipc_tr;
34
35 /* convenience error trace for mismatched internal structures */
36 #define IPC_SIZE_ERROR_TRACE(ctx, object) \
37 tr_err(ctx, "ipc: size %d expected %d", \
38 (object).hdr.size, sizeof(object))
39
40 /* Returns pipeline source component */
41 #define ipc_get_ppl_src_comp(ipc, ppl_id) \
42 ipc_get_ppl_comp(ipc, ppl_id, PPL_DIR_UPSTREAM)
43
44 /* Returns pipeline sink component */
45 #define ipc_get_ppl_sink_comp(ipc, ppl_id) \
46 ipc_get_ppl_comp(ipc, ppl_id, PPL_DIR_DOWNSTREAM)
47
48 #define IPC_TASK_INLINE BIT(0)
49 #define IPC_TASK_IN_THREAD BIT(1)
50 #define IPC_TASK_SECONDARY_CORE BIT(2)
51 #define IPC_TASK_POWERDOWN BIT(3)
52
53 struct ipc {
54 struct k_spinlock lock; /* locking mechanism */
55 void *comp_data;
56
57 /* PM */
58 int pm_prepare_D3; /* do we need to prepare for D3 */
59
60 struct list_item msg_list; /* queue of messages to be sent */
61 bool is_notification_pending; /* notification is being sent to host */
62 uint32_t task_mask; /* tasks to be completed by this IPC */
63 unsigned int core; /* core, processing the IPC */
64
65 struct list_item comp_list; /* list of component devices */
66
67 /* processing task */
68 struct task ipc_task;
69
70 #ifdef __ZEPHYR__
71 struct k_work_delayable z_delayed_work;
72 #endif
73
74 void *private;
75 };
76
77 #define ipc_set_drvdata(ipc, data) \
78 ((ipc)->private = data)
79 #define ipc_get_drvdata(ipc) \
80 ((ipc)->private)
81
82 extern struct task_ops ipc_task_ops;
83
84 /**
85 * \brief Get the IPC global context.
86 * @return The global IPC context.
87 */
ipc_get(void)88 static inline struct ipc *ipc_get(void)
89 {
90 return sof_get()->ipc;
91 }
92
93 /**
94 * \brief Initialise global IPC context.
95 * @param[in,out] sof Global SOF context.
96 * @return 0 on success.
97 */
98 int ipc_init(struct sof *sof);
99
100 /**
101 * \brief Free global IPC context.
102 * @param[in] ipc Global IPC context.
103 */
104 void ipc_free(struct ipc *ipc);
105
106 /**
107 * \brief Data provided by the platform which use ipc...page_descriptors().
108 *
109 * Note: this should be made private for ipc-host-ptable.c and ipc
110 * drivers for platforms that use ptables.
111 */
112 struct ipc_data_host_buffer {
113 /* DMA */
114 struct dma *dmac;
115 uint8_t *page_table;
116 };
117
118 /**
119 * \brief Processes page tables for the host buffer.
120 * @param[in] ipc Ipc
121 * @param[in] ring Ring description sent via Ipc
122 * @param[in] direction Direction (playback/capture)
123 * @param[out] elem_array Array of SG elements
124 * @param[out] ring_size Size of the ring
125 * @return Status, 0 if successful, error code otherwise.
126 */
127 int ipc_process_host_buffer(struct ipc *ipc,
128 struct sof_ipc_host_buffer *ring,
129 uint32_t direction,
130 struct dma_sg_elem_array *elem_array,
131 uint32_t *ring_size);
132
133 /**
134 * \brief Send DMA trace host buffer position to host.
135 * @return 0 on success.
136 */
137 int ipc_dma_trace_send_position(void);
138
139 /**
140 * \brief send a IPC buffer status notify message
141 */
142 void ipc_send_buffer_status_notify(void);
143
144 /**
145 * \brief Configure DAI.
146 * @return 0 on success.
147 */
148 int ipc_dai_data_config(struct comp_dev *dev);
149
150 /**
151 * \brief create a IPC boot complete message.
152 * @param[in] header header.
153 * @param[in] data data.
154 */
155 void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data);
156
157 /**
158 * \brief Read a compact IPC message or return NULL for normal message.
159 * @return Pointer to the compact message data.
160 */
161 struct ipc_cmd_hdr *ipc_compact_read_msg(void);
162
163 /**
164 * \brief Write a compact IPC message.
165 * @param[in] hdr Compact message header data.
166 * @return Number of words written.
167 */
168 int ipc_compact_write_msg(struct ipc_cmd_hdr *hdr);
169
170 /**
171 * \brief Prepare an IPC message for sending.
172 * @param[in] msg The ipc msg.
173 * @return pointer to raw header or NULL.
174 */
175 struct ipc_cmd_hdr *ipc_prepare_to_send(const struct ipc_msg *msg);
176
177 /**
178 * \brief Validate mailbox contents for valid IPC header.
179 * @return pointer to header if valid or NULL.
180 */
181 struct ipc_cmd_hdr *mailbox_validate(void);
182
183 /**
184 * Generic IPC command handler. Expects that IPC command (the header plus
185 * any optional payload) is deserialized from the IPC HW by the platform
186 * specific method.
187 *
188 * @param _hdr Points to the IPC command header.
189 */
190 void ipc_cmd(struct ipc_cmd_hdr *_hdr);
191
192 /**
193 * \brief IPC message to be processed on other core.
194 * @param[in] core Core id for IPC to be processed on.
195 * @param[in] blocking Process in blocking mode: wait for completion.
196 * @return 1 if successful (reply sent by other core), error code otherwise.
197 */
198 int ipc_process_on_core(uint32_t core, bool blocking);
199
200 /**
201 * \brief reply to an IPC message.
202 * @param[in] reply pointer to the reply structure.
203 */
204 void ipc_msg_reply(struct sof_ipc_reply *reply);
205
206 /**
207 * \brief Call platform-specific IPC completion function.
208 */
209 void ipc_complete_cmd(struct ipc *ipc);
210
211 #endif /* __SOF_DRIVERS_IPC_H__ */
212