1 /* Copyright (c) 2022 Intel Corporation 2 * SPDX-License-Identifier: Apache-2.0 3 */ 4 #ifndef ZEPHYR_INCLUDE_INTEL_ADSP_IPC_H 5 #define ZEPHYR_INCLUDE_INTEL_ADSP_IPC_H 6 7 #include <intel_adsp_ipc_devtree.h> 8 #include <zephyr/kernel.h> 9 #include <zephyr/device.h> 10 #include <zephyr/pm/device.h> 11 12 struct intel_adsp_ipc_config { 13 volatile struct intel_adsp_ipc *regs; 14 }; 15 16 /** 17 * @brief Intel ADSP IPC Message Handler Callback. 18 * 19 * This function, once registered via intel_adsp_ipc_set_message_handler(), 20 * is invoked in interrupt context to service messages sent from the 21 * foreign/connected IPC context. The message contents of the TDR and 22 * TDD registers are provided in the data/ext_data argument. 23 * 24 * The function should return true if processing of the message is 25 * complete and return notification to the other side (via the TDA 26 * register) is desired immediately. Returning false means that no 27 * return "DONE" interrupt will occur until intel_adsp_ipc_complete() is 28 * called on this device at some point in the future. 29 * 30 * @note Further messages on the link will not be transmitted or 31 * received while an in-progress message remains incomplete! 32 * 33 * @param dev IPC device. 34 * @param arg Registered argument from intel_adsp_ipc_set_message_handler(). 35 * @param data Message data from other side (low bits of TDR register). 36 * @param ext_dat Extended message data (TDD register). 37 * @return true if the message is completely handled. 38 */ 39 typedef bool (*intel_adsp_ipc_handler_t)(const struct device *dev, void *arg, 40 uint32_t data, uint32_t ext_data); 41 42 /** 43 * @brief Intel ADSP IPC Message Complete Callback. 44 * 45 * This function, once registered via intel_adsp_ipc_set_done_handler(), is 46 * invoked in interrupt context when a "DONE" return interrupt is 47 * received from the other side of the connection (indicating that a 48 * previously sent message is finished processing). 49 * 50 * @note On Intel ADSP hardware the DONE interrupt is transmitted 51 * synchronously with the interrupt being cleared on the remote 52 * device. It is not possible to delay processing. This callback 53 * will still occur, but protocols which rely on notification of 54 * asynchronous command processing will need modification. 55 * 56 * @param dev IPC device. 57 * @param arg Registered argument from intel_adsp_ipc_set_done_handler(). 58 * @return True if IPC completion will be done externally, otherwise false. 59 * @note Returning True will cause this API to skip writing IPC registers 60 * signalling IPC message completion and those actions should be done by 61 * external code manually. Returning false from the handler will perform 62 * writing to IPC registers signalling message completion normally by this API. 63 */ 64 typedef bool (*intel_adsp_ipc_done_t)(const struct device *dev, void *arg); 65 66 struct intel_adsp_ipc_data { 67 struct k_sem sem; 68 struct k_spinlock lock; 69 intel_adsp_ipc_handler_t handle_message; 70 void *handler_arg; 71 intel_adsp_ipc_done_t done_notify; 72 void *done_arg; 73 bool tx_ack_pending; 74 }; 75 76 void z_intel_adsp_ipc_isr(const void *devarg); 77 78 /** 79 * @brief Register message callback handler. 80 * 81 * This function registers a handler function for received messages. 82 * 83 * @param dev IPC device. 84 * @param fn Callback function. 85 * @param arg Value to pass as the "arg" parameter to the function. 86 */ 87 void intel_adsp_ipc_set_message_handler(const struct device *dev, 88 intel_adsp_ipc_handler_t fn, void *arg); 89 90 /** 91 * @brief Register done callback handler. 92 * 93 * This function registers a handler function for message completion 94 * notifications. 95 * 96 * @param dev IPC device. 97 * @param fn Callback function. 98 * @param arg Value to pass as the "arg" parameter to the function. 99 */ 100 void intel_adsp_ipc_set_done_handler(const struct device *dev, 101 intel_adsp_ipc_done_t fn, void *arg); 102 103 /** @brief Initialize Intel ADSP IPC device. 104 * 105 * Initialize the device. Must be called before any API calls or 106 * interrupts can be serviced. 107 * 108 * @param dev IPC device. 109 * @return Zero on success, negative codes for error. 110 */ 111 int intel_adsp_ipc_init(const struct device *dev); 112 113 /** @brief Complete an in-progress message. 114 * 115 * Notify the other side that the current in-progress message is 116 * complete. This is a noop if no message is in progress. 117 * 118 * @note Further messages on the link will not be transmitted or 119 * received while an in-progress message remains incomplete! 120 * 121 * @param dev IPC device. 122 */ 123 void intel_adsp_ipc_complete(const struct device *dev); 124 125 /** @brief Message-in-progress predicate. 126 * 127 * Returns false if a message has been received but not yet completed 128 * via intel_adsp_ipc_complete(), true otherwise. 129 * 130 * @param dev IPC device. 131 * @return True if no message is in progress. 132 */ 133 bool intel_adsp_ipc_is_complete(const struct device *dev); 134 135 /** @brief Send an IPC message. 136 * 137 * Sends a message to the other side of an IPC link. The data and 138 * ext_data parameters are passed using the IDR/IDD registers. 139 * Returns 0 if the message was sent, negative error values: 140 * -EBUSY if there is already IPC message processed (intel_adsp_ipc_is_complete returns false). 141 * -ESHUTDOWN if IPC device will not send the message as it undergoes power 142 * transition. 143 * 144 * @param dev IPC device. 145 * @param data 30 bits value to transmit with the message (IDR register). 146 * @param ext_data Extended value to transmit with the message (IDD register). 147 * @return message successfully transmitted. 148 */ 149 int intel_adsp_ipc_send_message(const struct device *dev, 150 uint32_t data, uint32_t ext_data); 151 152 /** @brief Send an IPC message, block until completion. 153 * 154 * As for intel_adsp_ipc_send_message(), but blocks the current thread until 155 * the completion of the message or the expiration of the provided 156 * timeout. Returns immediately if IPC device is during power transition. 157 * 158 * @param dev IPC device 159 * @param data 30 bits value to transmit with the message (IDR register) 160 * @param ext_data Extended value to transmit with the message (IDD register) 161 * @param timeout Maximum time to wait, or K_FOREVER, or K_NO_WAIT 162 * @return returns 0 if message successfully transmited, otherwise error code. 163 */ 164 int intel_adsp_ipc_send_message_sync(const struct device *dev, 165 uint32_t data, uint32_t ext_data, k_timeout_t timeout); 166 167 168 /** @brief Send an emergency IPC message. 169 * 170 * Sends a message to the other side of an IPC link. The data and ext_data parameters are passed 171 * using the IDR/IDD registers. Waits in a loop until it is possible to send a message. 172 * 173 * @param dev IPC device. 174 * @param data 30 bits value to transmit with the message (IDR register). 175 * @param ext_data Extended value to transmit with the message (IDD register). 176 */ 177 void intel_adsp_ipc_send_message_emergency(const struct device *dev, uint32_t data, 178 uint32_t ext_data); 179 180 #ifdef CONFIG_PM_DEVICE 181 182 typedef int (*intel_adsp_ipc_resume_handler_t)(const struct device *dev, void *arg); 183 184 typedef int (*intel_adsp_ipc_suspend_handler_t)(const struct device *dev, void *arg); 185 186 /** 187 * @brief Registers resume callback handler used to resume Device from suspended state. 188 * 189 * @param dev IPC device. 190 * @param fn Callback function. 191 * @param arg Value to pass as the "arg" parameter to the function. 192 */ 193 void intel_adsp_ipc_set_resume_handler(const struct device *dev, 194 intel_adsp_ipc_resume_handler_t fn, void *arg); 195 196 /** 197 * @brief Registers suspend callback handler used to suspend active Device. 198 * 199 * @param dev IPC device. 200 * @param fn Callback function. 201 * @param arg Value to pass as the "arg" parameter to the function. 202 */ 203 void intel_adsp_ipc_set_suspend_handler(const struct device *dev, 204 intel_adsp_ipc_suspend_handler_t fn, void *arg); 205 206 struct ipc_control_driver_api { 207 intel_adsp_ipc_resume_handler_t resume_fn; 208 void *resume_fn_args; 209 intel_adsp_ipc_suspend_handler_t suspend_fn; 210 void *suspend_fn_args; 211 }; 212 213 #endif /* CONFIG_PM_DEVICE */ 214 #endif /* ZEPHYR_INCLUDE_INTEL_ADSP_IPC_H */ 215