forked from Mirrors/opensbi
11
plat/common/serial/objects.mk
Normal file
11
plat/common/serial/objects.mk
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Copyright (c) 2018 Western Digital Corporation or its affiliates.
|
||||
#
|
||||
# Authors:
|
||||
# Anup Patel <anup.patel@wdc.com>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
|
||||
plat-common-objs-$(PLAT_SERIAL_UART8250) += serial/uart8250.o
|
||||
plat-common-objs-$(PLAT_SERIAL_SIFIVE_UART) += serial/sifive-uart.o
|
73
plat/common/serial/sifive-uart.c
Normal file
73
plat/common/serial/sifive-uart.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sbi/riscv_io.h>
|
||||
#include <plat/serial/sifive-uart.h>
|
||||
|
||||
#define UART_REG_TXFIFO 0
|
||||
#define UART_REG_RXFIFO 1
|
||||
#define UART_REG_TXCTRL 2
|
||||
#define UART_REG_RXCTRL 3
|
||||
#define UART_REG_IE 4
|
||||
#define UART_REG_IP 5
|
||||
#define UART_REG_DIV 6
|
||||
|
||||
#define UART_TXFIFO_FULL 0x80000000
|
||||
#define UART_RXFIFO_EMPTY 0x80000000
|
||||
#define UART_RXFIFO_DATA 0x000000ff
|
||||
#define UART_TXCTRL_TXEN 0x1
|
||||
#define UART_RXCTRL_RXEN 0x1
|
||||
|
||||
static volatile void *uart_base;
|
||||
static u32 uart_in_freq;
|
||||
static u32 uart_baudrate;
|
||||
|
||||
static u32 get_reg(u32 num)
|
||||
{
|
||||
return readl(uart_base + (num * 0x4));
|
||||
}
|
||||
|
||||
static void set_reg(u32 num, u32 val)
|
||||
{
|
||||
writel(val, uart_base + (num * 0x4));
|
||||
}
|
||||
|
||||
void sifive_uart_putc(char ch)
|
||||
{
|
||||
while (get_reg(UART_REG_TXFIFO) & UART_TXFIFO_FULL);
|
||||
|
||||
set_reg(UART_REG_TXFIFO, ch);
|
||||
}
|
||||
|
||||
char sifive_uart_getc(void)
|
||||
{
|
||||
u32 ret = get_reg(UART_REG_RXFIFO);
|
||||
if (!(ret & UART_RXFIFO_EMPTY))
|
||||
return ret & UART_RXFIFO_DATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sifive_uart_init(unsigned long base,
|
||||
u32 in_freq, u32 baudrate)
|
||||
{
|
||||
uart_base = (volatile void *)base;
|
||||
uart_in_freq = in_freq;
|
||||
uart_baudrate = baudrate;
|
||||
|
||||
/* Configure baudrate */
|
||||
set_reg(UART_REG_DIV, (in_freq / baudrate) - 1);
|
||||
/* Disable interrupts */
|
||||
set_reg(UART_REG_IE, 0);
|
||||
/* Enable TX */
|
||||
set_reg(UART_REG_TXCTRL, UART_TXCTRL_TXEN);
|
||||
/* Enable Rx */
|
||||
set_reg(UART_REG_RXCTRL, UART_RXCTRL_RXEN);
|
||||
|
||||
return 0;
|
||||
}
|
117
plat/common/serial/uart8250.c
Normal file
117
plat/common/serial/uart8250.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sbi/riscv_io.h>
|
||||
#include <plat/serial/uart8250.h>
|
||||
|
||||
#define UART_RBR_OFFSET 0 /* In: Recieve Buffer Register */
|
||||
#define UART_THR_OFFSET 0 /* Out: Transmitter Holding Register */
|
||||
#define UART_DLL_OFFSET 0 /* Out: Divisor Latch Low */
|
||||
#define UART_IER_OFFSET 1 /* I/O: Interrupt Enable Register */
|
||||
#define UART_DLM_OFFSET 1 /* Out: Divisor Latch High */
|
||||
#define UART_FCR_OFFSET 2 /* Out: FIFO Control Register */
|
||||
#define UART_IIR_OFFSET 2 /* I/O: Interrupt Identification Register */
|
||||
#define UART_LCR_OFFSET 3 /* Out: Line Control Register */
|
||||
#define UART_MCR_OFFSET 4 /* Out: Modem Control Register */
|
||||
#define UART_LSR_OFFSET 5 /* In: Line Status Register */
|
||||
#define UART_MSR_OFFSET 6 /* In: Modem Status Register */
|
||||
#define UART_SCR_OFFSET 7 /* I/O: Scratch Register */
|
||||
#define UART_MDR1_OFFSET 8 /* I/O: Mode Register */
|
||||
|
||||
#define UART_LSR_FIFOE 0x80 /* Fifo error */
|
||||
#define UART_LSR_TEMT 0x40 /* Transmitter empty */
|
||||
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
|
||||
#define UART_LSR_BI 0x10 /* Break interrupt indicator */
|
||||
#define UART_LSR_FE 0x08 /* Frame error indicator */
|
||||
#define UART_LSR_PE 0x04 /* Parity error indicator */
|
||||
#define UART_LSR_OE 0x02 /* Overrun error indicator */
|
||||
#define UART_LSR_DR 0x01 /* Receiver data ready */
|
||||
#define UART_LSR_BRK_ERROR_BITS 0x1E /* BI, FE, PE, OE bits */
|
||||
|
||||
static volatile void *uart8250_base;
|
||||
static u32 uart8250_in_freq;
|
||||
static u32 uart8250_baudrate;
|
||||
static u32 uart8250_reg_width;
|
||||
static u32 uart8250_reg_shift;
|
||||
|
||||
static u32 get_reg(u32 num)
|
||||
{
|
||||
u32 offset = num << uart8250_reg_shift;
|
||||
|
||||
if (uart8250_reg_width == 1)
|
||||
return readb(uart8250_base + offset);
|
||||
else if (uart8250_reg_width == 2)
|
||||
return readw(uart8250_base + offset);
|
||||
else
|
||||
return readl(uart8250_base + offset);
|
||||
}
|
||||
|
||||
static void set_reg(u32 num, u32 val)
|
||||
{
|
||||
u32 offset = num << uart8250_reg_shift;
|
||||
|
||||
if (uart8250_reg_width == 1)
|
||||
writeb(val, uart8250_base + offset);
|
||||
else if (uart8250_reg_width == 2)
|
||||
writew(val, uart8250_base + offset);
|
||||
else
|
||||
writel(val, uart8250_base + offset);
|
||||
}
|
||||
|
||||
void uart8250_putc(char ch)
|
||||
{
|
||||
while ((get_reg(UART_LSR_OFFSET) & UART_LSR_THRE) == 0);
|
||||
|
||||
set_reg(UART_THR_OFFSET, ch);
|
||||
}
|
||||
|
||||
char uart8250_getc(void)
|
||||
{
|
||||
if (get_reg(UART_LSR_OFFSET) & UART_LSR_DR)
|
||||
return get_reg(UART_RBR_OFFSET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart8250_init(unsigned long base,
|
||||
u32 in_freq, u32 baudrate,
|
||||
u32 reg_shift, u32 reg_width)
|
||||
{
|
||||
u16 bdiv;
|
||||
|
||||
uart8250_base = (volatile void *)base;
|
||||
uart8250_reg_shift = reg_shift;
|
||||
uart8250_reg_width = reg_width;
|
||||
uart8250_in_freq = in_freq;
|
||||
uart8250_baudrate = baudrate;
|
||||
|
||||
bdiv = uart8250_in_freq / (16 * uart8250_baudrate);
|
||||
|
||||
/* Disable all interrupts */
|
||||
set_reg(UART_IER_OFFSET, 0x00);
|
||||
/* Enable DLAB */
|
||||
set_reg(UART_LCR_OFFSET, 0x80);
|
||||
/* Set divisor low byte */
|
||||
set_reg(UART_DLL_OFFSET, bdiv & 0xff);
|
||||
/* Set divisor high byte */
|
||||
set_reg(UART_DLM_OFFSET, (bdiv >> 8) & 0xff);
|
||||
/* 8 bits, no parity, one stop bit */
|
||||
set_reg(UART_LCR_OFFSET, 0x03);
|
||||
/* Enable FIFO */
|
||||
set_reg(UART_FCR_OFFSET, 0x01);
|
||||
/* No modem control DTR RTS */
|
||||
set_reg(UART_MCR_OFFSET, 0x00);
|
||||
/* Clear line status */
|
||||
get_reg(UART_LSR_OFFSET);
|
||||
/* Read receive buffer */
|
||||
get_reg(UART_RBR_OFFSET);
|
||||
/* Set scratchpad */
|
||||
set_reg(UART_SCR_OFFSET, 0x00);
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user