IPC Mailbox Changes

This commit is contained in:
Justin Hammond 2023-02-03 23:54:37 +08:00
parent 7c892825e7
commit e17d63c2b6
4 changed files with 135 additions and 13 deletions

View file

@ -18,7 +18,7 @@
chosen {
stdout-path = "serial0:2000000n8";
bootargs = "console=ttyS0,2000000 loglevel=8 earlycon=sbi root=/dev/mmcblk0p2 rootwait rootfstype=ext4";
bootargs = "console=ttyS0,2000000 loglevel=8 earlycon=sbi root=/dev/mmcblk0p2 rootwait rootfstype=ext4 dyndbg=\"file drivers/remoteproc/* +p; file drivers/rpmsg/* +p; file drivers/virtio/* +p; file drivers/mailbox/* +p;\"";
linux,initrd-start = <0x0 0x52000000>;
linux,initrd-end = <0x0 0x52941784>;
};
@ -28,6 +28,7 @@
reg = <0x50000000 0x04000000>;
};
xip_flash@58500000 {
compatible = "mtd-rom";
reg = <0x58500000 0x400000>;
@ -53,6 +54,7 @@
status = "okay";
};
&enet0 {
&rproc {
status = "okay";
};

View file

@ -59,6 +59,31 @@
#clock-cells = <0>;
};
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
/* putting this at the top of uncached WRAM for the moment */
vdev0vring0: vdev0vring0@22054000 {
compatible = "shared-dma-pool";
reg = <0x22050000 0x4000>;
no-map;
};
vdev0vring1: vdev0vring1@22055000 {
compatible = "shared-dma-pool";
reg = <0x22054000 0x4000>;
no-map;
};
vdev0buffer: vdev0buffer@22056000 {
compatible = "shared-dma-pool";
reg = <0x22042000 0x8000>;
no-map;
};
};
soc {
compatible = "simple-bus";
ranges;
@ -140,5 +165,22 @@
#interrupt-cells = <2>;
riscv,ndev = <64>;
};
clint: timer@e4000000 {
compatible = "thead,c900-clint";
reg = <0xe4000000 0xc000>;
interrupts-extended = <&cpu0_intc 3>,
<&cpu0_intc 7>;
};
rproc: rproc@22054000 {
compatible = "bflb,bl808-rproc";
reg = <0x22054000 0x4000>;
memory-region = <&vdev0vring0>, <&vdev0vring1>, <&vdev0buffer>;
mboxes = <&ipclic BFLB_IPC_TARGET_M0 BFLB_IPC_MBOX_VIRTIO_KICK>;
status = "disabled";
};
};
};

View file

