Merge changes from topic "add_s32g274ardb2_support" into integration

* changes:
  feat(s32g274a): enable BL31 stage
  feat(s32g274a): add S32G274ARDB2 board support
  feat(nxp-drivers): add Linflex driver
This commit is contained in:
Manish Pandey 2024-05-08 17:16:50 +02:00 committed by TrustedFirmware Code Review
commit 4bd1e7bdc6
21 changed files with 1144 additions and 1 deletions

View file

@ -504,6 +504,13 @@ subsections:
- title: LS1088AQDS
scope: ls1088aqds
- title: S32G274A
scope: s32g274a
subsections:
- title: S32G274ARDB
scope: s32g274ardb
- title: QEMU
scope: qemu

View file

@ -710,6 +710,15 @@ NXP SoC Part LS1088A and its platform port
:|F|: plat/nxp/soc-ls1088a/ls1088ardb
:|F|: plat/nxp/soc-ls1088a/ls1088aqds
NXP SoC Part S32G274A and its platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:|M|: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
:|G|: `gprocopciucnxp`_
:|F|: docs/plat/s32g274a.rst
:|F|: drivers/nxp/console/linflex_console.S
:|F|: include/drivers/nxp/console/linflex.h
:|F|: plat/nxp/s32
QEMU platform port
^^^^^^^^^^^^^^^^^^
:|M|: Jens Wiklander <jens.wiklander@linaro.org>
@ -983,6 +992,7 @@ Conventional Changelog Extensions
.. _davidvincze: https://github.com/davidvincze
.. _etienne-lms: https://github.com/etienne-lms
.. _glneo: https://github.com/glneo
.. _gprocopciucnxp: https://github.com/gprocopciucnxp
.. _grandpaul: https://github.com/grandpaul
.. _harrisonmutai-arm: https://github.com/harrisonmutai-arm
.. _hilamirandakuzi1: https://github.com/hilamirandakuzi1

View file

@ -29,6 +29,7 @@ Platform Ports
imx8m
imx8ulp
imx9
s32g274a
npcm845x
nxp/index
poplar

99
docs/plat/s32g274a.rst Normal file
View file

@ -0,0 +1,99 @@
NXP S32G274A
============
S32G2 is an NXP vehicle network processor combining ASIL D safety, hardware
security, high-performance real-time and application processing and network
acceleration. S32G2 supports the needs of new vehicle architectures:
service-oriented gateways, domain controllers, zonal processors, safety
processors and more. It is equipped with 4 Cortex-A53 cores operating at
1.0GHz.
The TF-A includes support for one single S32G2-based board called S32G274ARDB2.
The S32G-VNP-RDB2 is a compact, highly optimized and integrated board
engineering for vehicle service-oriented gateway (SoG), domain control
applications, high-performance processing, safety and security applications.
More details about this board can be found at `s32g274ardb2`_.
Boot Flow
---------
::
BootROM -> BL2 (SRAM) -> BL31 (SRAM) -> BL33 (DDR - TODO)
.. warning::
This boot flow is a preliminary version that will serve as a foundation for
upcoming S32G2 contributions. The execution will hang after the BL31 stage
due to U-Boot being deployed in SRAM instead of DDR. This issue will be
resolved with the addition of the DDR driver.
Code Locations
--------------
- Downstream TF-A:
`link: <https://github.com/nxp-auto-linux/arm-trusted-firmware>`__
- Downstream U-Boot:
`link <https://github.com/nxp-auto-linux/u-boot>`__
- Downstream Linux:
`link <https://github.com/nxp-auto-linux/linux>`__
How to build
------------
The port currently available on the S32G274ARDB2 platform is in its initial
stage. This means that important drivers like DDR and storage are not yet
available. Consequently, the boot process depends on BootROM to load all TF-A
stages in SRAM. To create a bootable image, the script below should be used.
This script makes use of the ``mkimage`` tool, which is part of the U-Boot drop
for S32G274A SoCs.
.. code:: bash
#!/bin/bash -xe
TF_A="${TF_A:-`pwd`}"
UBOOT="${UBOOT:-${TF_A}/../u-boot}"
DEBUG="${DEBUG:-1}"
FIP_BASE="0x34100000"
if [ "${DEBUG}" -eq "1" ]; then
BUILD="debug"
else
BUILD="release"
fi
BOOT_IMAGE="build/s32g274ardb2/${BUILD}/BOOT_IMAGE.bin"
BL2_BIN="build/s32g274ardb2/${BUILD}/bl2.bin"
FIP_BIN="build/s32g274ardb2/${BUILD}/fip.bin"
# Generate bl2, bl31 and fip image
make -C "${TF_A}" -j9 'PLAT=s32g274ardb2' \
BL33="${UBOOT}/u-boot-nodtb.bin" DEBUG="${DEBUG}" clean
make -C "${TF_A}" -j9 'PLAT=s32g274ardb2' \
BL33="${UBOOT}/u-boot-nodtb.bin" DEBUG="${DEBUG}" bl2
make -C "${TF_A}" -j9 'PLAT=s32g274ardb2' \
BL33="${UBOOT}/u-boot-nodtb.bin" DEBUG="${DEBUG}" fip
# Extract BL2 entry
BL2_START="0x$(poetry run memory -p s32g274ardb2 -b debug -f | \
grep BL2 | awk -F'|' '{print $3}' | xargs)"
# BL2 bin file size in bytes
BL2_SIZE="$(stat -c "%s" "${BL2_BIN}")"
# Pack bl2.bin and fip.bin by ensuring that the FIP image will start at FIP_BASE
cp -vf "${BL2_BIN}" "${BOOT_IMAGE}"
dd if="${FIP_BIN}" of="${BOOT_IMAGE}" seek="$((FIP_BASE - BL2_START))" bs=1
# Build a bootable image by appending the IVT
"${UBOOT}/tools/mkimage" \
-a "${BL2_START}" \
-e "${BL2_START}" \
-T s32ccimage \
-n "${UBOOT}/u-boot-s32.cfgout" \
-d "${BOOT_IMAGE}" \
fip.s32
.. _s32g2: https://www.nxp.com/products/processors-and-microcontrollers/s32-automotive-platform/s32g-vehicle-network-processors/s32g2-processors-for-vehicle-networking:S32G2
.. _s32g274ardb2: https://www.nxp.com/design/design-center/designs/s32g2-vehicle-networking-reference-design:S32G-VNP-RDB2

