/** * men_z135_handle_modem_status() - Handle change of modem status * @uart: The UART port * * Handle change of modem status register. This is done by reading the "delta" * versions of DCD (Data Carrier Detect) and CTS (Clear To Send).
*/ staticvoid men_z135_handle_modem_status(struct men_z135_port *uart)
{
u8 msr;
msr = (uart->stat_reg >> 8) & 0xff;
if (msr & MEN_Z135_MSR_DDCD)
uart_handle_dcd_change(&uart->port,
msr & MEN_Z135_MSR_DCD); if (msr & MEN_Z135_MSR_DCTS)
uart_handle_cts_change(&uart->port,
msr & MEN_Z135_MSR_CTS);
}
if (lsr & MEN_Z135_LSR_OE)
port->icount.overrun++; if (lsr & MEN_Z135_LSR_PE)
port->icount.parity++; if (lsr & MEN_Z135_LSR_FE)
port->icount.frame++; if (lsr & MEN_Z135_LSR_BI) {
port->icount.brk++;
uart_handle_break(port);
}
}
/** * get_rx_fifo_content() - Get the number of bytes in RX FIFO * @uart: The UART port * * Read RXC register from hardware and return current FIFO fill size.
*/ static u16 get_rx_fifo_content(struct men_z135_port *uart)
{ struct uart_port *port = &uart->port;
u32 stat_reg;
u16 rxc;
u8 rxc_lo;
u8 rxc_hi;
/** * men_z135_handle_rx() - RX tasklet routine * @uart: Pointer to struct men_z135_port * * Copy from RX FIFO and acknowledge number of bytes copied.
*/ staticvoid men_z135_handle_rx(struct men_z135_port *uart)
{ struct uart_port *port = &uart->port; struct tty_port *tport = &port->state->port; int copied;
u16 size; int room;
size = get_rx_fifo_content(uart);
if (size == 0) return;
/* Avoid accidently accessing TX FIFO instead of RX FIFO. Last * longword in RX FIFO cannot be read.(0x004-0x3FF)
*/ if (size > MEN_Z135_FIFO_WATERMARK)
size = MEN_Z135_FIFO_WATERMARK;
room = tty_buffer_request_room(tport, size); if (room != size)
dev_warn(&uart->mdev->dev, "Not enough room in flip buffer, truncating to %d\n",
room);
if (room == 0) return;
memcpy_fromio(uart->rxbuf, port->membase + MEN_Z135_RX_RAM, room); /* Be sure to first copy all data and then acknowledge it */
mb();
iowrite32(room, port->membase + MEN_Z135_RX_CTRL);
copied = tty_insert_flip_string(tport, uart->rxbuf, room); if (copied != room)
dev_warn(&uart->mdev->dev, "Only copied %d instead of %d bytes\n",
copied, room);
if (txc > MEN_Z135_FIFO_WATERMARK)
txc = MEN_Z135_FIFO_WATERMARK;
txfree = MEN_Z135_FIFO_WATERMARK - txc; if (txfree <= 0) {
dev_err(&uart->mdev->dev, "Not enough room in TX FIFO have %d, need %d\n",
txfree, qlen); goto irq_en;
}
/* if we're not aligned, it's better to copy only 1 or 2 bytes and * then the rest.
*/ if (align && qlen >= 3 && BYTES_TO_ALIGN(wptr))
n = 4 - BYTES_TO_ALIGN(wptr); elseif (qlen > txfree)
n = txfree; else
n = qlen;
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port);
irq_en: if (!kfifo_is_empty(&tport->xmit_fifo))
men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN); else
men_z135_reg_clr(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);
out: return;
}
/** * men_z135_intr() - Handle legacy IRQs * @irq: The IRQ number * @data: Pointer to UART port * * Check IIR register to find the cause of the interrupt and handle it. * It is possible that multiple interrupts reason bits are set and reading * the IIR is a destructive read, so we always need to check for all possible * interrupts and handle them.
*/ static irqreturn_t men_z135_intr(int irq, void *data)
{ struct men_z135_port *uart = (struct men_z135_port *)data; struct uart_port *port = &uart->port; bool handled = false; int irq_id;
/** * men_z135_request_irq() - Request IRQ for 16z135 core * @uart: z135 private uart port structure * * Request an IRQ for 16z135 to use. First try using MSI, if it fails * fall back to using legacy interrupts.
*/ staticint men_z135_request_irq(struct men_z135_port *uart)
{ struct device *dev = &uart->mdev->dev; struct uart_port *port = &uart->port; int err = 0;
/** * men_z135_tx_empty() - Handle tx_empty call * @port: The UART port * * This function tests whether the TX FIFO and shifter for the port * described by @port is empty.
*/ staticunsignedint men_z135_tx_empty(struct uart_port *port)
{
u32 wptr;
u16 txc;
if (txc == 0) return TIOCSER_TEMT; else return 0;
}
/** * men_z135_set_mctrl() - Set modem control lines * @port: The UART port * @mctrl: The modem control lines * * This function sets the modem control lines for a port described by @port * to the state described by @mctrl
*/ staticvoid men_z135_set_mctrl(struct uart_port *port, unsignedint mctrl)
{
u32 old;
u32 conf_reg;
conf_reg = old = ioread32(port->membase + MEN_Z135_CONF_REG); if (mctrl & TIOCM_RTS)
conf_reg |= MEN_Z135_MCR_RTS; else
conf_reg &= ~MEN_Z135_MCR_RTS;
if (conf_reg != old)
iowrite32(conf_reg, port->membase + MEN_Z135_CONF_REG);
}
/** * men_z135_get_mctrl() - Get modem control lines * @port: The UART port * * Retruns the current state of modem control inputs.
*/ staticunsignedint men_z135_get_mctrl(struct uart_port *port)
{ unsignedint mctrl = 0;
u8 msr;
if (msr & MEN_Z135_MSR_CTS)
mctrl |= TIOCM_CTS; if (msr & MEN_Z135_MSR_DSR)
mctrl |= TIOCM_DSR; if (msr & MEN_Z135_MSR_RI)
mctrl |= TIOCM_RI; if (msr & MEN_Z135_MSR_DCD)
mctrl |= TIOCM_CAR;
return mctrl;
}
/** * men_z135_stop_tx() - Stop transmitting characters * @port: The UART port * * Stop transmitting characters. This might be due to CTS line becomming * inactive or the tty layer indicating we want to stop transmission due to * an XOFF character.
*/ staticvoid men_z135_stop_tx(struct uart_port *port)
{ struct men_z135_port *uart = to_men_z135(port);
/** * men_z135_start_tx() - Start transmitting characters * @port: The UART port * * Start transmitting character. This actually doesn't transmit anything, but * fires off the TX tasklet.
*/ staticvoid men_z135_start_tx(struct uart_port *port)
{ struct men_z135_port *uart = to_men_z135(port);
if (uart->automode)
men_z135_disable_ms(port);
men_z135_handle_tx(uart);
}
/** * men_z135_stop_rx() - Stop receiving characters * @port: The UART port * * Stop receiving characters; the port is in the process of being closed.
*/ staticvoid men_z135_stop_rx(struct uart_port *port)
{ struct men_z135_port *uart = to_men_z135(port);
/** * men_z135_probe() - Probe a z135 instance * @mdev: The MCB device * @id: The MCB device ID * * men_z135_probe does the basic setup of hardware resources and registers the * new uart port to the tty layer.
*/ staticint men_z135_probe(struct mcb_device *mdev, conststruct mcb_device_id *id)
{ struct men_z135_port *uart; struct resource *mem; struct device *dev; int err;
dev = &mdev->dev;
uart = devm_kzalloc(dev, sizeof(struct men_z135_port), GFP_KERNEL); if (!uart) return -ENOMEM;
uart->rxbuf = (unsignedchar *)__get_free_page(GFP_KERNEL); if (!uart->rxbuf) return -ENOMEM;
/** * men_z135_init() - Driver Registration Routine * * men_z135_init is the first routine called when the driver is loaded. All it * does is register with the legacy MEN Chameleon subsystem.
*/ staticint __init men_z135_init(void)
{ int err;
err = uart_register_driver(&men_z135_driver); if (err) {
pr_err("Failed to register UART: %d\n", err); return err;
}
err = mcb_register_driver(&mcb_driver); if (err) {
pr_err("Failed to register MCB driver: %d\n", err);
uart_unregister_driver(&men_z135_driver); return err;
}
return 0;
}
module_init(men_z135_init);
/** * men_z135_exit() - Driver Exit Routine * * men_z135_exit is called just before the driver is removed from memory.
*/ staticvoid __exit men_z135_exit(void)
{
mcb_unregister_driver(&mcb_driver);
uart_unregister_driver(&men_z135_driver);
}
module_exit(men_z135_exit);
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.