[PATCH] mailbox: Enable BCM2835 mailbox support
Piotr Król
piotr.krol at 3mdeb.com
Fri Oct 24 16:30:57 PDT 2014
On Fri, Oct 24, 2014 at 03:31:47PM +0100, Ross Oldfield wrote:
> >
> >+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.
>
Thanks Ross,
I will add that I tested this driver with Lubomir's bcm2835-cpufreq and
using MAIL0_STA gives errors like:
cpufreq: __cpufreq_add_dev: ->get() failed
bcm2835-cpufreq soc:cpufreq: Could not register cpufreq driver
More about it here:
https://github.com/pietrushnic/rpi-dt-linux/issues/2
Changing tx_done and send_data to use MAIL1_STA fix those problems.
Regards,
Piotr Król
More information about the linux-rpi-kernel
mailing list