diff --git a/bootloader/soc/clock.c b/bootloader/soc/clock.c index 806d5f8..60a069b 100644 --- a/bootloader/soc/clock.c +++ b/bootloader/soc/clock.c @@ -128,6 +128,29 @@ void clock_enable_uart(u32 idx) clock_enable(&_clock_uart[idx]); } +void clock_disable_uart(u32 idx) +{ + clock_disable(&_clock_uart[idx]); +} + +#define UART_SRC_CLK_DIV_EN (1 << 24) + +int clock_uart_use_src_div(u32 idx, u32 baud) +{ + u32 clk_src_div = CLOCK(_clock_uart[idx].source) & 0xE0000000; + + if (baud == 1000000) + CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 49; + else + { + CLOCK(_clock_uart[idx].source) = clk_src_div | 2; + + return 1; + } + + return 0; +} + void clock_enable_i2c(u32 idx) { clock_enable(&_clock_i2c[idx]); diff --git a/bootloader/soc/clock.h b/bootloader/soc/clock.h index b849cfe..e769b7d 100644 --- a/bootloader/soc/clock.h +++ b/bootloader/soc/clock.h @@ -169,6 +169,8 @@ void clock_disable(const clock_t *clk); /*! Clock control for specific hardware portions. */ void clock_enable_fuse(bool enable); void clock_enable_uart(u32 idx); +void clock_disable_uart(u32 idx); +int clock_uart_use_src_div(u32 idx, u32 baud); void clock_enable_i2c(u32 idx); void clock_disable_i2c(u32 idx); void clock_enable_se(); diff --git a/bootloader/soc/uart.c b/bootloader/soc/uart.c index 57694c4..a788ac7 100644 --- a/bootloader/soc/uart.c +++ b/bootloader/soc/uart.c @@ -15,6 +15,7 @@ */ #include "../soc/uart.h" +#include "../soc/clock.h" #include "../soc/t210.h" #include "../utils/util.h" @@ -28,12 +29,15 @@ void uart_init(u32 idx, u32 baud) // Make sure no data is being sent. uart_wait_idle(idx, UART_TX_IDLE); + // Set clock. + bool clk_type = clock_uart_use_src_div(idx, baud); + // Misc settings. - u32 rate = (8 * baud + 408000000) / (16 * baud); + u32 div = clk_type ? ((8 * baud + 408000000) / (16 * baud)) : 1; // DIV_ROUND_CLOSEST. uart->UART_IER_DLAB = 0; // Disable interrupts. uart->UART_LCR = UART_LCR_DLAB | UART_LCR_WORD_LENGTH_8; // Enable DLAB & set 8n1 mode. - uart->UART_THR_DLAB = (u8)rate; // Divisor latch LSB. - uart->UART_IER_DLAB = (u8)(rate >> 8); // Divisor latch MSB. + uart->UART_THR_DLAB = (u8)div; // Divisor latch LSB. + uart->UART_IER_DLAB = (u8)(div >> 8); // Divisor latch MSB. uart->UART_LCR = UART_LCR_WORD_LENGTH_8; // Disable DLAB. (void)uart->UART_SPR; diff --git a/nyx/nyx_gui/soc/clock.c b/nyx/nyx_gui/soc/clock.c index 0a3b181..f54cfba 100644 --- a/nyx/nyx_gui/soc/clock.c +++ b/nyx/nyx_gui/soc/clock.c @@ -128,6 +128,29 @@ void clock_enable_uart(u32 idx) clock_enable(&_clock_uart[idx]); } +void clock_disable_uart(u32 idx) +{ + clock_disable(&_clock_uart[idx]); +} + +#define UART_SRC_CLK_DIV_EN (1 << 24) + +int clock_uart_use_src_div(u32 idx, u32 baud) +{ + u32 clk_src_div = CLOCK(_clock_uart[idx].source) & 0xE0000000; + + if (baud == 1000000) + CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 49; + else + { + CLOCK(_clock_uart[idx].source) = clk_src_div | 2; + + return 1; + } + + return 0; +} + void clock_enable_i2c(u32 idx) { clock_enable(&_clock_i2c[idx]); diff --git a/nyx/nyx_gui/soc/uart.c b/nyx/nyx_gui/soc/uart.c index 57694c4..a788ac7 100644 --- a/nyx/nyx_gui/soc/uart.c +++ b/nyx/nyx_gui/soc/uart.c @@ -15,6 +15,7 @@ */ #include "../soc/uart.h" +#include "../soc/clock.h" #include "../soc/t210.h" #include "../utils/util.h" @@ -28,12 +29,15 @@ void uart_init(u32 idx, u32 baud) // Make sure no data is being sent. uart_wait_idle(idx, UART_TX_IDLE); + // Set clock. + bool clk_type = clock_uart_use_src_div(idx, baud); + // Misc settings. - u32 rate = (8 * baud + 408000000) / (16 * baud); + u32 div = clk_type ? ((8 * baud + 408000000) / (16 * baud)) : 1; // DIV_ROUND_CLOSEST. uart->UART_IER_DLAB = 0; // Disable interrupts. uart->UART_LCR = UART_LCR_DLAB | UART_LCR_WORD_LENGTH_8; // Enable DLAB & set 8n1 mode. - uart->UART_THR_DLAB = (u8)rate; // Divisor latch LSB. - uart->UART_IER_DLAB = (u8)(rate >> 8); // Divisor latch MSB. + uart->UART_THR_DLAB = (u8)div; // Divisor latch LSB. + uart->UART_IER_DLAB = (u8)(div >> 8); // Divisor latch MSB. uart->UART_LCR = UART_LCR_WORD_LENGTH_8; // Disable DLAB. (void)uart->UART_SPR;