[PATCH] mailbox: Enable BCM2835 mailbox support
Ross Oldfield
ross at raspberrypi.org
Fri Oct 24 07:31:47 PDT 2014
Thanks,
>
> +#define MAIL0_CNF (ARM_0_MAIL0 + 0x1C)
> +#define MAIL1_WRT (ARM_0_MAIL1 + 0x00)
> +
> +#define MBOX_CHAN_COUNT 16
> +
I'd like to add:
#define MAIL1_STA (ARM_0_MAIL1 + 0x18)
... because ...
>
> +static int bcm2835_send_data(struct mbox_chan *link, void *data)
> +{
> + struct bcm2835_channel *chan = to_channel(link);
> + struct bcm2835_mbox *mbox = chan->mbox;
> + int ret = 0;
> +
> + if (!chan->started)
> + return -ENODEV;
> + spin_lock(&mbox->lock);
> + if (readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL) {
> + rmb(); /* Finished last mailbox read. */
> + ret = -EBUSY;
> + goto end;
> + }
The conditional here cannot ever be non-zero. Each of the two FIFOs we
are using here ( MAIL0 and MAIL1 ) have space for eight u32 entries in
them and the procotol is to only ever send or receive a single u32 at a
time. Something very bad must have happened for eight replies to be
waiting in the FIFO.
What we should be checking for is "has the remote end actually read the
last u32 we wrote". This is the same as saying "is the MAIL1_WRT FIFO
empty?" because if it is empty then it stands to reason that the remote
end read it already and so is not busy. So this conditional should be:
if (!(readl(mbox->regs + MAIL1_STA) & ARM_MS_EMPTY)) {
rmb(); /* Finished last mailbox read. */
ret =- EBUSY
Similarly,
> +static bool bcm2835_last_tx_done(struct mbox_chan *link)
> +{
> + struct bcm2835_channel *chan = to_channel(link);
> + struct bcm2835_mbox *mbox = chan->mbox;
> + bool ret;
> +
> + if (!chan->started)
> + return false;
> + spin_lock(&mbox->lock);
> + ret = !(readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL);
> + rmb(); /* Finished last mailbox read. */
> + spin_unlock(&mbox->lock);
> + return ret;
> +}
Again this should be checking for MAIL1 FIFO being empty as the tx is
"done" when the remote end has removed the last u32 written.
So,
ret = !!(readl(mbox->regs + MAIL1_STA) & ARM_MS_EMPTY);
... is better here I think.
As an aside, it turns out that we _may_ be able to make this a
non-polling driver because it turns out this peripheral has the ability
to generate an interrupt when the MAIL1 FIFO is empty. At the moment on
probe we set bit 1 of MAIL0_CNF to get an interrupt for "MAIL0 FIFO is
not empty". There are additonal options in the configuration register:
MAILn_CNF:
10 R/Wc Error: Read from empty mailbox
9 R/Wc Error: Write to full mailbox
8 R/Wc Error: None owner read mailbox
7 - <Unused, read as zero>
6 R Opposite Mailbox is empty interrupt pending
5 R My Mailbox has space interrupt pending
4 R My Mailbox has data interrupt pending
3 R/W Reset mailbox (set then clear this bit)
2 R/W Opp. Mailbox is empty interrupt enable
1 R/W Mailbox has space interrupt enable
0 R/W Mailbox has data interrupt enable
So by setting bit two we can now get interrupted when the remote end
has emptied MAIL1 and can check in the irq handler by reading bit 6
that this was the interrupt cause.
Thanks again,
Ross
More information about the linux-rpi-kernel
mailing list