/* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
/* * init function returns: * > 0 - number of ports * = 0 - use board->num_ports * < 0 - error
*/ struct pci_serial_quirk {
u32 vendor;
u32 device;
u32 subvendor;
u32 subdevice; int (*probe)(struct pci_dev *dev); int (*init)(struct pci_dev *dev); int (*setup)(struct serial_private *, conststruct pciserial_board *, struct uart_8250_port *, int); void (*exit)(struct pci_dev *dev);
};
struct f815xxa_data {
spinlock_t lock; int idx;
};
return setup_port(priv, port, bar, offset, board->reg_shift);
}
/* * AFAVLAB uses a different mixture of BARs and offsets * Not that ugly ;) -- HW
*/ staticint
afavlab_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *port, int idx)
{ unsignedint bar, offset = board->first_offset;
bar = FL_GET_BASE(board->flags); if (idx < 4)
bar += idx; else {
bar = 4;
offset += (idx - 4) * board->uart_offset;
}
return setup_port(priv, port, bar, offset, board->reg_shift);
}
/* * HP's Remote Management Console. The Diva chip came in several * different versions. N-class, L2000 and A500 have two Diva chips, each * with 3 UARTs (the third UART on the second chip is unused). Superdome * and Keystone have one Diva chip with 3 UARTs. Some later machines have * one Diva chip, but it has been expanded to 5 UARTs.
*/ staticint pci_hp_diva_init(struct pci_dev *dev)
{ int rc = 0;
switch (dev->subsystem_device) { case PCI_DEVICE_ID_HP_DIVA_TOSCA1: case PCI_DEVICE_ID_HP_DIVA_HALFDOME: case PCI_DEVICE_ID_HP_DIVA_KEYSTONE: case PCI_DEVICE_ID_HP_DIVA_EVEREST:
rc = 3; break; case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
rc = 2; break; case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
rc = 4; break; case PCI_DEVICE_ID_HP_DIVA_POWERBAR: case PCI_DEVICE_ID_HP_DIVA_HURRICANE:
rc = 1; break;
}
return rc;
}
/* * HP's Diva chip puts the 4th/5th serial port further out, and * some serial ports are supposed to be hidden on certain models.
*/ staticint
pci_hp_diva_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *port, int idx)
{ unsignedint offset = board->first_offset; unsignedint bar = FL_GET_BASE(board->flags);
switch (priv->dev->subsystem_device) { case PCI_DEVICE_ID_HP_DIVA_MAESTRO: if (idx == 3)
idx++; break; case PCI_DEVICE_ID_HP_DIVA_EVEREST: if (idx > 0)
idx++; if (idx > 2)
idx++; break;
} if (idx > 2)
offset = 0x18;
offset += idx * board->uart_offset;
return setup_port(priv, port, bar, offset, board->reg_shift);
}
/* * Added for EKF Intel i960 serial boards
*/ staticint pci_inteli960ni_init(struct pci_dev *dev)
{
u32 oldval;
if (!(dev->subsystem_device & 0x1000)) return -ENODEV;
/* is firmware started? */
pci_read_config_dword(dev, 0x44, &oldval); if (oldval == 0x00001000L) { /* RESET value */
pci_dbg(dev, "Local i960 firmware missing\n"); return -ENODEV;
} return 0;
}
/* * Some PCI serial cards using the PLX 9050 PCI interface chip require * that the card interrupt be explicitly enabled or disabled. This * seems to be mainly needed on card using the PLX which also use I/O * mapped memory.
*/ staticint pci_plx9050_init(struct pci_dev *dev)
{
u8 irq_config; void __iomem *p;
if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
moan_device("no memory in bar 0", dev); return 0;
}
if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
(dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) /* * As the megawolf cards have the int pins active * high, and have 2 UART chips, both ints must be * enabled on the 9050. Also, the UARTS are set in * 16450 mode by default, so we have to enable the * 16C950 'enhanced' mode so that we can use the * deep FIFOs
*/
irq_config = 0x5b; /* * enable/disable interrupts
*/
p = ioremap(pci_resource_start(dev, 0), 0x80); if (p == NULL) return -ENOMEM;
writel(irq_config, p + 0x4c);
/* * Read the register back to ensure that it took effect.
*/
readl(p + 0x4c);
iounmap(p);
if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
moan_device("no memory in bar", dev); return;
}
p = pci_ioremap_bar(dev, bar); if (p == NULL) return;
/* Disable the CPU Interrupt */
writel(MITE_LCIMR2_CLR_CPU_IE, p + MITE_LCIMR2);
iounmap(p);
}
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ staticint
sbs_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *port, int idx)
{ unsignedint bar, offset = board->first_offset;
bar = 0;
if (idx < 4) { /* first four channels map to 0, 0x100, 0x200, 0x300 */
offset += idx * board->uart_offset;
} elseif (idx < 8) { /* last four channels map to 0x1000, 0x1100, 0x1200, 0x1300 */
offset += idx * board->uart_offset + 0xC00;
} else/* we have only 8 ports on PMC-OCTALPRO */ return 1;
return setup_port(priv, port, bar, offset, board->reg_shift);
}
/* * This does initialization for PMC OCTALPRO cards: * maps the device memory, resets the UARTs (needed, bc * if the module is removed and inserted again, the card * is in the sleep mode) and enables global interrupt.
*/
/* global control register offset for SBS PMC-OctalPro */ #define OCT_REG_CR_OFF 0x500
if (p == NULL) return -ENOMEM; /* Set bit-4 Control Register (UART RESET) in to reset the uarts */
writeb(0x10, p + OCT_REG_CR_OFF);
udelay(50);
writeb(0x0, p + OCT_REG_CR_OFF);
/* Set bit-2 (INTENABLE) of Control Register */
writeb(0x4, p + OCT_REG_CR_OFF);
iounmap(p);
return 0;
}
/* * Disables the global interrupt of PMC-OctalPro
*/
p = pci_ioremap_bar(dev, 0); /* FIXME: What if resource_len < OCT_REG_CR_OFF */ if (p != NULL)
writeb(0, p + OCT_REG_CR_OFF);
iounmap(p);
}
/* * SIIG serial cards have an PCI interface chip which also controls * the UART clocking frequency. Each UART can be clocked independently * (except cards equipped with 4 UARTs) and initial clocking settings * are stored in the EEPROM chip. It can cause problems because this * version of serial driver doesn't support differently clocked UART's * on single PCI card. To prevent this, initialization functions set * high frequency clocking for all UART's on given card. It is safe (I * hope) because it doesn't touch EEPROM settings to prevent conflicts * with other OSes (like M$ DOS). * * SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999 * * There is two family of SIIG serial cards with different PCI * interface chip and different configuration methods: * - 10x cards have control registers in IO and/or memory space; * - 20x cards have control registers in standard PCI configuration space. * * Note: all 10x cards have PCI device ids 0x10.. * all 20x cards have PCI device ids 0x20.. * * There are also Quartet Serial cards which use Oxford Semiconductor * 16954 quad UART PCI chip clocked by 18.432 MHz quartz. * * Note: some SIIG cards are probed by the parport_serial object.
*/
/* Change clock frequency for the first UART. */
pci_read_config_byte(dev, 0x6f, &data);
pci_write_config_byte(dev, 0x6f, data & 0xef);
/* If this card has 2 UART, we have to do the same with second UART. */ if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
pci_read_config_byte(dev, 0x73, &data);
pci_write_config_byte(dev, 0x73, data & 0xef);
} return 0;
}
/* * Timedia has an explosion of boards, and to avoid the PCI table from * growing *huge*, we use this function to collapse some 70 entries * in the PCI table into one, for sanity's and compactness's sake.
*/ staticconstunsignedshort timedia_single_port[] = {
0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0
};
/* * There are nearly 70 different Timedia/SUNIX PCI serial devices. Instead of * listing them individually, this driver merely grabs them all with * PCI_ANY_ID. Some of these devices, however, also feature a parallel port, * and should be left free to be claimed by parport_serial instead.
*/ staticint pci_timedia_probe(struct pci_dev *dev)
{ /* * Check the third digit of the subdevice ID * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
*/ if ((dev->subsystem_device & 0x00f0) >= 0x70) {
pci_info(dev, "ignoring Timedia subdevice %04x for parport_serial\n",
dev->subsystem_device); return -ENODEV;
}
return 0;
}
staticint pci_timedia_init(struct pci_dev *dev)
{ constunsignedshort *ids; int i, j;
for (i = 0; i < ARRAY_SIZE(timedia_data); i++) {
ids = timedia_data[i].ids; for (j = 0; ids[j]; j++) if (dev->subsystem_device == ids[j]) return timedia_data[i].num;
} return 0;
}
/* * Timedia/SUNIX uses a mixture of BARs and offsets * Ugh, this is ugly as all hell --- TYT
*/ staticint
pci_timedia_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *port, int idx)
{ unsignedint bar = 0, offset = board->first_offset;
switch (idx) { case 0:
bar = 0; break; case 1:
offset = board->uart_offset;
bar = 0; break; case 2:
bar = 1; break; case 3:
offset = board->uart_offset;
fallthrough; case 4: /* BAR 2 */ case 5: /* BAR 3 */ case 6: /* BAR 4 */ case 7: /* BAR 5 */
bar = idx - 2;
}
return setup_port(priv, port, bar, offset, board->reg_shift);
}
/* * Some Titan cards are also a little weird
*/ staticint
titan_400l_800l_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *port, int idx)
{ unsignedint bar, offset = board->first_offset;
switch (idx) { case 0:
bar = 1; break; case 1:
bar = 2; break; default:
bar = 4;
offset = (idx - 2) * board->uart_offset;
}
return setup_port(priv, port, bar, offset, board->reg_shift);
}
if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) {
moan_device("no memory in bar", dev); return 0;
}
p = pci_ioremap_bar(dev, bar); if (p == NULL) return -ENOMEM;
/* * Set device window address and size in BAR0, while acknowledging that * the resource structure may contain a translated address that differs * from the address the device responds to.
*/
pcibios_resource_to_bus(dev->bus, ®ion, &dev->resource[bar]);
device_window = ((region.start + MITE_IOWBSR1_WIN_OFFSET) & 0xffffff00)
| MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE;
writel(device_window, p + MITE_IOWBSR1);
/* Set window access to go to RAMSEL IO address space */
writel((readl(p + MITE_IOWCR1) & MITE_IOWCR1_RAMSEL_MASK),
p + MITE_IOWCR1);
/* Enable IO Bus Interrupt 0 */
writel(MITE_LCIMR1_IO_IE_0, p + MITE_LCIMR1);
/* Enable CPU Interrupt */
writel(MITE_LCIMR2_SET_CPU_IE, p + MITE_LCIMR2);
iounmap(p); return 0;
}
/* UART Port Control Register */ #define NI8430_PORTCON 0x0f #define NI8430_PORTCON_TXVR_ENABLE (1 << 3)
if ((priv->dev->device != PCI_DEVICE_ID_NETMOS_9865) &&
(priv->dev->subsystem_device & 0xff00) == 0x3000) { /* netmos apparently orders BARs by datasheet layout, so serial * ports get BARs 0 and 3 (or 1 and 4 for memmapped)
*/
bar = 3 * idx;
return setup_port(priv, port, bar, 0, board->reg_shift);
}
/* the 99xx series comes with a range of device IDs and a variety * of capabilities: * * 9900 has varying capabilities and can cascade to sub-controllers * (cascading should be purely internal) * 9904 is hardwired with 4 serial ports * 9912 and 9922 are hardwired with 2 serial ports
*/ staticint pci_netmos_9900_numports(struct pci_dev *dev)
{ unsignedint c = dev->class; unsignedint pi; unsignedshort sub_serports;
pi = c & 0xff;
if (pi == 2) return 1;
if ((pi == 0) && (dev->device == PCI_DEVICE_ID_NETMOS_9900)) { /* two possibilities: 0x30ps encodes number of parallel and * serial ports, or 0x1000 indicates *something*. This is not * immediately obvious, since the 2s1p+4s configuration seems * to offer all functionality on functions 0..2, while still * advertising the same function 3 as the 4s+2s1p config.
*/
sub_serports = dev->subsystem_device & 0xf; if (sub_serports > 0) return sub_serports;
pci_err(dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); return 0;
}
moan_device("unknown NetMos/Mostech program interface", dev); return 0;
}
staticint pci_netmos_init(struct pci_dev *dev)
{ /* subdevice 0x00PS means <P> parallel, <S> serial */ unsignedint num_serial = dev->subsystem_device & 0xf;
if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
(dev->device == PCI_DEVICE_ID_NETMOS_9865)) return 0;
if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
dev->subsystem_device == 0x0299) return 0;
switch (dev->device) { /* FALLTHROUGH on all */ case PCI_DEVICE_ID_NETMOS_9904: case PCI_DEVICE_ID_NETMOS_9912: case PCI_DEVICE_ID_NETMOS_9922: case PCI_DEVICE_ID_NETMOS_9900:
num_serial = pci_netmos_9900_numports(dev); break;
/* * These chips are available with optionally one parallel port and up to * two serial ports. Unfortunately they all have the same product id. * * Basic configuration is done over a region of 32 I/O ports. The base * ioport is called INTA or INTC, depending on docs/other drivers. * * The region of the 32 I/O ports is configured in POSIO0R...
*/
/* inta_addr are the configuration addresses of the ITE */ staticconstshort inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, 0x200, 0x280 }; staticint pci_ite887x_init(struct pci_dev *dev)
{ int ret, i, type; struct resource *iobase = NULL;
u32 miscr, uartbar, ioport;
if (!IS_ENABLED(CONFIG_HAS_IOPORT)) return serial_8250_warn_need_ioport(dev);
/* search for the base-ioport */ for (i = 0; i < ARRAY_SIZE(inta_addr); i++) {
iobase = request_region(inta_addr[i], ITE_887x_IOSIZE, "ite887x"); if (iobase != NULL) { /* write POSIO0R - speed | size | ioport */
pci_write_config_dword(dev, ITE_887x_POSIO0,
ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]); /* write INTCBAR - ioport */
pci_write_config_dword(dev, ITE_887x_INTCBAR,
inta_addr[i]);
ret = inb(inta_addr[i]); if (ret != 0xff) { /* ioport connected */ break;
}
release_region(iobase->start, ITE_887x_IOSIZE);
}
}
if (i == ARRAY_SIZE(inta_addr)) {
pci_err(dev, "could not find iobase\n"); return -ENODEV;
}
/* start of undocumented type checking (see parport_pc.c) */
type = inb(iobase->start + 0x18) & 0x0f;
switch (type) { case 0x2: /* ITE8871 (1P) */ case 0xa: /* ITE8875 (1P) */
ret = 0; break; case 0xe: /* ITE8872 (2S1P) */
ret = 2; break; case 0x6: /* ITE8873 (1S) */
ret = 1; break; case 0x8: /* ITE8874 (2S) */
ret = 2; break; default:
moan_device("Unknown ITE887x", dev);
ret = -ENODEV;
}
/* configure all serial ports */ for (i = 0; i < ret; i++) { /* read the I/O port from the device */
pci_read_config_dword(dev, ITE_887x_PS0BAR + (0x4 * (i + 1)),
&ioport);
ioport &= 0x0000FF00; /* the actual base address */
pci_write_config_dword(dev, ITE_887x_POSIO0 + (0x4 * (i + 1)),
ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |
ITE_887x_POSIO_IOSIZE_8 | ioport);
/* write the ioport to the UARTBAR */
pci_read_config_dword(dev, ITE_887x_UARTBAR, &uartbar);
uartbar &= ~(0xffff << (16 * i)); /* clear half the reg */
uartbar |= (ioport << (16 * i)); /* set the ioport */
pci_write_config_dword(dev, ITE_887x_UARTBAR, uartbar);
/* get current config */
pci_read_config_dword(dev, ITE_887x_MISCR, &miscr); /* disable interrupts (UARTx_Routing[3:0]) */
miscr &= ~(0xf << (12 - 4 * i)); /* activate the UART (UARTx_En) */
miscr |= 1 << (23 - i); /* write new config with activated UART */
pci_write_config_dword(dev, ITE_887x_MISCR, miscr);
}
if (ret <= 0) { /* the device has no UARTs if we get here */
release_region(iobase->start, ITE_887x_IOSIZE);
}
return ret;
}
staticvoid pci_ite887x_exit(struct pci_dev *dev)
{
u32 ioport; /* the ioport is bit 0-15 in POSIO0R */
pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport);
ioport &= 0xffff;
release_region(ioport, ITE_887x_IOSIZE);
}
/* * Oxford Semiconductor Inc. * Check if an OxSemi device is part of the Tornado range of devices.
*/ #define PCI_VENDOR_ID_ENDRUN 0x7401 #define PCI_DEVICE_ID_ENDRUN_1588 0xe100
staticbool pci_oxsemi_tornado_p(struct pci_dev *dev)
{ /* OxSemi Tornado devices are all 0xCxxx */ if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
(dev->device & 0xf000) != 0xc000) returnfalse;
/* EndRun devices are all 0xExxx */ if (dev->vendor == PCI_VENDOR_ID_ENDRUN &&
(dev->device & 0xf000) != 0xe000) returnfalse;
returntrue;
}
/* * Determine the number of ports available on a Tornado device.
*/ staticint pci_oxsemi_tornado_init(struct pci_dev *dev)
{
u8 __iomem *p; unsignedlong deviceID; unsignedint number_uarts = 0;
if (!pci_oxsemi_tornado_p(dev)) return 0;
p = pci_iomap(dev, 0, 5); if (p == NULL) return -ENOMEM;
/* * Set the oversampling rate in the transmitter clock cycle register (TCR), * the clock prescaler in the clock prescaler register (CPR and CPR2), and * the clock divisor in the divisor latch (DLL and DLM). Note that for * backwards compatibility any write to CPR clears CPR2 and therefore CPR * has to be written first, followed by CPR2, which occupies the location * of CKS used with earlier UART designs.
*/ staticvoid pci_oxsemi_tornado_set_divisor(struct uart_port *port, unsignedint baud, unsignedint quot, unsignedint quot_frac)
{ struct uart_8250_port *up = up_to_u8250p(port);
u8 cpr2 = quot_frac >> 16;
u8 cpr = quot_frac >> 8;
u8 tcr = quot_frac;
/* * For Tornado devices we force MCR[7] set for the Divide-by-M N/8 baud rate * generator prescaler (CPR and CPR2). Otherwise no prescaler would be used.
*/ staticvoid pci_oxsemi_tornado_set_mctrl(struct uart_port *port, unsignedint mctrl)
{ struct uart_8250_port *up = up_to_u8250p(port);
/* * We require EFR features for clock programming, so set UPF_FULL_PROBE * for full probing regardless of CONFIG_SERIAL_8250_16550A_VARIANTS setting.
*/ staticint pci_oxsemi_tornado_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *up, int idx)
{ struct pci_dev *dev = priv->dev;
if (!IS_ENABLED(CONFIG_HAS_IOPORT)) return serial_8250_warn_need_ioport(dev);
match = pci_match_id(quatech_cards, dev); if (match)
amcc = match->driver_data; else
pci_err(dev, "unknown port type '0x%04X'.\n", dev->device);
if (amcc) { unsignedlong base = pci_resource_start(dev, 0); if (base) {
u32 tmp;
outl(inl(base + 0x38) | 0x00002000, base + 0x38);
tmp = inl(base + 0x3c);
outl(tmp | 0x01000000, base + 0x3c);
outl(tmp & ~0x01000000, base + 0x3c);
}
} return 0;
}
staticint pci_quatech_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *port, int idx)
{ if (!IS_ENABLED(CONFIG_HAS_IOPORT)) return serial_8250_warn_need_ioport(priv->dev);
/* Needed by pci_quatech calls below */
port->port.iobase = pci_resource_start(priv->dev, FL_GET_BASE(board->flags)); /* Set up the clocking */
port->port.uartclk = pci_quatech_clock(port); /* For now just warn about RS422 */ if (pci_quatech_rs422(port))
pci_warn(priv->dev, "software control of RS422 features not currently supported.\n"); return pci_default_setup(priv, board, port, idx);
}
staticint pci_default_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *port, int idx)
{ unsignedint bar, offset = board->first_offset, maxnr;
bar = FL_GET_BASE(board->flags); if (board->flags & FL_BASE_BARS)
bar += idx; else
offset += idx * board->uart_offset;
/* RTS will control by MCR if this bit is 0 */ #define FINTEK_RTS_CONTROL_BY_HW BIT(4) /* only worked with FINTEK_RTS_CONTROL_BY_HW on */ #define FINTEK_RTS_INVERT BIT(5)
/* We should do proper H/W transceiver setting before change to RS485 mode */ staticint pci_fintek_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485)
{ struct pci_dev *pci_dev = to_pci_dev(port->dev);
u8 setting;
u8 *index = (u8 *) port->private_data;
staticconststruct serial_rs485 pci_fintek_rs485_supported = {
.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND, /* F81504/508/512 does not support RTS delay before or after send */
};
staticvoid kt_handle_break(struct uart_port *p)
{ struct uart_8250_port *up = up_to_u8250p(p); /* * On receipt of a BI, serial device in Intel ME (Intel * management engine) needs to have its fifos cleared for sane * SOL (Serial Over Lan) output.
*/
serial8250_clear_and_reinit_fifos(up);
}
/* * When the Intel ME (management engine) gets reset its serial * port registers could return 0 momentarily. Functions like * serial8250_console_write, read and save the IER, perform * some operation and then restore it. In order to avoid * setting IER register inadvertently to 0, if the value read * is 0, double check with ier value in uart_8250_port and use * that instead. up->ier should be the same value as what is * currently configured.
*/
val = inb(p->iobase + offset); if (offset == UART_IER) { if (val == 0)
val = up->ier;
} return val;
}
staticint kt_serial_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *port, int idx)
{ if (!IS_ENABLED(CONFIG_HAS_IOPORT)) return serial_8250_warn_need_ioport(priv->dev);
if (port_idx % 2) {
val &= ~MOXA_ODD_RS_MASK;
val |= FIELD_PREP(MOXA_ODD_RS_MASK, mode);
} else {
val &= ~MOXA_EVEN_RS_MASK;
val |= FIELD_PREP(MOXA_EVEN_RS_MASK, mode);
}
outb(val, UIR_addr);
if (!IS_ENABLED(CONFIG_HAS_IOPORT)) return serial_8250_warn_need_ioport(dev);
if (!(pci_moxa_supported_rs(dev) & MOXA_SUPP_RS232)) {
init_mode = MOXA_RS422;
} for (i = 0; i < num_ports; ++i)
pci_moxa_set_interface(dev, i, init_mode);
/* * Enable hardware buffer to prevent break signal output when system boots up. * This hardware buffer is only supported on Mini PCIe series.
*/ if (pci_moxa_is_mini_pcie(device)) { /* Set GPIO direction */
val = inb(iobar_addr + MOXA_PUART_GPIO_EN);
val |= MOXA_GPIO_PIN2;
outb(val, iobar_addr + MOXA_PUART_GPIO_EN); /* Enable low GPIO */
val = inb(iobar_addr + MOXA_PUART_GPIO_OUT);
val &= ~MOXA_GPIO_PIN2;
outb(val, iobar_addr + MOXA_PUART_GPIO_OUT);
}
return num_ports;
}
staticint
pci_moxa_setup(struct serial_private *priv, conststruct pciserial_board *board, struct uart_8250_port *port, int idx)
{ unsignedint bar = FL_GET_BASE(board->flags); int offset;
if (!IS_ENABLED(CONFIG_HAS_IOPORT)) return serial_8250_warn_need_ioport(priv->dev);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.