View file

@ -1,5 +1,5 @@
#
# Copyright 2021 NXP
# Copyright 2021-2024 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
@ -27,9 +27,14 @@ else
ifeq ($(CONSOLE), PL011)
CONSOLE_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \
${PLAT_DRIVERS_PATH}/console/console_pl011.c
else
ifeq ($(CONSOLE), LINFLEX)
CONSOLE_SOURCES := ${PLAT_DRIVERS_PATH}/console/linflex_console.S
else
$(error -> CONSOLE not set!)
endif
endif
endif
ifeq (${BL_COMM_CONSOLE_NEEDED},yes)

View file

@ -0,0 +1,259 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lib/libc/errno.h>
#include <asm_macros.S>
#include <console_macros.S>
#include <lib/utils_def.h>
#define LDIV_MULTIPLIER U(16)
#define LINFLEX_LINCR1 (0x0)
#define LINCR1_INIT BIT_32(0)
#define LINCR1_MME BIT_32(4)
#define LINFLEX_LINSR (0x8)
#define LINSR_LINS_INITMODE (0x00001000)
#define LINSR_LINS_MASK (0x0000F000)
#define LINFLEX_UARTCR (0x10)
#define UARTCR_ROSE BIT_32(23)
#define LINFLEX_UARTSR (0x14)
#define LINFLEX_LINIBRR (0x28)
#define LINFLEX_LINFBRR (0x24)
#define LINFLEX_BDRL (0x38)
#define LINFLEX_UARTPTO (0x50)
#define UARTCR_UART BIT_32(0)
#define UARTCR_WL0 BIT_32(1)
#define UARTCR_PC0 BIT_32(3)
#define UARTCR_TXEN BIT_32(4)
#define UARTCR_RXEN BIT_32(5)
#define UARTCR_PC1 BIT_32(6)
#define UARTCR_TFBM BIT_32(8)
#define UARTCR_RFBM BIT_32(9)
#define UARTCR_OSR_SHIFT U(24)
#define UARTCR_OSR_WIDTH U(4)
#define UARTSR_DTF BIT_32(1)
/*
* "core" functions are low-level implementations that do not require
* writable memory and are thus safe to call in BL1 crash context.
*/
.globl console_linflex_core_init
.globl console_linflex_core_putc
.globl console_linflex_register
.globl console_linflex_putc
/**
* uint32_t get_ldiv_mult(uintptr_t baseaddr, uint32_t clock,
* uint32_t baud, console_t *console,);
*
* Clobber list : x0 - x6
* Out x4: LDIV multiplier
*/
func get_ldiv_mult
ldr w4, [x0, LINFLEX_UARTCR]
mov w5, w4
/* Prepare choices in w5 and w6 */
ubfx x5, x5, #UARTCR_OSR_SHIFT, #UARTCR_OSR_WIDTH
mov w6, #LDIV_MULTIPLIER
and w4, w4, #UARTCR_ROSE
cmp w4, #0x0
csel w4, w5, w6, ne
ret
endfunc get_ldiv_mult
/*
* void linflex_set_brg(uintptr_t baseaddr, uint32_t clock
* uint32_t baud, console_t *console);
*
* Clobber list : x0 - x7, x13
*/
func linflex_set_brg
mov x13, x30
bl get_ldiv_mult
mov x30, x13
/* (x4) dividr = baudrate * ldiv_mult */
mul x4, x4, x2
/* (x5) divisr = clock rate */
mov x5, x1
/* (x6) ibr = divisr / dividr */
udiv x6, x5, x4
/* (x7) fbr = divisr % dividr */
msub x7, x6, x4, x5
/* fbr *= 16 / dividr */
lsl x7, x7, #4
udiv x7, x7, x4
/* fbr &= 0xf */
and w7, w7, #0xf
str w6, [x0, LINFLEX_LINIBRR]
str w7, [x0, LINFLEX_LINFBRR]
ret
endfunc linflex_set_brg
/**
* int console_linflex_core_init(uintptr_t baseaddr, uint32_t clock,
* uint32_t baud);
*
* In: x0 - Linflex base address
* x1 - clock frequency
* x2 - baudrate
* Out: x0 - 1 on success, 0 on error
* Clobber list : x0 - x7, x13 - x14
*/
func console_linflex_core_init
/* Set master mode and init mode */
mov w4, #(LINCR1_INIT)
str w4, [x0, LINFLEX_LINCR1]
mov w4, #(LINCR1_MME | LINCR1_INIT)
str w4, [x0, LINFLEX_LINCR1]
/* wait for init mode entry */
wait_init_entry:
ldr w4, [x0, LINFLEX_LINSR]
and w4, w4, #LINSR_LINS_MASK
cmp w4, #LINSR_LINS_INITMODE
b.ne wait_init_entry
/* Set UART bit */
mov w4, #UARTCR_UART
str w4, [x0, LINFLEX_UARTCR]
mov x14, x30
bl linflex_set_brg
mov x30, x14
/* Set preset timeout register value. */
mov w4, #0xf
str w4, [x0, LINFLEX_UARTPTO]
/* 8-bit data, no parity, Tx/Rx enabled, UART mode */
mov w4, #(UARTCR_PC1 | UARTCR_RXEN | UARTCR_TXEN | UARTCR_PC0 | \
UARTCR_WL0 | UARTCR_UART | UARTCR_RFBM | UARTCR_TFBM)
str w4, [x0, LINFLEX_UARTCR]
/* End init mode */
ldr w4, [x0, LINFLEX_LINCR1]
bic w4, w4, #LINCR1_INIT
str w4, [x0, LINFLEX_LINCR1]
ret
endfunc console_linflex_core_init
/**
* int console_linflex_register(uintptr_t baseaddr, uint32_t clock,
* uint32_t clock, uint32_t baud);
*
* Function to initialize and register the console.
* The caller needs to pass an empty console_linflex_t
* structure in which *MUST* be allocated in
* persistent memory (e.g. a global or static local
* variable, *NOT* on the stack).
* In: x0 - Linflex base address
* x1 - clock frequency
* x2 - baudrate
* x3 - pointer to empty console_t structure
* Out: x0 - 1 on success, 0 on error
* Clobber list : x0 - x7, x13 - x15
*/
func console_linflex_register
mov x15, x30
bl console_linflex_core_init
mov x30, x15
/* Populate the base address */
str x0, [x3, #CONSOLE_T_BASE]
mov x0, x3
finish_console_register linflex, putc=1, getc=0, flush=0
endfunc console_linflex_register
/**
* int console_linflex_core_putc(int c, uintptr_t baseaddr);
* Out: w0 - printed character on success, < 0 on error.
* Clobber list : x0 - x3
*/
func console_linflex_core_putc
cbz x1, putc_error
cmp w0, #'\n'
b.ne print_char
/* Print '\r\n' for each '\n' */
mov x0, #'\r'
mov x14, x30
bl console_linflex_core_putc
mov x30, x14
mov x0, #'\n'
print_char:
ldr w2, [x1, LINFLEX_UARTCR]
and w2, w2, #UARTCR_TFBM
cmp w2, #0x0
b.eq buffer_mode
fifo_mode:
/* UART is in FIFO mode */
ldr w2, [x1, LINFLEX_UARTSR]
and w2, w2, #UARTSR_DTF
cmp w2, #0
b.ne fifo_mode
strb w0, [x1, LINFLEX_BDRL]
b no_error
buffer_mode:
strb w0, [x1, LINFLEX_BDRL]
buffer_loop:
ldr w2, [x1, LINFLEX_UARTSR]
and w3, w2, #UARTSR_DTF
cmp w3, #0
b.eq buffer_loop
/**
* In Buffer Mode the DTFTFF bit of UARTSR register
* has to be set in software
*/
mov w2, #UARTSR_DTF
str w2, [x1, LINFLEX_UARTSR]
no_error:
mov x0, #0
ret
putc_error:
mov x0, #-EINVAL
ret
endfunc console_linflex_core_putc
/**
* int console_linflex_putc(int c, console_t *console);
*
* Function to output a character over the console. It
* returns the character printed on success or -EINVAL on error.
* In : w0 - character to be printed
* x1 - pointer to console_t struct
* Out: w0 - printed character on success, < 0 on error.
* Clobber list : x0 - x3, x15
*/
func console_linflex_putc
cbz x1, putc_error
ldr x1, [x1, #CONSOLE_T_BASE]
b console_linflex_core_putc
puct_error:
mov x0, #-EINVAL
ret
endfunc console_linflex_putc

View file

@ -0,0 +1,18 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef LINFLEX_H
#define LINFLEX_H
#ifndef __ASSEMBLER__
#include <drivers/console.h>
int console_linflex_core_init(uintptr_t baseaddr, uint32_t clock,
uint32_t baud);
int console_linflex_register(uintptr_t baseaddr, uint32_t clock,
uint32_t baud, console_t *console);
#endif
#endif /* LINFLEX_H */

View file

@ -0,0 +1,12 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_CONSOLE_H
#define PLAT_CONSOLE_H
void console_s32g2_register(void);
#endif

View file

@ -0,0 +1,12 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_HELPERS_H
#define PLAT_HELPERS_H
unsigned int s32g2_core_pos_by_mpidr(u_register_t mpidr);
#endif /* PLAT_HELPERS_H */

View file

@ -0,0 +1,12 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_IO_STORAGE_H
#define PLAT_IO_STORAGE_H
void plat_s32g2_io_setup(void);
#endif

View file

@ -0,0 +1,22 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_MACROS_S
#define PLAT_MACROS_S
/* ---------------------------------------------
* The below required platform porting macro
* prints out relevant GIC and CCI registers
* whenever an unhandled exception is taken in
* BL31.
* Clobbers: x0 - x10, x16, x17, sp
* ---------------------------------------------
*/
.macro plat_crash_print_regs
.endm
#endif /* PLAT_MACROS_S */

View file

@ -0,0 +1,78 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLATFORM_DEF_H
#define PLATFORM_DEF_H
#include <plat/common/common_def.h>
#define PLATFORM_STACK_SIZE U(0x1000)
/* Caches */
#define CACHE_WRITEBACK_SHIFT U(6)
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
/* CPU Topology */
#define PLATFORM_CORE_COUNT U(4)
#define PLATFORM_SYSTEM_COUNT U(1)
#define PLATFORM_CLUSTER_COUNT U(2)
#define PLATFORM_PRIMARY_CPU U(0)
#define PLATFORM_MPIDR_CPU_MASK_BITS U(1)
#define PLATFORM_MAX_CPUS_PER_CLUSTER U(2)
/* Power Domains */
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_SYSTEM_COUNT + \
PLATFORM_CLUSTER_COUNT + \
PLATFORM_CORE_COUNT)
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
#define PLAT_MAX_OFF_STATE U(2)
#define PLAT_MAX_RET_STATE U(1)
#define PLAT_MAX_PWR_LVL_STATES U(2)
/* BL2 stage */
#define BL2_BASE UL(0x34078000)
#define BL2_LIMIT UL(0x34100000)
/* BL31 stage */
#define BL31_BASE UL(0x34200000)
#define BL31_LIMIT UL(0x34300000)
/* It is a dummy value for now, given the missing DDR */
#define BL33_BASE UL(0x34500000)
#define BL33_LIMIT UL(0x345FF000)
#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 36)
/* We'll be doing a 1:1 mapping anyway */
#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 36)
#define MAX_MMAP_REGIONS U(8)
#define MAX_XLAT_TABLES U(32)
/* Console settings */
#define UART_BASE UL(0x401C8000)
#define UART_BAUDRATE U(115200)
/* FIRC clock */
#define UART_CLOCK_HZ U(48000000)
#define S32G_FIP_BASE UL(0x34100000)
#define S32G_FIP_SIZE UL(0x100000)
#define MAX_IO_HANDLES U(2)
#define MAX_IO_DEVICES U(2)
/* GIC settings */
#define S32G_GIC_BASE UL(0x50800000)
#define PLAT_GICD_BASE S32G_GIC_BASE
#define PLAT_GICR_BASE (S32G_GIC_BASE + UL(0x80000))
/* Generic timer frequency; this goes directly into CNTFRQ_EL0.
* Its end-value is 5MHz; this is based on the assumption that
* GPR00[CA53_COUNTER_CLK_DIV_VAL] contains the reset value of 0x7, hence
* producing a divider value of 8, applied to the FXOSC frequency of 40MHz.
*/
#define COUNTER_FREQUENCY U(5000000)
#endif /* PLATFORM_DEF_H */

View file

@ -0,0 +1,62 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/desc_image_load.h>
#include <lib/mmio.h>
#include <plat/common/platform.h>
#include <plat_console.h>
#include <plat_io_storage.h>
#define SIUL2_PC09_MSCR UL(0x4009C2E4)
#define SIUL2_PC10_MSCR UL(0x4009C2E8)
#define SIUL2_PC10_LIN0_IMCR UL(0x4009CA40)
#define LIN0_TX_MSCR_CFG U(0x00214001)
#define LIN0_RX_MSCR_CFG U(0x00094000)
#define LIN0_RX_IMCR_CFG U(0x00000002)
struct bl_load_info *plat_get_bl_image_load_info(void)
{
return get_bl_load_info_from_mem_params_desc();
}
struct bl_params *plat_get_next_bl_params(void)
{
return get_next_bl_params_from_mem_params_desc();
}
void plat_flush_next_bl_params(void)
{
flush_bl_params_desc();
}
void bl2_platform_setup(void)
{
}
static void linflex_config_pinctrl(void)
{
/* set PC09 - MSCR[41] - for UART0 TXD */
mmio_write_32(SIUL2_PC09_MSCR, LIN0_TX_MSCR_CFG);
/* set PC10 - MSCR[42] - for UART0 RXD */
mmio_write_32(SIUL2_PC10_MSCR, LIN0_RX_MSCR_CFG);
/* set PC10 - MSCR[512]/IMCR[0] - for UART0 RXD */
mmio_write_32(SIUL2_PC10_LIN0_IMCR, LIN0_RX_IMCR_CFG);
}
void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
linflex_config_pinctrl();
console_s32g2_register();
plat_s32g2_io_setup();
}
void bl2_el3_plat_arch_setup(void)
{
}

