drivers/mailbox/mtk-gpueb-mailbox.c

Source file repositories/reference/linux-study-clean/drivers/mailbox/mtk-gpueb-mailbox.c

File Facts

System
Linux kernel
Corpus path
drivers/mailbox/mtk-gpueb-mailbox.c
Extension
.c
Size
9118 bytes
Lines
320
Domain
Driver Families
Bucket
drivers/mailbox
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mtk_gpueb_mbox {
	struct device *dev;
	struct clk *clk;
	void __iomem *mbox_mmio;
	void __iomem *mbox_ctl;
	struct mbox_controller mbox;
	struct mtk_gpueb_mbox_chan *ch;
	int irq;
	const struct mtk_gpueb_mbox_variant *v;
};

/**
 * struct mtk_gpueb_mbox_chan - per-channel runtime data
 * @ebm: pointer to the parent &struct mtk_gpueb_mbox mailbox
 * @full_name: descriptive name of channel for IRQ subsystem
 * @num: channel number, starting at 0
 * @rx_status: signifies whether channel reception is turned off, or full
 * @c: pointer to the constant &struct mtk_gpueb_mbox_chan_desc channel data
 */
struct mtk_gpueb_mbox_chan {
	struct mtk_gpueb_mbox *ebm;
	char *full_name;
	u8 num;
	atomic_t rx_status;
	const struct mtk_gpueb_mbox_chan_desc *c;
};

/**
 * struct mtk_gpueb_mbox_chan_desc - per-channel constant data
 * @name: name of this channel
 * @num: index of this channel, starting at 0
 * @tx_offset: byte offset measured from mmio base for outgoing data
 * @tx_len: size, in bytes, of the outgoing data on this channel
 * @rx_offset: bytes offset measured from mmio base for incoming data
 * @rx_len: size, in bytes, of the incoming data on this channel
 */
struct mtk_gpueb_mbox_chan_desc {
	const char *name;
	const u8 num;
	const u16 tx_offset;
	const u8 tx_len;
	const u16 rx_offset;
	const u8 rx_len;
};

struct mtk_gpueb_mbox_variant {
	const u8 num_channels;
	const struct mtk_gpueb_mbox_chan_desc channels[] __counted_by(num_channels);
};

/**
 * mtk_gpueb_mbox_read_rx - read RX buffer from MMIO into channel's RX buffer
 * @buf: buffer to read into
 * @chan: pointer to the channel to read
 */
static void mtk_gpueb_mbox_read_rx(void *buf, struct mtk_gpueb_mbox_chan *chan)
{
	memcpy_fromio(buf, chan->ebm->mbox_mmio + chan->c->rx_offset, chan->c->rx_len);
}

static irqreturn_t mtk_gpueb_mbox_isr(int irq, void *data)
{
	struct mtk_gpueb_mbox_chan *ch = data;
	u32 rx_sts;

	rx_sts = readl(ch->ebm->mbox_ctl + GPUEB_MBOX_CTL_RX_STS);

	if (rx_sts & BIT(ch->num)) {
		if (!atomic_cmpxchg(&ch->rx_status, 0, GPUEB_MBOX_FULL | GPUEB_MBOX_BLOCKED))
			return IRQ_WAKE_THREAD;
	}

	return IRQ_NONE;
}

static irqreturn_t mtk_gpueb_mbox_thread(int irq, void *data)
{
	struct mtk_gpueb_mbox_chan *ch = data;
	int status;

	status = atomic_cmpxchg(&ch->rx_status, GPUEB_MBOX_FULL | GPUEB_MBOX_BLOCKED,
				GPUEB_MBOX_FULL);
	if (status == (GPUEB_MBOX_FULL | GPUEB_MBOX_BLOCKED)) {
		u8 buf[GPUEB_MBOX_MAX_RX_SIZE] = {};

		mtk_gpueb_mbox_read_rx(buf, ch);
		writel(BIT(ch->num), ch->ebm->mbox_ctl + GPUEB_MBOX_CTL_IRQ_CLR);
		mbox_chan_received_data(&ch->ebm->mbox.chans[ch->num], buf);
		atomic_set(&ch->rx_status, 0);
		return IRQ_HANDLED;

Annotation

Implementation Notes