Re: [U-Boot] [PATCH 1/2] ARM: bcm2835: add mailbox driver

2012-10-18 Thread Albert ARIBAUD
Hi Stephen,

On Mon, 15 Oct 2012 23:10:35 -0600, Stephen Warren
swar...@wwwdotorg.org wrote:

 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 swar...@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 000..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(regs-status);
 + if (val  BCM2835_MBOX_STATUS_RD_EMPTY)
 + break;
 + if (get_timer(0) = endtime)
 + return -1;
 + val = readl(regs-read);
 + }
 +
 + /* Send the request */
 +
 + /* FIXME: timeout */

Develop this FIXME to indicate what exactly should be fixed.

 + for (;;) {
 + val = readl(regs-status);
 + if (!(val  BCM2835_MBOX_STATUS_WR_FULL))
 + break;
 + if (get_timer(0) = endtime)
 + return -1;
 + }
 +
 + writel(BCM2835_MBOX_PACK(chan, send), regs-write);
 +
 + /* Wait for the response */
 +
 + /* FIXME: timeout */

Ditto.

 + for (;;) {
 + val = readl(regs-status);
 + if (!(val  BCM2835_MBOX_STATUS_RD_EMPTY))
 + break;
 + if (get_timer(0) = endtime)
 + return -1;
 + }
 +
 + val = readl(regs-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 000..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
 + * 

Re: [U-Boot] [PATCH 1/2] ARM: bcm2835: add mailbox driver

2012-10-18 Thread Stephen Warren
On 10/18/2012 02:23 PM, Albert ARIBAUD wrote:
 Hi Stephen,
 
 On Mon, 15 Oct 2012 23:10:35 -0600, Stephen Warren
 swar...@wwwdotorg.org wrote:
 
 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.

 +++ b/arch/arm/cpu/arm1176/bcm2835/mbox.c

 +int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv)

 +/* FIXME: timeout */
 
 Develop this FIXME to indicate what exactly should be fixed.
 
 +for (;;) {
 +val = readl(regs-status);
 +if (!(val  BCM2835_MBOX_STATUS_WR_FULL))
 +break;
 +if (get_timer(0) = endtime)
 +return -1;
 +}

The FIXME is actually already implemented by the last if test in the
loop; I simply forgot to remove the comment when I implemented it:-(

I'll repost with those removed. I've also learned a few things about
better constructing the message buffers while implementing a more
complex mbox client, so I might re-organize some of the tag structures
below a little too...

 diff --git a/arch/arm/include/asm/arch-bcm2835/mbox.h 
 b/arch/arm/include/asm/arch-bcm2835/mbox.h

 +struct bcm2835_mbox_prop_hdr {
 +u32 buf_size;
 +u32 code;
 +} __packed;
 
 Remove __packed here, as all fields are 32 bits and thus no padding
 would happen anyway.

I'd prefer to keep it for consistency; see below.

 +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;
 
 Ditto.

Here, multiple structs are packed into another struct. Isn't the
alignment requirement for a struct larger than for a u32, such that
without __packed, gaps may be left between those component structs and
unions if __packed isn't specified? I certainly added __packed during
development in order to make the code work, although it's possible there
was actually some other bug and I could have gone back and reverted
adding __packed...

Assuming __packed is needed here, I'd prefer to specify it for all
message buffer structs for consistency; that way, if someone chooses the
wrong thing to cut/paste, they'll still pick up the required __packed
attribute.

 Also, what is the point of bcm2835_mbox_buf_get_arm_mem which is not
 referenced in the API below?

The idea is that you'll actually pass a struct
bcm2835_mbox_buf_get_arm_mem (or one of tens of other message-specific
struct types) to bcm2835_mbox_call_prop, rather than just a message
header. I could use void * in the prototype below, but chose struct
bcm2835_mbox_prop_hdr as it is at least a requirement that all message
buffers start with that header.

 +int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv);
 +int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_prop_hdr *buffer);
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [PATCH 1/2] ARM: bcm2835: add mailbox driver

2012-10-18 Thread Albert ARIBAUD
Hi Stephen,

On Thu, 18 Oct 2012 14:34:27 -0600, Stephen Warren
swar...@wwwdotorg.org wrote:

 On 10/18/2012 02:23 PM, Albert ARIBAUD wrote:
  Hi Stephen,
  
  On Mon, 15 Oct 2012 23:10:35 -0600, Stephen Warren
  swar...@wwwdotorg.org wrote:
  
  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.
 
  +++ b/arch/arm/cpu/arm1176/bcm2835/mbox.c
 
  +int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv)
 
  +  /* FIXME: timeout */
  
  Develop this FIXME to indicate what exactly should be fixed.
  
  +  for (;;) {
  +  val = readl(regs-status);
  +  if (!(val  BCM2835_MBOX_STATUS_WR_FULL))
  +  break;
  +  if (get_timer(0) = endtime)
  +  return -1;
  +  }
 
 The FIXME is actually already implemented by the last if test in the
 loop; I simply forgot to remove the comment when I implemented it:-(
 
 I'll repost with those removed. I've also learned a few things about
 better constructing the message buffers while implementing a more
 complex mbox client, so I might re-organize some of the tag structures
 below a little too...
 
  diff --git a/arch/arm/include/asm/arch-bcm2835/mbox.h 
  b/arch/arm/include/asm/arch-bcm2835/mbox.h
 
  +struct bcm2835_mbox_prop_hdr {
  +  u32 buf_size;
  +  u32 code;
  +} __packed;
  
  Remove __packed here, as all fields are 32 bits and thus no padding
  would happen anyway.
 
 I'd prefer to keep it for consistency; see below.
 
  +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;
  
  Ditto.
 
 Here, multiple structs are packed into another struct. Isn't the
 alignment requirement for a struct larger than for a u32, such that
 without __packed, gaps may be left between those component structs and
 unions if __packed isn't specified? I certainly added __packed during
 development in order to make the code work, although it's possible there
 was actually some other bug and I could have gone back and reverted
 adding __packed...
 
 Assuming __packed is needed here, I'd prefer to specify it for all
 message buffer structs for consistency; that way, if someone chooses the
 wrong thing to cut/paste, they'll still pick up the required __packed
 attribute.

Strictly speaking, the alignment of a struct is that of its first
member (recursively if that member is a struct). This is according to
the C99 TC3 (last publically available draft), section 67.2.1, 
paragraph 14. In practice, struct members are aligned within the
struct, so to maintain these alignments, the struct alignment must be
the greater of the alignments of its members. Thus here it can never go
beyond u32.

  Also, what is the point of bcm2835_mbox_buf_get_arm_mem which is not
  referenced in the API below?
 
 The idea is that you'll actually pass a struct
 bcm2835_mbox_buf_get_arm_mem (or one of tens of other message-specific
 struct types) to bcm2835_mbox_call_prop, rather than just a message
 header. I could use void * in the prototype below, but chose struct
 bcm2835_mbox_prop_hdr as it is at least a requirement that all message
 buffers start with that header.
 
  +int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv);
  +int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_prop_hdr 
  *buffer);

Understood. This, plus your anwser to 2/2, leads me to asking for a 3rd
option: that the mbox driver header file make it clear (through
comments) how this struct (and future others) is used.

Amicalement,
-- 
Albert.
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot