[PATCH 1/2] ARM: bcm2835: add mailbox driver
Stephen Warren
swarren at wwwdotorg.org
Tue Oct 16 01:10:35 EDT 2012
The BCM2835 SoC contains (at least) two CPUs; the VideoCore (a/k/a "GPU")
and the ARM CPU. The ARM CPU is often thought of as the main CPU.
However, the VideoCore actually controls the initial SoC boot, and hides
much of the hardware behind a protocol. This protocol is transported
using the SoC's mailbox hardware module. The mailbox supports two forms
of communication: Raw 28-bit values, and a so-called "property"
interface, where the 28-bit value is a physical pointer to a memory
buffer that contains various "tags".
Here, we add a very simplistic driver for the mailbox module, and define
a few structures for the property messages.
Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
arch/arm/cpu/arm1176/bcm2835/Makefile | 2 +-
arch/arm/cpu/arm1176/bcm2835/mbox.c | 92 ++++++++++++++++++++++++++++++
arch/arm/include/asm/arch-bcm2835/mbox.h | 87 ++++++++++++++++++++++++++++
3 files changed, 180 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/cpu/arm1176/bcm2835/mbox.c
create mode 100644 arch/arm/include/asm/arch-bcm2835/mbox.h
diff --git a/arch/arm/cpu/arm1176/bcm2835/Makefile b/arch/arm/cpu/arm1176/bcm2835/Makefile
index 95da6a8..135de42 100644
--- a/arch/arm/cpu/arm1176/bcm2835/Makefile
+++ b/arch/arm/cpu/arm1176/bcm2835/Makefile
@@ -17,7 +17,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).o
SOBJS := lowlevel_init.o
-COBJS := init.o reset.o timer.o
+COBJS := init.o reset.o timer.o mbox.o
SRCS := $(SOBJS:.o=.c) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/arch/arm/cpu/arm1176/bcm2835/mbox.c b/arch/arm/cpu/arm1176/bcm2835/mbox.c
new file mode 100644
index 0000000..f5c060b
--- /dev/null
+++ b/arch/arm/cpu/arm1176/bcm2835/mbox.c
@@ -0,0 +1,92 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/mbox.h>
+
+#define TIMEOUT (100 * 1000) /* 100mS in uS */
+
+int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv)
+{
+ struct bcm2835_mbox_regs *regs =
+ (struct bcm2835_mbox_regs *)BCM2835_MBOX_PHYSADDR;
+ ulong endtime = get_timer(0) + TIMEOUT;
+ u32 val;
+
+ if (send & BCM2835_CHAN_MASK)
+ return -1;
+
+ /* Drain any stale responses */
+
+ for (;;) {
+ val = readl(®s->status);
+ if (val & BCM2835_MBOX_STATUS_RD_EMPTY)
+ break;
+ if (get_timer(0) >= endtime)
+ return -1;
+ val = readl(®s->read);
+ }
+
+ /* Send the request */
+
+ /* FIXME: timeout */
+ for (;;) {
+ val = readl(®s->status);
+ if (!(val & BCM2835_MBOX_STATUS_WR_FULL))
+ break;
+ if (get_timer(0) >= endtime)
+ return -1;
+ }
+
+ writel(BCM2835_MBOX_PACK(chan, send), ®s->write);
+
+ /* Wait for the response */
+
+ /* FIXME: timeout */
+ for (;;) {
+ val = readl(®s->status);
+ if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY))
+ break;
+ if (get_timer(0) >= endtime)
+ return -1;
+ }
+
+ val = readl(®s->read);
+
+ /* Validate the response */
+
+ if (BCM2835_MBOX_UNPACK_CHAN(val) != chan)
+ return -1;
+
+ *recv = BCM2835_MBOX_UNPACK_DATA(val);
+
+ return 0;
+}
+
+int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_prop_hdr *buffer)
+{
+ int ret;
+ u32 rbuffer;
+
+ ret = bcm2835_mbox_call_raw(chan, (u32)buffer, &rbuffer);
+ if (ret)
+ return ret;
+ if (rbuffer != (u32)buffer)
+ return -1;
+
+ return 0;
+}
diff --git a/arch/arm/include/asm/arch-bcm2835/mbox.h b/arch/arm/include/asm/arch-bcm2835/mbox.h
new file mode 100644
index 0000000..907fabd
--- /dev/null
+++ b/arch/arm/include/asm/arch-bcm2835/mbox.h
@@ -0,0 +1,87 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _BCM2835_MBOX_H
+#define _BCM2835_MBOX_H
+
+#include <linux/compiler.h>
+
+/* Raw mailbox HW */
+
+#define BCM2835_MBOX_PHYSADDR 0x2000b880
+
+struct bcm2835_mbox_regs {
+ u32 read;
+ u32 rsvd0[5];
+ u32 status;
+ u32 config;
+ u32 write;
+};
+
+#define BCM2835_MBOX_STATUS_WR_FULL 0x80000000
+#define BCM2835_MBOX_STATUS_RD_EMPTY 0x40000000
+
+#define BCM2835_CHAN_MASK 0xf
+
+#define BCM2835_MBOX_PACK(chan, data) (((data) & (~BCM2835_CHAN_MASK)) | \
+ (chan & BCM2835_CHAN_MASK))
+#define BCM2835_MBOX_UNPACK_CHAN(val) ((val) & BCM2835_CHAN_MASK)
+#define BCM2835_MBOX_UNPACK_DATA(val) ((val) & (~BCM2835_CHAN_MASK))
+
+/* Property mailbox buffer structures */
+
+#define BCM2835_MBOX_PROP_CHAN 8
+
+struct bcm2835_mbox_prop_hdr {
+ u32 buf_size;
+ u32 code;
+} __packed;
+
+#define BCM2835_MBOX_REQ_CODE 0
+#define BCM2835_MBOX_RESP_CODE_SUCCESS 0x80000000
+
+struct bcm2835_mbox_tag_hdr {
+ u32 tag;
+ u32 val_buf_size;
+ u32 val_len;
+} __packed;
+
+#define BCM2835_MBOX_TAG_VAL_LEN_RESPONSE 0x80000000
+
+#define BCM2835_MBOX_TAG_GET_ARM_MEMORY 0x00010005
+
+struct bcm2835_mbox_req_get_arm_mem {
+} __packed;
+
+struct bcm2835_mbox_resp_get_arm_mem {
+ u32 mem_base;
+ u32 mem_size;
+} __packed;
+
+struct bcm2835_mbox_buf_get_arm_mem {
+ struct bcm2835_mbox_prop_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct bcm2835_mbox_req_get_arm_mem req;
+ struct bcm2835_mbox_resp_get_arm_mem resp;
+ } body;
+ u32 end_tag;
+} __packed;
+
+int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv);
+int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_prop_hdr *buffer);
+
+#endif
--
1.7.9.5
More information about the linux-rpi-kernel
mailing list