Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * rWTM BIU Mailbox driver for Armada 37xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Author: Marek Behun <marek.behun@nic.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/mailbox_controller.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/armada-37xx-rwtm-mailbox.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #define DRIVER_NAME	"armada-37xx-rwtm-mailbox"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) /* relative to rWTM BIU Mailbox Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define RWTM_MBOX_PARAM(i)		(0x0 + ((i) << 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define RWTM_MBOX_COMMAND		0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define RWTM_MBOX_RETURN_STATUS		0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define RWTM_MBOX_STATUS(i)		(0x84 + ((i) << 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define RWTM_MBOX_FIFO_STATUS		0xc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define FIFO_STS_RDY			0x100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define FIFO_STS_CNTR_MASK		0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define FIFO_STS_CNTR_MAX		4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define RWTM_HOST_INT_RESET		0xc8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define RWTM_HOST_INT_MASK		0xcc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define SP_CMD_COMPLETE			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define SP_CMD_QUEUE_FULL_ACCESS	BIT(17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define SP_CMD_QUEUE_FULL		BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) struct a37xx_mbox {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	struct mbox_controller controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static void a37xx_mbox_receive(struct mbox_chan *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	struct a37xx_mbox *mbox = chan->con_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	struct armada_37xx_rwtm_rx_msg rx_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	rx_msg.retval = readl(mbox->base + RWTM_MBOX_RETURN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	for (i = 0; i < 16; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		rx_msg.status[i] = readl(mbox->base + RWTM_MBOX_STATUS(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	mbox_chan_received_data(chan, &rx_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) static irqreturn_t a37xx_mbox_irq_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	struct mbox_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	struct a37xx_mbox *mbox = chan->con_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	reg = readl(mbox->base + RWTM_HOST_INT_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	if (reg & SP_CMD_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		a37xx_mbox_receive(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (reg & (SP_CMD_QUEUE_FULL_ACCESS | SP_CMD_QUEUE_FULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		dev_err(mbox->dev, "Secure processor command queue full\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	writel(reg, mbox->base + RWTM_HOST_INT_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	if (reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		mbox_chan_txdone(chan, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	return reg ? IRQ_HANDLED : IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static int a37xx_mbox_send_data(struct mbox_chan *chan, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	struct a37xx_mbox *mbox = chan->con_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	struct armada_37xx_rwtm_tx_msg *msg = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	reg = readl(mbox->base + RWTM_MBOX_FIFO_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	if (!(reg & FIFO_STS_RDY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		dev_warn(mbox->dev, "Secure processor not ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if ((reg & FIFO_STS_CNTR_MASK) >= FIFO_STS_CNTR_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		dev_err(mbox->dev, "Secure processor command queue full\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	for (i = 0; i < 16; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		writel(msg->args[i], mbox->base + RWTM_MBOX_PARAM(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	writel(msg->command, mbox->base + RWTM_MBOX_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int a37xx_mbox_startup(struct mbox_chan *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct a37xx_mbox *mbox = chan->con_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	ret = devm_request_irq(mbox->dev, mbox->irq, a37xx_mbox_irq_handler, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			       DRIVER_NAME, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		dev_err(mbox->dev, "Cannot request irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	/* enable IRQ generation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	reg = readl(mbox->base + RWTM_HOST_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	reg &= ~(SP_CMD_COMPLETE | SP_CMD_QUEUE_FULL_ACCESS | SP_CMD_QUEUE_FULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	writel(reg, mbox->base + RWTM_HOST_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static void a37xx_mbox_shutdown(struct mbox_chan *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	struct a37xx_mbox *mbox = chan->con_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	/* disable interrupt generation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	reg = readl(mbox->base + RWTM_HOST_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	reg |= SP_CMD_COMPLETE | SP_CMD_QUEUE_FULL_ACCESS | SP_CMD_QUEUE_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	writel(reg, mbox->base + RWTM_HOST_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	devm_free_irq(mbox->dev, mbox->irq, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static const struct mbox_chan_ops a37xx_mbox_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	.send_data	= a37xx_mbox_send_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	.startup	= a37xx_mbox_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	.shutdown	= a37xx_mbox_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static int armada_37xx_mbox_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	struct a37xx_mbox *mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	struct mbox_chan *chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	if (!mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	/* Allocated one channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	if (!chans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	mbox->base = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (IS_ERR(mbox->base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		return PTR_ERR(mbox->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	mbox->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	if (mbox->irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		return mbox->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	mbox->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	/* Hardware supports only one channel. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	chans[0].con_priv = mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	mbox->controller.dev = mbox->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	mbox->controller.num_chans = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	mbox->controller.chans = chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	mbox->controller.ops = &a37xx_mbox_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	mbox->controller.txdone_irq = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	ret = devm_mbox_controller_register(mbox->dev, &mbox->controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		dev_err(&pdev->dev, "Could not register mailbox controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	platform_set_drvdata(pdev, mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static const struct of_device_id armada_37xx_mbox_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	{ .compatible = "marvell,armada-3700-rwtm-mailbox" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	{ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) MODULE_DEVICE_TABLE(of, armada_37xx_mbox_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static struct platform_driver armada_37xx_mbox_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	.probe	= armada_37xx_mbox_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	.driver	= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		.name		= DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		.of_match_table	= armada_37xx_mbox_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) module_platform_driver(armada_37xx_mbox_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) MODULE_DESCRIPTION("rWTM BIU Mailbox driver for Armada 37xx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");