Files
gk-sdk/mcu/riscv/drivers/serial/serial.c
T

200 lines
3.2 KiB
C
Executable File

/* serial.c - print to uart */
#include <platform.h>
#include <serial.h>
#include <common.h>
static int serial_test_enable(void)
{
#ifdef CONFIG_SERIAL_DISABLE
return 0;
#else
return 1;
#endif
}
static void pl01x_putc(char c)
{
/* Wait until there is space in the FIFO */
while (readl(UART_PL01x_FR) & UART_PL01x_FR_TXFF);
/* Send the character */
writel(c, UART_PL01x_DR);
}
static u32 pl01x_getc(void)
{
u32 data;
while (readl(UART_PL01x_FR) & UART_PL01x_FR_RXFE) {
/* Wait until there is data in the FIFO */
}
data = readl(UART_PL01x_DR);
/* Check for an error flag */
if (data & 0xFFFFFF00) {
/* Clear the error */
writel(0xFFFFFFFF, UART_PL01x_ECR);
return 0;
}
return data;
}
void serial_putc(const char c)
{
if (!serial_test_enable())
return;
if (c == '\n')
pl01x_putc('\r');
pl01x_putc(c);
}
char serial_getc(void)
{
return (pl01x_getc() & 0xFF);
}
void serial_puts(const char *s)
{
if (!serial_test_enable())
return;
if (s == NULL)
return;
while (*s) {
serial_putc(*s);
s++;
}
}
void serial_puts_always(const char *s)
{
if (s == NULL)
return;
while (*s) {
if (*s == '\n')
pl01x_putc('\r');
pl01x_putc(*s);
s++;
}
}
void serial_put_dec(u32 dec)
{
u32 num = dec;
char c[20] = {0}; /* size 20 */
int i = 0;
if (!serial_test_enable())
return;
if (num == 0) {
pl01x_putc('0');
return;
}
while (num) {
c[i] = '0' + (num % 10); /* bit size 10 */
++i;
num /= 10; /* bit size 10 */
}
for (i -= 1; i >= 0; --i)
pl01x_putc(c[i]);
}
void serial_put_hex(u32 hex)
{
int i;
char c;
if (!serial_test_enable())
return;
for (i = 28; i >= 0; i -= 4) { /* bit size 28 4 */
c = ((unsigned int)hex >> (unsigned int)i) & 0x0F;
if (c < 10) /* bit size 10 */
c += '0';
else
c += 'A' - 10; /* bit size 10 */
pl01x_putc(c);
}
}
void serial_put_hex_always(u32 hex)
{
int i;
char c;
for (i = 28; i >= 0; i -= 4) { /* bit size 28 4 */
c = ((unsigned int)hex >> (unsigned int)i) & 0x0F;
if (c < 10) /* bit size 10 */
c += '0';
else
c += 'A' - 10; /* bit size 10 */
pl01x_putc(c);
}
}
static void _serial_crg_init(void)
{
u32 tmp;
/* configure pinmux of uart */
/* writel(0x1502, 0x112C00F0);
* writel(0x1402, 0x119800E0); */
/* enable uart clock */
tmp = readl(REG_PERI_CRG110);
tmp |= 1 << 3;
writel(tmp, REG_PERI_CRG110);
/* cancel uart reset */
tmp = readl(REG_PERI_CRG110);
tmp &= ~(1 << 11);
writel(tmp, REG_PERI_CRG110);
}
void serial_init(void)
{
u32 tmp;
u32 divider;
u32 remainder;
u32 fraction;
_serial_crg_init();
/* first, disable everything */
writel(0, UART_PL01x_CR);
/*
* Set baud rate
*
* IBRD = UART_CLK / (16 * BAUD_RATE)
* FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
* / (16 * BAUD_RATE))
*/
tmp = 16 * UART_BAUDRATE;
divider = UART_CLOCK / tmp;
remainder = UART_CLOCK % tmp;
tmp = (8 * remainder) / UART_BAUDRATE;
fraction = (tmp >> 1) + (tmp & 1);
writel(divider, UART_PL01x_IBRD);
writel(fraction, UART_PL01x_FBRD);
writel(UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN, UART_PL01x_LCRH);
/* Finally, enable the UART */
writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
UART_PL011_CR_RXE, UART_PL01x_CR);
return;
}