View file

@ -0,0 +1,41 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/desc_image_load.h>
#include <plat/common/platform.h>
static bl_mem_params_node_t bl2_mem_params_descs[] = {
{
.image_id = BL31_IMAGE_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
entry_point_info_t,
SECURE | EXECUTABLE | EP_FIRST_EXE),
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS),
.ep_info.pc = BL31_BASE,
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
.image_info.image_base = BL31_BASE,
.next_handoff_image_id = BL33_IMAGE_ID,
},
{
.image_id = BL33_IMAGE_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
entry_point_info_t,
NON_SECURE | EXECUTABLE),
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
image_info_t, 0),
.image_info.image_max_size = BL33_LIMIT - BL33_BASE,
.image_info.image_base = BL33_BASE,
.next_handoff_image_id = INVALID_IMAGE_ID,
},
};
REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)

View file

@ -0,0 +1,75 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <drivers/arm/gicv3.h>
#include <plat/common/platform.h>
#include <plat_console.h>
static entry_point_info_t bl33_image_ep_info;
static unsigned int s32g2_mpidr_to_core_pos(unsigned long mpidr);
static uint32_t get_spsr_for_bl33_entry(void)
{
unsigned long mode = MODE_EL1;
uint32_t spsr;
spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
return spsr;
}
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
console_s32g2_register();
SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
bl33_image_ep_info.pc = BL33_BASE;
bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
}
void bl31_plat_arch_setup(void)
{
}
struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
{
return &bl33_image_ep_info;
}
void bl31_platform_setup(void)
{
static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
static gicv3_driver_data_t plat_gic_data = {
.gicd_base = PLAT_GICD_BASE,
.gicr_base = PLAT_GICR_BASE,
.rdistif_num = PLATFORM_CORE_COUNT,
.rdistif_base_addrs = rdistif_base_addrs,
.mpidr_to_core_pos = s32g2_mpidr_to_core_pos,
};
unsigned int pos = plat_my_core_pos();
gicv3_driver_init(&plat_gic_data);
gicv3_distif_init();
gicv3_rdistif_init(pos);
gicv3_cpuif_enable(pos);
}
static unsigned int s32g2_mpidr_to_core_pos(unsigned long mpidr)
{
int core;
core = plat_core_pos_by_mpidr(mpidr);
if (core < 0) {
return 0;
}
return (unsigned int)core;
}

