mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-19 08:52:25 +00:00
thermosphere: uart refactor, now it doesn't work at all
This commit is contained in:
parent
66b047255b
commit
88382f4fc3
6 changed files with 119 additions and 46 deletions
|
@ -23,6 +23,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
case CARDEVICE_UARTA: return 0x178;
|
case CARDEVICE_UARTA: return 0x178;
|
||||||
case CARDEVICE_UARTB: return 0x17C;
|
case CARDEVICE_UARTB: return 0x17C;
|
||||||
case CARDEVICE_UARTC: return 0x1A0;
|
case CARDEVICE_UARTC: return 0x1A0;
|
||||||
|
case CARDEVICE_UARTD: return 0x1C0;
|
||||||
case CARDEVICE_I2C1: return 0x124;
|
case CARDEVICE_I2C1: return 0x124;
|
||||||
case CARDEVICE_I2C5: return 0x128;
|
case CARDEVICE_I2C5: return 0x128;
|
||||||
case CARDEVICE_TZRAM: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
|
@ -46,6 +47,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||||
case CARDEVICE_UARTA: return 0;
|
case CARDEVICE_UARTA: return 0;
|
||||||
case CARDEVICE_UARTB: return 0;
|
case CARDEVICE_UARTB: return 0;
|
||||||
case CARDEVICE_UARTC: return 0;
|
case CARDEVICE_UARTC: return 0;
|
||||||
|
case CARDEVICE_UARTD: return 0;
|
||||||
case CARDEVICE_I2C1: return 6;
|
case CARDEVICE_I2C1: return 6;
|
||||||
case CARDEVICE_I2C5: return 6;
|
case CARDEVICE_I2C5: return 6;
|
||||||
case CARDEVICE_TZRAM: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
|
@ -66,9 +68,10 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||||
|
|
||||||
static inline uint32_t get_clk_source_div(CarDevice dev) {
|
static inline uint32_t get_clk_source_div(CarDevice dev) {
|
||||||
switch (dev) {
|
switch (dev) {
|
||||||
case CARDEVICE_UARTA: return 0;
|
case CARDEVICE_UARTA: return 1 << 24; // enable bit
|
||||||
case CARDEVICE_UARTB: return 0;
|
case CARDEVICE_UARTB: return 1 << 24; // enable bit
|
||||||
case CARDEVICE_UARTC: return 0;
|
case CARDEVICE_UARTC: return 1 << 24; // enable bit
|
||||||
|
case CARDEVICE_UARTD: return 1 << 24; // enable bit
|
||||||
case CARDEVICE_I2C1: return 0;
|
case CARDEVICE_I2C1: return 0;
|
||||||
case CARDEVICE_I2C5: return 0;
|
case CARDEVICE_I2C5: return 0;
|
||||||
case CARDEVICE_TZRAM: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
|
|
|
@ -37,6 +37,7 @@ typedef enum {
|
||||||
CARDEVICE_UARTA = ((0 << 5) | 0x6),
|
CARDEVICE_UARTA = ((0 << 5) | 0x6),
|
||||||
CARDEVICE_UARTB = ((0 << 5) | 0x7),
|
CARDEVICE_UARTB = ((0 << 5) | 0x7),
|
||||||
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
||||||
|
CARDEVICE_UARTD = ((2 << 5) | 0x1),
|
||||||
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
||||||
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
||||||
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
|
|
|
@ -95,7 +95,7 @@ static inline volatile tegra_gpio_t *gpio_get_regs(void)
|
||||||
|
|
||||||
/* Mode select */
|
/* Mode select */
|
||||||
#define GPIO_MODE_GPIO 0
|
#define GPIO_MODE_GPIO 0
|
||||||
#define GPIO_MODE_SFIO 1
|
#define GPIO_MODE_SDIO 1
|
||||||
|
|
||||||
/* Direction */
|
/* Direction */
|
||||||
#define GPIO_DIRECTION_INPUT 0
|
#define GPIO_DIRECTION_INPUT 0
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "car.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "gpio.h"
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// Init uart (hardcoded atm)
|
|
||||||
gpio_configure_mode(TEGRA_GPIO(G, 0), GPIO_MODE_GPIO); // Leave UART-B as GPIO
|
|
||||||
gpio_configure_mode(TEGRA_GPIO(D, 1), GPIO_MODE_SFIO); // Change UART-C to SPIO
|
|
||||||
uart_select(UART_C); // Configure pinmux for UART-C
|
|
||||||
clkrst_reboot(CARDEVICE_UARTC); // Enable UART-C clock
|
|
||||||
uart_init(UART_C, 115200, true);
|
uart_init(UART_C, 115200, true);
|
||||||
|
|
||||||
//uart_send(UART_C, "0123\n", 3);
|
//uart_send(UART_C, "0123\n", 3);
|
||||||
|
|
|
@ -18,8 +18,21 @@
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "car.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
void uart_select(UartDevice dev) {
|
static inline void uart_wait_cycles(u32 baud, u32 num)
|
||||||
|
{
|
||||||
|
udelay((num * 1000000 + 16 * baud - 1) / (16 * baud));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uart_wait_syms(u32 baud, u32 num)
|
||||||
|
{
|
||||||
|
udelay((num * 1000000 + baud - 1) / baud);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_select(UartDevice dev)
|
||||||
|
{
|
||||||
unsigned int id = (unsigned int)dev;
|
unsigned int id = (unsigned int)dev;
|
||||||
PINMUX_AUX_UARTn_TX_0(id) = 0; /* UART */
|
PINMUX_AUX_UARTn_TX_0(id) = 0; /* UART */
|
||||||
PINMUX_AUX_UARTn_RX_0(id) = 0x48; /* UART, enable, pull up */
|
PINMUX_AUX_UARTn_RX_0(id) = 0x48; /* UART, enable, pull up */
|
||||||
|
@ -27,59 +40,119 @@ void uart_select(UartDevice dev) {
|
||||||
PINMUX_AUX_UARTn_CTS_0(id) = 0x44; /* UART, enable, pull down */
|
PINMUX_AUX_UARTn_CTS_0(id) = 0x44; /* UART, enable, pull down */
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_init(UartDevice dev, u32 baud, bool txInverted) {
|
void uart_set_baudrate(UartDevice dev, u32 baud)
|
||||||
|
{
|
||||||
|
//Set baud rate.
|
||||||
volatile uart_t *uart = get_uart_device(dev);
|
volatile uart_t *uart = get_uart_device(dev);
|
||||||
|
|
||||||
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE);
|
// Round to closest (hence the 8 * baud: +0.5)
|
||||||
|
u32 rate = (8 * baud + UART_CLKRATE) / (16 * baud);
|
||||||
|
|
||||||
/* Set baud rate. */
|
// Enable DLAB
|
||||||
u32 rate = (8 * baud + 408000000) / (16 * baud);
|
uart->UART_LCR |= UART_LCR_DLAB;
|
||||||
uart->UART_LCR = UART_LCR_DLAB; /* Enable DLAB. */
|
|
||||||
uart->UART_THR_DLAB = (u8)rate; /* Divisor latch LSB. */
|
|
||||||
uart->UART_IER_DLAB = (u8)(rate >> 8); /* Divisor latch MSB. */
|
|
||||||
uart->UART_LCR = 0; /* Diable DLAB. */
|
|
||||||
|
|
||||||
/* Setup UART in fifo mode. */
|
// Set divisor
|
||||||
uart->UART_IER_DLAB = 0;
|
uart->UART_THR_DLAB = (u8)rate;
|
||||||
uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Enable and clear TX and RX FIFOs. */
|
uart->UART_IER_DLAB = (u8)(rate >> 8);
|
||||||
|
|
||||||
|
// Disable DLAB
|
||||||
|
uart->UART_LCR &= ~UART_LCR_DLAB;
|
||||||
uart->UART_LSR;
|
uart->UART_LSR;
|
||||||
udelay(3 * ((baud + 999999) / baud));
|
|
||||||
uart->UART_LCR = UART_LCR_WD_LENGTH_8; /* Set word length 8. */
|
// Wait 2 characters worth of time
|
||||||
|
uart_wait_syms(baud, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_flush_fifos(UartDevice dev, u32 baud, bool reset)
|
||||||
|
{
|
||||||
|
volatile uart_t *uart = get_uart_device(dev);
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
uart->UART_IIR_FCR &= ~UART_FCR_FCR_EN_FIFO;
|
||||||
|
udelay(60); // From nvidia
|
||||||
|
uart->UART_IIR_FCR |= UART_FCR_TX_CLR | UART_FCR_RX_CLR;
|
||||||
|
uart->UART_IIR_FCR |= UART_FCR_FCR_EN_FIFO;
|
||||||
|
} else {
|
||||||
|
uart->UART_IIR_FCR |= UART_FCR_TX_CLR | UART_FCR_RX_CLR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uart->UART_LSR;
|
||||||
|
|
||||||
|
// Erratum fix
|
||||||
|
uart_wait_cycles(baud, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_init(UartDevice dev, u32 baud, bool txInverted)
|
||||||
|
{
|
||||||
|
volatile uart_t *uart = get_uart_device(dev);
|
||||||
|
|
||||||
|
CarDevice uartCarDevs[] = { CARDEVICE_UARTA, CARDEVICE_UARTB, CARDEVICE_UARTC, CARDEVICE_UARTD };
|
||||||
|
if (dev == UART_C) {
|
||||||
|
gpio_configure_mode(TEGRA_GPIO(G, 0), GPIO_MODE_GPIO); // Leave UART-B as GPIO
|
||||||
|
gpio_configure_mode(TEGRA_GPIO(D, 1), GPIO_MODE_SDIO); // Change UART-C to SPIO
|
||||||
|
// Fixme other uart?
|
||||||
|
}
|
||||||
|
uart_select(dev);
|
||||||
|
clkrst_reboot(uartCarDevs[dev]);
|
||||||
|
|
||||||
uart->UART_MCR = 0;
|
uart->UART_MCR = 0;
|
||||||
uart->UART_MSR = 0;
|
uart->UART_MSR = 0;
|
||||||
uart->UART_IRDA_CSR = txInverted ? 2 : 0;
|
uart->UART_RX_FIFO_CFG = 1; // Reset value
|
||||||
uart->UART_RX_FIFO_CFG = 1; /* Set RX_FIFO trigger level */
|
|
||||||
uart->UART_MIE = 0;
|
uart->UART_MIE = 0;
|
||||||
uart->UART_ASR = 0;
|
uart->UART_ASR = 0;
|
||||||
|
|
||||||
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE | UART_VENDOR_STATE_RX_IDLE);
|
// Enable FIFO, etc
|
||||||
|
uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_16 | UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_1;
|
||||||
|
uart->UART_IRDA_CSR = txInverted ? 2 : 0;
|
||||||
|
uart->UART_LSR;
|
||||||
|
|
||||||
|
// Erratum fix
|
||||||
|
uart_wait_cycles(baud, 3);
|
||||||
|
|
||||||
|
// Set baud rate, etc.
|
||||||
|
uart->UART_LCR = UART_LCR_WD_LENGTH_8;
|
||||||
|
uart_set_baudrate(dev, baud);
|
||||||
|
|
||||||
|
uart_flush_fifos(dev, baud, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function blocks until the UART device (dev) is in the desired state (status). Make sure the desired state can be reached! */
|
// This function blocks until the UART device (dev) is in the desired state (status). Make sure the desired state can be reached!
|
||||||
void uart_wait_idle(UartDevice dev, UartVendorStatus status) {
|
void uart_wait_idle(UartDevice dev, UartVendorStatus status)
|
||||||
while (!(get_uart_device(dev)->UART_VENDOR_STATUS & status)) {
|
{
|
||||||
/* Wait */
|
while (!(get_uart_device(dev)->UART_VENDOR_STATUS & status));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_send(UartDevice dev, const void *buf, size_t len) {
|
void uart_send(UartDevice dev, const void *buf, size_t len)
|
||||||
|
{
|
||||||
volatile uart_t *uart = get_uart_device(dev);
|
volatile uart_t *uart = get_uart_device(dev);
|
||||||
|
const u8 *buf8 = (const u8 *)buf;
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
while (uart->UART_LSR & UART_LSR_TX_FIFO_FULL) {
|
while (uart->UART_LSR & UART_LSR_TX_FIFO_FULL);
|
||||||
/* Wait until the TX FIFO isn't full */
|
uart->UART_THR_DLAB = buf8[i];
|
||||||
}
|
|
||||||
uart->UART_THR_DLAB = *((const u8 *)buf + i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_recv(UartDevice dev, void *buf, size_t len) {
|
void uart_recv(UartDevice dev, void *buf, size_t len)
|
||||||
|
{
|
||||||
volatile uart_t *uart = get_uart_device(dev);
|
volatile uart_t *uart = get_uart_device(dev);
|
||||||
|
u8 *buf8 = (u8 *)buf;
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY) {
|
while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY);
|
||||||
/* Wait until the RX FIFO isn't empty */
|
buf8[i] = uart->UART_THR_DLAB;
|
||||||
}
|
|
||||||
*((u8 *)buf + i) = uart->UART_THR_DLAB;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t uart_recv_max(UartDevice dev, void *buf, size_t maxlen)
|
||||||
|
{
|
||||||
|
volatile uart_t *uart = get_uart_device(dev);
|
||||||
|
u8 *buf8 = (u8 *)buf;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < maxlen && !(uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY); i++) {
|
||||||
|
buf8[i] = uart->UART_THR_DLAB;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define UART_BASE 0x70006000ull
|
#define UART_BASE 0x70006000
|
||||||
|
|
||||||
#define BAUD_115200 115200
|
|
||||||
|
|
||||||
|
#define BAUD_115200 115200
|
||||||
|
#define UART_CLKRATE 408000000
|
||||||
/* Exosphère: add the clkreset values for UART C,D,E */
|
/* Exosphère: add the clkreset values for UART C,D,E */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UART_A = 0,
|
UART_A = 0,
|
||||||
|
@ -156,10 +156,13 @@ typedef struct {
|
||||||
} uart_t;
|
} uart_t;
|
||||||
|
|
||||||
void uart_select(UartDevice dev);
|
void uart_select(UartDevice dev);
|
||||||
|
void uart_set_baudrate(UartDevice dev, u32 baud);
|
||||||
|
void uart_flush_fifos(UartDevice dev, u32 baud, bool reset);
|
||||||
void uart_init(UartDevice dev, u32 baud, bool txInverted);
|
void uart_init(UartDevice dev, u32 baud, bool txInverted);
|
||||||
void uart_wait_idle(UartDevice dev, UartVendorStatus status);
|
void uart_wait_idle(UartDevice dev, UartVendorStatus status);
|
||||||
void uart_send(UartDevice dev, const void *buf, size_t len);
|
void uart_send(UartDevice dev, const void *buf, size_t len);
|
||||||
void uart_recv(UartDevice dev, void *buf, size_t len);
|
void uart_recv(UartDevice dev, void *buf, size_t len);
|
||||||
|
size_t uart_recv_max(UartDevice dev, void *buf, size_t maxlen);
|
||||||
|
|
||||||
static inline volatile uart_t *get_uart_device(UartDevice dev) {
|
static inline volatile uart_t *get_uart_device(UartDevice dev) {
|
||||||
static const size_t offsets[] = {0, 0x40, 0x200, 0x300, 0x400};
|
static const size_t offsets[] = {0, 0x40, 0x200, 0x300, 0x400};
|
||||||
|
|
Loading…
Reference in a new issue