Add BCM2708 mailbox definitions and implementation.

The mailbox is used to communicate with the VideoCore on the rPi for
various tasks. First it will be used to configure the framebuffer.
This commit is contained in:
Michael Lotz 2012-11-27 20:24:20 +01:00
parent 5db97b2668
commit 4818400fcf
4 changed files with 114 additions and 0 deletions

View File

@ -40,6 +40,18 @@
#define BCM2708_SDRAM_BASE 0x00000000
#define BCM2708_PERIPHERAL_BASE 0x20000000
// Added to physical addresses to select the different cache behaviours
#define BCM2708_VIDEO_CORE_L1_L2_CACHED (0 << 30)
#define BCM2708_VIDEO_CORE_L2_COHERENT (1 << 30)
#define BCM2708_VIDEO_CORE_L2_CACHED (2 << 30)
#define BCM2708_VIDEO_CORE_UNCACHED (3 << 30)
// The highest two bits are used to select aliases to the physical memory
// with different cache semantic. Clearing them converts the address to
// physical memory as seen by ARM.
#define BCM2708_BUS_TO_PHYSICAL(x) (x & ~BCM2708_VIDEO_CORE_UNCACHED)
#define ST_BASE 0x3000
// System Timer, sec 12.0, page 172
#define DMA_BASE 0x7000
@ -122,4 +134,19 @@
#define UART_SYSC 20
/* Mailbox */
#define ARM_CTRL_0_MAILBOX_BASE (ARM_CTRL_0_SBM_BASE + 0x80)
#define ARM_MAILBOX_READ 0x00
#define ARM_MAILBOX_STATUS 0x18
#define ARM_MAILBOX_WRITE 0x20
#define ARM_MAILBOX_FULL (1 << 31)
#define ARM_MAILBOX_EMPTY (1 << 30)
#define ARM_MAILBOX_DATA_MASK 0xfffffff0
#define ARM_MAILBOX_CHANNEL_MASK 0x0000000f
#define ARM_MAILBOX_CHANNEL_FRAMEBUFFER 1
#endif /* __PLATFORM_BCM2708_H */

View File

@ -29,6 +29,7 @@ BootMergeObject boot_platform_raspberrypi_arm.o :
devices.cpp
gpio.cpp
keyboard.cpp
mailbox.cpp
menu.cpp
serial.cpp
video.cpp

View File

@ -0,0 +1,74 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz, mmlr@mlotz.ch
*/
#include <arch_cpu.h>
#include "bcm2708.h"
extern addr_t gPeripheralBase;
static inline addr_t
convert_mailbox_reg(addr_t reg)
{
return gPeripheralBase + ARM_CTRL_0_MAILBOX_BASE + reg;
}
static inline void
write_mailbox_reg(addr_t reg, uint32 value)
{
arch_cpu_memory_write_barrier();
*(volatile uint32*)convert_mailbox_reg(reg) = value;
}
static inline uint32
read_mailbox_reg(addr_t reg)
{
uint32 result = *(volatile uint32*)convert_mailbox_reg(reg);
arch_cpu_memory_read_barrier();
return result;
}
status_t
write_mailbox(uint8 channel, uint32 value)
{
// We have to wait for the mailbox to drain if it is marked full.
while ((read_mailbox_reg(ARM_MAILBOX_STATUS) & ARM_MAILBOX_FULL) != 0)
;
value &= ARM_MAILBOX_DATA_MASK;
write_mailbox_reg(ARM_MAILBOX_WRITE, value | channel);
return B_OK;
}
status_t
read_mailbox(uint8 channel, uint32& value)
{
while (true) {
// Wait for something to arrive in the mailbox.
if ((read_mailbox_reg(ARM_MAILBOX_STATUS) & ARM_MAILBOX_EMPTY) != 0)
continue;
value = read_mailbox_reg(ARM_MAILBOX_READ);
if ((value & ARM_MAILBOX_CHANNEL_MASK) != channel) {
// Not for us, retry.
continue;
}
break;
}
value &= ARM_MAILBOX_DATA_MASK;
return B_OK;
}

View File

@ -0,0 +1,12 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _PLATFORM_MAILBOX_H_
#define _PLATFORM_MAILBOX_H_
status_t write_mailbox(uint8 channel, uint32 value);
status_t read_mailbox(uint8 channel, uint32& value);
#endif // _PLATFORM_MAILBOX_H_