serial: 8250_pci: Add F81504A series Support
Fintek F81504A/508A/512A is PCIE to 4/8/12 UARTs device. It's support IO/MMIO/PCIE conf to access all functions. The old F81504/508/512 is only support IO. Signed-off-by: Ji-Ze Hong (Peter Hong) <hpeter+linux_kernel@gmail.com> Link: https://lore.kernel.org/r/1565933249-23076-1-git-send-email-hpeter+linux_kernel@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
4ad8e34d1f
commit
68e26a8d22
|
@ -43,6 +43,11 @@ struct pci_serial_quirk {
|
||||||
void (*exit)(struct pci_dev *dev);
|
void (*exit)(struct pci_dev *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct f815xxa_data {
|
||||||
|
spinlock_t lock;
|
||||||
|
int idx;
|
||||||
|
};
|
||||||
|
|
||||||
#define PCI_NUM_BAR_RESOURCES 6
|
#define PCI_NUM_BAR_RESOURCES 6
|
||||||
|
|
||||||
struct serial_private {
|
struct serial_private {
|
||||||
|
@ -1707,6 +1712,77 @@ static int pci_fintek_init(struct pci_dev *dev)
|
||||||
return max_port;
|
return max_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void f815xxa_mem_serial_out(struct uart_port *p, int offset, int value)
|
||||||
|
{
|
||||||
|
struct f815xxa_data *data = p->private_data;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&data->lock, flags);
|
||||||
|
writeb(value, p->membase + offset);
|
||||||
|
readb(p->membase + UART_SCR); /* Dummy read for flush pcie tx queue */
|
||||||
|
spin_unlock_irqrestore(&data->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pci_fintek_f815xxa_setup(struct serial_private *priv,
|
||||||
|
const struct pciserial_board *board,
|
||||||
|
struct uart_8250_port *port, int idx)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = priv->dev;
|
||||||
|
struct f815xxa_data *data;
|
||||||
|
|
||||||
|
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||||
|
if (!data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data->idx = idx;
|
||||||
|
spin_lock_init(&data->lock);
|
||||||
|
|
||||||
|
port->port.private_data = data;
|
||||||
|
port->port.iotype = UPIO_MEM;
|
||||||
|
port->port.flags |= UPF_IOREMAP;
|
||||||
|
port->port.mapbase = pci_resource_start(pdev, 0) + 8 * idx;
|
||||||
|
port->port.serial_out = f815xxa_mem_serial_out;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pci_fintek_f815xxa_init(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
u32 max_port, i;
|
||||||
|
int config_base;
|
||||||
|
|
||||||
|
if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
switch (dev->device) {
|
||||||
|
case 0x1204: /* 4 ports */
|
||||||
|
case 0x1208: /* 8 ports */
|
||||||
|
max_port = dev->device & 0xff;
|
||||||
|
break;
|
||||||
|
case 0x1212: /* 12 ports */
|
||||||
|
max_port = 12;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set to mmio decode */
|
||||||
|
pci_write_config_byte(dev, 0x209, 0x40);
|
||||||
|
|
||||||
|
for (i = 0; i < max_port; ++i) {
|
||||||
|
/* UART0 configuration offset start from 0x2A0 */
|
||||||
|
config_base = 0x2A0 + 0x08 * i;
|
||||||
|
|
||||||
|
/* Select 128-byte FIFO and 8x FIFO threshold */
|
||||||
|
pci_write_config_byte(dev, config_base + 0x01, 0x33);
|
||||||
|
|
||||||
|
/* Enable UART I/O port */
|
||||||
|
pci_write_config_byte(dev, config_base + 0, 0x01);
|
||||||
|
}
|
||||||
|
|
||||||
|
return max_port;
|
||||||
|
}
|
||||||
|
|
||||||
static int skip_tx_en_setup(struct serial_private *priv,
|
static int skip_tx_en_setup(struct serial_private *priv,
|
||||||
const struct pciserial_board *board,
|
const struct pciserial_board *board,
|
||||||
struct uart_8250_port *port, int idx)
|
struct uart_8250_port *port, int idx)
|
||||||
|
@ -2819,6 +2895,30 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||||
.subdevice = PCI_ANY_ID,
|
.subdevice = PCI_ANY_ID,
|
||||||
.setup = pci_moxa_setup,
|
.setup = pci_moxa_setup,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.vendor = 0x1c29,
|
||||||
|
.device = 0x1204,
|
||||||
|
.subvendor = PCI_ANY_ID,
|
||||||
|
.subdevice = PCI_ANY_ID,
|
||||||
|
.setup = pci_fintek_f815xxa_setup,
|
||||||
|
.init = pci_fintek_f815xxa_init,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.vendor = 0x1c29,
|
||||||
|
.device = 0x1208,
|
||||||
|
.subvendor = PCI_ANY_ID,
|
||||||
|
.subdevice = PCI_ANY_ID,
|
||||||
|
.setup = pci_fintek_f815xxa_setup,
|
||||||
|
.init = pci_fintek_f815xxa_init,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.vendor = 0x1c29,
|
||||||
|
.device = 0x1212,
|
||||||
|
.subvendor = PCI_ANY_ID,
|
||||||
|
.subdevice = PCI_ANY_ID,
|
||||||
|
.setup = pci_fintek_f815xxa_setup,
|
||||||
|
.init = pci_fintek_f815xxa_init,
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default "match everything" terminator entry
|
* Default "match everything" terminator entry
|
||||||
|
@ -3014,6 +3114,9 @@ enum pci_board_num_t {
|
||||||
pbn_fintek_4,
|
pbn_fintek_4,
|
||||||
pbn_fintek_8,
|
pbn_fintek_8,
|
||||||
pbn_fintek_12,
|
pbn_fintek_12,
|
||||||
|
pbn_fintek_F81504A,
|
||||||
|
pbn_fintek_F81508A,
|
||||||
|
pbn_fintek_F81512A,
|
||||||
pbn_wch382_2,
|
pbn_wch382_2,
|
||||||
pbn_wch384_4,
|
pbn_wch384_4,
|
||||||
pbn_pericom_PI7C9X7951,
|
pbn_pericom_PI7C9X7951,
|
||||||
|
@ -3773,6 +3876,21 @@ static struct pciserial_board pci_boards[] = {
|
||||||
.base_baud = 115200,
|
.base_baud = 115200,
|
||||||
.first_offset = 0x40,
|
.first_offset = 0x40,
|
||||||
},
|
},
|
||||||
|
[pbn_fintek_F81504A] = {
|
||||||
|
.num_ports = 4,
|
||||||
|
.uart_offset = 8,
|
||||||
|
.base_baud = 115200,
|
||||||
|
},
|
||||||
|
[pbn_fintek_F81508A] = {
|
||||||
|
.num_ports = 8,
|
||||||
|
.uart_offset = 8,
|
||||||
|
.base_baud = 115200,
|
||||||
|
},
|
||||||
|
[pbn_fintek_F81512A] = {
|
||||||
|
.num_ports = 12,
|
||||||
|
.uart_offset = 8,
|
||||||
|
.base_baud = 115200,
|
||||||
|
},
|
||||||
[pbn_wch382_2] = {
|
[pbn_wch382_2] = {
|
||||||
.flags = FL_BASE0,
|
.flags = FL_BASE0,
|
||||||
.num_ports = 2,
|
.num_ports = 2,
|
||||||
|
@ -5719,6 +5837,9 @@ static const struct pci_device_id serial_pci_tbl[] = {
|
||||||
{ PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 },
|
{ PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 },
|
||||||
{ PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 },
|
{ PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 },
|
||||||
{ PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 },
|
{ PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 },
|
||||||
|
{ PCI_DEVICE(0x1c29, 0x1204), .driver_data = pbn_fintek_F81504A },
|
||||||
|
{ PCI_DEVICE(0x1c29, 0x1208), .driver_data = pbn_fintek_F81508A },
|
||||||
|
{ PCI_DEVICE(0x1c29, 0x1212), .driver_data = pbn_fintek_F81512A },
|
||||||
|
|
||||||
/* MKS Tenta SCOM-080x serial cards */
|
/* MKS Tenta SCOM-080x serial cards */
|
||||||
{ PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 },
|
{ PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 },
|
||||||
|
|
Loading…
Reference in New Issue