arch/x86/early_serial: General code cleanup
This patch is almost entirely aesthetics, designed to isolate the variant configurations to a simple macro API (just IN/OUT), reduce complexity derived from code pasted out of the larger ns16550 driver, and keep the complexity out of the (very simple!) core code. Useful when hacking on the driver in contexts where it isn't working yet. The sole behavioral change here is that I've removed the runtime printk hook installation in favor of defining an arch_printk_char_out() function which overrides the weak-linked default (that is, we don't need to install a hook, we can be the default hook at startup). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
d2eca354e8
commit
f7dd9856ba
1 changed files with 54 additions and 77 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Intel Corporation
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -7,78 +7,61 @@
|
|||
#include <kernel.h>
|
||||
#include <sys/util.h>
|
||||
#include <drivers/pcie/pcie.h>
|
||||
|
||||
#include <soc.h>
|
||||
|
||||
#if defined(X86_SOC_EARLY_SERIAL_PCIDEV)
|
||||
#define UART_PCIE_BDF X86_SOC_EARLY_SERIAL_PCIDEV
|
||||
#define UART_NS16550_PCIE_ENABLED 1
|
||||
#elif defined(UART_NS16550_ACCESS_IOPORT)
|
||||
#undef UART_NS16550_PCIE_ENABLED
|
||||
#else
|
||||
#error "Incomplete x86 SoC early serial config"
|
||||
#endif
|
||||
|
||||
/* Super-primitive 8250/16550 serial output-only driver, 115200 8n1 */
|
||||
#define REG_OFFSET_THR 0x00 /* Transmitter holding reg. */
|
||||
#define REG_OFFSET_IER 0x01 /* Interrupt enable reg. */
|
||||
#define REG_OFFSET_FCR 0x02 /* FIFO control reg. */
|
||||
#define REG_OFFSET_LCR 0x03 /* Line control reg. */
|
||||
#define REG_OFFSET_MCR 0x04 /* Modem control reg. */
|
||||
#define REG_OFFSET_LSR 0x05 /* Line status reg. */
|
||||
#define REG_OFFSET_BRDL 0x00 /* Baud rate divisor (LSB) */
|
||||
#define REG_OFFSET_BRDH 0x01 /* Baud rate divisor (MSB) */
|
||||
|
||||
#define IER_DISABLE 0x00
|
||||
#define LCR_8N1 (BIT(0) | BIT(1))
|
||||
#define LCR_DLAB_SELECT BIT(7)
|
||||
#define MCR_DTR BIT(0)
|
||||
#define MCR_RTS BIT(1)
|
||||
#define LSR_THRE BIT(5)
|
||||
|
||||
#define FCR_FIFO BIT(0) /* enable XMIT and RCVR FIFO */
|
||||
#define FCR_RCVRCLR BIT(1) /* clear RCVR FIFO */
|
||||
#define FCR_XMITCLR BIT(2) /* clear XMIT FIFO */
|
||||
#define FCR_FIFO_1 0 /* 1 byte in RCVR FIFO */
|
||||
|
||||
/* convenience defines */
|
||||
#define REG_THR(x) (x + REG_OFFSET_THR * UART_REG_ADDR_INTERVAL)
|
||||
#define REG_IER(x) (x + REG_OFFSET_IER * UART_REG_ADDR_INTERVAL)
|
||||
#define REG_FCR(x) (x + REG_OFFSET_FCR * UART_REG_ADDR_INTERVAL)
|
||||
#define REG_LCR(x) (x + REG_OFFSET_LCR * UART_REG_ADDR_INTERVAL)
|
||||
#define REG_MCR(x) (x + REG_OFFSET_MCR * UART_REG_ADDR_INTERVAL)
|
||||
#define REG_LSR(x) (x + REG_OFFSET_LSR * UART_REG_ADDR_INTERVAL)
|
||||
#define REG_BRDL(x) (x + REG_OFFSET_BRDL * UART_REG_ADDR_INTERVAL)
|
||||
#define REG_BRDH(x) (x + REG_OFFSET_BRDH * UART_REG_ADDR_INTERVAL)
|
||||
|
||||
/* Legacy I/O Port Access to a NS16550 UART */
|
||||
#ifdef UART_NS16550_ACCESS_IOPORT
|
||||
#define INBYTE(x) sys_in8(x)
|
||||
#define OUTBYTE(x, d) sys_out8(d, x)
|
||||
#ifndef UART_REG_ADDR_INTERVAL
|
||||
#define UART_REG_ADDR_INTERVAL 1 /* address diff of adjacent regs. */
|
||||
#endif /* UART_REG_ADDR_INTERVAL */
|
||||
#else
|
||||
#define INBYTE(x) sys_read8(x)
|
||||
#define OUTBYTE(x, d) sys_write8(d, x)
|
||||
#ifndef UART_REG_ADDR_INTERVAL
|
||||
#define UART_REG_ADDR_INTERVAL 4 /* address diff of adjacent regs. */
|
||||
#define IN(reg) sys_in8(reg + UART_NS16550_ACCESS_IOPORT)
|
||||
#define OUT(reg, val) sys_out8(val, reg + UART_NS16550_ACCESS_IOPORT)
|
||||
#endif
|
||||
#endif /* UART_NS16550_ACCESS_IOPORT */
|
||||
|
||||
#ifdef UART_NS16550_PCIE_ENABLED
|
||||
static mm_reg_t base;
|
||||
#else
|
||||
#define base PORT
|
||||
/* "Modern" mapping of a UART into a PCI MMIO device. The registers
|
||||
* are still bytes, but spaced at a 32 bit stride instead of packed
|
||||
* together.
|
||||
*/
|
||||
#ifdef X86_SOC_EARLY_SERIAL_PCIDEV
|
||||
static uintptr_t pci_bar;
|
||||
#define IN(reg) (sys_read32(pci_bar + reg * 4) & 0xff)
|
||||
#define OUT(reg, val) sys_write32((val) & 0xff, pci_bar + reg * 4)
|
||||
#endif
|
||||
|
||||
/* Still other devices use a MMIO region containing packed byte
|
||||
* registers
|
||||
*/
|
||||
#ifdef X86_SOC_EARLY_SERIAL_MMIO8_ADDR
|
||||
#define IN(reg) sys_read8(X86_SOC_EARLY_SERIAL_MMIO8_ADDR + reg)
|
||||
#define OUT(reg, val) sys_write8(val, X86_SOC_EARLY_SERIAL_MMIO8_ADDR + reg)
|
||||
#endif
|
||||
|
||||
#define REG_THR 0x00 /* Transmitter holding reg. */
|
||||
#define REG_IER 0x01 /* Interrupt enable reg. */
|
||||
#define REG_FCR 0x02 /* FIFO control reg. */
|
||||
#define REG_LCR 0x03 /* Line control reg. */
|
||||
#define REG_MCR 0x04 /* Modem control reg. */
|
||||
#define REG_LSR 0x05 /* Line status reg. */
|
||||
#define REG_BRDL 0x00 /* Baud rate divisor (LSB) */
|
||||
#define REG_BRDH 0x01 /* Baud rate divisor (MSB) */
|
||||
|
||||
#define IER_DISABLE 0x00
|
||||
#define LCR_8N1 (BIT(0) | BIT(1))
|
||||
#define LCR_DLAB_SELECT BIT(7)
|
||||
#define MCR_DTR BIT(0)
|
||||
#define MCR_RTS BIT(1)
|
||||
#define LSR_THRE BIT(5)
|
||||
|
||||
#define FCR_FIFO BIT(0) /* enable XMIT and RCVR FIFO */
|
||||
#define FCR_RCVRCLR BIT(1) /* clear RCVR FIFO */
|
||||
#define FCR_XMITCLR BIT(2) /* clear XMIT FIFO */
|
||||
#define FCR_FIFO_1 0 /* 1 byte in RCVR FIFO */
|
||||
|
||||
static void serout(int c)
|
||||
{
|
||||
while ((INBYTE(REG_LSR(base)) & LSR_THRE) == 0) {
|
||||
while ((IN(REG_LSR) & LSR_THRE) == 0) {
|
||||
}
|
||||
OUTBYTE(REG_THR(base), c);
|
||||
OUT(REG_THR, c);
|
||||
}
|
||||
|
||||
static int console_out(int c)
|
||||
int arch_printk_char_out(int c)
|
||||
{
|
||||
if (c == '\n') {
|
||||
serout('\r');
|
||||
|
@ -87,26 +70,20 @@ static int console_out(int c)
|
|||
return c;
|
||||
}
|
||||
|
||||
extern void __printk_hook_install(int (*fn)(int));
|
||||
|
||||
void z_x86_early_serial_init(void)
|
||||
{
|
||||
#ifdef UART_NS16550_PCIE_ENABLED
|
||||
base = pcie_get_mbar(UART_PCIE_BDF, 0);
|
||||
pcie_set_cmd(UART_PCIE_BDF, PCIE_CONF_CMDSTAT_MEM, true);
|
||||
#ifdef X86_SOC_EARLY_SERIAL_PCIDEV
|
||||
pci_bar = pcie_get_mbar(X86_SOC_EARLY_SERIAL_PCIDEV, 0);
|
||||
pcie_set_cmd(X86_SOC_EARLY_SERIAL_PCIDEV, PCIE_CONF_CMDSTAT_MEM, true);
|
||||
#endif
|
||||
|
||||
OUTBYTE(REG_IER(base), IER_DISABLE); /* Disable interrupts */
|
||||
OUTBYTE(REG_LCR(base), LCR_DLAB_SELECT);/* DLAB select */
|
||||
OUTBYTE(REG_BRDL(base), 1); /* Baud divisor = 1 */
|
||||
OUTBYTE(REG_BRDH(base), 0);
|
||||
OUTBYTE(REG_LCR(base), LCR_8N1); /* LCR = 8n1 + DLAB off */
|
||||
OUTBYTE(REG_MCR(base), MCR_DTR | MCR_RTS);
|
||||
OUT(REG_IER, IER_DISABLE); /* Disable interrupts */
|
||||
OUT(REG_LCR, LCR_DLAB_SELECT); /* DLAB select */
|
||||
OUT(REG_BRDL, 1); /* Baud divisor = 1 */
|
||||
OUT(REG_BRDH, 0);
|
||||
OUT(REG_LCR, LCR_8N1); /* LCR = 8n1 + DLAB off */
|
||||
OUT(REG_MCR, MCR_DTR | MCR_RTS);
|
||||
|
||||
/* Turn on FIFO. Some hardware needs this before transmitting */
|
||||
OUTBYTE(REG_FCR(base),
|
||||
FCR_FIFO | FCR_FIFO_1 | FCR_RCVRCLR | FCR_XMITCLR);
|
||||
|
||||
/* Will be replaced later when a real serial driver comes up */
|
||||
__printk_hook_install(console_out);
|
||||
OUT(REG_FCR, FCR_FIFO | FCR_FIFO_1 | FCR_RCVRCLR | FCR_XMITCLR);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue