mirror of
https://github.com/torvalds/linux
synced 2024-10-17 08:46:50 +00:00
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);
|
||||
};
|
||||
|
||||
struct f815xxa_data {
|
||||
spinlock_t lock;
|
||||
int idx;
|
||||
};
|
||||
|
||||
#define PCI_NUM_BAR_RESOURCES 6
|
||||
|
||||
struct serial_private {
|
||||
|
@ -1707,6 +1712,77 @@ static int pci_fintek_init(struct pci_dev *dev)
|
|||
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,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *port, int idx)
|
||||
|
@ -2819,6 +2895,30 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
|||
.subdevice = PCI_ANY_ID,
|
||||
.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
|
||||
|
@ -3014,6 +3114,9 @@ enum pci_board_num_t {
|
|||
pbn_fintek_4,
|
||||
pbn_fintek_8,
|
||||
pbn_fintek_12,
|
||||
pbn_fintek_F81504A,
|
||||
pbn_fintek_F81508A,
|
||||
pbn_fintek_F81512A,
|
||||
pbn_wch382_2,
|
||||
pbn_wch384_4,
|
||||
pbn_pericom_PI7C9X7951,
|
||||
|
@ -3773,6 +3876,21 @@ static struct pciserial_board pci_boards[] = {
|
|||
.base_baud = 115200,
|
||||
.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] = {
|
||||
.flags = FL_BASE0,
|
||||
.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, 0x1108), .driver_data = pbn_fintek_8 },
|
||||
{ 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 */
|
||||
{ PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 },
|
||||
|
|
Loading…
Reference in a new issue