mirror of
https://github.com/apache/nuttx.git
synced 2026-10-03 20:27:53 +00:00
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:
parent
040e661200
commit
706d389b37
9 changed files with 911 additions and 5 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
550
arch/arm64/src/bcm2711/bcm2711_mailbox.c
Normal file
550
arch/arm64/src/bcm2711/bcm2711_mailbox.c
Normal 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;
|
||||
}
|
||||
283
arch/arm64/src/bcm2711/bcm2711_mailbox.h
Normal file
283
arch/arm64/src/bcm2711/bcm2711_mailbox.h
Normal 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 */
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue