[PATCH 2/3] i386/pc386: Add IO and memory support to PCI UART devices.

Joel Sherrill joel at rtems.org
Wed Apr 20 22:57:05 UTC 2016


On Wed, Apr 20, 2016 at 2:20 AM, Chris Johns <chrisj at rtems.org> wrote:

> Use the BAR to determine IO and memory mapped support for PCI UART
> boards.
> ---
>  c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c | 150
> ++++++++++++++++-----
>  1 file changed, 113 insertions(+), 37 deletions(-)
>
> diff --git a/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c
> b/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c
> index 60d35e8..7b48248 100644
> --- a/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c
> +++ b/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c
> @@ -36,6 +36,7 @@
>  #ifdef __rtems__
>  #include <stddef.h>
>  #include <stdint.h>
> +#include <i386_io.h>
>  #else
>  #include <sys/cdefs.h>
>  __FBSDID("$FreeBSD$");
> @@ -54,6 +55,7 @@ __FBSDID("$FreeBSD$");
>
>  #include <dev/uart/uart.h>
>  #include <dev/uart/uart_bus.h>
> +
>  #endif
>
>  #define        DEFAULT_RCLK    1843200
> @@ -225,11 +227,11 @@ DRIVER_MODULE(uart, pci, uart_pci_driver,
> uart_devclass, NULL, NULL);
>  #ifdef __rtems__
>
>  #include <bsp.h>
> -// #include <termios.h>
> +#include <bsp/bspimpl.h>
> +
>  #include <stdio.h>
>  #include <stdlib.h>
>
> -// #include <rtems/termiostypes.h>
>  #include <libchip/serial.h>
>  #include <libchip/ns16550.h>
>  #include <rtems/bspIo.h>
> @@ -242,36 +244,58 @@ DRIVER_MODULE(uart, pci, uart_pci_driver,
> uart_devclass, NULL, NULL);
>   * Information saved from PCI scan
>   */
>  typedef struct {
> -  bool      found;
> -  uint32_t  base;
> -  uint8_t   irq;
> -  uint8_t   bus;
> -  uint8_t   slot;
> -  int       ports;
> -  uint32_t  clock;
> +  bool        found;
> +  const char* desc;
> +  uint32_t    base;
> +  uint8_t     irq;
> +  uint8_t     bus;
> +  uint8_t     slot;
> +  int         ports;
> +  uint32_t    clock;
>  } port_instance_conf_t;
>
>  /*
> - *  Register Access Routines
> + *  Memory Mapped Register Access Routines
>   */
> -static uint8_t pci_ns16550_get_register(uint32_t addr, uint8_t i)
> +
> +#define UART_PCI_IO (0)
> +
> +static uint8_t pci_ns16550_mem_get_register(uint32_t addr, uint8_t i)
>  {
>    uint8_t          val = 0;
>    volatile uint32_t *reg = (volatile uint32_t *)(addr + (i*4));
> -
>    val = *reg;
> -  /* printk( "RD(%p -> 0x%02x) ", reg, val ); */
> +  if (UART_PCI_IO)
> +    printk( "RD(%p -> 0x%02x) ", reg, val );
>    return val;
>  }
>
> -static void pci_ns16550_set_register(uint32_t addr, uint8_t i, uint8_t
> val)
> +static void pci_ns16550_mem_set_register(uint32_t addr, uint8_t i,
> uint8_t val)
>  {
>    volatile uint32_t *reg = (volatile uint32_t *)(addr + (i*4));
> -
> -  /* printk( "WR(%p <- 0x%02x) ", reg, val ); */
> +  if (UART_PCI_IO)
> +    printk( "WR(%p <- 0x%02x) ", reg, val );
>    *reg = val;
>  }
>
> +/*
> + *  IO Register Access Routines
> + */
> +static uint8_t pci_ns16550_io_get_register(uint32_t addr, uint8_t i)
> +{
> +  uint8_t val = rtems_inb(addr + i);
> +  if (UART_PCI_IO)
> +    printk( "RD(%p -> 0x%02x) ", addr + i, val );
> +  return val;
> +}
> +
> +static void pci_ns16550_io_set_register(uint32_t addr, uint8_t i, uint8_t
> val)
> +{
> +  if (UART_PCI_IO)
> +    printk( "WR(%p <- 0x%02x) ", addr + i, val );
> +  rtems_outb(addr + i, val);
> +}
> +
>

Is it possible to use the same com access ports that are used for com1-com4?
Or at least move to shared ones?

They are in conscfg.c. It would be good if we could eliminate some code
during
this. :)


