You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.7 KiB
214 lines
7.7 KiB
/* Copyright (c) 2022 Intel Corporation |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
#ifndef ZEPHYR_INCLUDE_INTEL_ADSP_IPC_H |
|
#define ZEPHYR_INCLUDE_INTEL_ADSP_IPC_H |
|
|
|
#include <intel_adsp_ipc_devtree.h> |
|
#include <zephyr/kernel.h> |
|
#include <zephyr/device.h> |
|
#include <zephyr/pm/device.h> |
|
|
|
struct intel_adsp_ipc_config { |
|
volatile struct intel_adsp_ipc *regs; |
|
}; |
|
|
|
/** |
|
* @brief Intel ADSP IPC Message Handler Callback. |
|
* |
|
* This function, once registered via intel_adsp_ipc_set_message_handler(), |
|
* is invoked in interrupt context to service messages sent from the |
|
* foreign/connected IPC context. The message contents of the TDR and |
|
* TDD registers are provided in the data/ext_data argument. |
|
* |
|
* The function should return true if processing of the message is |
|
* complete and return notification to the other side (via the TDA |
|
* register) is desired immediately. Returning false means that no |
|
* return "DONE" interrupt will occur until intel_adsp_ipc_complete() is |
|
* called on this device at some point in the future. |
|
* |
|
* @note Further messages on the link will not be transmitted or |
|
* received while an in-progress message remains incomplete! |
|
* |
|
* @param dev IPC device. |
|
* @param arg Registered argument from intel_adsp_ipc_set_message_handler(). |
|
* @param data Message data from other side (low bits of TDR register). |
|
* @param ext_dat Extended message data (TDD register). |
|
* @return true if the message is completely handled. |
|
*/ |
|
typedef bool (*intel_adsp_ipc_handler_t)(const struct device *dev, void *arg, |
|
uint32_t data, uint32_t ext_data); |
|
|
|
/** |
|
* @brief Intel ADSP IPC Message Complete Callback. |
|
* |
|
* This function, once registered via intel_adsp_ipc_set_done_handler(), is |
|
* invoked in interrupt context when a "DONE" return interrupt is |
|
* received from the other side of the connection (indicating that a |
|
* previously sent message is finished processing). |
|
* |
|
* @note On Intel ADSP hardware the DONE interrupt is transmitted |
|
* synchronously with the interrupt being cleared on the remote |
|
* device. It is not possible to delay processing. This callback |
|
* will still occur, but protocols which rely on notification of |
|
* asynchronous command processing will need modification. |
|
* |
|
* @param dev IPC device. |
|
* @param arg Registered argument from intel_adsp_ipc_set_done_handler(). |
|
* @return True if IPC completion will be done externally, otherwise false. |
|
* @note Returning True will cause this API to skip writing IPC registers |
|
* signalling IPC message completion and those actions should be done by |
|
* external code manually. Returning false from the handler will perform |
|
* writing to IPC registers signalling message completion normally by this API. |
|
*/ |
|
typedef bool (*intel_adsp_ipc_done_t)(const struct device *dev, void *arg); |
|
|
|
struct intel_adsp_ipc_data { |
|
struct k_sem sem; |
|
struct k_spinlock lock; |
|
intel_adsp_ipc_handler_t handle_message; |
|
void *handler_arg; |
|
intel_adsp_ipc_done_t done_notify; |
|
void *done_arg; |
|
bool tx_ack_pending; |
|
}; |
|
|
|
void z_intel_adsp_ipc_isr(const void *devarg); |
|
|
|
/** |
|
* @brief Register message callback handler. |
|
* |
|
* This function registers a handler function for received messages. |
|
* |
|
* @param dev IPC device. |
|
* @param fn Callback function. |
|
* @param arg Value to pass as the "arg" parameter to the function. |
|
*/ |
|
void intel_adsp_ipc_set_message_handler(const struct device *dev, |
|
intel_adsp_ipc_handler_t fn, void *arg); |
|
|
|
/** |
|
* @brief Register done callback handler. |
|
* |
|
* This function registers a handler function for message completion |
|
* notifications. |
|
* |
|
* @param dev IPC device. |
|
* @param fn Callback function. |
|
* @param arg Value to pass as the "arg" parameter to the function. |
|
*/ |
|
void intel_adsp_ipc_set_done_handler(const struct device *dev, |
|
intel_adsp_ipc_done_t fn, void *arg); |
|
|
|
/** @brief Initialize Intel ADSP IPC device. |
|
* |
|
* Initialize the device. Must be called before any API calls or |
|
* interrupts can be serviced. |
|
* |
|
* @param dev IPC device. |
|
* @return Zero on success, negative codes for error. |
|
*/ |
|
int intel_adsp_ipc_init(const struct device *dev); |
|
|
|
/** @brief Complete an in-progress message. |
|
* |
|
* Notify the other side that the current in-progress message is |
|
* complete. This is a noop if no message is in progress. |
|
* |
|
* @note Further messages on the link will not be transmitted or |
|
* received while an in-progress message remains incomplete! |
|
* |
|
* @param dev IPC device. |
|
*/ |
|
void intel_adsp_ipc_complete(const struct device *dev); |
|
|
|
/** @brief Message-in-progress predicate. |
|
* |
|
* Returns false if a message has been received but not yet completed |
|
* via intel_adsp_ipc_complete(), true otherwise. |
|
* |
|
* @param dev IPC device. |
|
* @return True if no message is in progress. |
|
*/ |
|
bool intel_adsp_ipc_is_complete(const struct device *dev); |
|
|
|
/** @brief Send an IPC message. |
|
* |
|
* Sends a message to the other side of an IPC link. The data and |
|
* ext_data parameters are passed using the IDR/IDD registers. |
|
* Returns 0 if the message was sent, negative error values: |
|
* -EBUSY if there is already IPC message processed (intel_adsp_ipc_is_complete returns false). |
|
* -ESHUTDOWN if IPC device will not send the message as it undergoes power |
|
* transition. |
|
* |
|
* @param dev IPC device. |
|
* @param data 30 bits value to transmit with the message (IDR register). |
|
* @param ext_data Extended value to transmit with the message (IDD register). |
|
* @return message successfully transmitted. |
|
*/ |
|
int intel_adsp_ipc_send_message(const struct device *dev, |
|
uint32_t data, uint32_t ext_data); |
|
|
|
/** @brief Send an IPC message, block until completion. |
|
* |
|
* As for intel_adsp_ipc_send_message(), but blocks the current thread until |
|
* the completion of the message or the expiration of the provided |
|
* timeout. Returns immediately if IPC device is during power transition. |
|
* |
|
* @param dev IPC device |
|
* @param data 30 bits value to transmit with the message (IDR register) |
|
* @param ext_data Extended value to transmit with the message (IDD register) |
|
* @param timeout Maximum time to wait, or K_FOREVER, or K_NO_WAIT |
|
* @return returns 0 if message successfully transmited, otherwise error code. |
|
*/ |
|
int intel_adsp_ipc_send_message_sync(const struct device *dev, |
|
uint32_t data, uint32_t ext_data, k_timeout_t timeout); |
|
|
|
|
|
/** @brief Send an emergency IPC message. |
|
* |
|
* Sends a message to the other side of an IPC link. The data and ext_data parameters are passed |
|
* using the IDR/IDD registers. Waits in a loop until it is possible to send a message. |
|
* |
|
* @param dev IPC device. |
|
* @param data 30 bits value to transmit with the message (IDR register). |
|
* @param ext_data Extended value to transmit with the message (IDD register). |
|
*/ |
|
void intel_adsp_ipc_send_message_emergency(const struct device *dev, uint32_t data, |
|
uint32_t ext_data); |
|
|
|
#ifdef CONFIG_PM_DEVICE |
|
|
|
typedef int (*intel_adsp_ipc_resume_handler_t)(const struct device *dev, void *arg); |
|
|
|
typedef int (*intel_adsp_ipc_suspend_handler_t)(const struct device *dev, void *arg); |
|
|
|
/** |
|
* @brief Registers resume callback handler used to resume Device from suspended state. |
|
* |
|
* @param dev IPC device. |
|
* @param fn Callback function. |
|
* @param arg Value to pass as the "arg" parameter to the function. |
|
*/ |
|
void intel_adsp_ipc_set_resume_handler(const struct device *dev, |
|
intel_adsp_ipc_resume_handler_t fn, void *arg); |
|
|
|
/** |
|
* @brief Registers suspend callback handler used to suspend active Device. |
|
* |
|
* @param dev IPC device. |
|
* @param fn Callback function. |
|
* @param arg Value to pass as the "arg" parameter to the function. |
|
*/ |
|
void intel_adsp_ipc_set_suspend_handler(const struct device *dev, |
|
intel_adsp_ipc_suspend_handler_t fn, void *arg); |
|
|
|
struct ipc_control_driver_api { |
|
intel_adsp_ipc_resume_handler_t resume_fn; |
|
void *resume_fn_args; |
|
intel_adsp_ipc_suspend_handler_t suspend_fn; |
|
void *suspend_fn_args; |
|
}; |
|
|
|
#endif /* CONFIG_PM_DEVICE */ |
|
#endif /* ZEPHYR_INCLUDE_INTEL_ADSP_IPC_H */
|
|
|