mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
ADSP host driver is enhanced to be multi-instance
capable and reentrant:
- Trailing unique identifier string in compatible DT property, like
"adsp", "adsp1" or "aon", is used to identify the driver instances
- Each probed driver instance is inserted into a global list, from
which the handle can be fetched using 'nvadsp_get_handle' API
(passing the above unique identifier as argument)
- Above unique identifier is also used as name for the DBFS
directory (containing files like adsp_console, adsp_logger, etc.)
- 'nvadsp_get_handle' is the only exported API; all other APIs are
accessible via function pointers within 'struct nvadsp_handle'
- APIs above maintain one-is-to-one correspondence with all
legacy APIs, with the addition of a new argument
'struct nvadsp_handle *' at the beginning
- Legacy APIs continue to be supported, but they are hardwired to
work only if the kernel probes just one driver instance
- All driver files are cleaned up to not use any global state
variables (necessary for reentrancy)
Bug 3682950
Change-Id: Id5db49e861b2f81716ae8352b36b406654da2bbd
Signed-off-by: Viswanath L <viswanathl@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3092701
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Dara Ramesh <dramesh@nvidia.com>
113 lines
3.6 KiB
C
113 lines
3.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
// SPDX-FileCopyrightText: Copyright (c) 2014-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
|
|
#ifndef __HWMAILBOX_H
|
|
#define __HWMAILBOX_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/completion.h>
|
|
#include <linux/spinlock.h>
|
|
|
|
/*
|
|
* The interpretation of hwmailbox content is:
|
|
* 31 30 29 0
|
|
* [TAG|TYPE|MESSAGE]
|
|
*/
|
|
#define HWMBOX_TAG_SHIFT 31
|
|
#define HWMBOX_TAG_MASK 0x1
|
|
#define HWMBOX_TAG_INVALID 0
|
|
#define HWMBOX_TAG_VALID 1
|
|
/* Set Invalid TAG */
|
|
#define SET_HWMBOX_TAG_INVALID (HWMBOX_TAG_INVALID << HWMBOX_TAG_SHIFT)
|
|
/* Set Valid TAG */
|
|
#define SET_HWMBOX_TAG_VALID (HWMBOX_TAG_VALID << HWMBOX_TAG_SHIFT)
|
|
/* Get current TAG */
|
|
#define HWMBOX_TAG(val) ((val & HWMBOX_TAG_MASK) << HWMBOX_TAG_SHIFT)
|
|
|
|
/*
|
|
* Mailbox can be used for sending short messages and long messages
|
|
*/
|
|
#define HWMBOX_MSG_TYPE_SHIFT 30
|
|
#define HWMBOX_MSG_TYPE_MASK 0x1
|
|
#define HWMBOX_MSG_SMSG 0
|
|
#define HWMBOX_MSG_LMSG 1
|
|
/* Set SMSG type */
|
|
#define SET_HWMBOX_MSG_SMSG (HWMBOX_MSG_SMSG << HWMBOX_MSG_TYPE_SHIFT)
|
|
/* Set LMSG type */
|
|
#define SET_HWMBOX_MSG_LMSG (HWMBOX_MSG_LMSG << HWMBOX_MSG_TYPE_SHIFT)
|
|
/* Get MSG type */
|
|
#define HWMBOX_MSG_TYPE(val) \
|
|
((val >> HWMBOX_MSG_TYPE_SHIFT) & HWMBOX_MSG_TYPE_MASK)
|
|
/* Check if SMSG */
|
|
#define IS_HWMBOX_MSG_SMSG(val) \
|
|
(!((val >> HWMBOX_MSG_TYPE_SHIFT) & HWMBOX_MSG_TYPE_MASK))
|
|
/* Check if LMSG */
|
|
#define IS_HWMBOX_MSG_LMSG(val) \
|
|
((val >> HWMBOX_MSG_TYPE_SHIFT) & HWMBOX_MSG_TYPE_MASK)
|
|
|
|
/*
|
|
* The format for a short message is:
|
|
* 31 30 29 20 19 0
|
|
* [TAG|TYPE|MBOX ID|SHORT MESSAGE]
|
|
* 1b 1b 10bits 20bits
|
|
*/
|
|
#define HWMBOX_SMSG_SHIFT 0
|
|
#define HWMBOX_SMSG_MASK 0x3FFFFFFF
|
|
#define HWMBOX_SMSG(val) ((val >> HWMBOX_SMSG_SHIFT) & HWMBOX_SMSG_MASK)
|
|
#define HWMBOX_SMSG_MID_SHIFT 20
|
|
#define HWMBOX_SMSG_MID_MASK 0x3FF
|
|
#define HWMBOX_SMSG_MID(val) \
|
|
((val >> HWMBOX_SMSG_MID_SHIFT) & HWMBOX_SMSG_MID_MASK)
|
|
#define HWMBOX_SMSG_MSG_SHIFT 0
|
|
#define HWMBOX_SMSG_MSG_MASK 0xFFFFF
|
|
#define HWMBOX_SMSG_MSG(val) \
|
|
((val >> HWMBOX_SMSG_MSG_SHIFT) & HWMBOX_SMSG_MSG_MASK)
|
|
/* Set mailbox id for a short message */
|
|
#define SET_HWMBOX_SMSG_MID(val) \
|
|
((val & HWMBOX_SMSG_MID_MASK) << HWMBOX_SMSG_MID_SHIFT)
|
|
/* Set msg value in a short message */
|
|
#define SET_HWMBOX_SMSG_MSG(val) \
|
|
((val & HWMBOX_SMSG_MSG_MASK) << HWMBOX_SMSG_MSG_SHIFT)
|
|
|
|
/* Prepare a small message with mailbox id and data */
|
|
#define PREPARE_HWMBOX_SMSG(mid, data) (SET_HWMBOX_TAG_VALID | \
|
|
SET_HWMBOX_MSG_SMSG | \
|
|
SET_HWMBOX_SMSG_MID(mid) | \
|
|
SET_HWMBOX_SMSG_MSG(data))
|
|
/* Prepare empty mailbox value */
|
|
#define PREPARE_HWMBOX_EMPTY_MSG() (HWMBOX_TAG_INVALID | 0x0)
|
|
|
|
/* Enable and Disable macros for interrupt */
|
|
#define INT_ENABLE 0x1
|
|
#define INT_DISABLE 0x0
|
|
|
|
/*
|
|
* Queue size must be power of 2 as '&' op
|
|
* is being used to manage circular queues
|
|
*/
|
|
#define HWMBOX_QUEUE_SIZE 1024
|
|
#define HWMBOX_QUEUE_SIZE_MASK (HWMBOX_QUEUE_SIZE - 1)
|
|
struct hwmbox_queue {
|
|
uint32_t array[HWMBOX_QUEUE_SIZE];
|
|
uint16_t head;
|
|
uint16_t tail;
|
|
uint16_t count;
|
|
struct completion comp;
|
|
spinlock_t lock;
|
|
bool is_hwmbox_busy;
|
|
uint32_t hwmbox_last_msg;
|
|
};
|
|
|
|
u32 hwmbox_readl(struct nvadsp_drv_data *, u32 reg);
|
|
void hwmbox_writel(struct nvadsp_drv_data *, u32 val, u32 reg);
|
|
status_t nvadsp_hwmbox_send_data(struct nvadsp_drv_data *,
|
|
uint16_t, uint32_t, uint32_t);
|
|
void dump_mailbox_regs(struct nvadsp_drv_data *);
|
|
|
|
int nvadsp_hwmbox_init(struct platform_device *);
|
|
int nvadsp_setup_hwmbox_interrupts(struct platform_device *pdev);
|
|
void nvadsp_free_hwmbox_interrupts(struct platform_device *pdev);
|
|
|
|
#endif /* __HWMAILBOX_H */
|