View file

@ -0,0 +1,28 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <linflex.h>
#include <plat_console.h>
#include <platform_def.h>
void console_s32g2_register(void)
{
static console_t s32g2_console;
int ret;
(void)memset(&s32g2_console, 0, sizeof(s32g2_console));
ret = console_linflex_register(UART_BASE, UART_CLOCK_HZ,
UART_BAUDRATE, &s32g2_console);
if (ret == 0) {
panic();
}
console_set_scope(&s32g2_console,
CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH |
CONSOLE_FLAG_TRANSLATE_CRLF);
}

View file

@ -0,0 +1,130 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <asm_macros.S>
#include <platform_def.h>
#define S32G_NCORE_CAIU0_BASE_ADDR UL(0x50400000)
#define S32G_NCORE_CAIUTC_OFF U(0x0)
#define S32G_NCORE_CAIUTC_ISOLEN_SHIFT U(1)
.globl plat_crash_console_flush
.globl plat_crash_console_init
.globl plat_crash_console_putc
.globl plat_is_my_cpu_primary
.globl plat_my_core_pos
.globl plat_reset_handler
.globl plat_secondary_cold_boot_setup
.globl platform_mem_init
.globl s32g2_core_pos_by_mpidr
/* int plat_crash_console_init(void); */
func plat_crash_console_init
mov_imm x0, UART_BASE
mov_imm x1, UART_CLOCK_HZ
mov_imm x2, UART_BAUDRATE
b console_linflex_core_init
endfunc plat_crash_console_init
/* int plat_crash_console_putc(int); */
func plat_crash_console_putc
mov_imm x1, UART_BASE
b console_linflex_core_putc
ret
endfunc plat_crash_console_putc
/* void plat_crash_console_flush(void); */
func plat_crash_console_flush
ret
endfunc plat_crash_console_flush
/**
* unsigned int s32g2_core_pos_by_mpidr(u_register_t mpidr);
*
* In: x0 - MPIDR_EL1
* Out: x0
* Clobber list: x0, x1
*/
func s32g2_core_pos_by_mpidr
and x1, x0, #MPIDR_CPU_MASK
and x0, x0, #MPIDR_CLUSTER_MASK
lsr x0, x0, #MPIDR_AFF1_SHIFT
add x0, x1, x0, lsl #PLATFORM_MPIDR_CPU_MASK_BITS
ret
endfunc s32g2_core_pos_by_mpidr
/**
* unsigned int plat_my_core_pos(void);
*
* Out: x0
* Clobber list: x0, x1, x8
*/
func plat_my_core_pos
mov x8, x30
mrs x0, mpidr_el1
bl s32g2_core_pos_by_mpidr
mov x30, x8
ret
endfunc plat_my_core_pos
/**
* unsigned int plat_is_my_cpu_primary(void);
*
* Clobber list: x0, x1, x7, x8
*/
func plat_is_my_cpu_primary
mov x7, x30
bl plat_my_core_pos
cmp x0, #PLATFORM_PRIMARY_CPU
cset x0, eq
mov x30, x7
ret
endfunc plat_is_my_cpu_primary
/**
* void plat_secondary_cold_boot_setup (void);
*/
func plat_secondary_cold_boot_setup
ret
endfunc plat_secondary_cold_boot_setup
/**
* void plat_reset_handler(void);
*
* Set the CAIUTC[IsolEn] bit for the primary A53 cluster.
* This is so cache invalidate operations from the early TF-A boot code
* won't cause Ncore to crash.
*
* Clobber list: x0, x1, x2
*/
func plat_reset_handler
mov x0, #S32G_NCORE_CAIU0_BASE_ADDR
ldr w1, [x0, #S32G_NCORE_CAIUTC_OFF]
movz w2, #1
lsl w2, w2, #S32G_NCORE_CAIUTC_ISOLEN_SHIFT
orr w1, w1, w2
str w1, [x0, #S32G_NCORE_CAIUTC_OFF]
ret
endfunc plat_reset_handler
/* void platform_mem_init(void); */
func platform_mem_init
mov x10, x30
mov x0, #BL31_BASE
mov x1, #(BL31_LIMIT & 0xFFFFU)
movk x1, #(BL31_LIMIT >> 16), lsl #16
sub x1, x1, x0
bl zeromem
mov x0, #BL33_BASE
mov x1, #(BL33_LIMIT & 0xFFFFU)
movk x1, #(BL33_LIMIT >> 16), lsl #16
sub x1, x1, x0
bl zeromem
mov x30, x10
ret
endfunc platform_mem_init

View file

@ -0,0 +1,135 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <drivers/io/io_driver.h>
#include <drivers/io/io_fip.h>
#include <drivers/io/io_memmap.h>
#include <plat/common/platform.h>
#include <tools_share/firmware_image_package.h>
#include <plat_io_storage.h>
struct plat_io_policy {
uintptr_t *dev_handle;
uintptr_t image_spec;
int (*check)(const uintptr_t spec);
};
static int open_memmap(const uintptr_t spec);
static int open_fip(const uintptr_t spec);
static uintptr_t fip_dev_handle;
static uintptr_t memmap_dev_handle;
static int open_memmap(const uintptr_t spec)
{
uintptr_t temp_handle = 0U;
int result;
result = io_dev_init(memmap_dev_handle, (uintptr_t)0);
if (result != 0) {
return result;
}
result = io_open(memmap_dev_handle, spec, &temp_handle);
if (result == 0) {
(void)io_close(temp_handle);
}
return result;
}
static int open_fip(const uintptr_t spec)
{
uintptr_t temp_handle = 0U;
int result;
/* See if a Firmware Image Package is available */
result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
if (result != 0) {
return result;
}
result = io_open(fip_dev_handle, spec, &temp_handle);
if (result == 0) {
(void)io_close(temp_handle);
}
return result;
}
void plat_s32g2_io_setup(void)
{
static const io_dev_connector_t *memmap_dev_con;
static const io_dev_connector_t *fip_dev_con;
int result __unused;
result = register_io_dev_memmap(&memmap_dev_con);
assert(result == 0);
result = io_dev_open(memmap_dev_con, (uintptr_t)0,
&memmap_dev_handle);
assert(result == 0);
result = register_io_dev_fip(&fip_dev_con);
assert(result == 0);
result = io_dev_open(fip_dev_con, (uintptr_t)0,
&fip_dev_handle);
assert(result == 0);
}
int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
uintptr_t *image_spec)
{
static const io_block_spec_t fip_block_spec = {
.offset = S32G_FIP_BASE,
.length = S32G_FIP_SIZE,
};
static const io_uuid_spec_t bl31_uuid_spec = {
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
};
static const io_uuid_spec_t bl33_uuid_spec = {
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
};
static const struct plat_io_policy policies[BL33_IMAGE_ID + 1] = {
[FIP_IMAGE_ID] = {
.dev_handle = &memmap_dev_handle,
.image_spec = (uintptr_t)&fip_block_spec,
.check = open_memmap,
},
[BL31_IMAGE_ID] = {
.dev_handle = &fip_dev_handle,
.image_spec = (uintptr_t)&bl31_uuid_spec,
.check = open_fip,
},
[BL33_IMAGE_ID] = {
.dev_handle = &fip_dev_handle,
.image_spec = (uintptr_t)&bl33_uuid_spec,
.check = open_fip,
},
};
const struct plat_io_policy *policy;
int result;
assert(image_id < ARRAY_SIZE(policies));
policy = &policies[image_id];
result = policy->check(policy->image_spec);
assert(result == 0);
*image_spec = policy->image_spec;
*dev_handle = *policy->dev_handle;
return result;
}

View file

@ -0,0 +1,65 @@
#
# Copyright 2024 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
include drivers/arm/gic/v3/gicv3.mk
include lib/xlat_tables_v2/xlat_tables.mk
PLAT_DRIVERS_PATH := drivers/nxp
PLAT_COMMON_PATH := plat/nxp/common
PLAT_S32G274ARDB2 := plat/nxp/s32/s32g274ardb2
CONSOLE := LINFLEX
include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk
PLAT_INCLUDES = \
-I${PLAT_S32G274ARDB2}/include
PROGRAMMABLE_RESET_ADDRESS := 1
COLD_BOOT_SINGLE_CPU := 0
ENABLE_SVE_FOR_NS := 0
RESET_TO_BL2 := 1
INIT_UNUSED_NS_EL2 := 1
ERRATA_A53_855873 := 1
ERRATA_A53_836870 := 1
ERRATA_A53_1530924 := 1
ERRATA_SPECULATIVE_AT := 1
# Selecting Drivers for SoC
$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
include ${PLAT_DRIVERS_PATH}/drivers.mk
BL_COMMON_SOURCES += \
${PLAT_S32G274ARDB2}/plat_console.c \
${PLAT_S32G274ARDB2}/plat_helpers.S \
BL2_SOURCES += \
${BL_COMMON_SOURCES} \
${PLAT_S32G274ARDB2}/plat_bl2_el3_setup.c \
${PLAT_S32G274ARDB2}/plat_bl2_image_desc.c \
${PLAT_S32G274ARDB2}/plat_io_storage.c \
common/desc_image_load.c \
drivers/io/io_fip.c \
drivers/io/io_memmap.c \
drivers/io/io_storage.c \
lib/cpus/aarch64/cortex_a53.S \
BL31_SOURCES += \
${GICV3_SOURCES} \
${PLAT_S32G274ARDB2}/plat_bl31_setup.c \
${PLAT_S32G274ARDB2}/s32g2_psci.c \
${PLAT_S32G274ARDB2}/s32g2_soc.c \
${XLAT_TABLES_LIB_SRCS} \
lib/cpus/aarch64/cortex_a53.S \
plat/common/plat_gicv3.c \
plat/common/plat_psci_common.c \

View file

@ -0,0 +1,20 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lib/psci/psci.h>
#include <plat/common/platform.h>
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
static const plat_psci_ops_t s32g2_psci_ops = {
};
*psci_ops = &s32g2_psci_ops;
return 0;
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <plat/common/platform.h>
#include <plat_helpers.h>
const unsigned char *plat_get_power_domain_tree_desc(void)
{
static const unsigned char s32g_power_domain_tree_desc[] = {
PLATFORM_SYSTEM_COUNT,
PLATFORM_CLUSTER_COUNT,
PLATFORM_CORE_COUNT / U(2),
PLATFORM_CORE_COUNT / U(2),
};
return s32g_power_domain_tree_desc;
}
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
unsigned int cluster_id, cpu_id, core_id;
u_register_t mpidr_priv = mpidr;
mpidr_priv &= MPIDR_AFFINITY_MASK;
if ((mpidr_priv & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) {
return -1;
}
cluster_id = MPIDR_AFFLVL1_VAL(mpidr_priv);
cpu_id = MPIDR_AFFLVL0_VAL(mpidr_priv);
if ((cluster_id >= PLATFORM_CLUSTER_COUNT) ||
(cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)) {
return -1;
}
core_id = s32g2_core_pos_by_mpidr(mpidr_priv);
if (core_id >= PLATFORM_CORE_COUNT) {
return -1;
}
return (int)core_id;
}
unsigned int plat_get_syscnt_freq2(void)
{
return COUNTER_FREQUENCY;
}