zephyr/drivers/ipm/ipm_cavs_host.c

213 lines
5.9 KiB
C
Raw Normal View History

drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
/* Copyright (c) 2022, Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/drivers/ipm.h>
#include <adsp_memory.h>
#include <adsp_shim.h>
soc: intel_adsp: Refactored IPC/IDC Changes to code: 1. Renamed CAVS_IPC API from common/include/cavs_ipc.h to common/include/intel_adsp_ipc.h. Renamed all API functions and structs - added "intel_adsp_" prefix. 2. Moved definitions from intel-ipc-regs.h and ace-ipc-regs.g to SOC specific headers include/<soc_name>/adsp_ipc_regs.h. 3. Added new common intel_adsp_ipc_devtree.h header with new macros to retrieve IPC and IDC nodes and register addresses. Put those new macros in code replacing hardcoded values outside of devicetree. 4. Changed documentation of IDC and renamed IDC register struct to have common name between all intel adsp socs. 5. Removed excessive docs description on cAVS IPC protocol. Changes to Devicetree: 1. Renamed in all CAVS boards .dtsi files content in IPC nodes: - "cavs_host_ipc" node labels to "adsp_ipc" labels. - compatible "intel,cavs-host-ipc" renamed to "intel,adsp-host-ipc". 2. Added (previously missing) yaml file for "intel,adsp-host-ipc" compatible. 3. Renamed in all CAVS boards .dtsi files content in IDC nodes: - "idc" node labels to "adsp_idc" labels. - compatible "intel,cavs-idc" renamed to "intel-adsp-idc" 4. Renamed intel,cavs_idc.yaml file to intel,adsp_idc.yaml so it is suitable for both CAVS and ACE SoC family. Moved it from ipm bindings to ipc bindings where it belongs. Changes to Kconfig: 1. Renamed existing Kconfig option CONFIG_CAVS_IPC to INTEL_ADSP_IPC. 2. For renamed INTEL_ADSP_IPC addded default value based on status of the "adsp-ipc" and "adsp-ipc" node. Signed-off-by: Andrey Borisovich <andrey.borisovich@intel.com>
2022-07-13 05:15:06 +08:00
#include <intel_adsp_ipc.h>
#include <mem_window.h>
#include <zephyr/cache.h>
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
/* Matches SOF_IPC_MSG_MAX_SIZE, though in practice nothing anywhere
* near that big is ever sent. Should maybe consider making this a
* kconfig to avoid waste.
*/
#define MAX_MSG 384
/* Note: these addresses aren't flexible! We require that they match
* current SOF ipc3/4 layout, which means that:
*
* + Buffer addresses are 4k-aligned (this is a hardware requirement)
* + Inbuf must be 4k after outbuf, with no use of the intervening memory
* + Outbuf must be 4k after the start of win0 (this is where the host driver looks)
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
*
* One side effect is that the word "before" MSG_INBUF is owned by our
* code too, and can be used for a nice trick below.
*/
/* host windows */
#define DMWBA(win_base) (win_base + 0x0)
#define DMWLO(win_base) (win_base + 0x4)
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
struct ipm_cavs_host_data {
ipm_callback_t callback;
void *user_data;
bool enabled;
};
soc: intel_adsp: Refactored IPC/IDC Changes to code: 1. Renamed CAVS_IPC API from common/include/cavs_ipc.h to common/include/intel_adsp_ipc.h. Renamed all API functions and structs - added "intel_adsp_" prefix. 2. Moved definitions from intel-ipc-regs.h and ace-ipc-regs.g to SOC specific headers include/<soc_name>/adsp_ipc_regs.h. 3. Added new common intel_adsp_ipc_devtree.h header with new macros to retrieve IPC and IDC nodes and register addresses. Put those new macros in code replacing hardcoded values outside of devicetree. 4. Changed documentation of IDC and renamed IDC register struct to have common name between all intel adsp socs. 5. Removed excessive docs description on cAVS IPC protocol. Changes to Devicetree: 1. Renamed in all CAVS boards .dtsi files content in IPC nodes: - "cavs_host_ipc" node labels to "adsp_ipc" labels. - compatible "intel,cavs-host-ipc" renamed to "intel,adsp-host-ipc". 2. Added (previously missing) yaml file for "intel,adsp-host-ipc" compatible. 3. Renamed in all CAVS boards .dtsi files content in IDC nodes: - "idc" node labels to "adsp_idc" labels. - compatible "intel,cavs-idc" renamed to "intel-adsp-idc" 4. Renamed intel,cavs_idc.yaml file to intel,adsp_idc.yaml so it is suitable for both CAVS and ACE SoC family. Moved it from ipm bindings to ipc bindings where it belongs. Changes to Kconfig: 1. Renamed existing Kconfig option CONFIG_CAVS_IPC to INTEL_ADSP_IPC. 2. For renamed INTEL_ADSP_IPC addded default value based on status of the "adsp-ipc" and "adsp-ipc" node. Signed-off-by: Andrey Borisovich <andrey.borisovich@intel.com>
2022-07-13 05:15:06 +08:00
/* Note: this call is unsynchronized. The IPM docs are silent as to
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
* whether this is required, and the SOF code that will be using this
* is externally synchronized already.
*/
static int send(const struct device *dev, int wait, uint32_t id,
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
const void *data, int size)
{
const struct device *mw0 = DEVICE_DT_GET(DT_NODELABEL(mem_window0));
if (!device_is_ready(mw0)) {
return -ENODEV;
}
const struct mem_win_config *mw0_config = mw0->config;
uint32_t *buf = (uint32_t *)sys_cache_uncached_ptr_get(
(void *)((uint32_t)mw0_config->mem_base
+ CONFIG_IPM_CAVS_HOST_OUTBOX_OFFSET));
soc: intel_adsp: Refactored IPC/IDC Changes to code: 1. Renamed CAVS_IPC API from common/include/cavs_ipc.h to common/include/intel_adsp_ipc.h. Renamed all API functions and structs - added "intel_adsp_" prefix. 2. Moved definitions from intel-ipc-regs.h and ace-ipc-regs.g to SOC specific headers include/<soc_name>/adsp_ipc_regs.h. 3. Added new common intel_adsp_ipc_devtree.h header with new macros to retrieve IPC and IDC nodes and register addresses. Put those new macros in code replacing hardcoded values outside of devicetree. 4. Changed documentation of IDC and renamed IDC register struct to have common name between all intel adsp socs. 5. Removed excessive docs description on cAVS IPC protocol. Changes to Devicetree: 1. Renamed in all CAVS boards .dtsi files content in IPC nodes: - "cavs_host_ipc" node labels to "adsp_ipc" labels. - compatible "intel,cavs-host-ipc" renamed to "intel,adsp-host-ipc". 2. Added (previously missing) yaml file for "intel,adsp-host-ipc" compatible. 3. Renamed in all CAVS boards .dtsi files content in IDC nodes: - "idc" node labels to "adsp_idc" labels. - compatible "intel,cavs-idc" renamed to "intel-adsp-idc" 4. Renamed intel,cavs_idc.yaml file to intel,adsp_idc.yaml so it is suitable for both CAVS and ACE SoC family. Moved it from ipm bindings to ipc bindings where it belongs. Changes to Kconfig: 1. Renamed existing Kconfig option CONFIG_CAVS_IPC to INTEL_ADSP_IPC. 2. For renamed INTEL_ADSP_IPC addded default value based on status of the "adsp-ipc" and "adsp-ipc" node. Signed-off-by: Andrey Borisovich <andrey.borisovich@intel.com>
2022-07-13 05:15:06 +08:00
if (!intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV)) {
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
return -EBUSY;
}
if ((size < 0) || (size > MAX_MSG)) {
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
return -EMSGSIZE;
}
if ((id & 0xc0000000) != 0) {
/* cAVS IDR register has only 30 usable bits */
return -EINVAL;
}
uint32_t ext_data = 0;
/* Protocol variant (used by SOF "ipc4"): store the first word
* of the message in the IPC scratch registers
*/
if (IS_ENABLED(CONFIG_IPM_CAVS_HOST_REGWORD) && size >= 4) {
ext_data = ((uint32_t *)data)[0];
data = &((const uint32_t *)data)[1];
size -= 4;
}
memcpy(buf, data, size);
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
int ret = intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, id, ext_data);
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
/* The IPM docs call for "busy waiting" here, but in fact
* there's a blocking synchronous call available that might be
soc: intel_adsp: Refactored IPC/IDC Changes to code: 1. Renamed CAVS_IPC API from common/include/cavs_ipc.h to common/include/intel_adsp_ipc.h. Renamed all API functions and structs - added "intel_adsp_" prefix. 2. Moved definitions from intel-ipc-regs.h and ace-ipc-regs.g to SOC specific headers include/<soc_name>/adsp_ipc_regs.h. 3. Added new common intel_adsp_ipc_devtree.h header with new macros to retrieve IPC and IDC nodes and register addresses. Put those new macros in code replacing hardcoded values outside of devicetree. 4. Changed documentation of IDC and renamed IDC register struct to have common name between all intel adsp socs. 5. Removed excessive docs description on cAVS IPC protocol. Changes to Devicetree: 1. Renamed in all CAVS boards .dtsi files content in IPC nodes: - "cavs_host_ipc" node labels to "adsp_ipc" labels. - compatible "intel,cavs-host-ipc" renamed to "intel,adsp-host-ipc". 2. Added (previously missing) yaml file for "intel,adsp-host-ipc" compatible. 3. Renamed in all CAVS boards .dtsi files content in IDC nodes: - "idc" node labels to "adsp_idc" labels. - compatible "intel,cavs-idc" renamed to "intel-adsp-idc" 4. Renamed intel,cavs_idc.yaml file to intel,adsp_idc.yaml so it is suitable for both CAVS and ACE SoC family. Moved it from ipm bindings to ipc bindings where it belongs. Changes to Kconfig: 1. Renamed existing Kconfig option CONFIG_CAVS_IPC to INTEL_ADSP_IPC. 2. For renamed INTEL_ADSP_IPC addded default value based on status of the "adsp-ipc" and "adsp-ipc" node. Signed-off-by: Andrey Borisovich <andrey.borisovich@intel.com>
2022-07-13 05:15:06 +08:00
* better. But then we'd have to check whether we're in
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
* interrupt context, and it's not clear to me that SOF would
soc: intel_adsp: Refactored IPC/IDC Changes to code: 1. Renamed CAVS_IPC API from common/include/cavs_ipc.h to common/include/intel_adsp_ipc.h. Renamed all API functions and structs - added "intel_adsp_" prefix. 2. Moved definitions from intel-ipc-regs.h and ace-ipc-regs.g to SOC specific headers include/<soc_name>/adsp_ipc_regs.h. 3. Added new common intel_adsp_ipc_devtree.h header with new macros to retrieve IPC and IDC nodes and register addresses. Put those new macros in code replacing hardcoded values outside of devicetree. 4. Changed documentation of IDC and renamed IDC register struct to have common name between all intel adsp socs. 5. Removed excessive docs description on cAVS IPC protocol. Changes to Devicetree: 1. Renamed in all CAVS boards .dtsi files content in IPC nodes: - "cavs_host_ipc" node labels to "adsp_ipc" labels. - compatible "intel,cavs-host-ipc" renamed to "intel,adsp-host-ipc". 2. Added (previously missing) yaml file for "intel,adsp-host-ipc" compatible. 3. Renamed in all CAVS boards .dtsi files content in IDC nodes: - "idc" node labels to "adsp_idc" labels. - compatible "intel,cavs-idc" renamed to "intel-adsp-idc" 4. Renamed intel,cavs_idc.yaml file to intel,adsp_idc.yaml so it is suitable for both CAVS and ACE SoC family. Moved it from ipm bindings to ipc bindings where it belongs. Changes to Kconfig: 1. Renamed existing Kconfig option CONFIG_CAVS_IPC to INTEL_ADSP_IPC. 2. For renamed INTEL_ADSP_IPC addded default value based on status of the "adsp-ipc" and "adsp-ipc" node. Signed-off-by: Andrey Borisovich <andrey.borisovich@intel.com>
2022-07-13 05:15:06 +08:00
* benefit anyway as all its usage is async. This is OK for
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
* now.
*/
if (ret == -EBUSY && wait) {
soc: intel_adsp: Refactored IPC/IDC Changes to code: 1. Renamed CAVS_IPC API from common/include/cavs_ipc.h to common/include/intel_adsp_ipc.h. Renamed all API functions and structs - added "intel_adsp_" prefix. 2. Moved definitions from intel-ipc-regs.h and ace-ipc-regs.g to SOC specific headers include/<soc_name>/adsp_ipc_regs.h. 3. Added new common intel_adsp_ipc_devtree.h header with new macros to retrieve IPC and IDC nodes and register addresses. Put those new macros in code replacing hardcoded values outside of devicetree. 4. Changed documentation of IDC and renamed IDC register struct to have common name between all intel adsp socs. 5. Removed excessive docs description on cAVS IPC protocol. Changes to Devicetree: 1. Renamed in all CAVS boards .dtsi files content in IPC nodes: - "cavs_host_ipc" node labels to "adsp_ipc" labels. - compatible "intel,cavs-host-ipc" renamed to "intel,adsp-host-ipc". 2. Added (previously missing) yaml file for "intel,adsp-host-ipc" compatible. 3. Renamed in all CAVS boards .dtsi files content in IDC nodes: - "idc" node labels to "adsp_idc" labels. - compatible "intel,cavs-idc" renamed to "intel-adsp-idc" 4. Renamed intel,cavs_idc.yaml file to intel,adsp_idc.yaml so it is suitable for both CAVS and ACE SoC family. Moved it from ipm bindings to ipc bindings where it belongs. Changes to Kconfig: 1. Renamed existing Kconfig option CONFIG_CAVS_IPC to INTEL_ADSP_IPC. 2. For renamed INTEL_ADSP_IPC addded default value based on status of the "adsp-ipc" and "adsp-ipc" node. Signed-off-by: Andrey Borisovich <andrey.borisovich@intel.com>
2022-07-13 05:15:06 +08:00
while (!intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV)) {
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
k_busy_wait(1);
}
}
return ret;
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
}
static bool ipc_handler(const struct device *dev, void *arg,
uint32_t data, uint32_t ext_data)
{
ARG_UNUSED(arg);
struct device *ipmdev = arg;
struct ipm_cavs_host_data *devdata = ipmdev->data;
const struct device *mw1 = DEVICE_DT_GET(DT_NODELABEL(mem_window1));
if (!device_is_ready(mw1)) {
return -ENODEV;
}
const struct mem_win_config *mw1_config = mw1->config;
uint32_t *msg = sys_cache_uncached_ptr_get((void *)mw1_config->mem_base);
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
/* We play tricks to leave one word available before the
* beginning of the SRAM window, this way the host can see the
* same offsets it does with the original ipc4 protocol
* implementation, but here in the firmware we see a single
* contiguous buffer. See above.
*/
if (IS_ENABLED(CONFIG_IPM_CAVS_HOST_REGWORD)) {
msg = &msg[-1];
msg[0] = ext_data;
}
if (devdata->enabled && (devdata->callback != NULL)) {
devdata->callback(ipmdev, devdata->user_data,
data & 0x3fffffff, msg);
}
/* Return false for async handling */
return !IS_ENABLED(IPM_CALLBACK_ASYNC);
}
static int max_data_size_get(const struct device *ipmdev)
{
return MAX_MSG;
}
static uint32_t max_id_val_get(const struct device *ipmdev)
{
/* 30 user-writable bits in cAVS IDR register */
return 0x3fffffff;
}
static void register_callback(const struct device *port,
ipm_callback_t cb,
void *user_data)
{
struct ipm_cavs_host_data *data = port->data;
data->callback = cb;
data->user_data = user_data;
}
static int set_enabled(const struct device *ipmdev, int enable)
{
/* This protocol doesn't support any kind of queuing, and in
* fact will stall if a message goes unacknowledged. Support
* it as best we can by gating the callbacks only. That will
* allow the DONE notifications to proceed as normal, at the
* cost of dropping any messages received while not "enabled"
* of course.
*/
struct ipm_cavs_host_data *data = ipmdev->data;
data->enabled = enable;
return 0;
}
static void complete(const struct device *ipmdev)
{
soc: intel_adsp: Refactored IPC/IDC Changes to code: 1. Renamed CAVS_IPC API from common/include/cavs_ipc.h to common/include/intel_adsp_ipc.h. Renamed all API functions and structs - added "intel_adsp_" prefix. 2. Moved definitions from intel-ipc-regs.h and ace-ipc-regs.g to SOC specific headers include/<soc_name>/adsp_ipc_regs.h. 3. Added new common intel_adsp_ipc_devtree.h header with new macros to retrieve IPC and IDC nodes and register addresses. Put those new macros in code replacing hardcoded values outside of devicetree. 4. Changed documentation of IDC and renamed IDC register struct to have common name between all intel adsp socs. 5. Removed excessive docs description on cAVS IPC protocol. Changes to Devicetree: 1. Renamed in all CAVS boards .dtsi files content in IPC nodes: - "cavs_host_ipc" node labels to "adsp_ipc" labels. - compatible "intel,cavs-host-ipc" renamed to "intel,adsp-host-ipc". 2. Added (previously missing) yaml file for "intel,adsp-host-ipc" compatible. 3. Renamed in all CAVS boards .dtsi files content in IDC nodes: - "idc" node labels to "adsp_idc" labels. - compatible "intel,cavs-idc" renamed to "intel-adsp-idc" 4. Renamed intel,cavs_idc.yaml file to intel,adsp_idc.yaml so it is suitable for both CAVS and ACE SoC family. Moved it from ipm bindings to ipc bindings where it belongs. Changes to Kconfig: 1. Renamed existing Kconfig option CONFIG_CAVS_IPC to INTEL_ADSP_IPC. 2. For renamed INTEL_ADSP_IPC addded default value based on status of the "adsp-ipc" and "adsp-ipc" node. Signed-off-by: Andrey Borisovich <andrey.borisovich@intel.com>
2022-07-13 05:15:06 +08:00
intel_adsp_ipc_complete(INTEL_ADSP_IPC_HOST_DEV);
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
}
static int init(const struct device *dev)
{
struct ipm_cavs_host_data *data = dev->data;
const struct device *mw1 = DEVICE_DT_GET(DT_NODELABEL(mem_window1));
if (!device_is_ready(mw1)) {
return -ENODEV;
}
const struct mem_win_config *mw1_config = mw1->config;
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
/* Initialize hardware SRAM window. SOF will give the host 8k
* here, let's limit it to just the memory we're using for
* futureproofing.
*/
sys_write32(ROUND_UP(MAX_MSG, 8) | 0x7, DMWLO(mw1_config->base_addr));
sys_write32((mw1_config->mem_base | ADSP_DMWBA_ENABLE), DMWBA(mw1_config->base_addr));
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
soc: intel_adsp: Refactored IPC/IDC Changes to code: 1. Renamed CAVS_IPC API from common/include/cavs_ipc.h to common/include/intel_adsp_ipc.h. Renamed all API functions and structs - added "intel_adsp_" prefix. 2. Moved definitions from intel-ipc-regs.h and ace-ipc-regs.g to SOC specific headers include/<soc_name>/adsp_ipc_regs.h. 3. Added new common intel_adsp_ipc_devtree.h header with new macros to retrieve IPC and IDC nodes and register addresses. Put those new macros in code replacing hardcoded values outside of devicetree. 4. Changed documentation of IDC and renamed IDC register struct to have common name between all intel adsp socs. 5. Removed excessive docs description on cAVS IPC protocol. Changes to Devicetree: 1. Renamed in all CAVS boards .dtsi files content in IPC nodes: - "cavs_host_ipc" node labels to "adsp_ipc" labels. - compatible "intel,cavs-host-ipc" renamed to "intel,adsp-host-ipc". 2. Added (previously missing) yaml file for "intel,adsp-host-ipc" compatible. 3. Renamed in all CAVS boards .dtsi files content in IDC nodes: - "idc" node labels to "adsp_idc" labels. - compatible "intel,cavs-idc" renamed to "intel-adsp-idc" 4. Renamed intel,cavs_idc.yaml file to intel,adsp_idc.yaml so it is suitable for both CAVS and ACE SoC family. Moved it from ipm bindings to ipc bindings where it belongs. Changes to Kconfig: 1. Renamed existing Kconfig option CONFIG_CAVS_IPC to INTEL_ADSP_IPC. 2. For renamed INTEL_ADSP_IPC addded default value based on status of the "adsp-ipc" and "adsp-ipc" node. Signed-off-by: Andrey Borisovich <andrey.borisovich@intel.com>
2022-07-13 05:15:06 +08:00
intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_handler, (void *)dev);
drivers/ipm: Add ipm_cavs_host: host/DSP communication on adsp_intel Intel Audio DSPs have "IPC" interrupt delivery and shared memory window hardware. The Sound Open Firmware project has historically used the combination of these to implement a bidirectional message-passing interface. As it happens, this protocol is an excellent fit for Zephyr's somewhat geriatric but still useful IPM interface. This implements a SOF-protocol-compatible transport that will hopefully prove a bit more futureproof for non-Intel SOF architectures. It is a software-only device, built on top of the underlying SOC APIs for the SRAM windows (in cavs-shim) and IPC (cavs_ipc). Note that SOF actually has two protocol variants (ipc3 and ipc4): in both, the command header (passed as the "id" parameter in IPM) is sent via the hardware doorbell register. But in ipc4, the second hardware scratch register is used to transmit the first four bytes of the command before involving the SRAM window (in ipc3, it's ignored). Both modes are supported by this driver, set IPM_CAVS_HOST_REGWORD to choose the "ipc4" variant. Finally: note that the memory layout for the windows in question is inherited from SOF, and for compatibility (with both SOF and with the offsets used by the host!) these can't be changed without major surgery. They're defined in kconfig, but should be treated as read-only until we get a chance to rework the way Zephyr does its SRAM window management (and probably in concert with the host drivers). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2022-02-16 00:44:37 +08:00
data->enabled = true;
return 0;
}
static const struct ipm_driver_api api = {
.send = send,
.max_data_size_get = max_data_size_get,
.max_id_val_get = max_id_val_get,
.register_callback = register_callback,
.set_enabled = set_enabled,
.complete = complete,
};
static struct ipm_cavs_host_data data;
DEVICE_DEFINE(ipm_cavs_host, "ipm_cavs_host", init, NULL, &data, NULL,
PRE_KERNEL_2, 1, &api);