tegra124: Implement and enable serial console support for tegra124.
The driver is very similar to the 8250 driver, except it isn't in two parts, and it also spaces its registers 4 bytes apart instead of having them directly adjacent to each other. Also, eliminate the UART test function in the bootblock. It's no longer needed since the actual console output serves the same purpose. Right now the clock divisor is fixed for now, and we'll want to actually figure out what value to use at some point. BUG=None TEST=Built for link, pit, nyan and lumpy. Booted into the bootblock on nyan and saw serial output on the console. BRANCH=None Change-Id: Idd659222901eb76b0ed8cbb986deb5124096f2f6 Signed-off-by: Gabe Black <gabeblack@google.com> Reviewed-on: https://chromium-review.googlesource.com/171337 Reviewed-by: Gabe Black <gabeblack@chromium.org> Commit-Queue: Gabe Black <gabeblack@chromium.org> Tested-by: Gabe Black <gabeblack@chromium.org>
This commit is contained in:
parent
a93900be8d
commit
86f5e2875b
4 changed files with 185 additions and 40 deletions
|
|
@ -2,6 +2,10 @@ config SOC_NVIDIA_TEGRA124
|
|||
depends on ARCH_ARMV7
|
||||
bool
|
||||
default n
|
||||
select HAVE_UART_MEMORY_MAPPED
|
||||
select HAVE_UART_SPECIAL
|
||||
select BOOTBLOCK_CONSOLE
|
||||
select EARLY_CONSOLE
|
||||
select ARM_BOOTBLOCK_CUSTOM
|
||||
|
||||
if SOC_NVIDIA_TEGRA124
|
||||
|
|
@ -52,4 +56,47 @@ config STACK_SIZE
|
|||
hex
|
||||
default 0x800
|
||||
|
||||
choice CONSOLE_SERIAL_TEGRA124_UART_CHOICES
|
||||
prompt "Serial Console UART"
|
||||
default CONSOLE_SERIAL_UARTA
|
||||
depends on CONSOLE_SERIAL_UART
|
||||
|
||||
config CONSOLE_SERIAL_UARTA
|
||||
bool "UARTA"
|
||||
help
|
||||
Serial console on UART A.
|
||||
|
||||
config CONSOLE_SERIAL_UARTB
|
||||
bool "UARTB"
|
||||
help
|
||||
Serial console on UART B.
|
||||
|
||||
config CONSOLE_SERIAL_UARTC
|
||||
bool "UARTC"
|
||||
help
|
||||
Serial console on UART C.
|
||||
|
||||
config CONSOLE_SERIAL_UARTD
|
||||
bool "UARTD"
|
||||
help
|
||||
Serial console on UART D.
|
||||
|
||||
config CONSOLE_SERIAL_UARTE
|
||||
bool "UARTE"
|
||||
help
|
||||
Serial console on UART E.
|
||||
|
||||
endchoice
|
||||
|
||||
config CONSOLE_SERIAL_UART_ADDRESS
|
||||
hex
|
||||
depends on CONSOLE_SERIAL_UART
|
||||
default 0x70006000 if CONSOLE_SERIAL_UARTA
|
||||
default 0x70006040 if CONSOLE_SERIAL_UARTB
|
||||
default 0x70006200 if CONSOLE_SERIAL_UARTC
|
||||
default 0x70006300 if CONSOLE_SERIAL_UARTD
|
||||
default 0x70006400 if CONSOLE_SERIAL_UARTE
|
||||
help
|
||||
Map the UART names to the respective MMIO addres.
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -6,14 +6,17 @@ bootblock-S-ccopts += -marm -march=armv4t
|
|||
bootblock-y += bootblock.c
|
||||
bootblock-y += bootblock_asm.S
|
||||
bootblock-y += cbfs.c
|
||||
bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c
|
||||
|
||||
romstage-y += cbfs.c
|
||||
romstage-y += monotonic_timer.c
|
||||
romstage-y += timer.c
|
||||
romstage-$(CONFIG_EARLY_CONSOLE) += uart.c
|
||||
|
||||
ramstage-y += cbfs.c
|
||||
ramstage-y += monotonic_timer.c
|
||||
ramstage-y += timer.c
|
||||
ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c
|
||||
|
||||
# We want to grab the bootblock right before it goes into the image and wrap
|
||||
# it inside a BCT, but ideally we would do that without making special, one
|
||||
|
|
|
|||
|
|
@ -19,22 +19,8 @@
|
|||
|
||||
#include <arch/hlt.h>
|
||||
#include <arch/io.h>
|
||||
#include <arch/stages.h>
|
||||
#include <cbfs.h>
|
||||
#include <console/console.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define UART_TEST 0
|
||||
|
||||
static uint8_t readr(int reg)
|
||||
{
|
||||
return read8((void *)(0x70000000 + 0x6000 + 4 * reg));
|
||||
}
|
||||
|
||||
static void writer(int reg, uint8_t val)
|
||||
{
|
||||
write8(val, (void *)(0x70000000 + 0x6000 + 4 * reg));
|
||||
}
|
||||
|
||||
static void hacky_hardcoded_uart_setup_function(void)
|
||||
{
|
||||
|
|
@ -83,42 +69,16 @@ static void hacky_hardcoded_uart_setup_function(void)
|
|||
clrbits_le32((void *)(0x60006000 + 4 + 0), 1 << 6);
|
||||
}
|
||||
|
||||
static void test_func(void)
|
||||
{
|
||||
const unsigned divisor = 221;
|
||||
|
||||
while (!(readr(5) & 0x40));
|
||||
|
||||
writer(1, 0);
|
||||
writer(3, 0x80 | 0x3);
|
||||
writer(0, 0);
|
||||
writer(1, 0);
|
||||
writer(3, 0x3);
|
||||
writer(2, 0x01 | 0x2 | 0x4);
|
||||
writer(3, 0x80 | 0x3);
|
||||
writer(0, divisor & 0xff);
|
||||
writer(1, (divisor >> 8) & 0xff);
|
||||
writer(3, 0x3);
|
||||
|
||||
for (;;) {
|
||||
writer(0, '!');
|
||||
}
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
void *entry;
|
||||
|
||||
hacky_hardcoded_uart_setup_function();
|
||||
|
||||
if (UART_TEST)
|
||||
test_func();
|
||||
|
||||
if (CONFIG_BOOTBLOCK_CONSOLE)
|
||||
console_init();
|
||||
|
||||
entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/romstage");
|
||||
|
||||
if (entry) stage_exit(entry);
|
||||
hlt();
|
||||
}
|
||||
|
|
|
|||
135
src/soc/nvidia/tegra124/uart.c
Normal file
135
src/soc/nvidia/tegra124/uart.c
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2009 Samsung Electronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <uart.h>
|
||||
#include <arch/io.h>
|
||||
#include <console/console.h> /* for __console definition */
|
||||
#include <stdint.h>
|
||||
#include <uart8250.h>
|
||||
|
||||
struct tegra124_uart {
|
||||
union {
|
||||
uint32_t thr; // Transmit holding register.
|
||||
uint32_t rbr; // Receive buffer register.
|
||||
uint32_t dll; // Divisor latch lsb.
|
||||
};
|
||||
union {
|
||||
uint32_t ier; // Interrupt enable register.
|
||||
uint32_t dlm; // Divisor latch msb.
|
||||
};
|
||||
union {
|
||||
uint32_t iir; // Interrupt identification register.
|
||||
uint32_t fcr; // FIFO control register.
|
||||
};
|
||||
uint32_t lcr; // Line control register.
|
||||
uint32_t mcr; // Modem control register.
|
||||
uint32_t lsr; // Line status register.
|
||||
uint32_t msr; // Modem status register.
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static struct tegra124_uart * const uart_ptr =
|
||||
(void *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
|
||||
|
||||
static void tegra124_uart_tx_flush(void);
|
||||
static int tegra124_uart_tst_byte(void);
|
||||
|
||||
static void tegra124_uart_init(void)
|
||||
{
|
||||
// Use a hardcoded divisor for now.
|
||||
const unsigned divisor = 221;
|
||||
const uint8_t line_config = UART8250_LCR_WLS_8; // 8n1
|
||||
|
||||
tegra124_uart_tx_flush();
|
||||
|
||||
// Disable interrupts.
|
||||
write8(0, &uart_ptr->ier);
|
||||
// Set line configuration, access divisor latches.
|
||||
write8(UART8250_LCR_DLAB | line_config, &uart_ptr->lcr);
|
||||
// Set the divisor.
|
||||
write8(divisor & 0xff, &uart_ptr->dll);
|
||||
write8((divisor >> 8) & 0xff, &uart_ptr->dlm);
|
||||
// Hide the divisor latches.
|
||||
write8(line_config, &uart_ptr->lcr);
|
||||
// Enable FIFOs, and clear receive and transmit.
|
||||
write8(UART8250_FCR_FIFO_EN |
|
||||
UART8250_FCR_CLEAR_RCVR |
|
||||
UART8250_FCR_CLEAR_XMIT, &uart_ptr->fcr);
|
||||
}
|
||||
|
||||
static void tegra124_uart_tx_byte(unsigned char data)
|
||||
{
|
||||
while (!(read8(&uart_ptr->lsr) & UART8250_LSR_THRE));
|
||||
write8(data, &uart_ptr->thr);
|
||||
}
|
||||
|
||||
static void tegra124_uart_tx_flush(void)
|
||||
{
|
||||
while (!(read8(&uart_ptr->lsr) & UART8250_LSR_TEMT));
|
||||
}
|
||||
|
||||
static unsigned char tegra124_uart_rx_byte(void)
|
||||
{
|
||||
if (!tegra124_uart_tst_byte())
|
||||
return 0;
|
||||
return read8(&uart_ptr->rbr);
|
||||
}
|
||||
|
||||
static int tegra124_uart_tst_byte(void)
|
||||
{
|
||||
return (read8(&uart_ptr->lsr) & UART8250_LSR_DR) == UART8250_LSR_DR;
|
||||
}
|
||||
|
||||
#if !defined(__PRE_RAM__)
|
||||
|
||||
static const struct console_driver tegra124_uart_console __console = {
|
||||
.init = tegra124_uart_init,
|
||||
.tx_byte = tegra124_uart_tx_byte,
|
||||
.tx_flush = tegra124_uart_tx_flush,
|
||||
.rx_byte = tegra124_uart_rx_byte,
|
||||
.tst_byte = tegra124_uart_tst_byte,
|
||||
};
|
||||
|
||||
uint32_t uartmem_getbaseaddr(void)
|
||||
{
|
||||
return (uintptr_t)uart_ptr;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
tegra124_uart_init();
|
||||
}
|
||||
|
||||
void uart_tx_byte(unsigned char data)
|
||||
{
|
||||
tegra124_uart_tx_byte(data);
|
||||
}
|
||||
|
||||
void uart_tx_flush(void)
|
||||
{
|
||||
tegra124_uart_tx_flush();
|
||||
}
|
||||
|
||||
unsigned char uart_rx_byte(void)
|
||||
{
|
||||
return tegra124_uart_rx_byte();
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue