drivers/mailbox/armada-37xx-rwtm-mailbox.c

Source file repositories/reference/linux-study-clean/drivers/mailbox/armada-37xx-rwtm-mailbox.c

File Facts

System
Linux kernel
Corpus path
drivers/mailbox/armada-37xx-rwtm-mailbox.c
Extension
.c
Size
5178 bytes
Lines
207
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 a37xx_mbox {
	struct device *dev;
	struct mbox_controller controller;
	void __iomem *base;
	int irq;
};

static void a37xx_mbox_receive(struct mbox_chan *chan)
{
	struct a37xx_mbox *mbox = chan->con_priv;
	struct armada_37xx_rwtm_rx_msg rx_msg;
	int i;

	rx_msg.retval = readl(mbox->base + RWTM_MBOX_RETURN_STATUS);
	for (i = 0; i < 16; ++i)
		rx_msg.status[i] = readl(mbox->base + RWTM_MBOX_STATUS(i));

	mbox_chan_received_data(chan, &rx_msg);
}

static irqreturn_t a37xx_mbox_irq_handler(int irq, void *data)
{
	struct mbox_chan *chan = data;
	struct a37xx_mbox *mbox = chan->con_priv;
	u32 reg;

	reg = readl(mbox->base + RWTM_HOST_INT_RESET);

	if (reg & SP_CMD_COMPLETE)
		a37xx_mbox_receive(chan);

	if (reg & (SP_CMD_QUEUE_FULL_ACCESS | SP_CMD_QUEUE_FULL))
		dev_err(mbox->dev, "Secure processor command queue full\n");

	writel(reg, mbox->base + RWTM_HOST_INT_RESET);
	if (reg)
		mbox_chan_txdone(chan, 0);

	return reg ? IRQ_HANDLED : IRQ_NONE;
}

static int a37xx_mbox_send_data(struct mbox_chan *chan, void *data)
{
	struct a37xx_mbox *mbox = chan->con_priv;
	struct armada_37xx_rwtm_tx_msg *msg = data;
	int i;
	u32 reg;

	if (!data)
		return -EINVAL;

	reg = readl(mbox->base + RWTM_MBOX_FIFO_STATUS);
	if (!(reg & FIFO_STS_RDY))
		dev_warn(mbox->dev, "Secure processor not ready\n");

	if ((reg & FIFO_STS_CNTR_MASK) >= FIFO_STS_CNTR_MAX) {
		dev_err(mbox->dev, "Secure processor command queue full\n");
		return -EBUSY;
	}

	for (i = 0; i < 16; ++i)
		writel(msg->args[i], mbox->base + RWTM_MBOX_PARAM(i));
	writel(msg->command, mbox->base + RWTM_MBOX_COMMAND);

	return 0;
}

static int a37xx_mbox_startup(struct mbox_chan *chan)
{
	struct a37xx_mbox *mbox = chan->con_priv;
	u32 reg;
	int ret;

	ret = devm_request_irq(mbox->dev, mbox->irq, a37xx_mbox_irq_handler, 0,
			       DRIVER_NAME, chan);
	if (ret < 0) {
		dev_err(mbox->dev, "Cannot request irq\n");
		return ret;
	}

	/* enable IRQ generation */
	reg = readl(mbox->base + RWTM_HOST_INT_MASK);
	reg &= ~(SP_CMD_COMPLETE | SP_CMD_QUEUE_FULL_ACCESS | SP_CMD_QUEUE_FULL);
	writel(reg, mbox->base + RWTM_HOST_INT_MASK);

	return 0;
}

static void a37xx_mbox_shutdown(struct mbox_chan *chan)
{

Annotation

Implementation Notes