Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
f9d2808a
Unverified
Commit
f9d2808a
authored
Jul 16, 2018
by
Soby Mathew
Committed by
GitHub
Jul 16, 2018
Browse files
Merge pull request #1478 from antonio-nino-diaz-arm/an/rpi3-improvements
rpi3: A few improvements
parents
9ceda8b9
4f2f66a2
Changes
7
Hide whitespace changes
Inline
Side-by-side
docs/plat/rpi3.rst
View file @
f9d2808a
...
...
@@ -196,29 +196,19 @@ Then compile TF-A. For a AArch32 kernel, use the following command line:
CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
RPI3_BL33_IN_AARCH32=1 \
BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin \
all fip
BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin
For a AArch64 kernel, use this other command line:
.. code:: shell
CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin \
all fip
BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin
Then, join BL1 and the FIP with the following instructions (replace ``release``
by ``debug`` if you set the build option ``DEBUG=1``):
.. code:: shell
cp build/rpi3/release/bl1.bin bl1.pad.bin
truncate --size=131072 bl1.pad.bin
cat bl1.pad.bin build/rpi3/release/fip.bin > armstub8.bin
The resulting file, ``armstub8.bin``, contains BL1 and the FIP in the place they
need to be for TF-A to boot correctly. Now, follow the instructions in
`Setup SD card`_.
The build system concatenates BL1 and the FIP so that the addresses match the
ones in the memory map. The resulting file is ``armstub8.bin``, located in the
build folder (e.g. ``build/rpi3/debug/armstub8.bin``). Now, follow the
instructions in `Setup SD card`_.
The following build options are supported:
...
...
plat/rpi3/platform.mk
View file @
f9d2808a
...
...
@@ -20,7 +20,8 @@ BL1_SOURCES += drivers/io/io_fip.c \
plat/common/aarch64/platform_mp_stack.S
\
plat/rpi3/aarch64/plat_helpers.S
\
plat/rpi3/rpi3_bl1_setup.c
\
plat/rpi3/rpi3_io_storage.c
plat/rpi3/rpi3_io_storage.c
\
plat/rpi3/rpi3_mbox.c
BL2_SOURCES
+=
common/desc_image_load.c
\
drivers/io/io_fip.c
\
...
...
@@ -54,6 +55,26 @@ else
TF_CFLAGS_aarch64
+=
-mtune
=
cortex-a53
endif
# Platform Makefile target
# ------------------------
RPI3_BL1_PAD_BIN
:=
${BUILD_PLAT}
/bl1_pad.bin
RPI3_ARMSTUB8_BIN
:=
${BUILD_PLAT}
/armstub8.bin
# Add new default target when compiling this platform
all
:
armstub
# This target concatenates BL1 and the FIP so that the base addresses match the
# ones defined in the memory map
armstub
:
bl1 fip
@
echo
" CAT
$@
"
${Q}
cp
${BUILD_PLAT}
/bl1.bin
${RPI3_BL1_PAD_BIN}
${Q}
truncate
--size
=
131072
${RPI3_BL1_PAD_BIN}
${Q}
cat
${RPI3_BL1_PAD_BIN}
${BUILD_PLAT}
/fip.bin
>
${RPI3_ARMSTUB8_BIN}
@
${ECHO_BLANK_LINE}
@
echo
"Built
$@
successfully"
@
${ECHO_BLANK_LINE}
# Build config flags
# ------------------
...
...
plat/rpi3/rpi3_bl1_setup.c
View file @
f9d2808a
...
...
@@ -7,6 +7,7 @@
#include <arch.h>
#include <arch_helpers.h>
#include <bl_common.h>
#include <debug.h>
#include <platform_def.h>
#include <xlat_mmu_helpers.h>
#include <xlat_tables_defs.h>
...
...
@@ -56,6 +57,39 @@ void bl1_plat_arch_setup(void)
void
bl1_platform_setup
(
void
)
{
uint32_t
__unused
rev
;
int
__unused
rc
;
rc
=
rpi3_vc_hardware_get_board_revision
(
&
rev
);
if
(
rc
==
0
)
{
const
char
__unused
*
model
,
__unused
*
info
;
switch
(
rev
)
{
case
0xA02082
:
model
=
"Raspberry Pi 3 Model B"
;
info
=
"(1GB, Sony, UK)"
;
break
;
case
0xA22082
:
model
=
"Raspberry Pi 3 Model B"
;
info
=
"(1GB, Embest, China)"
;
break
;
case
0xA020D3
:
model
=
"Raspberry Pi 3 Model B+"
;
info
=
"(1GB, Sony, UK)"
;
break
;
default:
model
=
"Unknown"
;
info
=
"(Unknown)"
;
ERROR
(
"rpi3: Unknown board revision 0x%08x
\n
"
,
rev
);
break
;
}
NOTICE
(
"rpi3: Detected: %s %s [0x%08x]
\n
"
,
model
,
info
,
rev
);
}
else
{
ERROR
(
"rpi3: Unable to detect board revision
\n
"
);
}
/* Initialise the IO layer and register platform IO devices */
plat_rpi3_io_setup
();
}
plat/rpi3/rpi3_hw.h
View file @
f9d2808a
/*
* Copyright (c) 2016-201
7
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2016-201
8
, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
...
...
@@ -17,11 +17,25 @@
#define RPI3_IO_SIZE ULL(0x01000000)
/*
*
Serial port (called 'Mini UART' in the BCM docucmentation).
*
ARM <-> VideoCore mailboxes
*/
#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040)
#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET)
#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000)
#define RPI3_MBOX_OFFSET ULL(0x0000B880)
#define RPI3_MBOX_BASE (RPI3_IO_BASE + RPI3_MBOX_OFFSET)
/* VideoCore -> ARM */
#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000)
#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010)
#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014)
#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018)
#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C)
/* ARM -> VideoCore */
#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020)
#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030)
#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034)
#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038)
#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C)
/* Mailbox status constants */
#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000)
/* Set if full */
#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000)
/* Set if empty */
/*
* Power management, reset controller, watchdog.
...
...
@@ -30,11 +44,26 @@
#define RPI3_PM_BASE (RPI3_IO_BASE + RPI3_IO_PM_OFFSET)
/* Registers on top of RPI3_PM_BASE. */
#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
#define RPI3_PM_RSTS_OFFSET ULL(0x00000020)
#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
/* Watchdog constants */
#define RPI3_PM_PASSWORD ULL(0x5A000000)
#define RPI3_PM_RSTC_WRCFG_MASK ULL(0x00000030)
#define RPI3_PM_RSTC_WRCFG_FULL_RESET ULL(0x00000020)
#define RPI3_PM_PASSWORD U(0x5A000000)
#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030)
#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020)
/*
* The RSTS register is used by the VideoCore firmware when booting the
* Raspberry Pi to know which partition to boot from. The partition value is
* formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware
* to indicate halt.
*/
#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555)
/*
* Serial port (called 'Mini UART' in the BCM docucmentation).
*/
#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040)
#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET)
#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000)
/*
* Local interrupt controller
...
...
plat/rpi3/rpi3_mbox.c
0 → 100644
View file @
f9d2808a
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <arch_helpers.h>
#include <debug.h>
#include <mmio.h>
#include <platform_def.h>
#include "rpi3_hw.h"
/* This struct must be aligned to 16 bytes */
typedef
struct
__packed
__aligned
(
16
)
rpi3_mbox_request
{
uint32_t
size
;
/* Buffer size in bytes */
uint32_t
code
;
/* Request/response code */
uint32_t
tags
[
0
];
}
rpi3_mbox_request_t
;
#define RPI3_MBOX_BUFFER_SIZE U(256)
static
uint8_t
__aligned
(
16
)
rpi3_mbox_buffer
[
RPI3_MBOX_BUFFER_SIZE
];
/* Constants to perform a request/check the status of a request. */
#define RPI3_MBOX_PROCESS_REQUEST U(0x00000000)
#define RPI3_MBOX_REQUEST_SUCCESSFUL U(0x80000000)
#define RPI3_MBOX_REQUEST_ERROR U(0x80000001)
/* Command constants */
#define RPI3_TAG_HARDWARE_GET_BOARD_REVISION U(0x00010002)
#define RPI3_TAG_END U(0x00000000)
#define RPI3_TAG_REQUEST U(0x00000000)
#define RPI3_TAG_IS_RESPONSE U(0x80000000)
/* Set if response */
#define RPI3_TAG_RESPONSE_LENGTH_MASK U(0x7FFFFFFF)
#define RPI3_CHANNEL_ARM_TO_VC U(0x8)
#define RPI3_CHANNEL_MASK U(0xF)
#define RPI3_MAILBOX_MAX_RETRIES U(1000000)
/*******************************************************************************
* Helpers to send requests to the VideoCore using the mailboxes.
******************************************************************************/
static
void
rpi3_vc_mailbox_request_send
(
void
)
{
uint32_t
st
,
data
;
uintptr_t
resp_addr
,
addr
;
unsigned
int
retries
;
/* This is the location of the request buffer */
addr
=
(
uintptr_t
)
&
rpi3_mbox_buffer
;
/* Make sure that the changes are seen by the VideoCore */
flush_dcache_range
(
addr
,
RPI3_MBOX_BUFFER_SIZE
);
/* Wait until the outbound mailbox is empty */
retries
=
0U
;
do
{
st
=
mmio_read_32
(
RPI3_MBOX_BASE
+
RPI3_MBOX1_STATUS_OFFSET
);
retries
++
;
if
(
retries
==
RPI3_MAILBOX_MAX_RETRIES
)
{
ERROR
(
"rpi3: mbox: Send request timeout
\n
"
);
return
;
}
}
while
((
st
&
RPI3_MBOX_STATUS_EMPTY_MASK
)
==
0U
);
/* Send base address of this message to start request */
mmio_write_32
(
RPI3_MBOX_BASE
+
RPI3_MBOX1_WRITE_OFFSET
,
RPI3_CHANNEL_ARM_TO_VC
|
(
uint32_t
)
addr
);
/* Wait until the inbound mailbox isn't empty */
retries
=
0U
;
do
{
st
=
mmio_read_32
(
RPI3_MBOX_BASE
+
RPI3_MBOX0_STATUS_OFFSET
);
retries
++
;
if
(
retries
==
RPI3_MAILBOX_MAX_RETRIES
)
{
ERROR
(
"rpi3: mbox: Receive response timeout
\n
"
);
return
;
}
}
while
((
st
&
RPI3_MBOX_STATUS_EMPTY_MASK
)
!=
0U
);
/* Get location and channel */
data
=
mmio_read_32
(
RPI3_MBOX_BASE
+
RPI3_MBOX0_READ_OFFSET
);
if
((
data
&
RPI3_CHANNEL_MASK
)
!=
RPI3_CHANNEL_ARM_TO_VC
)
{
ERROR
(
"rpi3: mbox: Wrong channel: 0x%08x
\n
"
,
data
);
panic
();
}
resp_addr
=
(
uintptr_t
)(
data
&
~
RPI3_CHANNEL_MASK
);
if
(
addr
!=
resp_addr
)
{
ERROR
(
"rpi3: mbox: Unexpected address: 0x%08x
\n
"
,
data
);
panic
();
}
/* Make sure that the data seen by the CPU is up to date */
inv_dcache_range
(
addr
,
RPI3_MBOX_BUFFER_SIZE
);
}
/*******************************************************************************
* Request board revision. Returns the revision and 0 on success, -1 on error.
******************************************************************************/
int
rpi3_vc_hardware_get_board_revision
(
uint32_t
*
revision
)
{
uint32_t
tag_request_size
=
sizeof
(
uint32_t
);
rpi3_mbox_request_t
*
req
=
(
rpi3_mbox_request_t
*
)
rpi3_mbox_buffer
;
assert
(
revision
!=
NULL
);
VERBOSE
(
"rpi3: mbox: Sending request at %p
\n
"
,
(
void
*
)
req
);
req
->
size
=
sizeof
(
rpi3_mbox_buffer
);
req
->
code
=
RPI3_MBOX_PROCESS_REQUEST
;
req
->
tags
[
0
]
=
RPI3_TAG_HARDWARE_GET_BOARD_REVISION
;
req
->
tags
[
1
]
=
tag_request_size
;
/* Space available for the response */
req
->
tags
[
2
]
=
RPI3_TAG_REQUEST
;
req
->
tags
[
3
]
=
0
;
/* Placeholder for the response */
req
->
tags
[
4
]
=
RPI3_TAG_END
;
rpi3_vc_mailbox_request_send
();
if
(
req
->
code
!=
RPI3_MBOX_REQUEST_SUCCESSFUL
)
{
ERROR
(
"rpi3: mbox: Code = 0x%08x
\n
"
,
req
->
code
);
return
-
1
;
}
if
(
req
->
tags
[
2
]
!=
(
RPI3_TAG_IS_RESPONSE
|
tag_request_size
))
{
ERROR
(
"rpi3: mbox: get board revision failed (0x%08x)
\n
"
,
req
->
tags
[
2
]);
return
-
1
;
}
*
revision
=
req
->
tags
[
3
];
return
0
;
}
plat/rpi3/rpi3_pm.c
View file @
f9d2808a
/*
* Copyright (c) 2015-201
7
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-201
8
, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
...
...
@@ -150,41 +150,61 @@ void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state)
}
/*******************************************************************************
* Platform handler
to reboot the
system
* Platform handler
s for system reset and
system
off.
******************************************************************************/
#define RESET_TIMEOUT 10
static
void
__dead2
rpi3_system_reset
(
void
)
{
/* Setup watchdog for reset */
/* 10 ticks (Watchdog timer = Timer clock / 16) */
#define RESET_TIMEOUT U(10)
static
const
uintptr_t
base
=
RPI3_PM_BASE
;
static
void
__dead2
rpi3_watchdog_reset
(
void
)
{
uint32_t
rstc
;
INFO
(
"rpi3: PSCI System Reset: invoking watchdog reset
\n
"
);
console_flush
();
rstc
=
mmio_read_32
(
base
+
RPI3_PM_RSTC_OFFSET
);
rstc
&=
~
RPI3_PM_RSTC_WRCFG_MASK
;
rstc
|=
RPI3_PM_RSTC_WRCFG_FULL_RESET
;
dmbst
();
dsbsy
();
isb
();
/*
* Watchdog timer = Timer clock / 16
* Password (31:16) | Value (11:0)
*/
mmio_write_32
(
base
+
RPI3_PM_WDOG_OFFSET
,
mmio_write_32
(
RPI3_PM_BASE
+
RPI3_PM_WDOG_OFFSET
,
RPI3_PM_PASSWORD
|
RESET_TIMEOUT
);
mmio_write_32
(
base
+
RPI3_PM_RSTC_OFFSET
,
RPI3_PM_PASSWORD
|
rstc
);
rstc
=
mmio_read_32
(
RPI3_PM_BASE
+
RPI3_PM_RSTC_OFFSET
);
rstc
&=
~
RPI3_PM_RSTC_WRCFG_MASK
;
rstc
|=
RPI3_PM_PASSWORD
|
RPI3_PM_RSTC_WRCFG_FULL_RESET
;
mmio_write_32
(
RPI3_PM_BASE
+
RPI3_PM_RSTC_OFFSET
,
rstc
);
for
(;;)
{
wfi
();
}
}
static
void
__dead2
rpi3_system_reset
(
void
)
{
INFO
(
"rpi3: PSCI_SYSTEM_RESET: Invoking watchdog reset
\n
"
);
rpi3_watchdog_reset
();
}
static
void
__dead2
rpi3_system_off
(
void
)
{
uint32_t
rsts
;
INFO
(
"rpi3: PSCI_SYSTEM_OFF: Invoking watchdog reset
\n
"
);
/*
* This function doesn't actually make the Raspberry Pi turn itself off,
* the hardware doesn't allow it. It simply reboots it and the RSTS
* value tells the bootcode.bin firmware not to continue the regular
* bootflow and to stay in a low power mode.
*/
rsts
=
mmio_read_32
(
RPI3_PM_BASE
+
RPI3_PM_RSTS_OFFSET
);
rsts
|=
RPI3_PM_PASSWORD
|
RPI3_PM_RSTS_WRCFG_HALT
;
mmio_write_32
(
RPI3_PM_BASE
+
RPI3_PM_RSTS_OFFSET
,
rsts
);
rpi3_watchdog_reset
();
}
/*******************************************************************************
* Platform handlers and setup function.
******************************************************************************/
...
...
@@ -192,6 +212,7 @@ static const plat_psci_ops_t plat_rpi3_psci_pm_ops = {
.
cpu_standby
=
rpi3_cpu_standby
,
.
pwr_domain_on
=
rpi3_pwr_domain_on
,
.
pwr_domain_on_finish
=
rpi3_pwr_domain_on_finish
,
.
system_off
=
rpi3_system_off
,
.
system_reset
=
rpi3_system_reset
,
.
validate_power_state
=
rpi3_validate_power_state
,
};
...
...
plat/rpi3/rpi3_private.h
View file @
f9d2808a
...
...
@@ -33,4 +33,7 @@ uint32_t rpi3_get_spsr_for_bl33_entry(void);
/* IO storage utility functions */
void
plat_rpi3_io_setup
(
void
);
/* VideoCore firmware commands */
int
rpi3_vc_hardware_get_board_revision
(
uint32_t
*
revision
);
#endif
/*__RPI3_PRIVATE_H__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment