bcm2711/mailbox: Implementation for mailbox API

A basic implementation of mailbox API with some helpers for accessing
properties implemented. Uses busy-wait due to documentation challenges
with mailbox API.

Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
This commit is contained in:
Matteo Golin 2025-09-23 00:23:19 -04:00 • committed by Xiang Xiao
parent 040e661200
commit 706d389b37
9 changed files with 911 additions and 5 deletions

View file

@ -20,7 +20,8 @@
# BCM2711 specific C source files
set(SRCS bcm2711_boot.c bcm2711_serial.c bcm2711_gpio.c bcm2711_timer.c)
set(SRCS bcm2711_boot.c bcm2711_mailbox.c bcm2711_serial.c bcm2711_gpio.c
bcm2711_timer.c)
# Early boot logging

View file

@ -23,6 +23,7 @@ include common/Make.defs
# BCM2711 specific C source files
CHIP_CSRCS += bcm2711_boot.c
CHIP_CSRCS += bcm2711_mailbox.c
CHIP_CSRCS += bcm2711_serial.c
CHIP_CSRCS += bcm2711_gpio.c
CHIP_CSRCS += bcm2711_timer.c

View file

@ -0,0 +1,550 @@
/****************************************************************************
* arch/arm64/src/bcm2711/bcm2711_mailbox.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/* NOTE: this module is written with the expectation that all requests are
* coming from the ARM core, since that is where NuttX runs. As such, mailbox
* 0 is used only to read responses from the VC, while mailbox 1 is used
* only to write requests from the ARM core to the VC.
*
* TODO: The VideoCore mailbox API is capable of asynchronous
* request/response. It is not guaranteed that requests will be responded to
* in the same order they were went. In order to save myself the headache of
* working around this, I've implemented each request/response interaction as
* a single atomic transaction. All other callers must wait for the lock in
* order to get their turn. This is not the most efficient, but it allows me
* to move on to other features and the slow-down should be very negligible,
* at least for the current use-case of getting property tags.
*/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/cache.h>
#include <nuttx/config.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include "arm64_arch.h"
#include "arm64_gic.h"
#include "arm64_internal.h"
#include "bcm2711_mailbox.h"
#include "chip.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Aliases for mailboxes so it is difficult to accidentally violate r/w
* constraints.
*/
#define READ_MBOX BCM_VC_MBOX0
#define WRITE_MBOX BCM_VC_MBOX1
/* Power status get tag uses bit 1 to indicate if the device ID exists */
#define MBOX_DEVICE_DNE (1 << 1)
/* Read and write timeouts in seconds */
#define R_TIMEOUT (5)
#define W_TIMEOUT (3)
/* Constants to keep track of field count for determining buffer sizes */
#define TAG_FIELDS (3) /* See bcm2711_mbox_tag_s fields */
#define BUF_FIELDS (3) /* Size, request flags, taglist terminator */
/* Helper for special buffer alignment */
#define ALIGNED_MBOX __attribute__((aligned(16)))
/* Helpers */
#define mbox_full(box) \
(getreg32(BCM_VC_MBOX_STATUS((box))) & BCM_VC_MBOX_STATUS_FULL)
#define mbox_empty(box) \
(getreg32(BCM_VC_MBOX_STATUS((box))) & BCM_VC_MBOX_STATUS_EMPTY)
/****************************************************************************
* Private Types
****************************************************************************/
/* Represents the format of a mailbox tag */
struct bcm2711_mbox_tag_s
{
uint32_t tagid; /* Tag identifier */
uint32_t vbufsiz; /* Value buffer size in bytes */
uint32_t code; /* Request/response code */
/* NOTE: Following this structure there should be the value buffer of size
* `vbufsiz`
*/
};
/* Contains necessary state for operating interrupt-driven API */
struct bcm2711_mbox_s
{
mutex_t lock; /* Lock for atomic request/response interactions */
};
/****************************************************************************
* Private Data
****************************************************************************/
static struct bcm2711_mbox_s g_mbox =
{
.lock = NXMUTEX_INITIALIZER,
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int bcm2711_mbox_rword(uint8_t channel, uint32_t *result);
static int bcm2711_mbox_wword(uint8_t channel, uint32_t data);
static void bcm2711_mbox_makereq(uint32_t tag, FAR void *buf, uint32_t nval,
uint32_t nbuf);
static int bcm2711_mbox_sendreq(FAR uint32_t *buf, uint8_t n);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bcm2711_mbox_rword
*
* Description:
* Read a single word from the mailbox that matches `channel`
* WARNING: Data read not from the expected channel is discarded. For now
* this is okay, since the implementation _only_ considers reading the
* property tags.
*
* Input parameters:
* channel - The mailbox channel data should come from
* result - Where to store the value returned from the mailbox
*
* Returned Value:
* 0 on success, -ETIMEDOUT if it takes over 3 seconds to see space in the
* mailbox
****************************************************************************/
static int bcm2711_mbox_rword(uint8_t channel, uint32_t *result)
{
uint32_t data;
int usecs_waited = 0;
for (; ; )
{
/* Wait for mailbox to have data */
while (mbox_empty(READ_MBOX))
{
up_udelay(10);
usecs_waited += 10;
if (usecs_waited >= R_TIMEOUT * 1000000)
{
ipcerr("Read timed out.");
return -ETIMEDOUT;
}
}
data = getreg32(BCM_VC_MBOX_RW(READ_MBOX));
/* Channel matches, return word! */
if ((data & BCM_VC_MBOX_RW_CHAN_MASK) == channel)
{
*result = data & ~BCM_VC_MBOX_RW_CHAN_MASK;
return 0;
}
/* No channel match, so we continue until it does. */
}
}
/****************************************************************************
* Name: bcm2711_mbox_wword
*
* Description:
* Write a single word to the mailbox channel `channel`
*
* Input parameters:
* channel - The mailbox channel data will be written to
* data - The data to write to the mailbox
*
* Returned Value:
* 0 on success, -ETIMEDOUT if it takes over 3 seconds to see space in the
* mailbox
****************************************************************************/
static int bcm2711_mbox_wword(uint8_t channel, uint32_t data)
{
int usecs_waited = 0;
/* Wait for space when the mailbox is full */
while (mbox_full(WRITE_MBOX))
{
up_udelay(10);
usecs_waited += 10;
if (usecs_waited >= W_TIMEOUT * 1000000)
{
ipcerr("Read timed out.");
return -ETIMEDOUT;
}
}
/* Mask excess channel bits */
channel &= BCM_VC_MBOX_RW_CHAN_MASK;
/* Write the data */
putreg32((data & (~0xf)) | channel, BCM_VC_MBOX_RW(WRITE_MBOX));
return 0;
}
/****************************************************************************
* Name: bcm2711_mbox_sendreq
*
* Description:
* Send a request to the VideoCore through the mailbox. This is atomic
* (other requests must wait for this one to complete).
* WARNING: The `buf` parameter must be 16-byte aligned and not NULL.
*
* Input parameters:
* buf - A buffer containing enough space for the tag (12 bytes), buffer
* size indicator (4 bytes), buffer request code (4 bytes), end tag
* (4 bytes) and the maximum size of the response length or the tag
* value length (tag dependent).
*
* Returned Value:
* 0 on success, -EIO on failure. Results are inside the buffer.
****************************************************************************/
static int bcm2711_mbox_sendreq(FAR uint32_t *buf, uint8_t n)
{
int res;
uint32_t retbuf;
uint32_t bufptr = (uint32_t)(uintptr_t)(buf);
/* Write the buffer to the VideoCore */
up_flush_dcache(bufptr, bufptr + n);
nxmutex_lock(&g_mbox.lock);
res = bcm2711_mbox_wword(MBOX_CHAN_TAGS, bufptr);
if (res < 0)
{
nxmutex_unlock(&g_mbox.lock);
return res;
}
/* Get the response from the VideoCore.
*
* Before we check the buffer contents, we must invalidate the data cache
* on this buffer's contents or we'll just read back what we sent without
* modification. This is done before the 'write' to provide time for the
* cache to flush.
*/
res = bcm2711_mbox_rword(MBOX_CHAN_TAGS, &retbuf);
nxmutex_unlock(&g_mbox.lock);
if (res < 0)
{
return res;
}
/* The mailbox _MUST_ return the the same buffer address, it is
* not possible for it to do otherwise (according to raspberrypi/firmware
* docs).
*/
if (retbuf != bufptr)
{
ipcerr("Expected %08x, got %08x", bufptr, res);
return -EIO; /* Wrong buffer responded */
}
/* Make sure we have a response */
if (buf[1] == BCM_VC_MBOX_RESP_OK)
{
return 0; /* Successful response */
}
else if (buf[1] == BCM_VC_MBOX_RESP_ERR)
{
/* Had a response error that was reported, partial response */
ipcerr("Unsuccessful response: %08x", buf[1]);
return -EIO;
}
/* Unknown response code, typically due to unknown tag */
ipcerr("Unknown response code: %08x", buf[1]);
return -EINVAL;
}
/****************************************************************************
* Name: bcm2711_mbox_makereq
*
* Description:
* Construct a buffer to send to the video core.
* WARNING: The `buf` parameter must be 16-byte aligned.
*
* Input parameters:
* tag - The tag identifier (MBOX_TAG_*) for the request
* buf - A buffer containing enough space for the tag (12 bytes), buffer
* size indicator (4 bytes), buffer request code (4 bytes), end tag
* (4 bytes) and the maximum size of the response length or the tag
* value length (tag dependent).
* nval - The max size of either the value sent or the value expected in
* response
* nbuf - The total size of the buffer
*
****************************************************************************/
static void bcm2711_mbox_makereq(uint32_t tag, FAR void *buf, uint32_t nval,
uint32_t nbuf)
{
void *bufpos = buf;
struct bcm2711_mbox_tag_s mtag = {
.tagid = tag,
.vbufsiz = nval, /* The value size already in the buffer */
.code = BCM_VC_MBOX_REQUEST,
};
/* Buffer must be large enough to store the buffer size (u32), req/resp
* code (u32), a series of tags (in this case one), the tag's value size,
* and the tag terminator (u32).
*/
DEBUGASSERT(nbuf >= sizeof(mtag) + nval + 3 * sizeof(uint32_t));
/* Move the value in the buffer back so it starts right after where the
* buffer fields (2 u32s) and tag will go.
*/
if (nval != 0)
{
memcpy(buf + sizeof(mtag) + 2 * sizeof(uint32_t), buf, nval);
}
/* Populate buffer fields */
((uint32_t *)(bufpos))[0] = nbuf; /* The total buf size */
((uint32_t *)(bufpos))[1] = BCM_VC_MBOX_REQUEST; /* The req/resp flag */
bufpos += 2 * sizeof(uint32_t); /* Move past buf fields */
/* The tag is inserted next, following the first two fields */
memcpy(bufpos, &mtag, sizeof(mtag));
bufpos += sizeof(mtag); /* Move past tag */
/* After the tag is `nval` bytes worth of the tag value being passed.
* Once we skip over those bytes, we can finally add the tag list
* terminator.
*/
bufpos += nval; /* Skips tag value */
*((uint32_t *)(bufpos)) = BCM_VC_MBOX_TAGLIST_END;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bcm2711_mbox_getcputemp
*
* Description:
* Gets the temperature of the SoC in millidegrees Celsius.
*
* Input parameters:
* temp - A pointer to where to store the temperature
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getcputemp(uint32_t *temp)
{
int err;
uint32_t buf[BUF_FIELDS + TAG_FIELDS + 2] ALIGNED_MBOX;
DEBUGASSERT(temp != NULL);
buf[0] = 0; /* ID should always be 0 for temp */
bcm2711_mbox_makereq(MBOX_TAG_GETTEMP, buf, 2 * sizeof(uint32_t),
sizeof(buf));
err = bcm2711_mbox_sendreq(buf, sizeof(buf));
*temp = buf[6];
return err;
}
/****************************************************************************
* Name: bcm2711_mbox_getrev
*
* Description:
* Gets the board revision.
*
* Input parameters:
* rev - A pointer to where to store the revision number
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getrev(uint32_t *rev)
{
int err;
uint32_t buf[BUF_FIELDS + TAG_FIELDS + 1] ALIGNED_MBOX;
DEBUGASSERT(rev != NULL);
bcm2711_mbox_makereq(MBOX_TAG_BREV, buf, sizeof(uint32_t), sizeof(buf));
err = bcm2711_mbox_sendreq(buf, sizeof(buf));
*rev = buf[5];
return err;
}
/****************************************************************************
* Name: bcm2711_mbox_getmodel
*
* Description:
* Gets the board model number.
*
* Input parameters:
* model - A pointer to where to store the model number
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getmodel(uint32_t *model)
{
int err;
uint32_t buf[BUF_FIELDS + TAG_FIELDS + 1] ALIGNED_MBOX;
DEBUGASSERT(model != NULL);
bcm2711_mbox_makereq(MBOX_TAG_BMODEL, buf, sizeof(uint32_t), sizeof(buf));
err = bcm2711_mbox_sendreq(buf, sizeof(buf));
*model = buf[5];
return err;
}
/****************************************************************************
* Name: bcm2711_mbox_getmac
*
* Description:
* Gets the board MAC address in network byte order
*
* Input parameters:
* mac - A pointer to where to store the MAC address
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getmac(uint64_t *mac)
{
int err;
uint32_t buf[BUF_FIELDS + TAG_FIELDS + 2] ALIGNED_MBOX;
DEBUGASSERT(mac != NULL);
bcm2711_mbox_makereq(MBOX_TAG_MAC, buf, 2 * sizeof(uint32_t), sizeof(buf));
err = bcm2711_mbox_sendreq(buf, sizeof(buf));
*mac = *((uint64_t *)(buf + 5));
return err;
}
/****************************************************************************
* Name: bcm2711_mbox_getpwr
*
* Description:
* Gets the power state of `id`.
*
* Input parameters:
* id - The device ID to know the power state of
* state - A pointer to where to store the state
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getpwr(uint8_t id, bool *state)
{
int err;
uint32_t buf[BUF_FIELDS + TAG_FIELDS + 2] ALIGNED_MBOX;
buf[0] = id; /* First argument is the device ID */
DEBUGASSERT(state != NULL);
bcm2711_mbox_makereq(MBOX_TAG_GETPWR, buf, 2 * sizeof(uint32_t),
sizeof(buf));
err = bcm2711_mbox_sendreq(buf, sizeof(buf));
/* Check if mailbox recognized device */
if (buf[6] & MBOX_DEVICE_DNE)
{
return -EINVAL;
}
*state = buf[6] & 0x1;
return err;
}
/****************************************************************************
* Name: bcm2711_mbox_ledset
*
* Description:
* Sets the state of the LED specified by `pin`
*
* Input parameters:
* pin - The pin number of the LED to modify the state of
* on - True to turn on the LED, false to turn it off
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_ledset(uint8_t pin, bool on)
{
int err;
uint32_t buf[BUF_FIELDS + TAG_FIELDS + 2] ALIGNED_MBOX;
buf[0] = pin;
buf[1] = on;
bcm2711_mbox_makereq(MBOX_TAG_SETLED, buf, 2 * sizeof(uint32_t),
sizeof(buf));
err = bcm2711_mbox_sendreq(buf, sizeof(buf));
return err;
}

View file

@ -0,0 +1,283 @@
/****************************************************************************
* arch/arm64/src/bcm2711/bcm2711_mailbox.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_ARM64_SRC_BCM2711_BCM2711_MAILBOX_H
#define __ARCH_ARM64_SRC_BCM2711_BCM2711_MAILBOX_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include <nuttx/compiler.h>
#include <arch/chip/chip.h>
#include "arm64_arch.h"
#include "arm64_internal.h"
#include "hardware/bcm2711_mailbox.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* List of mailbox channels */
#define MBOX_CHAN_POWER (0x0) /* Power management interface */
#define MBOX_CHAN_FRAMEBUF (0x1) /* Frame buffer */
#define MBOX_CHAN_VUART (0x2) /* Virtual UART */
#define MBOX_CHAN_VCHIQ (0x3) /* VCHIQ interface */
#define MBOX_CHAN_LED (0x4) /* LED interface */
#define MBOX_CHAN_BUTTON (0x5) /* Button interface */
#define MBOX_CHAN_TOUCH (0x6) /* Touchscreen interface */
#define MBOX_CHAN_COUNT (0x7) /* Counter */
#define MBOX_CHAN_TAGS (0x8) /* Tags (ARM to VC) */
#define MBOX_CHAN_TAGSVC (0x9) /* Tags (VC to ARM) */
/* List of tags for mailbox communication */
#define MBOX_TAG_FWREV (0x1) /* Get firmware revision */
#define MBOX_TAG_BMODEL (0x10001) /* Get board model */
#define MBOX_TAG_BREV (0x10002) /* Get board revision */
#define MBOX_TAG_MAC (0x10003) /* Get board MAC address */
#define MBOX_TAG_SER (0x10004) /* Get board serial number */
#define MBOX_TAG_ARMMEM (0x10005) /* Get ARM memory */
#define MBOX_TAG_VCMEM (0x10006) /* Get VideoCore memory */
#define MBOX_TAG_CLOCKS (0x10007) /* Get clocks */
#define MBOX_TAG_CMDLINE (0x50001) /* Get command line string */
#define MBOX_TAG_DMACHAN (0x60001) /* Get DMA channels */
#define MBOX_TAG_DMACHAN (0x60001) /* Get DMA channels */
#define MBOX_TAG_GETPWR (0x20001) /* Get power state */
#define MBOX_TAG_GETTIME (0x20002) /* Get power-on wait time */
#define MBOX_TAG_SETPWR (0x28001) /* Set power state */
#define MBOX_TAG_GETCLKS (0x30001) /* Get clock state */
#define MBOX_TAG_SETCLKS (0x38001) /* Set clock state */
#define MBOX_TAG_GETCLKR (0x30002) /* Get clock rate */
#define MBOX_TAG_GETLED (0x30041) /* Get on-board LED status */
#define MBOX_TAG_TESTLED (0x34041) /* Test on-board LED status */
#define MBOX_TAG_SETLED (0x38041) /* Set on-board LED status */
#define MBOX_TAG_GETCLKRM (0x30047) /* Get measured clock rate */
#define MBOX_TAG_SETCLKR (0x38002) /* Set clock rate */
#define MBOX_TAG_GETMAXCLKR (0x30004) /* Get max clock rate */
#define MBOX_TAG_GETMINCLKR (0x30007) /* Get min clock rate */
#define MBOX_TAG_GETTURBO (0x30009) /* Get turbo state */
#define MBOX_TAG_SETTURBO (0x38009) /* Set turbo state */
#define MBOX_TAG_GETVOLT (0x30003) /* Get voltage */
#define MBOX_TAG_SETVOLT (0x38003) /* Set voltage */
#define MBOX_TAG_GETMAXVOLT (0x30005) /* Get max voltage */
#define MBOX_TAG_GETMINVOLT (0x30008) /* Get min voltage */
#define MBOX_TAG_GETTEMP (0x30006) /* Get temperature */
#define MBOX_TAG_GETMAXTEMP (0x3000a) /* Get max temperature */
#define MBOX_TAG_ALLOCMEM (0x3000c) /* Allocate memory */
#define MBOX_TAG_LOCKMEM (0x3000d) /* Lock memory */
#define MBOX_TAG_UNLOCKMEM (0x3000e) /* Lock memory */
#define MBOX_TAG_RELMEM (0x3000f) /* Release memory */
#define MBOX_TAG_EXEC (0x30010) /* Execute code */
#define MBOX_TAG_DISPMANX (0x30014) /* Get Dispmanx mem handle */
#define MBOX_TAG_EDID (0x30020) /* Get EDID block */
#define MBOX_TAG_FALLOC (0x40001) /* Allocate frame buffer */
#define MBOX_TAG_FREL (0x48001) /* Release frame buffer */
#define MBOX_TAG_BLANK (0x40002) /* Blank screen */
#define MBOX_TAG_GETDISP (0x40003) /* Get physical display w/h */
#define MBOX_TAG_TESTDISP (0x44003) /* Test physical display w/h */
#define MBOX_TAG_SETDISP (0x48003) /* Set physical display w/h */
#define MBOX_TAG_GETVBUF (0x40004) /* Get virtual buffer w/h */
#define MBOX_TAG_TESTVBUF (0x44004) /* Test virtual buffer w/h */
#define MBOX_TAG_SETVBUF (0x48004) /* Set virtual buffer w/h */
#define MBOX_TAG_GETDEPTH (0x40005) /* Get depth */
#define MBOX_TAG_TESTDEPTH (0x44005) /* Test depth */
#define MBOX_TAG_SETDEPTH (0x48005) /* Set depth */
#define MBOX_TAG_GETPIXORD (0x40006) /* Get pixel order */
#define MBOX_TAG_TESTPIXORD (0x44006) /* Test pixel order */
#define MBOX_TAG_SETPIXORD (0x48006) /* Set pixel order */
#define MBOX_TAG_GETALPHA (0x40007) /* Get alpha */
#define MBOX_TAG_TESTALPHA (0x44007) /* Test alpha */
#define MBOX_TAG_SETALPHA (0x48007) /* Set alpha */
#define MBOX_TAG_GETPITCH (0x40008) /* Get pitch */
#define MBOX_TAG_GETVIRTOFF (0x40009) /* Get virtual offset */
#define MBOX_TAG_TESTVIRTOFF (0x44009) /* Test virtual offset */
#define MBOX_TAG_SETVIRTOFF (0x48009) /* Set virtual offset */
#define MBOX_TAG_GETOVSCAN (0x4000a) /* Get overscan */
#define MBOX_TAG_TESTOVSCAN (0x4400a) /* Test overscan */
#define MBOX_TAG_SETOVSCAN (0x4800a) /* Set overscan */
#define MBOX_TAG_GETPALETTE (0x4000b) /* Get palette */
#define MBOX_TAG_TESTPALETTE (0x4400b) /* Test palette */
#define MBOX_TAG_SETPALETTE (0x4800b) /* Set palette */
#define MBOX_TAG_CURSINFO (0x08010) /* Set cursor info */
#define MBOX_TAG_CURSSTATE (0x08011) /* Set cursor state */
/* Power domain IDs */
#define MBOX_PDOM_SDCARD (0x0)
#define MBOX_PDOM_UART0 (0x1)
#define MBOX_PDOM_UART1 (0x2)
#define MBOX_PDOM_USBHCD (0x3)
#define MBOX_PDOM_I2C0 (0x4)
#define MBOX_PDOM_I2C1 (0x5)
#define MBOX_PDOM_I2C2 (0x6)
#define MBOX_PDOM_SPI (0x7)
#define MBOX_PDOM_CCP2TX (0x8)
#define MBOX_PDOM_UNK1 (0x9) /* Unknown, RPi4B */
#define MBOX_PDOM_UNK2 (0xa) /* Unknown, RPi4B */
/* Clock IDs */
#define MBOX_CLK_EMMC (0x1)
#define MBOX_CLK_UART (0x2)
#define MBOX_CLK_ARM (0x3)
#define MBOX_CLK_CORE (0x4)
#define MBOX_CLK_V3D (0x5)
#define MBOX_CLK_H264 (0x6)
#define MBOX_CLK_ISP (0x7)
#define MBOX_CLK_SDRAM (0x8)
#define MBOX_CLK_PIXEL (0x9)
#define MBOX_CLK_PWM (0xa)
#define MBOX_CLK_HEVC (0xb)
#define MBOX_CLK_EMMC2 (0xc)
#define MBOX_CLK_M2MC (0xd)
#define MBOX_CLK_PIXELBVB (0xe)
/* Voltage IDs */
#define MBOX_VOLT_CORE (0x1)
#define MBOX_VOLT_SDRAMC (0x2)
#define MBOX_VOLT_SDRAMP (0x3)
#define MBOX_VOLT_SDRAMI (0x4)
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Name: bcm2711_mbox_getcputemp
*
* Description:
* Gets the temperature of the SoC.
*
* Input parameters:
* temp - A pointer to where to store the temperature
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getcputemp(uint32_t *temp);
/****************************************************************************
* Name: bcm2711_mbox_getrev
*
* Description:
* Gets the board revision.
*
* Input parameters:
* rev - A pointer to where to store the revision number
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getrev(uint32_t *rev);
/****************************************************************************
* Name: bcm2711_mbox_getmodel
*
* Description:
* Gets the board model number.
*
* Input parameters:
* model - A pointer to where to store the model number
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getmodel(uint32_t *model);
/****************************************************************************
* Name: bcm2711_mbox_getmac
*
* Description:
* Gets the board MAC address in network byte order
*
* Input parameters:
* mac - A pointer to where to store the MAC address
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getmac(uint64_t *mac);
/****************************************************************************
* Name: bcm2711_mbox_getpwr
*
* Description:
* Gets the power state of `id`.
*
* Input parameters:
* id - The device ID to know the power state of
* state - A pointer to where to store the state
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_getpwr(uint8_t id, bool *state);
/****************************************************************************
* Name: bcm2711_mbox_ledset
*
* Description:
* Sets the state of the LED specified by `pin`
*
* Input parameters:
* pin - The pin number of the LED to modify the state of
* on - True to turn on the LED, false to turn it off
*
* Returned Value:
* 0 on success, negated error code on failure.
****************************************************************************/
int bcm2711_mbox_ledset(uint8_t pin, bool on);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM64_SRC_BCM2711_BCM2711_MAILBOX_H */

View file

@ -33,7 +33,7 @@
* Pre-processor Definitions
****************************************************************************/
/* Mailbox register offsets */
/* ARM_LOCAL mailbox register offsets */
#define BCM_MBOX_SET00_OFFSET 0x80
#define BCM_MBOX_SET01_OFFSET 0x84
@ -68,7 +68,7 @@
#define BCM_MBOX_CLR14_OFFSET 0xf8
#define BCM_MBOX_CLR15_OFFSET 0xfc
/* Mailbox register addresses */
/* ARM_LOCAL mailbox register addresses */
#define _BCM_MBOX(offset) (BCM_ARMLOCAL_BASEADDR + (offset))
@ -105,4 +105,59 @@
#define BCM_MBOX_CLR14 _BCM_MBOX(BCM_MBOX_CLR14_OFFSET)
#define BCM_MBOX_CLR15 _BCM_MBOX(BCM_MBOX_CLR15_OFFSET)
/* VideoCore mailbox offsets */
#define BCM_VC_MBOX0 \
(BCM_VC_MBOX_BASEADDR + 0x00) /* Always for VC -> ARM, never write */
#define BCM_VC_MBOX1 \
(BCM_VC_MBOX_BASEADDR + 0x20) /* Always for ARM -> VC, never read */
/* VideoCore mailbox register offsets (from mailbox<n> base) */
#define BCM_VC_MBOX_RW_OFFSET (0x00) /* Read/write */
#define BCM_VC_MBOX_PEEK_OFFSET (0x10)
#define BCM_VC_MBOX_SENDER_OFFSET (0x14)
#define BCM_VC_MBOX_STATUS_OFFSET (0x18)
#define BCM_VC_MBOX_CONFIG_OFFSET (0x1c)
/* VideoCore mailbox registers */
#define BCM_VC_MBOX_RW(base) (BCM_VC_MBOX_RW_OFFSET + (base))
#define BCM_VC_MBOX_PEEK(base) (BCM_VC_MBOX_PEEK_OFFSET + (base))
#define BCM_VC_MBOX_SENDER(base) (BCM_VC_MBOX_SENDER_OFFSET + (base))
#define BCM_VC_MBOX_STATUS(base) (BCM_VC_MBOX_STATUS_OFFSET + (base))
#define BCM_VC_MBOX_CONFIG(base) (BCM_VC_MBOX_CONFIG_OFFSET + (base))
/* VideoCore mailbox flags */
#define BCM_VC_MBOX_STATUS_FULL (1 << 31)
#define BCM_VC_MBOX_STATUS_EMPTY (1 << 30)
#define BCM_VC_MBOX_CONFIG_ERR_EMPTY (1 << 10) /* Read from empty MBOX */
#define BCM_VC_MBOX_CONFIG_ERR_FULL (1 << 9) /* Write to full mbox */
#define BCM_VC_MBOX_CONFIG_ERR_OWN (1 << 8) /* Non-owner read attempt */
#define BCM_VC_MBOX_CONFIG_IRQEN_EMPTY (1 << 6) /* Enable opp empty IRQ */
#define BCM_VC_MBOX_CONFIG_IRQEN_NEWM (1 << 5) /* Enable new mail IRQ */
#define BCM_VC_MBOX_CONFIG_IRQEN_SPACE (1 << 4) /* Enable space avail IRQ */
#define BCM_VC_MBOX_CONFIG_CLEAR (1 << 3) /* Clear mailbox */
#define BCM_VC_MBOX_CONFIG_INT_EMPTY (1 << 2) /* IRQ pend opp empty */
#define BCM_VC_MBOX_CONFIG_INT_NEWM (1 << 1) /* IRQ pend new mail */
#define BCM_VC_MBOX_CONFIG_INT_SPACE (1 << 0) /* IRQ pend new mail */
/* NOTE: bitbanged.com article about these configuration register bits states
* there is currently no documentation for the 'opp empty' IRQ.
*/
#define BCM_VC_MBOX_RW_CHAN_MASK (0xf) /* Mask for channel ID */
#define BCM_VC_MBOX_RW_DATSHIFT (4) /* Shift amount for data */
#define BCM_VC_MBOX_REQUEST (0) /* Request code */
#define BCM_VC_MBOX_RESP_OK (0x80000000) /* Response: success */
#define BCM_VC_MBOX_RESP_ERR (0x80000001) /* Response: error */
#define BCM_VC_MBOX_TAGLIST_END (0) /* End of tag list in request */
/* VideoCore mailbox information */
#define BCM_VC_MBOX_FIFO_DEPTH (8) /* 8-deep FIFO of 32-bit words */
#endif /* __ARCH_ARM64_SRC_BCM2711_MAILBOX_H */

View file

@ -115,4 +115,8 @@
#define BCM_ARMLOCAL_BASEADDR 0x4c0000000
#endif /* defined(CONFIG_BCM2711_LOW_PERIPHERAL) */
/* VideoCore mailbox base address */
#define BCM_VC_MBOX_BASEADDR (BCM_PERIPHERAL_BASEADDR + 0xb880)
#endif /* __ARCH_ARM64_SRC_BCM2711_MM_H */

View file

@ -33,6 +33,11 @@
* Pre-processor Definitions
****************************************************************************/
/* Onboard LEDs */
#define STATUS_LED (42) /* Green LED */
#define POWER_LED (130) /* Red LED */
/* TODO: define all the GPIO pins properly */
#define BOARD_NGPIOOUT 1

View file

@ -24,11 +24,14 @@
* Included Files
****************************************************************************/
#include "rpi4b.h"
#include <nuttx/board.h>
#include <nuttx/config.h>
#include <stdint.h>
#include <nuttx/board.h>
#include "rpi4b.h"
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -26,6 +26,8 @@
#include <sys/types.h>
#include <syslog.h>
#include <arch/board/board.h>
#if defined(CONFIG_BCM2711_I2C_DRIVER)
#include "bcm2711_i2cdev.h"
#endif /* defined(CONFIG_BCM2711_I2C) */
@ -34,6 +36,8 @@
#include "bcm2711_i2c.h"
#endif
#include "bcm2711_mailbox.h"
#include "rpi4b.h"
/****************************************************************************