thermosphere: uart refactor, now it doesn't work at all

This commit is contained in:
TuxSH 2019-07-20 23:24:16 +02:00
parent 66b047255b
commit 88382f4fc3
6 changed files with 119 additions and 46 deletions

View file

@ -23,6 +23,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
case CARDEVICE_UARTA: return 0x178;
case CARDEVICE_UARTB: return 0x17C;
case CARDEVICE_UARTC: return 0x1A0;
case CARDEVICE_UARTD: return 0x1C0;
case CARDEVICE_I2C1: return 0x124;
case CARDEVICE_I2C5: return 0x128;
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_UARTB: return 0;
case CARDEVICE_UARTC: return 0;
case CARDEVICE_UARTD: return 0;
case CARDEVICE_I2C1: return 6;
case CARDEVICE_I2C5: return 6;
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) {
switch (dev) {
case CARDEVICE_UARTA: return 0;
case CARDEVICE_UARTB: return 0;
case CARDEVICE_UARTC: return 0;
case CARDEVICE_UARTA: return 1 << 24; // enable bit
case CARDEVICE_UARTB: return 1 << 24; // enable bit
case CARDEVICE_UARTC: return 1 << 24; // enable bit
case CARDEVICE_UARTD: return 1 << 24; // enable bit
case CARDEVICE_I2C1: return 0;
case CARDEVICE_I2C5: return 0;
case CARDEVICE_TZRAM: return 0;

View file

@ -37,6 +37,7 @@ typedef enum {
CARDEVICE_UARTA = ((0 << 5) | 0x6),
CARDEVICE_UARTB = ((0 << 5) | 0x7),
CARDEVICE_UARTC = ((1 << 5) | 0x17),
CARDEVICE_UARTD = ((2 << 5) | 0x1),
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),

View file

@ -95,7 +95,7 @@ static inline volatile tegra_gpio_t *gpio_get_regs(void)
/* Mode select */
#define GPIO_MODE_GPIO 0
#define GPIO_MODE_SFIO 1
#define GPIO_MODE_SDIO 1
/* Direction */
#define GPIO_DIRECTION_INPUT 0

View file

@ -1,16 +1,9 @@
#include "utils.h"
#include "uart.h"
#include "car.h"
#include "log.h"
#include "gpio.h"
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_send(UART_C, "0123\n", 3);

View file

@ -18,8 +18,21 @@
#include "timers.h"
#include "uart.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;
PINMUX_AUX_UARTn_TX_0(id) = 0; /* UART */
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 */
}
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);
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. */
u32 rate = (8 * baud + 408000000) / (16 * baud);
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. */
// Enable DLAB
uart->UART_LCR |= UART_LCR_DLAB;
/* Setup UART in fifo mode. */
uart->UART_IER_DLAB = 0;
uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Enable and clear TX and RX FIFOs. */
// Set divisor
uart->UART_THR_DLAB = (u8)rate;
uart->UART_IER_DLAB = (u8)(rate >> 8);
// Disable DLAB
uart->UART_LCR &= ~UART_LCR_DLAB;
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_MSR = 0;
uart->UART_IRDA_CSR = txInverted ? 2 : 0;
uart->UART_RX_FIFO_CFG = 1; /* Set RX_FIFO trigger level */
uart->UART_RX_FIFO_CFG = 1; // Reset value
uart->UART_MIE = 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! */
void uart_wait_idle(UartDevice dev, UartVendorStatus status) {
while (!(get_uart_device(dev)->UART_VENDOR_STATUS & status)) {
/* Wait */
}
// 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)
{
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);
const u8 *buf8 = (const u8 *)buf;
for (size_t i = 0; i < len; i++) {
while (uart->UART_LSR & UART_LSR_TX_FIFO_FULL) {
/* Wait until the TX FIFO isn't full */
}
uart->UART_THR_DLAB = *((const u8 *)buf + i);
while (uart->UART_LSR & UART_LSR_TX_FIFO_FULL);
uart->UART_THR_DLAB = buf8[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);
u8 *buf8 = (u8 *)buf;
for (size_t i = 0; i < len; i++) {
while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY) {
/* Wait until the RX FIFO isn't empty */
}
*((u8 *)buf + i) = uart->UART_THR_DLAB;
while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY);
buf8[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;
}

View file

@ -18,10 +18,10 @@
#pragma once
#include "utils.h"
#define UART_BASE 0x70006000ull
#define BAUD_115200 115200
#define UART_BASE 0x70006000
#define BAUD_115200 115200
#define UART_CLKRATE 408000000
/* Exosphère: add the clkreset values for UART C,D,E */
typedef enum {
UART_A = 0,
@ -156,10 +156,13 @@ typedef struct {
} uart_t;
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_wait_idle(UartDevice dev, UartVendorStatus status);
void uart_send(UartDevice dev, const 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 const size_t offsets[] = {0, 0x40, 0x200, 0x300, 0x400};