From: "Jan Beulich" <JBeulich@suse.com>
To: xen-devel <xen-devel@lists.xenproject.org>
Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>,
Keir Fraser <keir@xen.org>,
Ian Jackson <Ian.Jackson@eu.citrix.com>, Tim Deegan <tim@xen.org>
Subject: [PATCH 2/4] ns16550: enable Pericom controller support
Date: Tue, 23 Feb 2016 04:28:59 -0700 [thread overview]
Message-ID: <56CC508B02000078000D52B1@prv-mh.provo.novell.com> (raw)
In-Reply-To: <56CC4F0B02000078000D5290@prv-mh.provo.novell.com>
[-- Attachment #1: Type: text/plain, Size: 13748 bytes --]
Other than the controllers supported so far, multiple port Pericom
boards map all of their ports via BAR0, which requires a number of
adjustments: Instead of tracking "max_bars" we now flag whether all
ports use BAR0, and whether to expect a port-I/O or MMIO resource. As
a result pci_uart_config() now gets handed a port index, which it then
maps into a BAR index or an offset into BAR0 depending on the bar0
flag.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -78,10 +78,20 @@ static struct ns16550 {
#endif
} ns16550_com[2] = { { 0 } };
-struct ns16550_config_mmio {
+#ifdef CONFIG_HAS_PCI
+struct ns16550_config {
u16 vendor_id;
u16 dev_id;
- unsigned int param;
+ enum {
+ param_default, /* Must not be referenced by any table entry. */
+ param_trumanage,
+ param_oxford,
+ param_oxford_2port,
+ param_pericom_1port,
+ param_pericom_2port,
+ param_pericom_4port,
+ param_pericom_8port,
+ } param;
};
/* Defining uart config options for MMIO devices */
@@ -90,57 +100,91 @@ struct ns16550_config_param {
unsigned int reg_width;
unsigned int fifo_size;
u8 lsr_mask;
- unsigned int max_bars;
+ bool_t mmio;
+ bool_t bar0;
+ unsigned int max_ports;
unsigned int base_baud;
unsigned int uart_offset;
unsigned int first_offset;
};
-
-#ifdef CONFIG_HAS_PCI
-enum {
- param_default = 0,
- param_trumanage,
- param_oxford,
- param_oxford_2port,
-};
/*
- * Create lookup tables for specific MMIO devices..
- * It is assumed that if the device found is MMIO,
- * then you have indexed it here. Else, the driver
- * does nothing.
+ * Create lookup tables for specific devices. It is assumed that if
+ * the device found is MMIO, then you have indexed it here. Else, the
+ * driver does nothing for MMIO based devices.
*/
static const struct ns16550_config_param __initconst uart_param[] = {
- [param_default] = { }, /* Ignored. */
+ [param_default] = {
+ .reg_width = 1,
+ .lsr_mask = UART_LSR_THRE,
+ .max_ports = 1,
+ },
[param_trumanage] = {
.reg_shift = 2,
.reg_width = 1,
.fifo_size = 16,
.lsr_mask = (UART_LSR_THRE | UART_LSR_TEMT),
- .max_bars = 1,
+ .mmio = 1,
+ .max_ports = 1,
},
[param_oxford] = {
.base_baud = 4000000,
.uart_offset = 0x200,
.first_offset = 0x1000,
.reg_width = 1,
- .reg_shift = 0,
.fifo_size = 16,
.lsr_mask = UART_LSR_THRE,
- .max_bars = 1, /* It can do more, but we would need more custom code.*/
+ .mmio = 1,
+ .max_ports = 1, /* It can do more, but we would need more custom code.*/
},
[param_oxford_2port] = {
.base_baud = 4000000,
.uart_offset = 0x200,
.first_offset = 0x1000,
.reg_width = 1,
- .reg_shift = 0,
.fifo_size = 16,
.lsr_mask = UART_LSR_THRE,
- .max_bars = 2,
+ .mmio = 1,
+ .max_ports = 2,
+ },
+ [param_pericom_1port] = {
+ .base_baud = 921600,
+ .uart_offset = 8,
+ .reg_width = 1,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .max_ports = 1,
+ },
+ [param_pericom_2port] = {
+ .base_baud = 921600,
+ .uart_offset = 8,
+ .reg_width = 1,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .max_ports = 2,
+ },
+ [param_pericom_4port] = {
+ .base_baud = 921600,
+ .uart_offset = 8,
+ .reg_width = 1,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .max_ports = 4,
+ },
+ [param_pericom_8port] = {
+ .base_baud = 921600,
+ .uart_offset = 8,
+ .reg_width = 1,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .max_ports = 8,
}
};
-static const struct ns16550_config_mmio __initconst uart_config[] =
+static const struct ns16550_config __initconst uart_config[] =
{
/* Broadcom TruManage device */
{
@@ -339,6 +383,30 @@ static const struct ns16550_config_mmio
.vendor_id = PCI_VENDOR_ID_OXSEMI,
.dev_id = 0xc4cf,
.param = param_oxford,
+ },
+ /* Pericom PI7C9X7951 Uno UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_PERICOM,
+ .dev_id = 0x7951,
+ .param = param_pericom_1port
+ },
+ /* Pericom PI7C9X7952 Duo UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_PERICOM,
+ .dev_id = 0x7952,
+ .param = param_pericom_2port
+ },
+ /* Pericom PI7C9X7954 Quad UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_PERICOM,
+ .dev_id = 0x7954,
+ .param = param_pericom_4port
+ },
+ /* Pericom PI7C9X7958 Octal UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_PERICOM,
+ .dev_id = 0x7958,
+ .param = param_pericom_8port
}
};
#endif
@@ -629,7 +697,8 @@ static void __init ns16550_init_postirq(
uart->ps_bdf[2]));
else
{
- if ( rangeset_add_range(mmio_ro_ranges,
+ if ( uart->param->mmio &&
+ rangeset_add_range(mmio_ro_ranges,
uart->io_base,
uart->io_base + uart->io_size - 1) )
printk(XENLOG_INFO "Error while adding MMIO range of device to mmio_ro_ranges\n");
@@ -830,12 +899,11 @@ static int __init check_existence(struct
#ifdef CONFIG_HAS_PCI
static int __init
-pci_uart_config(struct ns16550 *uart, bool_t skip_amt, unsigned int bar_idx)
+pci_uart_config(struct ns16550 *uart, bool_t skip_amt, unsigned int idx)
{
u64 orig_base = uart->io_base;
unsigned int b, d, f, nextf, i;
- uart->io_base = 0;
/* NB. Start at bus 1 to avoid AMT: a plug-in card cannot be on bus 0. */
for ( b = skip_amt ? 1 : 0; b < 0x100; b++ )
{
@@ -843,8 +911,10 @@ pci_uart_config(struct ns16550 *uart, bo
{
for ( f = 0; f < 8; f = nextf )
{
+ unsigned int bar_idx = 0, port_idx = idx;
uint32_t bar, bar_64 = 0, len, len_64;
- u64 size;
+ u64 size = 0;
+ const struct ns16550_config_param *param = uart_param;
nextf = (f || (pci_conf_read16(0, b, d, f, PCI_HEADER_TYPE) &
0x80)) ? f + 1 : 8;
@@ -863,15 +933,38 @@ pci_uart_config(struct ns16550 *uart, bo
continue;
}
+ /* Check for params in uart_config lookup table */
+ for ( i = 0; i < ARRAY_SIZE(uart_config); i++)
+ {
+ u16 vendor = pci_conf_read16(0, b, d, f, PCI_VENDOR_ID);
+ u16 device = pci_conf_read16(0, b, d, f, PCI_DEVICE_ID);
+
+ if ( uart_config[i].vendor_id == vendor &&
+ uart_config[i].dev_id == device )
+ {
+ param += uart_config[i].param;
+ if ( !param->bar0 )
+ {
+ bar_idx = idx;
+ port_idx = 0;
+ }
+ break;
+ }
+ }
+
+ if ( port_idx >= param->max_ports )
+ {
+ idx -= param->max_ports;
+ continue;
+ }
+
+ uart->io_base = 0;
bar = pci_conf_read32(0, b, d, f,
PCI_BASE_ADDRESS_0 + bar_idx*4);
/* MMIO based */
- if ( !(bar & PCI_BASE_ADDRESS_SPACE_IO) )
+ if ( param->mmio && !(bar & PCI_BASE_ADDRESS_SPACE_IO) )
{
- u16 vendor = pci_conf_read16(0, b, d, f, PCI_VENDOR_ID);
- u16 device = pci_conf_read16(0, b, d, f, PCI_DEVICE_ID);
-
pci_conf_write32(0, b, d, f,
PCI_BASE_ADDRESS_0 + bar_idx*4, ~0u);
len = pci_conf_read32(0, b, d, f, PCI_BASE_ADDRESS_0 + bar_idx*4);
@@ -895,56 +988,11 @@ pci_uart_config(struct ns16550 *uart, bo
else
size = len & PCI_BASE_ADDRESS_MEM_MASK;
- size &= -size;
-
- /* Check for params in uart_config lookup table */
- for ( i = 0; i < ARRAY_SIZE(uart_config); i++)
- {
- const struct ns16550_config_param *param;
-
- if ( uart_config[i].vendor_id != vendor )
- continue;
-
- if ( uart_config[i].dev_id != device )
- continue;
-
- param = uart_param + uart_config[i].param;
-
- /*
- * Force length of mmio region to be at least
- * 8 bytes times (1 << reg_shift)
- */
- if ( size < (0x8 * (1 << param->reg_shift)) )
- continue;
-
- if ( bar_idx >= param->max_bars )
- continue;
-
- uart->param = param;
-
- if ( param->fifo_size )
- uart->fifo_size = param->fifo_size;
-
- uart->reg_shift = param->reg_shift;
- uart->reg_width = param->reg_width;
- uart->lsr_mask = param->lsr_mask;
- uart->io_base = ((u64)bar_64 << 32) |
- (bar & PCI_BASE_ADDRESS_MEM_MASK);
- uart->io_base += param->first_offset;
- uart->io_base += bar_idx * param->uart_offset;
- if ( param->base_baud )
- uart->clock_hz = param->base_baud * 16;
- size = max(8U << param->reg_shift,
- param->uart_offset);
- break;
- }
-
- /* If we have an io_base, then we succeeded in the lookup */
- if ( !uart->io_base )
- continue;
+ uart->io_base = ((u64)bar_64 << 32) |
+ (bar & PCI_BASE_ADDRESS_MEM_MASK);
}
/* IO based */
- else
+ else if ( !param->mmio && (bar & PCI_BASE_ADDRESS_SPACE_IO) )
{
pci_conf_write32(0, b, d, f,
PCI_BASE_ADDRESS_0 + bar_idx*4, ~0u);
@@ -952,22 +1000,45 @@ pci_uart_config(struct ns16550 *uart, bo
pci_conf_write32(0, b, d, f,
PCI_BASE_ADDRESS_0 + bar_idx*4, bar);
size = len & PCI_BASE_ADDRESS_IO_MASK;
- size &= -size;
-
- /* Not at least 8 bytes */
- if ( size < 8 )
- continue;
uart->io_base = bar & ~PCI_BASE_ADDRESS_SPACE_IO;
}
+ /* If we have an io_base, then we succeeded in the lookup. */
+ if ( !uart->io_base )
+ continue;
+
+ size &= -size;
+
+ /*
+ * Require length of actually used region to be at least
+ * 8 bytes times (1 << reg_shift).
+ */
+ if ( size < param->first_offset +
+ port_idx * param->uart_offset +
+ (8 << param->reg_shift) )
+ continue;
+
+ uart->param = param;
+
+ uart->reg_shift = param->reg_shift;
+ uart->reg_width = param->reg_width;
+ uart->lsr_mask = param->lsr_mask;
+ uart->io_base += param->first_offset +
+ port_idx * param->uart_offset;
+ if ( param->base_baud )
+ uart->clock_hz = param->base_baud * 16;
+ if ( param->fifo_size )
+ uart->fifo_size = param->fifo_size;
+
uart->ps_bdf[0] = b;
uart->ps_bdf[1] = d;
uart->ps_bdf[2] = f;
uart->bar_idx = bar_idx;
uart->bar = bar;
uart->bar64 = bar_64;
- uart->io_size = size;
+ uart->io_size = max(8U << param->reg_shift,
+ param->uart_offset);
uart->irq = pci_conf_read8(0, b, d, f, PCI_INTERRUPT_PIN) ?
pci_conf_read8(0, b, d, f, PCI_INTERRUPT_LINE) : 0;
--- a/xen/include/xen/pci_ids.h
+++ b/xen/include/xen/pci_ids.h
@@ -2,6 +2,8 @@
#define PCI_VENDOR_ID_NVIDIA 0x10de
+#define PCI_VENDOR_ID_PERICOM 0x12d8
+
#define PCI_VENDOR_ID_OXSEMI 0x1415
#define PCI_VENDOR_ID_BROADCOM 0x14e4
[-- Attachment #2: ns16550-Pericom.patch --]
[-- Type: text/plain, Size: 13790 bytes --]
ns16550: enable Pericom controller support
Other than the controllers supported so far, multiple port Pericom
boards map all of their ports via BAR0, which requires a number of
adjustments: Instead of tracking "max_bars" we now flag whether all
ports use BAR0, and whether to expect a port-I/O or MMIO resource. As
a result pci_uart_config() now gets handed a port index, which it then
maps into a BAR index or an offset into BAR0 depending on the bar0
flag.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -78,10 +78,20 @@ static struct ns16550 {
#endif
} ns16550_com[2] = { { 0 } };
-struct ns16550_config_mmio {
+#ifdef CONFIG_HAS_PCI
+struct ns16550_config {
u16 vendor_id;
u16 dev_id;
- unsigned int param;
+ enum {
+ param_default, /* Must not be referenced by any table entry. */
+ param_trumanage,
+ param_oxford,
+ param_oxford_2port,
+ param_pericom_1port,
+ param_pericom_2port,
+ param_pericom_4port,
+ param_pericom_8port,
+ } param;
};
/* Defining uart config options for MMIO devices */
@@ -90,57 +100,91 @@ struct ns16550_config_param {
unsigned int reg_width;
unsigned int fifo_size;
u8 lsr_mask;
- unsigned int max_bars;
+ bool_t mmio;
+ bool_t bar0;
+ unsigned int max_ports;
unsigned int base_baud;
unsigned int uart_offset;
unsigned int first_offset;
};
-
-#ifdef CONFIG_HAS_PCI
-enum {
- param_default = 0,
- param_trumanage,
- param_oxford,
- param_oxford_2port,
-};
/*
- * Create lookup tables for specific MMIO devices..
- * It is assumed that if the device found is MMIO,
- * then you have indexed it here. Else, the driver
- * does nothing.
+ * Create lookup tables for specific devices. It is assumed that if
+ * the device found is MMIO, then you have indexed it here. Else, the
+ * driver does nothing for MMIO based devices.
*/
static const struct ns16550_config_param __initconst uart_param[] = {
- [param_default] = { }, /* Ignored. */
+ [param_default] = {
+ .reg_width = 1,
+ .lsr_mask = UART_LSR_THRE,
+ .max_ports = 1,
+ },
[param_trumanage] = {
.reg_shift = 2,
.reg_width = 1,
.fifo_size = 16,
.lsr_mask = (UART_LSR_THRE | UART_LSR_TEMT),
- .max_bars = 1,
+ .mmio = 1,
+ .max_ports = 1,
},
[param_oxford] = {
.base_baud = 4000000,
.uart_offset = 0x200,
.first_offset = 0x1000,
.reg_width = 1,
- .reg_shift = 0,
.fifo_size = 16,
.lsr_mask = UART_LSR_THRE,
- .max_bars = 1, /* It can do more, but we would need more custom code.*/
+ .mmio = 1,
+ .max_ports = 1, /* It can do more, but we would need more custom code.*/
},
[param_oxford_2port] = {
.base_baud = 4000000,
.uart_offset = 0x200,
.first_offset = 0x1000,
.reg_width = 1,
- .reg_shift = 0,
.fifo_size = 16,
.lsr_mask = UART_LSR_THRE,
- .max_bars = 2,
+ .mmio = 1,
+ .max_ports = 2,
+ },
+ [param_pericom_1port] = {
+ .base_baud = 921600,
+ .uart_offset = 8,
+ .reg_width = 1,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .max_ports = 1,
+ },
+ [param_pericom_2port] = {
+ .base_baud = 921600,
+ .uart_offset = 8,
+ .reg_width = 1,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .max_ports = 2,
+ },
+ [param_pericom_4port] = {
+ .base_baud = 921600,
+ .uart_offset = 8,
+ .reg_width = 1,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .max_ports = 4,
+ },
+ [param_pericom_8port] = {
+ .base_baud = 921600,
+ .uart_offset = 8,
+ .reg_width = 1,
+ .fifo_size = 16,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .max_ports = 8,
}
};
-static const struct ns16550_config_mmio __initconst uart_config[] =
+static const struct ns16550_config __initconst uart_config[] =
{
/* Broadcom TruManage device */
{
@@ -339,6 +383,30 @@ static const struct ns16550_config_mmio
.vendor_id = PCI_VENDOR_ID_OXSEMI,
.dev_id = 0xc4cf,
.param = param_oxford,
+ },
+ /* Pericom PI7C9X7951 Uno UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_PERICOM,
+ .dev_id = 0x7951,
+ .param = param_pericom_1port
+ },
+ /* Pericom PI7C9X7952 Duo UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_PERICOM,
+ .dev_id = 0x7952,
+ .param = param_pericom_2port
+ },
+ /* Pericom PI7C9X7954 Quad UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_PERICOM,
+ .dev_id = 0x7954,
+ .param = param_pericom_4port
+ },
+ /* Pericom PI7C9X7958 Octal UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_PERICOM,
+ .dev_id = 0x7958,
+ .param = param_pericom_8port
}
};
#endif
@@ -629,7 +697,8 @@ static void __init ns16550_init_postirq(
uart->ps_bdf[2]));
else
{
- if ( rangeset_add_range(mmio_ro_ranges,
+ if ( uart->param->mmio &&
+ rangeset_add_range(mmio_ro_ranges,
uart->io_base,
uart->io_base + uart->io_size - 1) )
printk(XENLOG_INFO "Error while adding MMIO range of device to mmio_ro_ranges\n");
@@ -830,12 +899,11 @@ static int __init check_existence(struct
#ifdef CONFIG_HAS_PCI
static int __init
-pci_uart_config(struct ns16550 *uart, bool_t skip_amt, unsigned int bar_idx)
+pci_uart_config(struct ns16550 *uart, bool_t skip_amt, unsigned int idx)
{
u64 orig_base = uart->io_base;
unsigned int b, d, f, nextf, i;
- uart->io_base = 0;
/* NB. Start at bus 1 to avoid AMT: a plug-in card cannot be on bus 0. */
for ( b = skip_amt ? 1 : 0; b < 0x100; b++ )
{
@@ -843,8 +911,10 @@ pci_uart_config(struct ns16550 *uart, bo
{
for ( f = 0; f < 8; f = nextf )
{
+ unsigned int bar_idx = 0, port_idx = idx;
uint32_t bar, bar_64 = 0, len, len_64;
- u64 size;
+ u64 size = 0;
+ const struct ns16550_config_param *param = uart_param;
nextf = (f || (pci_conf_read16(0, b, d, f, PCI_HEADER_TYPE) &
0x80)) ? f + 1 : 8;
@@ -863,15 +933,38 @@ pci_uart_config(struct ns16550 *uart, bo
continue;
}
+ /* Check for params in uart_config lookup table */
+ for ( i = 0; i < ARRAY_SIZE(uart_config); i++)
+ {
+ u16 vendor = pci_conf_read16(0, b, d, f, PCI_VENDOR_ID);
+ u16 device = pci_conf_read16(0, b, d, f, PCI_DEVICE_ID);
+
+ if ( uart_config[i].vendor_id == vendor &&
+ uart_config[i].dev_id == device )
+ {
+ param += uart_config[i].param;
+ if ( !param->bar0 )
+ {
+ bar_idx = idx;
+ port_idx = 0;
+ }
+ break;
+ }
+ }
+
+ if ( port_idx >= param->max_ports )
+ {
+ idx -= param->max_ports;
+ continue;
+ }
+
+ uart->io_base = 0;
bar = pci_conf_read32(0, b, d, f,
PCI_BASE_ADDRESS_0 + bar_idx*4);
/* MMIO based */
- if ( !(bar & PCI_BASE_ADDRESS_SPACE_IO) )
+ if ( param->mmio && !(bar & PCI_BASE_ADDRESS_SPACE_IO) )
{
- u16 vendor = pci_conf_read16(0, b, d, f, PCI_VENDOR_ID);
- u16 device = pci_conf_read16(0, b, d, f, PCI_DEVICE_ID);
-
pci_conf_write32(0, b, d, f,
PCI_BASE_ADDRESS_0 + bar_idx*4, ~0u);
len = pci_conf_read32(0, b, d, f, PCI_BASE_ADDRESS_0 + bar_idx*4);
@@ -895,56 +988,11 @@ pci_uart_config(struct ns16550 *uart, bo
else
size = len & PCI_BASE_ADDRESS_MEM_MASK;
- size &= -size;
-
- /* Check for params in uart_config lookup table */
- for ( i = 0; i < ARRAY_SIZE(uart_config); i++)
- {
- const struct ns16550_config_param *param;
-
- if ( uart_config[i].vendor_id != vendor )
- continue;
-
- if ( uart_config[i].dev_id != device )
- continue;
-
- param = uart_param + uart_config[i].param;
-
- /*
- * Force length of mmio region to be at least
- * 8 bytes times (1 << reg_shift)
- */
- if ( size < (0x8 * (1 << param->reg_shift)) )
- continue;
-
- if ( bar_idx >= param->max_bars )
- continue;
-
- uart->param = param;
-
- if ( param->fifo_size )
- uart->fifo_size = param->fifo_size;
-
- uart->reg_shift = param->reg_shift;
- uart->reg_width = param->reg_width;
- uart->lsr_mask = param->lsr_mask;
- uart->io_base = ((u64)bar_64 << 32) |
- (bar & PCI_BASE_ADDRESS_MEM_MASK);
- uart->io_base += param->first_offset;
- uart->io_base += bar_idx * param->uart_offset;
- if ( param->base_baud )
- uart->clock_hz = param->base_baud * 16;
- size = max(8U << param->reg_shift,
- param->uart_offset);
- break;
- }
-
- /* If we have an io_base, then we succeeded in the lookup */
- if ( !uart->io_base )
- continue;
+ uart->io_base = ((u64)bar_64 << 32) |
+ (bar & PCI_BASE_ADDRESS_MEM_MASK);
}
/* IO based */
- else
+ else if ( !param->mmio && (bar & PCI_BASE_ADDRESS_SPACE_IO) )
{
pci_conf_write32(0, b, d, f,
PCI_BASE_ADDRESS_0 + bar_idx*4, ~0u);
@@ -952,22 +1000,45 @@ pci_uart_config(struct ns16550 *uart, bo
pci_conf_write32(0, b, d, f,
PCI_BASE_ADDRESS_0 + bar_idx*4, bar);
size = len & PCI_BASE_ADDRESS_IO_MASK;
- size &= -size;
-
- /* Not at least 8 bytes */
- if ( size < 8 )
- continue;
uart->io_base = bar & ~PCI_BASE_ADDRESS_SPACE_IO;
}
+ /* If we have an io_base, then we succeeded in the lookup. */
+ if ( !uart->io_base )
+ continue;
+
+ size &= -size;
+
+ /*
+ * Require length of actually used region to be at least
+ * 8 bytes times (1 << reg_shift).
+ */
+ if ( size < param->first_offset +
+ port_idx * param->uart_offset +
+ (8 << param->reg_shift) )
+ continue;
+
+ uart->param = param;
+
+ uart->reg_shift = param->reg_shift;
+ uart->reg_width = param->reg_width;
+ uart->lsr_mask = param->lsr_mask;
+ uart->io_base += param->first_offset +
+ port_idx * param->uart_offset;
+ if ( param->base_baud )
+ uart->clock_hz = param->base_baud * 16;
+ if ( param->fifo_size )
+ uart->fifo_size = param->fifo_size;
+
uart->ps_bdf[0] = b;
uart->ps_bdf[1] = d;
uart->ps_bdf[2] = f;
uart->bar_idx = bar_idx;
uart->bar = bar;
uart->bar64 = bar_64;
- uart->io_size = size;
+ uart->io_size = max(8U << param->reg_shift,
+ param->uart_offset);
uart->irq = pci_conf_read8(0, b, d, f, PCI_INTERRUPT_PIN) ?
pci_conf_read8(0, b, d, f, PCI_INTERRUPT_LINE) : 0;
--- a/xen/include/xen/pci_ids.h
+++ b/xen/include/xen/pci_ids.h
@@ -2,6 +2,8 @@
#define PCI_VENDOR_ID_NVIDIA 0x10de
+#define PCI_VENDOR_ID_PERICOM 0x12d8
+
#define PCI_VENDOR_ID_OXSEMI 0x1415
#define PCI_VENDOR_ID_BROADCOM 0x14e4
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2016-02-23 11:29 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-23 11:22 [PATCH 0/4] ns16550: enable support for Pericom controllers Jan Beulich
2016-02-23 11:28 ` [PATCH 1/4] ns16550: store pointer to config parameters for PCI Jan Beulich
2016-03-07 21:06 ` Konrad Rzeszutek Wilk
2016-02-23 11:28 ` Jan Beulich [this message]
2016-03-07 22:04 ` [PATCH 2/4] ns16550: enable Pericom controller support Konrad Rzeszutek Wilk
2016-03-08 8:48 ` Jan Beulich
2016-03-09 16:52 ` Konrad Rzeszutek Wilk
2016-03-09 17:01 ` Jan Beulich
2016-03-11 2:31 ` Konrad Rzeszutek Wilk
2016-03-11 11:02 ` Jan Beulich
2016-03-22 13:19 ` [PATCH v2 " Jan Beulich
2016-03-28 14:46 ` Konrad Rzeszutek Wilk
2016-02-23 11:30 ` [PATCH 3/4] console: adjust IRQ initialization Jan Beulich
2016-03-07 22:10 ` Konrad Rzeszutek Wilk
2016-02-23 11:30 ` [PATCH RFC 4/4] ns16550: enable use of PCI MSI Jan Beulich
2016-02-29 16:56 ` [PATCH 0/4] ns16550: enable support for Pericom controllers Konrad Rzeszutek Wilk
2016-02-29 17:03 ` Jan Beulich
2016-03-04 13:19 ` Ping: " Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56CC508B02000078000D52B1@prv-mh.provo.novell.com \
--to=jbeulich@suse.com \
--cc=Ian.Campbell@eu.citrix.com \
--cc=Ian.Jackson@eu.citrix.com \
--cc=keir@xen.org \
--cc=tim@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).