2021-01-12 18:22:11 +00:00
|
|
|
/* SPDX-License-Identifier: MIT */
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include "uart.h"
|
2021-04-15 13:47:33 +00:00
|
|
|
#include "iodev.h"
|
|
|
|
#include "types.h"
|
2021-05-04 18:23:25 +00:00
|
|
|
#include "uart_regs.h"
|
2021-01-12 18:22:11 +00:00
|
|
|
#include "utils.h"
|
|
|
|
#include "vsprintf.h"
|
|
|
|
|
2021-01-14 18:55:20 +00:00
|
|
|
#define UART_CLOCK 24000000
|
|
|
|
|
2021-01-12 18:22:11 +00:00
|
|
|
#define UART_BASE 0x235200000L
|
|
|
|
|
|
|
|
void *pxx = uart_init;
|
|
|
|
|
|
|
|
void uart_init(void)
|
|
|
|
{
|
|
|
|
/* keep UART config from iBoot */
|
|
|
|
}
|
|
|
|
|
|
|
|
void uart_putbyte(u8 c)
|
|
|
|
{
|
|
|
|
while (!(read32(UART_BASE + UTRSTAT) & 0x02))
|
|
|
|
;
|
|
|
|
|
|
|
|
write32(UART_BASE + UTXH, c);
|
|
|
|
}
|
|
|
|
|
2021-01-14 09:18:07 +00:00
|
|
|
u8 uart_getbyte(void)
|
|
|
|
{
|
|
|
|
while (!(read32(UART_BASE + UTRSTAT) & 0x01))
|
|
|
|
;
|
|
|
|
|
|
|
|
return read32(UART_BASE + URXH);
|
|
|
|
}
|
|
|
|
|
|
|
|
void uart_putchar(u8 c)
|
2021-01-12 18:22:11 +00:00
|
|
|
{
|
|
|
|
if (c == '\n')
|
|
|
|
uart_putbyte('\r');
|
|
|
|
|
|
|
|
uart_putbyte(c);
|
|
|
|
}
|
|
|
|
|
2021-01-14 09:18:07 +00:00
|
|
|
u8 uart_getchar(void)
|
|
|
|
{
|
2021-01-14 10:22:38 +00:00
|
|
|
return uart_getbyte();
|
2021-01-14 09:18:07 +00:00
|
|
|
}
|
|
|
|
|
2021-01-12 18:22:11 +00:00
|
|
|
void uart_puts(const char *s)
|
|
|
|
{
|
|
|
|
while (*s)
|
2021-01-14 09:18:07 +00:00
|
|
|
uart_putchar(*(s++));
|
2021-01-12 18:22:11 +00:00
|
|
|
|
2021-01-14 09:18:07 +00:00
|
|
|
uart_putchar('\n');
|
2021-01-12 18:22:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void uart_write(const void *buf, size_t count)
|
|
|
|
{
|
|
|
|
const u8 *p = buf;
|
|
|
|
|
|
|
|
while (count--)
|
|
|
|
uart_putbyte(*p++);
|
|
|
|
}
|
|
|
|
|
2021-01-14 10:22:38 +00:00
|
|
|
size_t uart_read(void *buf, size_t count)
|
2021-01-12 18:22:11 +00:00
|
|
|
{
|
2021-01-14 10:22:38 +00:00
|
|
|
u8 *p = buf;
|
|
|
|
size_t recvd = 0;
|
|
|
|
|
|
|
|
while (count--) {
|
|
|
|
*p++ = uart_getbyte();
|
|
|
|
recvd++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return recvd;
|
2021-01-12 18:22:11 +00:00
|
|
|
}
|
2021-01-14 18:55:20 +00:00
|
|
|
|
|
|
|
void uart_setbaud(int baudrate)
|
|
|
|
{
|
|
|
|
uart_flush();
|
|
|
|
write32(UART_BASE + UBRDIV, ((UART_CLOCK / baudrate + 7) / 16) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void uart_flush(void)
|
|
|
|
{
|
|
|
|
while (!(read32(UART_BASE + UTRSTAT) & 0x04))
|
|
|
|
;
|
|
|
|
}
|
2021-04-15 13:47:33 +00:00
|
|
|
|
2021-05-27 12:09:48 +00:00
|
|
|
int uart_printf(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
char buffer[512];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
i = vsnprintf(buffer, sizeof(buffer), fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
uart_write(buffer, min(i, (int)(sizeof(buffer) - 1)));
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2021-04-15 13:47:33 +00:00
|
|
|
static bool uart_iodev_can_write(void *opaque)
|
|
|
|
{
|
|
|
|
UNUSED(opaque);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool uart_iodev_can_read(void *opaque)
|
|
|
|
{
|
|
|
|
UNUSED(opaque);
|
|
|
|
return read32(UART_BASE + UTRSTAT) & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t uart_iodev_read(void *opaque, void *buf, size_t len)
|
|
|
|
{
|
|
|
|
UNUSED(opaque);
|
|
|
|
return uart_read(buf, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t uart_iodev_write(void *opaque, const void *buf, size_t len)
|
|
|
|
{
|
|
|
|
UNUSED(opaque);
|
|
|
|
uart_write(buf, len);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct iodev_ops iodev_uart_ops = {
|
|
|
|
.can_read = uart_iodev_can_read,
|
|
|
|
.can_write = uart_iodev_can_write,
|
|
|
|
.read = uart_iodev_read,
|
|
|
|
.write = uart_iodev_write,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iodev iodev_uart = {
|
|
|
|
.ops = &iodev_uart_ops,
|
|
|
|
.usage = USAGE_CONSOLE | USAGE_UARTPROXY,
|
|
|
|
};
|