[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