diff --git a/arch/arm64/src/bcm2711/CMakeLists.txt b/arch/arm64/src/bcm2711/CMakeLists.txt index d83a3aeb438..f7aa73aa394 100644 --- a/arch/arm64/src/bcm2711/CMakeLists.txt +++ b/arch/arm64/src/bcm2711/CMakeLists.txt @@ -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 diff --git a/arch/arm64/src/bcm2711/Make.defs b/arch/arm64/src/bcm2711/Make.defs index fbb70dc0eb8..d2a19e062e2 100644 --- a/arch/arm64/src/bcm2711/Make.defs +++ b/arch/arm64/src/bcm2711/Make.defs @@ -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 diff --git a/arch/arm64/src/bcm2711/bcm2711_mailbox.c b/arch/arm64/src/bcm2711/bcm2711_mailbox.c new file mode 100644 index 00000000000..b07a207d621 --- /dev/null +++ b/arch/arm64/src/bcm2711/bcm2711_mailbox.c @@ -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 +#include + +#include +#include +#include + +#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; +} diff --git a/arch/arm64/src/bcm2711/bcm2711_mailbox.h b/arch/arm64/src/bcm2711/bcm2711_mailbox.h new file mode 100644 index 00000000000..1c2baf5edd1 --- /dev/null +++ b/arch/arm64/src/bcm2711/bcm2711_mailbox.h @@ -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 + +#include +#include +#include + +#include + +#include + +#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 */ diff --git a/arch/arm64/src/bcm2711/hardware/bcm2711_mailbox.h b/arch/arm64/src/bcm2711/hardware/bcm2711_mailbox.h index b7a13720d20..f7fe0879c9d 100644 --- a/arch/arm64/src/bcm2711/hardware/bcm2711_mailbox.h +++ b/arch/arm64/src/bcm2711/hardware/bcm2711_mailbox.h @@ -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 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 */ diff --git a/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h b/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h index d1b48e26650..e2d9889cab9 100644 --- a/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h +++ b/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h @@ -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 */ diff --git a/boards/arm64/bcm2711/raspberrypi-4b/include/board.h b/boards/arm64/bcm2711/raspberrypi-4b/include/board.h index b9ffe16a39e..b520969d561 100644 --- a/boards/arm64/bcm2711/raspberrypi-4b/include/board.h +++ b/boards/arm64/bcm2711/raspberrypi-4b/include/board.h @@ -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 diff --git a/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_boardinitialize.c b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_boardinitialize.c index ddc82e4883f..87600c8af88 100644 --- a/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_boardinitialize.c +++ b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_boardinitialize.c @@ -24,11 +24,14 @@ * Included Files ****************************************************************************/ -#include "rpi4b.h" -#include #include + #include +#include + +#include "rpi4b.h" + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_bringup.c b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_bringup.c index 536c20077fc..a5a9330d34f 100644 --- a/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_bringup.c +++ b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_bringup.c @@ -26,6 +26,8 @@ #include #include +#include + #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" /****************************************************************************