mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 09:34:18 +00:00
feat(nxp-drivers): add Linflex driver
This is a UART controller found on NXP automotive parts. For instance: S32V, S32G and S32R. Change-Id: Iff0dd0c379633ac0651e5db287537c87666b57d2 Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com> Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
This commit is contained in:
parent
10784f5f38
commit
306946b014
3 changed files with 283 additions and 1 deletions
|
@ -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)
|
||||
|
|
259
drivers/nxp/console/linflex_console.S
Normal file
259
drivers/nxp/console/linflex_console.S
Normal 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
|
18
include/drivers/nxp/console/linflex.h
Normal file
18
include/drivers/nxp/console/linflex.h
Normal 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 */
|
Loading…
Add table
Reference in a new issue