/* pic32_sport pointer for console use */ staticstruct pic32_sport *pic32_sports[PIC32_MAX_UARTS];
staticinlinevoid pic32_wait_deplete_txbuf(struct pic32_sport *sport)
{ /* wait for tx empty, otherwise chars will be lost or corrupted */ while (!(pic32_uart_readl(sport, PIC32_UART_STA) & PIC32_UART_STA_TRMT))
udelay(1);
}
/* serial core request to check if uart tx buffer is empty */ staticunsignedint pic32_uart_tx_empty(struct uart_port *port)
{ struct pic32_sport *sport = to_pic32_sport(port);
u32 val = pic32_uart_readl(sport, PIC32_UART_STA);
return (val & PIC32_UART_STA_TRMT) ? 1 : 0;
}
/* serial core request to set UART outputs */ staticvoid pic32_uart_set_mctrl(struct uart_port *port, unsignedint mctrl)
{ struct pic32_sport *sport = to_pic32_sport(port);
/* set loopback mode */ if (mctrl & TIOCM_LOOP)
pic32_uart_writel(sport, PIC32_SET(PIC32_UART_MODE),
PIC32_UART_MODE_LPBK); else
pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
PIC32_UART_MODE_LPBK);
}
/* serial core request to return the state of misc UART input pins */ staticunsignedint pic32_uart_get_mctrl(struct uart_port *port)
{ struct pic32_sport *sport = to_pic32_sport(port); unsignedint mctrl = 0;
/* get the state of CTS input pin for this port */ if (!sport->cts_gpiod)
mctrl |= TIOCM_CTS; elseif (gpiod_get_value(sport->cts_gpiod))
mctrl |= TIOCM_CTS;
/* DSR and CD are not supported in PIC32, so return 1 *RIisnotsupportedinPIC32,soreturn0
*/
mctrl |= TIOCM_CD;
mctrl |= TIOCM_DSR;
return mctrl;
}
/* stop tx and start tx are not called in pairs, therefore a flag indicates *thestatusofirqtocontroltheirq-depth.
*/ staticinlinevoid pic32_uart_irqtxen(struct pic32_sport *sport, u8 en)
{ if (en && !sport->enable_tx_irq) {
enable_irq(sport->irq_tx);
sport->enable_tx_irq = true;
} elseif (!en && sport->enable_tx_irq) { /* use disable_irq_nosync() and not disable_irq() to avoid self *imposeddeadlockbynotwaitingforirqhandlertoend, *sincethiscallbackiscalledfrominterruptcontext.
*/
disable_irq_nosync(sport->irq_tx);
sport->enable_tx_irq = false;
}
}
/* serial core request to disable tx ASAP (used for flow control) */ staticvoid pic32_uart_stop_tx(struct uart_port *port)
{ struct pic32_sport *sport = to_pic32_sport(port);
if (!(pic32_uart_readl(sport, PIC32_UART_MODE) & PIC32_UART_MODE_ON)) return;
if (!(pic32_uart_readl(sport, PIC32_UART_STA) & PIC32_UART_STA_UTXEN)) return;
/* wait for tx empty */
pic32_wait_deplete_txbuf(sport);
/* serial core request to stop rx, called before port shutdown */ staticvoid pic32_uart_stop_rx(struct uart_port *port)
{ struct pic32_sport *sport = to_pic32_sport(port);
/* receiver Enable bit OFF */
pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
PIC32_UART_STA_URXEN);
}
/* serial core request to start/stop emitting break char */ staticvoid pic32_uart_break_ctl(struct uart_port *port, int ctl)
{ struct pic32_sport *sport = to_pic32_sport(port); unsignedlong flags;
uart_port_lock_irqsave(port, &flags);
if (ctl)
pic32_uart_writel(sport, PIC32_SET(PIC32_UART_STA),
PIC32_UART_STA_UTXBRK); else
pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
PIC32_UART_STA_UTXBRK);
uart_port_unlock_irqrestore(port, flags);
}
/* get port type in string format */ staticconstchar *pic32_uart_type(struct uart_port *port)
{ return (port->type == PORT_PIC32) ? PIC32_DEV_NAME : NULL;
}
/* read all chars in rx fifo and send them to core */ staticvoid pic32_uart_do_rx(struct uart_port *port)
{ struct pic32_sport *sport = to_pic32_sport(port); struct tty_port *tty; unsignedint max_count;
/* limit number of char read in interrupt, should not be *higherthanfifosizeanywaysincewe'remuchfasterthan *serialport
*/
max_count = PIC32_UART_RX_FIFO_DEPTH;
uart_port_lock(port);
tty = &port->state->port;
do {
u32 sta_reg, c; char flag;
/* get overrun/fifo empty information from status register */
sta_reg = pic32_uart_readl(sport, PIC32_UART_STA); if (unlikely(sta_reg & PIC32_UART_STA_OERR)) {
/* fifo reset is required to clear interrupt */
pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
PIC32_UART_STA_OERR);
/* Can at least one more character can be read? */ if (!(sta_reg & PIC32_UART_STA_URXDA)) break;
/* read the character and increment the rx counter */
c = pic32_uart_readl(sport, PIC32_UART_RX);
port->icount.rx++;
flag = TTY_NORMAL;
c &= 0xff;
if (unlikely((sta_reg & PIC32_UART_STA_PERR) ||
(sta_reg & PIC32_UART_STA_FERR))) {
/* do stats first */ if (sta_reg & PIC32_UART_STA_PERR)
port->icount.parity++; if (sta_reg & PIC32_UART_STA_FERR)
port->icount.frame++;
/* update flag wrt read_status_mask */
sta_reg &= port->read_status_mask;
if (sta_reg & PIC32_UART_STA_FERR)
flag = TTY_FRAME; if (sta_reg & PIC32_UART_STA_PERR)
flag = TTY_PARITY;
}
if (uart_handle_sysrq_char(port, c)) continue;
if ((sta_reg & port->ignore_status_mask) == 0)
tty_insert_flip_char(tty, c, flag);
} while (--max_count);
uart_port_unlock(port);
tty_flip_buffer_push(tty);
}
/* fill tx fifo with chars to send, stop when fifo is about to be full *orwhenallcharshavebeensent.
*/ staticvoid pic32_uart_do_tx(struct uart_port *port)
{ struct pic32_sport *sport = to_pic32_sport(port); struct tty_port *tport = &port->state->port; unsignedint max_count = PIC32_UART_TX_FIFO_DEPTH;
/* serial core request to initialize uart and start rx operation */ staticint pic32_uart_startup(struct uart_port *port)
{ struct pic32_sport *sport = to_pic32_sport(port);
u32 dflt_baud = (port->uartclk / PIC32_UART_DFLT_BRATE / 16) - 1; unsignedlong flags; int ret;
local_irq_save(flags);
ret = clk_prepare_enable(sport->clk); if (ret) {
local_irq_restore(flags); goto out_done;
}
/* clear status and mode registers */
pic32_uart_writel(sport, PIC32_UART_MODE, 0);
pic32_uart_writel(sport, PIC32_UART_STA, 0);
/* disable uart and mask all interrupts */
pic32_uart_dsbl_and_mask(port);
/* set default baud */
pic32_uart_writel(sport, PIC32_UART_BRG, dflt_baud);
local_irq_restore(flags);
/* Each UART of a PIC32 has three interrupts therefore, *wesetupdrivertoregisterthe3irqsforthedevice. * *Foreachirqrequest_irq()iscalledwithinterruptdisabled. *Andtheirqisenabledassoonaswearereadytohandlethem.
*/
sport->enable_tx_irq = false;
/* serial core request to do any port required auto-configuration */ staticvoid pic32_uart_config_port(struct uart_port *port, int flags)
{ if (flags & UART_CONFIG_TYPE) { if (pic32_uart_request_port(port)) return;
port->type = PORT_PIC32;
}
}
/* serial core request to check that port information in serinfo are suitable */ staticint pic32_uart_verify_port(struct uart_port *port, struct serial_struct *serinfo)
{ if (port->type != PORT_PIC32) return -EINVAL; if (port->irq != serinfo->irq) return -EINVAL; if (port->iotype != serinfo->io_type) return -EINVAL; if (port->mapbase != (unsignedlong)serinfo->iomem_base) return -EINVAL;
ret = uart_add_one_port(&pic32_uart_driver, port); if (ret) {
port->membase = NULL;
dev_err(port->dev, "%s: uart add port error!\n", __func__); goto err;
}
#ifdef CONFIG_SERIAL_PIC32_CONSOLE if (uart_console_registered(port)) { /* The peripheral clock has been enabled by console_setup, *sodisableittilltheportisused.
*/
clk_disable_unprepare(sport->clk);
} #endif
ret = uart_register_driver(&pic32_uart_driver); if (ret) {
pr_err("failed to register %s:%d\n",
pic32_uart_driver.driver_name, ret); return ret;
}
ret = platform_driver_register(&pic32_uart_platform_driver); if (ret) {
pr_err("fail to register pic32 uart\n");
uart_unregister_driver(&pic32_uart_driver);
}
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.