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