>  void pci_uart_probe(void)
>  {
>    port_instance_conf_t  conf[MAX_BOARDS];
> @@ -316,27 +340,28 @@ void pci_uart_probe(void)
>        if ( status == PCIB_ERR_SUCCESS ) {
>         uint8_t  irq;
>         uint32_t base;
> +       bool io;
>
> -        boards++;
> -        conf[instance].found = true;
> -        conf[instance].clock =  pci_ns8250_ids[i].rclk;
> -        conf[instance].ports = 1;
> -        total_ports += conf[instance].ports;
> -
> -       pci_read_config_byte( bus, dev, fun, PCI_INTERRUPT_LINE, &irq );
>         pci_read_config_dword( bus, dev, fun, PCI_BASE_ADDRESS_0, &base );
>
> -       conf[instance].irq  = irq;
> -       conf[instance].base = base;
> -
> -        printk(
> -          "Found %s #%d at 0x%08x IRQ %d with %d clock\n",
> -         pci_ns8250_ids[i].desc,
> -         instance,
> -         conf[instance].base,
> -         conf[instance].irq,
> -         conf[instance].clock
> -        );
> +       /*
> +        * Reject memory mapped 64-bit boards. We need 2 BAR registers and
> the
> +        * driver's base field is only 32-bits any way.
> +        */
> +       io = (base & 1) == 1;
> +       if (io || (!io && (((base >> 1) & 3) != 2))) {
> +         boards++;
> +         conf[instance].found = true;
> +         conf[instance].desc = pci_ns8250_ids[i].desc;
> +         conf[instance].clock =  pci_ns8250_ids[i].rclk;
> +         conf[instance].ports = 1;
> +         total_ports += conf[instance].ports;
> +
> +         pci_read_config_byte( bus, dev, fun, PCI_INTERRUPT_LINE, &irq );
> +
> +         conf[instance].irq  = irq;
> +         conf[instance].base = base;
> +       }
>        }
>      }
>    }
> @@ -352,6 +377,10 @@ void pci_uart_probe(void)
>        port_p = ports;
>        device_instance = 1;
>        for (b = 0; b < MAX_BOARDS; b++) {
> +       uint32_t base = 0;
> +       bool io;
> +       const char* locatable = "";
> +       const char* prefectable = locatable;
>         char name[32];
>         if ( conf[b].found == false )
>           continue;
> @@ -369,21 +398,68 @@ void pci_uart_probe(void)
>           port_p->pDeviceFns    = &ns16550_fns_polled;
>         }
>
> +       /*
> +        * PCI BAR (http://wiki.osdev.org/PCI#Base_Address_Registers):
> +        *
> +        *  Bit 0: 0 = memory, 1 = IO
> +        *
> +        * Memory:
> +        *  Bit 2-1  : 0 = any 32bit address,
> +        *             1 = < 1M
> +        *             2 = any 64bit address
> +        *  Bit 3    : 0 = no, 1 = yes
> +        *  Bit 31-4 : base address (16-byte aligned)
> +        *
> +        * IO:
> +        *  Bit 1    : reserved
> +        *  Bit 31-2 : base address (4-byte aligned)
> +        */
> +
> +       io = (conf[b].base & 1) == 1;
> +
> +       if (io) {
> +         base = conf[b].base & 0xfffffffc;
> +       } else {
> +         int loc = (conf[b].base >> 1) & 3;
> +         if (loc == 0) {
> +           base = conf[b].base & 0xfffffff0;
> +           locatable = ",A32";
> +         } else if (loc == 1) {
> +           base = conf[b].base & 0x0000fff0;
> +           locatable = ",A16";
> +         }
> +         prefectable = (conf[b].base & (1 << 3)) == 0 ? ",no-prefech" :
> ",prefetch";
> +       }
> +
>         port_p->deviceProbe   = NULL;
>         port_p->pDeviceFlow   = NULL;
>         port_p->ulMargin      = 16;
>         port_p->ulHysteresis  = 8;
>         port_p->pDeviceParams = (void *) 9600;
> -       port_p->ulCtrlPort1   = conf[b].base;
> +       port_p->ulCtrlPort1   = base;
>         port_p->ulCtrlPort2   = 0;                   /* NA */
>         port_p->ulDataPort    = 0;                   /* NA */
> -       port_p->getRegister   = pci_ns16550_get_register;
> -       port_p->setRegister   = pci_ns16550_set_register;
> +       if (io) {
> +         port_p->getRegister = pci_ns16550_io_get_register;
> +         port_p->setRegister = pci_ns16550_io_set_register;
> +       } else {
> +         port_p->getRegister = pci_ns16550_mem_get_register;
> +         port_p->setRegister = pci_ns16550_mem_set_register;
> +       }
>         port_p->getData       = NULL;                /* NA */
>         port_p->setData       = NULL;                /* NA */
>         port_p->ulClock       = conf[b].clock;
>         port_p->ulIntVector   = conf[b].irq;
>
> +
> +        printk(
> +          "%s:%d:%s,%s:0x%x%s%s,irq:%d,clk:%d\n", /*  */
> +         name, b, conf[b].desc,
> +         io ? "io" : "mem", base, locatable, prefectable,
> +         conf[b].irq, conf[b].clock
> +        );
> +
> +
>         port_p++;
>        }    /* end boards */
>
> --
> 2.4.6
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20160420/a04dbd19/attachment-0002.html>


More information about the devel mailing list