arch/x86: early_serial cleanup

Various cleanups to the x86 early serial driver, mostly with the goal
of simplifying its deployment during board bringup (which is really
the only reason it exists in the first place):

+ Configure it =y by default.  While there are surely constrained
  environments that will want to disable it, this is a TINY driver,
  and it serves a very important role for niche tasks.  It should be
  built always to make sure it works everywhere.

+ Decouple from devicetree as much as possible.  This code HAS to work
  during board bringup, often with configurations cribbed from other
  machines, before proper configuration gets written.  Experimentally,
  devicetree errors tend to be easy to make, and without a working
  console impossible to diagnose.  Specify the device via integer
  constants in soc.h (in the case of IOPORT access, we already had
  such a symbol) so that the path from what the developer intends to
  what the code executes is as short and obvious as possible.
  Unfortunately I'm not allowed to remove devicetree entirely here,
  but at least a developer adding a new platform will be able to
  override it in an obvious way instead of banging blindly on the
  other side of a DTS compiler.

+ Don't try to probe the PCI device by ID to "verify".  While this
  sounds like a good idea, in practice it's just an extra thing to get
  wrong.  If we bail on our early console because someone (yes, that's
  me) got the bus/device/function right but typoed the VID/DID
  numbers, we're doing no one any favors.

+ Remove the word-sized-I/O feature.  This is a x86 driver for a PCI
  device.  No known PC hardware requires that UART register access be
  done in dword units (in fact doing so would be a violation of the
  PCI specifciation as I understand it).  It looks to have been cut
  and pasted from the ns16550 driver, remove.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2020-06-12 07:59:28 -07:00 committed by Carles Cufí
commit d2eca354e8
5 changed files with 16 additions and 32 deletions

View file

@ -174,6 +174,7 @@ config EXCEPTION_DEBUG
config X86_VERY_EARLY_CONSOLE
bool "Support very early boot printk"
depends on PRINTK
default y
help
Non-emulated X86 devices often require special hardware to attach
a debugger, which may not be easily available. This option adds a

View file

@ -4,19 +4,19 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <devicetree.h>
#include <kernel.h>
#include <sys/util.h>
#include <drivers/pcie/pcie.h>
#include <soc.h>
#if DT_PROP(DT_CHOSEN(zephyr_console), pcie)
BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE");
#define UART_NS16550_PCIE_ENABLED
#include <drivers/pcie/pcie.h>
#define UART_PCIE_BDF (DT_REG_ADDR(DT_CHOSEN(zephyr_console)))
#define UART_PCIE_ID (DT_REG_SIZE(DT_CHOSEN(zephyr_console)))
#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 */
@ -51,38 +51,20 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE");
#define REG_BRDL(x) (x + REG_OFFSET_BRDL * UART_REG_ADDR_INTERVAL)
#define REG_BRDH(x) (x + REG_OFFSET_BRDH * UART_REG_ADDR_INTERVAL)
#if DT_NODE_HAS_PROP(DT_CHOSEN(zephyr_console), reg_shift)
#define UART_REG_ADDR_INTERVAL \
(1 << DT_PROP(DT_CHOSEN(zephyr_console), reg_shift))
#endif
#ifdef UART_NS16550_ACCESS_IOPORT
#define PORT ((io_port_t)DT_REG_ADDR(DT_CHOSEN(zephyr_console)))
#define INBYTE(x) sys_in8(x)
#define INWORD(x) sys_in32(x)
#define OUTBYTE(x, d) sys_out8(d, x)
#define OUTWORD(x, d) sys_out32(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 PORT ((mm_reg_t)DT_REG_ADDR(DT_CHOSEN(zephyr_console)))
#define INBYTE(x) sys_read8(x)
#define INWORD(x) sys_read32(x)
#define OUTBYTE(x, d) sys_write8(d, x)
#define OUTWORD(x, d) sys_write32(d, x)
#ifndef UART_REG_ADDR_INTERVAL
#define UART_REG_ADDR_INTERVAL 4 /* address diff of adjacent regs. */
#endif
#endif /* UART_NS16550_ACCESS_IOPORT */
#ifdef CONFIG_UART_NS16550_ACCESS_WORD_ONLY
#undef INBYTE
#define INBYTE(x) INWORD(x)
#undef OUTBYTE
#define OUTBYTE(x, d) OUTWORD(x, d)
#endif
#ifdef UART_NS16550_PCIE_ENABLED
static mm_reg_t base;
#else
@ -110,10 +92,6 @@ extern void __printk_hook_install(int (*fn)(int));
void z_x86_early_serial_init(void)
{
#ifdef UART_NS16550_PCIE_ENABLED
if (!pcie_probe(UART_PCIE_BDF, UART_PCIE_ID)) {
return;
}
base = pcie_get_mbar(UART_PCIE_BDF, 0);
pcie_set_cmd(UART_PCIE_BDF, PCIE_CONF_CMDSTAT_MEM, true);
#endif

View file

@ -27,4 +27,9 @@
#include "soc_gpio.h"
#endif
#include <drivers/pcie/pcie.h>
/* This expands to "PCIE_BDF(0, 0x18, 0)" on this platform */
#define X86_SOC_EARLY_SERIAL_PCIDEV DT_REG_ADDR(DT_CHOSEN(zephyr_console))
#endif /* __SOC_H_ */

View file

@ -25,7 +25,7 @@
/*
* UART
*/
#define UART_NS16550_ACCESS_IOPORT
#define UART_NS16550_ACCESS_IOPORT 0x3f8
/* PCI definitions */

View file

@ -25,7 +25,7 @@
/*
* UART
*/
#define UART_NS16550_ACCESS_IOPORT
#define UART_NS16550_ACCESS_IOPORT 0x3f8
/* PCI definitions */
#define PCI_BUS_NUMBERS 1