diff --git a/README.md b/README.md index 454bb3d..664ea8c 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,12 @@ recognised: * 57600 * 115200 (default if not specified or invalid) * 230400 + * console=*x*,*y* + * activate MMIO UART console, where *x* is the MMIO stride (reg. width) + * mmio = 8-bit MMIO + * mmio16 = 16-bit MMIO + * mmio32 = 32-bit MMIO + * and *y* is the MMIO address in hex. with `0x` prefix (eg: 0xFEDC9000) ## Keyboard Selection diff --git a/app/config.c b/app/config.c index 6309c1e..d00d6bb 100644 --- a/app/config.c +++ b/app/config.c @@ -104,11 +104,14 @@ bool pause_at_start = true; power_save_t power_save = POWER_SAVE_HIGH; bool enable_tty = false; -int tty_params_port = SERIAL_PORT_0x3F8; -int tty_params_baud = SERIAL_DEFAULT_BAUDRATE; -int tty_update_period = 2; // Update TTY every 2 seconds (default) +uintptr_t tty_address = 0x3F8; // Legacy IO or MMIO Address accepted +int tty_baud_rate = 115200; +int tty_update_period = 2; // Update TTY every 2 seconds (default) -bool err_banner_redraw = false; // Redraw banner on new errors (if previsouly removed) +uint32_t tty_mmio_ref_clk = UART_REF_CLK_MMIO; // Reference clock for MMIO (in Hz) +int tty_mmio_stride = 4; // Stride for MMIO (register width in bytes) + +bool err_banner_redraw = false; // Redraw banner on new errors //------------------------------------------------------------------------------ // Private Functions @@ -123,6 +126,28 @@ static void parse_serial_params(const char *params) return; } + // Check if console is MMIO and grab address and stride + uintptr_t mmio_adr = 0; + if (strncmp(params, "mmio,0x", 7) == 0) { + mmio_adr = hexstr2int(params+7); + tty_mmio_stride = 1; + } else if (strncmp(params, "mmio16,0x", 9) == 0) { + mmio_adr = hexstr2int(params+9); + tty_mmio_stride = 2; + } else if (strncmp(params, "mmio32,0x", 9) == 0) { + mmio_adr = hexstr2int(params+9); + tty_mmio_stride = 4; + } + + if(strncmp(params, "mmio", 4) == 0) { + if (mmio_adr > 0xFFFF) { + tty_address = mmio_adr; + } else { + enable_tty = false; + } + return; + } + // No TTY port passed, use default ttyS0 if (strncmp(params, "ttyS", 5) == 0) { return; @@ -130,7 +155,7 @@ static void parse_serial_params(const char *params) // Configure TTY port or use default if (params[4] >= '0' && params[4] <= '3') { - tty_params_port = params[4] - '0'; + tty_address = serial_io_ports[params[4] - '0']; } else { return; } @@ -145,27 +170,27 @@ static void parse_serial_params(const char *params) default: return; case '1': - tty_params_baud = (params[7] == '9') ? 19200 : 115200; + tty_baud_rate = (params[7] == '9') ? 19200 : 115200; tty_update_period = (params[7] == '9') ? 4 : 2; break; case '2': - tty_params_baud = 230400; + tty_baud_rate = 230400; tty_update_period = 2; break; case '3': - tty_params_baud = 38400; + tty_baud_rate = 38400; tty_update_period = 4; break; case '5': - tty_params_baud = 57600; + tty_baud_rate = 57600; tty_update_period = 3; break; case '7': - tty_params_baud = 76800; + tty_baud_rate = 76800; tty_update_period = 3; break; case '9': - tty_params_baud = 9600; + tty_baud_rate = 9600; tty_update_period = 5; break; } diff --git a/app/config.h b/app/config.h index d9eb5ba..cf6030a 100644 --- a/app/config.h +++ b/app/config.h @@ -64,9 +64,12 @@ extern bool pause_at_start; extern power_save_t power_save; -extern int tty_params_port; -extern int tty_params_baud; -extern int tty_update_period; +extern uintptr_t tty_address; +extern int tty_baud_rate; +extern int tty_update_period; + +extern uint32_t tty_mmio_ref_clk; +extern int tty_mmio_stride; extern bool err_banner_redraw; diff --git a/lib/string.c b/lib/string.c index e5ddfe1..dfe8274 100644 --- a/lib/string.c +++ b/lib/string.c @@ -9,6 +9,7 @@ // By Chris Brady #include +#include #include "string.h" @@ -92,3 +93,18 @@ char *itoa(int num, char *str) return str; } + +uint32_t hexstr2int(const char *hexstr) { + uint32_t ival = 0; + while (*hexstr) { + uint8_t b = *hexstr++; + + if (b >= '0' && b <= '9') b = b - '0'; + else if (b >= 'a' && b <='f') b = b - 'a' + 10; + else if (b >= 'A' && b <='F') b = b - 'A' + 10; + else return 0; + + ival = (ival << 4) | (b & 0xF); + } + return ival; +} diff --git a/lib/string.h b/lib/string.h index 9bca9af..62f3578 100644 --- a/lib/string.h +++ b/lib/string.h @@ -96,4 +96,11 @@ char *strstr(const char *haystack, const char *needle); char *itoa(int num, char *str); +/** + * Convert a hex string to the corresponding 32-bit uint value. + * returns 0 if a non-hex char is found (not 0-9/a-f/A-F). + */ + +uint32_t hexstr2int(const char *hexstr); + #endif // STRING_H diff --git a/system/serial.c b/system/serial.c index a825318..30776e9 100644 --- a/system/serial.c +++ b/system/serial.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (C) 2004-2022 Sam Demeulemeester +// Copyright (C) 2004-2023 Sam Demeulemeester #include #include @@ -101,13 +101,21 @@ void tty_init(void) unsigned char lcr; console_serial.enable = true; - console_serial.is_mmio = false; + console_serial.base_addr = tty_address; + console_serial.baudrate = tty_baud_rate; console_serial.parity = SERIAL_DEFAULT_PARITY; console_serial.bits = SERIAL_DEFAULT_BITS; - console_serial.baudrate = tty_params_baud; - console_serial.reg_width = 1; - console_serial.refclk = UART_REF_CLK; - console_serial.base_addr = serial_base_ports[tty_params_port]; + + // UART MMIO Address is usually above TOLUD and never < 1MB + if (console_serial.base_addr > 0xFFFF) { + console_serial.is_mmio = true; + console_serial.reg_width = tty_mmio_stride; + console_serial.refclk = tty_mmio_ref_clk; + } else { + console_serial.is_mmio = false; + console_serial.reg_width = 1; + console_serial.refclk = UART_REF_CLK_IO; + } /* read the Divisor Latch */ uart_status = serial_read_reg(&console_serial, UART_LCR); @@ -130,6 +138,12 @@ void tty_init(void) uart_status = serial_read_reg(&console_serial, UART_RX); /* COM? RBR */ serial_write_reg(&console_serial, UART_IER, 0x00); /* Disable all interrupts */ + /* In case of MMIO UART, set up FIFO Reg */ + if (console_serial.is_mmio) { + serial_write_reg(&console_serial, UART_FCR, 0x00); + serial_write_reg(&console_serial, UART_FCR, (0xFF) & (UART_FCR_ENA | UART_FCR_THR)); + } + tty_clear_screen(); tty_disable_cursor(); } diff --git a/system/serial.h b/system/serial.h index 2b73078..df5f97c 100644 --- a/system/serial.h +++ b/system/serial.h @@ -7,10 +7,9 @@ * display via Serial/UART. * *//* - * Copyright (C) 2004-2022 Sam Demeulemeester. + * Copyright (C) 2004-2023 Sam Demeulemeester. */ -#define SERIAL_DEFAULT_BAUDRATE 115200 #define SERIAL_DEFAULT_BITS 8 #define SERIAL_DEFAULT_PARITY 0 @@ -19,7 +18,7 @@ #define SERIAL_PORT_0x3E8 2 #define SERIAL_PORT_0x2E8 3 -static const uint16_t serial_base_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; +static const uint16_t serial_io_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; struct serial_port { bool enable; @@ -49,7 +48,8 @@ struct serial_port { * Definitions for the Base UART Registers */ -#define UART_REF_CLK 1843200 +#define UART_REF_CLK_IO 1843200 +#define UART_REF_CLK_MMIO 48000000 #define UART_RX 0 /* In: Receive buffer (DLAB=0) */ #define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ @@ -103,6 +103,12 @@ struct serial_port { #define UART_IIR_RDI 0x04 /* Receiver data interrupt */ #define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ +/* + * Definitions for the FIFO Control Register + */ +#define UART_FCR_ENA 0x01 /* FIFO Enable */ +#define UART_FCR_THR 0x20 /* FIFO Threshold */ + /* * Definitions for the Interrupt Enable Register */