[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