@ -64,6 +64,7 @@ static inline u32 bflb_ipc_get_hwirq(u16 source, u16 device)
{
pr_debug("%s: source: %u, device: %u\n", __func__, source, device);
return device;
}
@ -72,7 +73,7 @@ static void bflb_ipc_dump_regs(struct bflb_ipc *ipc)
{
int i;
for (i=0; i<4; i++) {
dev_dbg(ipc->dev, "base %px\n", ipc->base[i]);
dev_dbg(ipc->dev, "base %px %d\n", ipc->base[i], i);
dev_dbg(ipc->dev, "ISWR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_ISWR));
dev_dbg(ipc->dev, "IRSRR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_IRSRR));
dev_dbg(ipc->dev, "ICR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_ICR));
@ -85,6 +86,30 @@ static void bflb_ipc_dump_regs(struct bflb_ipc *ipc)
}
#endif
/* check the High/Low registers for the MBOX and send it off to
* the mailbox.
* JH: I'm guessing Source should map to the mailbox? But I've only allocated a single
* mailbox so far, so its discarded.
*/
static void bflb_mbox_poll(struct bflb_ipc *ipc)
{
u32 signal = readl(ipc->base[1] + IPC_REG_ILSHR);
u32 source = readl(ipc->base[1] + IPC_REG_ILSLR);
dev_dbg(ipc->dev, "signal: 0x%08x, source: 0x%08x\r\n", signal, source);
mbox_chan_received_data(&ipc->chans[0], signal);
/* clear the IPC_REG_ILSLR and IPC_REG_ILSHR */
writel(0, ipc->base[1] + IPC_REG_ILSLR);
writel(0, ipc->base[1] + IPC_REG_ILSHR);
return;
}
static irqreturn_t bflb_ipc_irq_fn(int irq, void *data)
{
struct bflb_ipc *ipc = data;
@ -92,12 +117,22 @@ static irqreturn_t bflb_ipc_irq_fn(int irq, void *data)
int pos;
stat = readl(ipc->base[1] + IPC_REG_ISR);
for_each_set_bit(pos, &stat, 32)
generic_handle_domain_irq(ipc->irq_domain, pos);
/*JH: I'm guessing there is a better way to pull out the mailbox IPC from others ?*/
for_each_set_bit(pos, &stat, 32) {
if (pos == BFLB_IPC_DEVICE_MBOX)
bflb_mbox_poll(ipc);
else
generic_handle_domain_irq(ipc->irq_domain, pos);
}
writel(stat, ipc->base[1] + IPC_REG_ICR);
/* EOI the irqs */
writel(stat, ipc->base[2] + IPC_REG_ISWR);
/* EOI the irqs except our MBOX */
/* JH: I don't EOI the mailbox, I just look to see if the High/Low registers are cleared on M0 side */
if (stat != (1 << BFLB_IPC_DEVICE_MBOX))
writel(stat, ipc->base[2] + IPC_REG_ISWR);
return IRQ_HANDLED;
}
@ -157,17 +192,42 @@ static const struct irq_domain_ops bflb_ipc_irq_ops = {
.xlate = bflb_ipc_domain_xlate,
};
/* JH: Figure out if M0 has processed the last signal sent
* by checking if the High/Low registers are cleared
*/
static int bflb_ipc_mbox_can_send(struct mbox_chan *chan)
{
struct bflb_ipc *ipc = to_bflb_ipc(chan->mbox);
u32 mbox_high = readl(ipc->base[2] + IPC_REG_ILSHR);
u32 mbox_low = readl(ipc->base[2] + IPC_REG_ILSLR);
dev_dbg(ipc->dev, "%s: low: 0x%08x high: 0x%08x\r\n", __func__, mbox_low, mbox_high);
return !(mbox_low | mbox_high);
}
static int bflb_ipc_mbox_send_data(struct mbox_chan *chan, void *data)
{
struct bflb_ipc *ipc = to_bflb_ipc(chan->mbox);
struct bflb_ipc_chan_info *mchan = chan->con_priv;
u32 hwirq;
hwirq = bflb_ipc_get_hwirq(mchan->client_id, mchan->signal_id);
if (!bflb_ipc_mbox_can_send(chan))
return -EBUSY;
dev_dbg(ipc->dev, "%s: hwirq: %u\n", __func__, hwirq);
// writel(hwirq, ipc->base + IPC_REG_SEND_ID);
dev_dbg(ipc->dev, "%s: %d %d\n", __func__, mchan->client_id, mchan->signal_id);
// /* write our signal number to high register */
writel(mchan->signal_id, ipc->base[2] + IPC_REG_ILSHR);
// /* write our data to low register */
writel((u32)data, ipc->base[2] + IPC_REG_ILSLR);
/* and now kick the remote processor */
writel((1 << BFLB_IPC_DEVICE_MBOX), ipc->base[2] + IPC_REG_ISWR);
return 0;
}
@ -219,6 +279,7 @@ static struct mbox_chan *bflb_ipc_mbox_xlate(struct mbox_controller *mbox,
return chan;
}
static const struct mbox_chan_ops ipc_mbox_chan_ops = {
.send_data = bflb_ipc_mbox_send_data,
.shutdown = bflb_ipc_mbox_shutdown,
@ -236,6 +297,7 @@ static int bflb_ipc_setup_mbox(struct bflb_ipc *ipc,
/*
* Find out the number of clients interested in this mailbox
* and create channels accordingly.
* JH: How do we allocate them so we can lookup by name?
*/
ipc->num_chans = 0;
for_each_node_with_property(client_dn, "mboxes") {
@ -253,7 +315,7 @@ static int bflb_ipc_setup_mbox(struct bflb_ipc *ipc,
}
}
}
dev_dbg(dev, "%s: num_chans: %d", __func__, ipc->num_chans);
/* If no clients are found, skip registering as a mbox controller */
if (!ipc->num_chans)
return 0;
@ -272,6 +334,14 @@ static int bflb_ipc_setup_mbox(struct bflb_ipc *ipc,
mbox->txdone_irq = false;
mbox->txdone_poll = false;
/* clear the IPC_REG_ILSLR and IPC_REG_ILSHR */
writel(0, ipc->base[2] + IPC_REG_ILSLR);
writel(0, ipc->base[2] + IPC_REG_ILSHR);
/* unmask our interupt */
writel(BIT(BFLB_IPC_DEVICE_MBOX), ipc->base[1] + IPC_REG_IUSR);
return devm_mbox_controller_register(dev, mbox);
}

View file

@ -13,7 +13,15 @@
/* Peripheral device ID */
#define BFLB_IPC_DEVICE_SDHCI 0
#define BFLB_IPC_DEVICE_UART2 1
#define BFLB_IPC_DEVICE_USB 2
#define BFLB_IPC_DEVICE_USB 2
#define BFLB_IPC_DEVICE_EMAC 3
#define BFLB_IPC_DEVICE_MBOX 5
#define BFLB_IPC_TARGET_M0 0
#define BFLB_IPC_TARGET_LP 1
/* MailBox Signals */
#define BFLB_IPC_MBOX_VIRTIO_KICK 1
#endif