[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <02A821E977914EF6B7B4BD36F07C1A2A@subhasishg>
Date: Fri, 18 Mar 2011 11:13:34 +0530
From: "Subhasish Ghosh" <subhasish@...tralsolutions.com>
To: "Greg Kroah-Hartman" <gregkh@...e.de>,
"Alan Cox" <alan@...rguk.ukuu.org.uk>
Cc: "Alan Cox" <alan@...rguk.ukuu.org.uk>,
"Arnd Bergmann" <arnd@...db.de>,
"Thomas Gleixner" <tglx@...utronix.de>,
<linux-arm-kernel@...ts.infradead.org>, <m-watkins@...com>,
<nsekhar@...com>, <sachi@...tralsolutions.com>,
"Andrew Morton \(commit_signer:1/4=25%\)" <akpm@...ux-foundation.org>,
"Randy Dunlap \(commit_signer:1/4=25%\)" <randy.dunlap@...cle.com>,
"open list" <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v3 7/7] tty: add pruss SUART driver
Hi Greg/Alan,
Any comments regarding this driver.
--------------------------------------------------
From: "Subhasish Ghosh" <subhasish@...tralsolutions.com>
Sent: Tuesday, March 08, 2011 7:27 PM
To: <davinci-linux-open-source@...ux.davincidsp.com>
Cc: <linux-arm-kernel@...ts.infradead.org>; <m-watkins@...com>;
<nsekhar@...com>; <sachi@...tralsolutions.com>; "Subhasish Ghosh"
<subhasish@...tralsolutions.com>; "Greg Kroah-Hartman (maintainer:TTY
LAYER,commit_signer:2/4=50%,commit_signer:1/2=50%)" <gregkh@...e.de>;
"Andrew Morton (commit_signer:1/4=25%)" <akpm@...ux-foundation.org>; "Randy
Dunlap (commit_signer:1/4=25%)" <randy.dunlap@...cle.com>; "open list"
<linux-kernel@...r.kernel.org>
Subject: [PATCH v3 7/7] tty: add pruss SUART driver
> This patch adds support for the TTY compliant
> Soft-UART device emulated on PRUSS.
>
> This patch depends on:
> davinci: macro rename DA8XX_LPSC0_DMAX to DA8XX_LPSC0_PRUSS.
> https://patchwork.kernel.org/patch/615681/
> davinci: changed SRAM allocator to shared ram.
> https://patchwork.kernel.org/patch/549351/
>
> Signed-off-by: Subhasish Ghosh <subhasish@...tralsolutions.com>
> ---
> drivers/tty/serial/Kconfig | 22 +
> drivers/tty/serial/Makefile | 10 +
> drivers/tty/serial/pruss_suart.c | 1058 +++++++++++++++++++
> drivers/tty/serial/pruss_suart.h | 1081 ++++++++++++++++++++
> drivers/tty/serial/pruss_suart_api.c | 1757
> ++++++++++++++++++++++++++++++++
> drivers/tty/serial/pruss_suart_utils.c | 391 +++++++
> include/linux/serial_core.h | 2 +
> 7 files changed, 4321 insertions(+), 0 deletions(-)
> create mode 100644 drivers/tty/serial/pruss_suart.c
> create mode 100644 drivers/tty/serial/pruss_suart.h
> create mode 100644 drivers/tty/serial/pruss_suart_api.c
> create mode 100644 drivers/tty/serial/pruss_suart_utils.c
>
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index 2b83346..14ea0a3 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1596,4 +1596,26 @@ config SERIAL_PCH_UART
> This driver is for PCH(Platform controller Hub) UART of Intel EG20T
> which is an IOH(Input/Output Hub) for x86 embedded processor.
> Enabling PCH_DMA, this PCH UART works as DMA mode.
> +
> +#
> +# SUART Kernel Configuration
> +#
> +
> +config SERIAL_PRUSS_SUART
> + depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850
> + select SERIAL_CORE
> + tristate "PRUSS based SoftUART emulation on DA8XX"
> + ---help---
> + This driver emulates upto eight different UARTs on the PRUSS.
> + You may modify the NR_SUARTS macro in the driver to emulate
> + less number of UARTS as per your requirement.
> + If not sure, mark N
> +
> +config PRUSS_SUART_MCASP
> + int "McASP number"
> + depends on ARCH_DAVINCI && ARCH_DAVINCI_DA830 && SERIAL_PRUSS_SUART
> + default "0"
> + ---help---
> + Enter the McASP number to use with SUART (0, 1 or 2).
> + You will need to recompile the kernel if this is changed.
> endmenu
> diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
> index 8ea92e9..f52a4eb 100644
> --- a/drivers/tty/serial/Makefile
> +++ b/drivers/tty/serial/Makefile
> @@ -92,3 +92,13 @@ obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
> obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
> obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o
> obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
> +
> +#
> +# Makefile for SoftUART emulation
> +#
> +
> +suart_emu-objs := pruss_suart.o \
> + pruss_suart_api.o \
> + pruss_suart_utils.o
> +
> +obj-$(CONFIG_SERIAL_PRUSS_SUART) += suart_emu.o
> diff --git a/drivers/tty/serial/pruss_suart.c
> b/drivers/tty/serial/pruss_suart.c
> new file mode 100644
> index 0000000..c411ff8
> --- /dev/null
> +++ b/drivers/tty/serial/pruss_suart.c
> @@ -0,0 +1,1058 @@
> +/*
> + * PRUSS SUART Emulation device driver
> + * Author: subhasish@...tralsolutions.com
> + *
> + * This driver supports TI's PRU SUART Emulation and the
> + * specs for the same is available at <http://www.ti.com>
> + *
> + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation version 2.
> + *
> + * This program is distributed as is WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/tty.h>
> +#include <linux/tty_flip.h>
> +#include <linux/serial.h>
> +#include <linux/serial_core.h>
> +#include <linux/module.h>
> +#include <mach/da8xx.h>
> +#include <linux/platform_device.h>
> +#include <linux/firmware.h>
> +#include <linux/clk.h>
> +#include <linux/serial_reg.h>
> +#include <linux/delay.h>
> +#include <linux/bitops.h>
> +#include <mach/sram.h>
> +#include "pruss_suart.h"
> +
> +#define NR_SUART 8
> +#define DRV_NAME "da8xx_pruss_uart"
> +#define DRV_DESC "PRUSS SUART Driver v1.0"
> +#define MAX_SUART_RETRIES 100
> +#define SUART_CNTX_SZ 512
> +#define SUART_FIFO_TIMEOUT_DFLT 5
> +#define SUART_FIFO_TIMEOUT_MIN 4
> +#define SUART_FIFO_TIMEOUT_MAX 500
> +
> +/* Default timeout set to 5ms */
> +static s16 suart_timeout = SUART_FIFO_TIMEOUT_DFLT;
> +module_param(suart_timeout, short, S_IRUGO);
> +MODULE_PARM_DESC(suart_timeout,
> + "fifo timeout in milli seconds (min: 4; max: 500)");
> +
> +struct suart_fifo {
> + void *fifo_vaddr_buff_tx;
> + void *fifo_vaddr_buff_rx;
> + void *fifo_phys_addr_tx;
> + void *fifo_phys_addr_rx;
> +};
> +
> +struct omapl_pru_suart {
> + struct uart_port port[NR_SUART];
> + struct device *dev;
> + unsigned long tx_empty[NR_SUART];
> + struct clk *clk_mcasp;
> + struct suart_fifo suart_fifo_addr[NR_SUART];
> + const struct firmware *fw;
> + struct suart_handle suart_hdl[NR_SUART];
> + struct pruss_suart_iomap suart_iomap;
> + struct tasklet_struct tx_task[NR_SUART];
> + u32 clk_freq_pru;
> + u32 clk_freq_mcasp;
> + u32 tx_loadsz;
> +};
> +
> +static u32 suart_get_duplex(struct omapl_pru_suart *soft_uart, u32
> uart_no)
> +{
> + return soft_uart->suart_hdl[uart_no].uart_type;
> +}
> +
> +static inline void __stop_tx(struct omapl_pru_suart *soft_uart, u32
> uart_no)
> +{
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> + struct uart_port *port = &soft_uart->port[uart_no];
> + u16 txready;
> + u32 i;
> +
> + /* Check if any TX in progress */
> + for (i = 0, txready = 1; (i < 10000) && txready; i++) {
> + txready = (pru_softuart_get_tx_status
> + (dev, &soft_uart->suart_hdl[uart_no]) &
> + CHN_TXRX_STATUS_RDY);
> + }
> + /* To stop tx, disable the TX interrupt */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[uart_no].uart_num,
> + PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + pru_softuart_clr_tx_status(dev, &soft_uart->suart_hdl[uart_no]);
> + spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static void pruss_suart_stop_tx(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> +
> + __stop_tx(soft_uart, port->line);
> +}
> +
> +static void omapl_pru_tx_chars(struct omapl_pru_suart *soft_uart, u32
> uart_no)
> +{
> + struct circ_buf *xmit = &soft_uart->port[uart_no].state->xmit;
> + struct device *dev = soft_uart->dev;
> + s32 count = 0;
> +
> + if (!(suart_get_duplex(soft_uart, uart_no) & ePRU_SUART_HALF_TX))
> + return;
> +
> + if (uart_circ_empty(xmit) ||
> + uart_tx_stopped(&soft_uart->port[uart_no])) {
> + pruss_suart_stop_tx(&soft_uart->port[uart_no]);
> + set_bit(0, &soft_uart->tx_empty[uart_no]);
> + return;
> + }
> +
> + for (count = 0; count <= soft_uart->tx_loadsz; count++) {
> + *((s8 *)soft_uart->suart_fifo_addr[uart_no].fifo_vaddr_buff_tx
> + + count) = xmit->buf[xmit->tail];
> + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
> + soft_uart->port[uart_no].icount.tx++;
> + if (uart_circ_empty(xmit)) {
> + uart_circ_clear(xmit);
> + break;
> + }
> + }
> +
> + if (count == (SUART_FIFO_LEN + 1))
> + count = SUART_FIFO_LEN;
> +
> + /* Write the character to the data port */
> + if (pru_softuart_write(dev,
> + &soft_uart->suart_hdl[uart_no],
> + (u32 *)&soft_uart->suart_fifo_addr
> + [uart_no].fifo_phys_addr_tx, count) != 0) {
> + dev_err(dev, "failed to tx data\n");
> + }
> +
> + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
> + uart_write_wakeup(&soft_uart->port[uart_no]);
> +
> +#if 0
> + if (uart_circ_empty(xmit))
> + __stop_tx(soft_uart, uart_no);
> +#endif
> +}
> +
> +static void suart_tx_task(unsigned long data)
> +{
> + struct uart_port *port = (struct uart_port *)data;
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> +
> + omapl_pru_tx_chars(soft_uart, port->line);
> +}
> +
> +static void omapl_pru_rx_chars(struct omapl_pru_suart *soft_uart, u32
> uart_no)
> +{
> + struct tty_struct *tty = NULL;
> + struct device *dev = soft_uart->dev;
> + s8 flags = TTY_NORMAL;
> + u16 rx_status, data_len = SUART_FIFO_LEN;
> + u32 data_len_read;
> + u8 suart_data[SUART_FIFO_LEN + 1];
> + s32 i = 0;
> +
> + if (!(suart_get_duplex(soft_uart, uart_no) & ePRU_SUART_HALF_RX))
> + return;
> +
> + /* read the status */
> + rx_status = pru_softuart_get_rx_status(dev,
> + &soft_uart->suart_hdl[uart_no]);
> +
> + pru_softuart_read_data(dev, &soft_uart->suart_hdl[uart_no],
> + suart_data, data_len + 1, &data_len_read);
> +
> + tty = tty_port_tty_get(&soft_uart->port[uart_no].state->port);
> +
> + if (!tty)
> + return;
> +
> + /* check for errors */
> + if (rx_status & CHN_TXRX_STATUS_ERR) {
> + if (rx_status & CHN_TXRX_STATUS_FE)
> + soft_uart->port[uart_no].icount.frame++;
> + if (rx_status & CHN_TXRX_STATUS_OVRNERR)
> + soft_uart->port[uart_no].icount.overrun++;
> + if (rx_status & CHN_TXRX_STATUS_BI)
> + soft_uart->port[uart_no].icount.brk++;
> + rx_status &= soft_uart->port[uart_no].
> + read_status_mask;
> + if (rx_status & CHN_TXRX_STATUS_FE)
> + flags = TTY_FRAME;
> + if (rx_status & CHN_TXRX_STATUS_OVRNERR)
> + flags = TTY_OVERRUN;
> + if (rx_status & CHN_TXRX_STATUS_BI)
> + flags = TTY_BREAK;
> +
> +#ifdef SUPPORT_SYSRQ
> + soft_uart->port[uart_no].sysrq = 0;
> +#endif
> + } else {
> + for (i = 0; i <= data_len_read; i++) {
> + soft_uart->port[uart_no].icount.rx++;
> + /* check for sys rq */
> + if (uart_handle_sysrq_char
> + (&soft_uart->port[uart_no], suart_data))
> + continue;
> + }
> + tty_insert_flip_string(tty, suart_data, data_len_read);
> + }
> +
> + /* push data into tty */
> + pru_softuart_clr_rx_status(dev, &soft_uart->suart_hdl[uart_no]);
> + tty_flip_buffer_push(tty);
> + tty_kref_put(tty);
> +}
> +
> +static irqreturn_t pruss_suart_interrupt(s32 irq, void *dev_id)
> +{
> + struct uart_port *port = dev_id;
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + u16 txrx_flag;
> + u32 ret;
> + unsigned long flags = 0;
> + u16 uart_num = port->line + 1;
> +
> + spin_lock_irqsave(&port->lock, flags);
> +
> + do {
> + ret = pru_softuart_get_isrstatus(dev, uart_num, &txrx_flag);
> + if (ret != 0) {
> + dev_err(dev, "suart%d: failed to get interrupt, ret:"
> + " 0x%X txrx_flag 0x%X\n",
> + port->line, ret, txrx_flag);
> + spin_unlock_irqrestore(&port->lock, flags);
> + return IRQ_NONE;
> + }
> + if ((PRU_RX_INTR & txrx_flag) == PRU_RX_INTR) {
> + pru_intr_clr_isrstatus(dev, uart_num, PRU_RX_INTR);
> + if ((soft_uart->port[port->line].ignore_status_mask &
> + CHN_TXRX_STATUS_RDY) == CHN_TXRX_STATUS_RDY) {
> + pru_softuart_clr_rx_status(dev,
> + &soft_uart->suart_hdl
> + [port->line]);
> + } else {
> + omapl_pru_rx_chars(soft_uart, port->line);
> + }
> + }
> +
> + if ((PRU_TX_INTR & txrx_flag) == PRU_TX_INTR) {
> + pru_intr_clr_isrstatus(dev, uart_num, PRU_TX_INTR);
> + pru_softuart_clr_tx_status(dev, &soft_uart->suart_hdl
> + [port->line]);
> + tasklet_schedule(&soft_uart->tx_task[port->line]);
> + }
> + } while (txrx_flag & (PRU_RX_INTR | PRU_TX_INTR));
> +
> + spin_unlock_irqrestore(&port->lock, flags);
> + return IRQ_HANDLED;
> +}
> +
> +static void pruss_suart_stop_rx(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> +
> + spin_lock_irqsave(&port->lock, flags);
> + /* disable rx interrupt */
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
> + | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
> + | CHN_TXRX_IE_MASK_TIMEOUT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static void pruss_suart_enable_ms(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + dev_err(dev, "modem control timer not supported\n");
> +}
> +
> +static void pruss_suart_start_tx(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> +
> + /* unmask the tx interrupts */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + if (test_and_clear_bit(0, &soft_uart->tx_empty[port->line]))
> + omapl_pru_tx_chars(soft_uart, port->line);
> +}
> +
> +static u32 pruss_suart_tx_empty(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> +
> + return (pru_softuart_get_tx_status(dev,
> + &soft_uart->suart_hdl[port->line])
> + & CHN_TXRX_STATUS_RDY) ? 0 : TIOCSER_TEMT;
> +}
> +
> +static u32 pruss_suart_get_mctrl(struct uart_port *port)
> +{
> + return -ENOTSUPP;
> +}
> +
> +static void pruss_suart_set_mctrl(struct uart_port *port, u32 mctrl)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + dev_dbg(dev, "modem control not supported\n");
> +}
> +
> +static void pruss_suart_break_ctl(struct uart_port *port, s32
> break_state)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> +
> + spin_lock_irqsave(&port->lock, flags);
> +
> + if (break_state == -1)
> + suart_intr_clrmask(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
> + else
> + suart_intr_setmask(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
> +
> + spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static void pruss_suart_set_termios(struct uart_port *port,
> + struct ktermios *termios,
> + struct ktermios *old)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + u8 cval = 0;
> + unsigned long flags = 0;
> + u32 baud = 0;
> + u32 old_csize = old ? old->c_cflag & CSIZE : CS8;
> +
> +/*
> + * Do not allow unsupported configurations to be set
> + */
> + if (1) {
> + termios->c_cflag &= ~(CRTSCTS | CMSPAR | CSTOPB
> + | PARENB | PARODD | CMSPAR);
> + }
> +
> + switch (termios->c_cflag & CSIZE) {
> + case CS6:
> + cval = ePRU_SUART_DATA_BITS6;
> + break;
> + case CS7:
> + cval = ePRU_SUART_DATA_BITS7;
> + break;
> + default:
> + case CS8:
> + cval = ePRU_SUART_DATA_BITS8;
> + break;
> + }
> + /*
> + * We do not support CS5.
> + */
> + if ((termios->c_cflag & CSIZE) == CS5) {
> + termios->c_cflag &= ~CSIZE;
> + termios->c_cflag |= old_csize;
> + }
> + if (pru_softuart_setdatabits
> + (dev, &soft_uart->suart_hdl[port->line], cval, cval) != 0)
> + dev_err(dev, "failed to set data bits to: %d\n", cval);
> +
> +/*
> + * Ask the core to calculate the divisor for us.
> + */
> + baud = uart_get_baud_rate(port, termios, old,
> + port->uartclk / 16 / 0xffff,
> + port->uartclk / 16);
> +
> +/*
> + * Ok, we're now changing the port state. Do it with
> + * interrupts disabled.
> + */
> + spin_lock_irqsave(&port->lock, flags);
> +
> + /* Set the baud */
> + if (pru_softuart_setbaud(dev, &soft_uart->suart_hdl[port->line],
> + SUART_DEFAULT_BAUD / baud,
> + SUART_DEFAULT_BAUD / baud) != 0)
> + dev_err(dev, "failed to set baud to: %d\n", baud);
> +
> +/*
> + * update port->read_config_mask and port->ignore_config_mask
> + * to indicate the events we are interested in receiving
> + */
> + suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, SUART_GBL_INTR_ERR_MASK);
> + port->read_status_mask = 0;
> + if (termios->c_iflag & INPCK) { /* Input parity check not supported,
> + just enabled FE */
> + port->read_status_mask |= CHN_TXRX_STATUS_FE;
> + suart_intr_setmask(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_FE);
> + }
> + if (termios->c_iflag & (BRKINT | PARMRK)) {
> + port->read_status_mask |= CHN_TXRX_STATUS_BI;
> + suart_intr_setmask(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
> + }
> +/*
> + * Characters to ignore
> + */
> + port->ignore_status_mask = 0;
> + if (termios->c_iflag & IGNBRK) {
> + port->ignore_status_mask |= CHN_TXRX_STATUS_BI;
> + /*
> + * If we're ignoring break indicators,
> + * ignore overruns too (for real raw support).
> + */
> + if (termios->c_iflag & IGNPAR) {
> + port->ignore_status_mask |=
> + (CHN_TXRX_STATUS_OVRNERR | CHN_TXRX_STATUS_FE);
> + /*
> + * Overrun in case of RX
> + * Underrun in case of TX
> + */
> + suart_intr_clrmask(dev, soft_uart->
> + suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_FE);
> + }
> + suart_intr_clrmask(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
> + }
> +/*
> + * ignore all characters if CREAD is not set
> + */
> + if ((termios->c_cflag & CREAD) == 0) {
> + port->ignore_status_mask |= CHN_TXRX_STATUS_RDY;
> + pruss_suart_stop_rx(port);
> + }
> + /*
> + * update the per port timeout
> + */
> + uart_update_timeout(port, termios->c_cflag, baud);
> +
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + /* Don't rewrite B0 */
> + if (tty_termios_baud_rate(termios))
> + tty_termios_encode_baud_rate(termios, baud, baud);
> +}
> +
> +/*
> + * Grab any interrupt resources and initialise any low level driver
> + * state. Enable the port for reception. It should not activate
> + * RTS nor DTR; this will be done via a separate call to set_mctrl.
> + *
> + * This method will only be called when the port is initially opened.
> + *
> + * Locking: port_sem taken.
> + * Interrupts: globally disabled.
> + */
> +static s32 pruss_suart_startup(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> + s32 retval;
> +
> + /*
> + * Disable interrupts from this port
> + */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
> + | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
> + | CHN_TXRX_IE_MASK_TIMEOUT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + retval = request_irq(port->irq, pruss_suart_interrupt,
> + port->irqflags, "suart_irq", port);
> + if (retval) {
> + free_irq(port->irq, port); /* should we free this if err */
> + goto out;
> + }
> + /*
> + * enable interrupts from this port
> + */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, SUART_GBL_INTR_ERR_MASK);
> +
> + suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
> + | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
> + | CHN_TXRX_IE_MASK_TIMEOUT);
> +
> + suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + if ((suart_get_duplex(soft_uart, port->line) & ePRU_SUART_HALF_TX)
> + == ePRU_SUART_HALF_TX) {
> + suart_pru_to_host_intr_enable(dev, soft_uart->
> + suart_hdl[port->line].uart_num, PRU_TX_INTR, true);
> + }
> + /* Seed RX if port is half-rx or full-duplex */
> + if ((suart_get_duplex(soft_uart, port->line) & ePRU_SUART_HALF_RX)
> + == ePRU_SUART_HALF_RX) {
> + suart_pru_to_host_intr_enable(dev, soft_uart->
> + suart_hdl[port->line].uart_num, PRU_RX_INTR, true);
> + pru_softuart_read(dev, &soft_uart->suart_hdl[port->line],
> + (u32 *)&soft_uart->suart_fifo_addr[port->line].
> + fifo_phys_addr_rx, SUART_FIFO_LEN);
> + }
> +out:
> + return retval;
> +}
> +
> +/*
> + * Disable the port, disable any break condition that may be in
> + * effect, and free any interrupt resources. It should not disable
> + * RTS nor DTR; this will have already been done via a separate
> + * call to set_mctrl.
> + *
> + * Drivers must not access port->info once this call has completed.
> + *
> + * This method will only be called when there are no more users of
> + * this port.
> + *
> + * Locking: port_sem taken.
> + * Interrupts: caller dependent.
> + */
> +
> +static void pruss_suart_shutdown(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> +
> + /*
> + * Disable interrupts from this port
> + */
> + /* Disable BI and FE intr */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
> + | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
> + | CHN_TXRX_IE_MASK_TIMEOUT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + /* free interrupts */
> + free_irq(port->irq, port);
> +}
> +
> +/*
> + * Return a pointer to a string constant describing the specified
> + * port, or return NULL, in which case the string 'unknown' is
> + * substituted.
> + *
> + * Locking: none.
> + * Interrupts: caller dependent.
> + */
> +
> +static const char *pruss_suart_type(struct uart_port *port)
> +{
> + return "suart_tty";
> +}
> +
> +/*
> + * Release any memory and IO region resources currently in use by
> + * the port.
> + *
> + * Locking: none.
> + * Interrupts: caller dependent.
> + */
> +
> +static void pruss_suart_release_port(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct platform_device *pdev = to_platform_device(port->dev);
> +
> + if (0 != pru_softuart_close(&soft_uart->suart_hdl[port->line]))
> + dev_err(&pdev->dev, "failed to close suart\n");
> +
> + return;
> +}
> +
> +/*
> + * Request any memory and IO region resources required by the port.
> + * If any fail, no resources should be registered when this function
> + * returns, and it should return -EBUSY on failure.
> + *
> + * Locking: none.
> + * Interrupts: caller dependent.
> + *
> + * We need to d/l the f/w in probe and since this api
> + * is called per uart, the request_mem_region should
> + * be called in probe itself.
> + */
> +static s32 pruss_suart_request_port(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct platform_device *pdev = to_platform_device(port->dev);
> + struct device *dev = soft_uart->dev;
> + struct suart_config pru_suart_config;
> + s16 timeout = 0;
> + u32 err = 0;
> +
> + if (soft_uart == NULL) {
> + dev_err(&pdev->dev, "soft_uart ptr failed\n");
> + return -ENODEV;
> + }
> + err = pru_softuart_open(&soft_uart->suart_hdl[port->line]);
> + if (err != 0) {
> + dev_err(&pdev->dev, "failed to open suart: %d\n", err);
> + err = -ENODEV;
> + goto exit;
> + }
> + set_bit(0, &soft_uart->tx_empty[port->line]);
> +
> + /* set fifo /timeout */
> + if (SUART_FIFO_TIMEOUT_MIN > suart_timeout) {
> + dev_err(&pdev->dev, "fifo timeout less than %d ms not supported\n",
> + SUART_FIFO_TIMEOUT_MIN);
> + suart_timeout = SUART_FIFO_TIMEOUT_MIN;
> + } else if (SUART_FIFO_TIMEOUT_MAX < suart_timeout) {
> + dev_err(&pdev->dev, "fifo timeout more than %d ms not supported\n",
> + SUART_FIFO_TIMEOUT_MAX);
> + suart_timeout = SUART_FIFO_TIMEOUT_MAX;
> + }
> +
> + /* This is only for x8 */
> + timeout = (SUART_DEFAULT_BAUD * suart_timeout) / 1000;
> + pru_set_fifo_timeout(dev, timeout);
> +
> + if (soft_uart->suart_hdl[port->line].uart_num == PRU_SUART_UART1) {
> + pru_suart_config.tx_serializer = PRU_SUART0_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART0_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART2) {
> + pru_suart_config.tx_serializer = PRU_SUART1_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART1_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART3) {
> + pru_suart_config.tx_serializer = PRU_SUART2_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART2_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART4) {
> + pru_suart_config.tx_serializer = PRU_SUART3_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART3_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART5) {
> + pru_suart_config.tx_serializer = PRU_SUART4_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART4_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART6) {
> + pru_suart_config.tx_serializer = PRU_SUART5_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART5_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART7) {
> + pru_suart_config.tx_serializer = PRU_SUART6_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART6_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART8) {
> + pru_suart_config.tx_serializer = PRU_SUART7_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART7_CONFIG_RX_SER;
> + } else {
> + return -ENOTSUPP;
> + }
> +
> + /* Some defaults to startup. reconfigured by terimos later */
> + pru_suart_config.tx_clk_divisor = 1;
> + pru_suart_config.rx_clk_divisor = 1;
> + pru_suart_config.tx_bits_per_char = ePRU_SUART_DATA_BITS8;
> + pru_suart_config.rx_bits_per_char = ePRU_SUART_DATA_BITS8;
> + pru_suart_config.oversampling = SUART_DEFAULT_OVRSMPL;
> +
> + if (pru_softuart_setconfig(dev, &soft_uart->suart_hdl[port->line],
> + &pru_suart_config) != 0) {
> + dev_err(&pdev->dev,
> + "pru_softuart_setconfig: failed to set config: %X\n",
> + err);
> + }
> +exit:
> + return err;
> +}
> +
> +/*
> + * Perform any autoconfiguration steps required for the port. `flag`
> + * contains a bit mask of the required configuration. UART_CONFIG_TYPE
> + * indicates that the port requires detection and identification.
> + * port->type should be set to the type found, or PORT_UNKNOWN if
> + * no port was detected.
> + *
> + * UART_CONFIG_IRQ indicates autoconfiguration of the interrupt signal,
> + * which should be probed using standard kernel autoprobing techniques.
> + * This is not necessary on platforms where ports have interrupts
> + * internally hard wired (eg, system on a chip implementations).
> + *
> + * Locking: none.
> + * Interrupts: caller dependent.
> + */
> +
> +static void pruss_suart_config_port(struct uart_port *port, s32 flags)
> +{
> + if (flags & UART_CONFIG_TYPE && pruss_suart_request_port(port) == 0)
> + port->type = PORT_DA8XX_PRU_SUART;
> +}
> +
> +/*
> + * Verify the new serial port information contained within serinfo is
> + * suitable for this port type.
> + *
> + * Locking: none.
> + * Interrupts: caller dependent.
> + */
> +static s32 pruss_suart_verify_port(struct uart_port *port,
> + struct serial_struct *ser)
> +{
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> + s32 ret = 0;
> +
> + if (ser->type != PORT_UNKNOWN && ser->type != PORT_DA8XX_PRU_SUART)
> + ret = -EINVAL;
> + if (soft_uart->port[port->line].irq != ser->irq)
> + ret = -EINVAL;
> + if (ser->io_type != UPIO_MEM)
> + ret = -EINVAL;
> + if (soft_uart->port[port->line].uartclk / 16 != ser->baud_base)
> + ret = -EINVAL;
> + if ((void *)soft_uart->port[port->line].mapbase != ser->iomem_base)
> + ret = -EINVAL;
> + if (soft_uart->port[port->line].iobase != ser->port)
> + ret = -EINVAL;
> + return ret;
> +}
> +
> +static struct uart_ops pruss_suart_ops = {
> + .tx_empty = pruss_suart_tx_empty,
> + .set_mctrl = pruss_suart_set_mctrl,
> + .get_mctrl = pruss_suart_get_mctrl,
> + .stop_tx = pruss_suart_stop_tx,
> + .start_tx = pruss_suart_start_tx,
> + .stop_rx = pruss_suart_stop_rx,
> + .enable_ms = pruss_suart_enable_ms,
> + .break_ctl = pruss_suart_break_ctl,
> + .startup = pruss_suart_startup,
> + .shutdown = pruss_suart_shutdown,
> + .set_termios = pruss_suart_set_termios,
> + .type = pruss_suart_type,
> + .release_port = pruss_suart_release_port,
> + .request_port = pruss_suart_request_port,
> + .config_port = pruss_suart_config_port,
> + .verify_port = pruss_suart_verify_port,
> +};
> +
> +static struct uart_driver pruss_suart_reg = {
> + .owner = THIS_MODULE,
> + .driver_name = DRV_NAME,
> + .dev_name = "ttySU",
> + .major = 0,
> + .minor = 16,
> + .nr = NR_SUART,
> +};
> +
> +static s32 __devinit pruss_suart_probe(struct platform_device *pdev)
> +{
> + struct omapl_pru_suart *soft_uart;
> + const struct da850_evm_pruss_suart_data *pdata;
> + struct device *dev = &pdev->dev;
> + struct resource *res;
> + s32 err, i;
> + u8 *fw_data = NULL;
> +
> + pdata = dev->platform_data;
> + if (!pdata) {
> + dev_err(&pdev->dev, "platform data not found\n");
> + return -EINVAL;
> + }
> +
> + soft_uart = kzalloc(sizeof(struct omapl_pru_suart), GFP_KERNEL);
> + if (!soft_uart)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "failed to get resource");
> + return -ENOMEM;
> + }
> +
> + if (!request_mem_region(res->start,
> + resource_size(res),
> + dev_name(&pdev->dev))) {
> + dev_err(&pdev->dev, "mcasp memory region already claimed!\n");
> + err = -EBUSY;
> + goto probe_exit;
> + }
> +
> + soft_uart->suart_iomap.mcasp_io_addr = ioremap(res->start,
> + resource_size(res));
> + if (!soft_uart->suart_iomap.mcasp_io_addr) {
> + dev_err(&pdev->dev, "mcasp ioremap failed\n");
> + err = -EFAULT;
> + goto probe_exit_1;
> + }
> +
> + soft_uart->suart_iomap.p_fifo_buff_virt_base =
> + sram_alloc(SUART_CNTX_SZ * NR_SUART * 2,
> + (dma_addr_t *) &soft_uart->suart_iomap.p_fifo_buff_phys_base);
> + if (!soft_uart->suart_iomap.p_fifo_buff_virt_base)
> + goto probe_exit_iounmap;
> +
> + soft_uart->clk_freq_pru = pruss_get_clk_freq(dev);
> +
> + soft_uart->clk_mcasp = clk_get(&pdev->dev, NULL);
> + if (IS_ERR(soft_uart->clk_mcasp)) {
> + dev_err(&pdev->dev, "no clock available: mcasp\n");
> + err = -ENODEV;
> + soft_uart->clk_mcasp = NULL;
> + goto probe_exit_sram_free;
> + }
> +
> + soft_uart->clk_freq_mcasp = clk_get_rate(soft_uart->clk_mcasp);
> + clk_enable(soft_uart->clk_mcasp);
> +
> + err = request_firmware(&soft_uart->fw, "PRU_SUART_Emulation.bin",
> + &pdev->dev);
> + if (err) {
> + dev_err(&pdev->dev, "can't load firmware\n");
> + err = -ENODEV;
> + goto probe_exit_clk;
> + }
> + dev_info(&pdev->dev, "fw size %td. downloading...\n",
> + soft_uart->fw->size);
> +
> + /* download firmware into pru & init */
> + fw_data = kmalloc(soft_uart->fw->size, GFP_KERNEL);
> + memcpy((void *)fw_data, (const void *)soft_uart->fw->data,
> + soft_uart->fw->size);
> +
> + soft_uart->suart_iomap.pru_clk_freq =
> + (soft_uart->clk_freq_pru / 1000000);
> +
> + err = pru_softuart_init(dev, SUART_DEFAULT_BAUD, SUART_DEFAULT_BAUD,
> + SUART_DEFAULT_OVRSMPL, fw_data,
> + soft_uart->fw->size, &soft_uart->suart_iomap);
> + if (err) {
> + dev_err(&pdev->dev, "pruss init error\n");
> + err = -ENODEV;
> + kfree((const void *)fw_data);
> + goto probe_release_fw;
> + }
> + kfree((const void *)fw_data);
> +
> + platform_set_drvdata(pdev, &soft_uart->port[0]);
> + soft_uart->dev = dev;
> +
> + for (i = 0; i < NR_SUART; i++) {
> + soft_uart->port[i].ops = &pruss_suart_ops;
> + soft_uart->port[i].iotype = UPIO_MEM;
> + soft_uart->port[i].flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
> + soft_uart->port[i].mapbase =
> + (u32)soft_uart->suart_iomap.p_fifo_buff_virt_base;
> + soft_uart->port[i].membase =
> + (u8 *)&soft_uart->suart_iomap;
> + soft_uart->port[i].type = PORT_DA8XX_PRU_SUART;
> + soft_uart->port[i].irq =
> + platform_get_irq(to_platform_device(dev->parent), i);
> + soft_uart->port[i].dev = &pdev->dev;
> + soft_uart->port[i].irqflags = IRQF_SHARED;
> + soft_uart->port[i].uartclk = soft_uart->clk_freq_mcasp;
> + soft_uart->port[i].fifosize = SUART_FIFO_LEN;
> + soft_uart->tx_loadsz = SUART_FIFO_LEN;
> + soft_uart->port[i].custom_divisor = 1;
> + soft_uart->port[i].line = i;
> + soft_uart->suart_hdl[i].uart_num = i + 1;
> + soft_uart->port[i].serial_in = NULL;
> +
> + soft_uart->suart_fifo_addr[i].fifo_vaddr_buff_tx =
> + soft_uart->suart_iomap.p_fifo_buff_virt_base +
> + (2 * SUART_CNTX_SZ * i);
> +
> + soft_uart->suart_fifo_addr[i].fifo_vaddr_buff_rx =
> + soft_uart->suart_iomap.p_fifo_buff_virt_base +
> + ((2 * SUART_CNTX_SZ * i) + SUART_CNTX_SZ);
> +
> + soft_uart->suart_fifo_addr[i].fifo_phys_addr_tx =
> + soft_uart->suart_iomap.p_fifo_buff_phys_base +
> + (2 * SUART_CNTX_SZ * i);
> +
> + soft_uart->suart_fifo_addr[i].fifo_phys_addr_rx =
> + soft_uart->suart_iomap.p_fifo_buff_phys_base +
> + ((2 * SUART_CNTX_SZ * i) + SUART_CNTX_SZ);
> +
> + soft_uart->port[i].serial_out = NULL;
> + tasklet_init(&soft_uart->tx_task[i], suart_tx_task,
> + (unsigned long)&soft_uart->port[i]);
> + uart_add_one_port(&pruss_suart_reg, &soft_uart->port[i]);
> + }
> +
> + dev_info(&pdev->dev,
> + "%s device registered (pru_clk=%d, asp_clk=%d)\n",
> + DRV_NAME, soft_uart->clk_freq_pru, soft_uart->clk_freq_mcasp);
> +
> + return 0;
> +
> +probe_release_fw:
> + release_firmware(soft_uart->fw);
> +probe_exit_clk:
> + clk_put(soft_uart->clk_mcasp);
> + clk_disable(soft_uart->clk_mcasp);
> +probe_exit_sram_free:
> + sram_free(soft_uart->suart_iomap.p_fifo_buff_virt_base,
> + SUART_CNTX_SZ * NR_SUART * 2);
> +probe_exit_iounmap:
> + iounmap(soft_uart->suart_iomap.mcasp_io_addr);
> +probe_exit_1:
> + release_mem_region(res->start,
> + resource_size(res));
> +probe_exit:
> + kfree(soft_uart);
> + return err;
> +}
> +
> +static s32 __devexit pruss_suart_remove(struct platform_device *pdev)
> +{
> + struct omapl_pru_suart *soft_uart = platform_get_drvdata(pdev);
> + const struct da850_evm_pruss_suart_data *pdata;
> + struct device *dev = &pdev->dev;
> + struct resource *res;
> + int i;
> +
> + pdata = dev->platform_data;
> + if (!pdata)
> + dev_err(&pdev->dev, "platform data not found\n");
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "failed to get resource");
> + return -ENOMEM;
> + }
> +
> + platform_set_drvdata(pdev, NULL);
> +
> + if (soft_uart) {
> + for (i = 0; i < NR_SUART; i++) {
> + uart_remove_one_port(&pruss_suart_reg,
> + &soft_uart->port[i]);
> + }
> + }
> +
> + sram_free(soft_uart->suart_iomap.p_fifo_buff_virt_base,
> + SUART_CNTX_SZ * NR_SUART * 2);
> + release_firmware(soft_uart->fw);
> + clk_put(soft_uart->clk_mcasp);
> + pru_mcasp_deinit();
> + clk_disable(soft_uart->clk_mcasp);
> + iounmap(soft_uart->suart_iomap.mcasp_io_addr);
> + if (pdata) {
> + release_mem_region(res->start,
> + resource_size(res));
> + }
> + kfree(soft_uart);
> + return 0;
> +}
> +
> +#define pruss_suart_suspend NULL
> +#define pruss_suart_resume NULL
> +
> +static struct platform_driver serial_pruss_driver = {
> + .probe = pruss_suart_probe,
> + .remove = __devexit_p(pruss_suart_remove),
> + .suspend = pruss_suart_suspend,
> + .resume = pruss_suart_resume,
> + .driver = {
> + .name = DRV_NAME,
> + .owner = THIS_MODULE,
> + },
> +};
> +
> +static s32 __init pruss_suart_init(void)
> +{
> + s32 ret;
> +
> + pruss_suart_reg.nr = NR_SUART;
> + ret = uart_register_driver(&pruss_suart_reg);
> + if (ret)
> + return ret;
> + ret = platform_driver_register(&serial_pruss_driver);
> + if (ret)
> + goto out;
> +
> + pr_debug("SUART serial driver loaded\n");
> + return ret;
> +out:
> + uart_unregister_driver(&pruss_suart_reg);
> + return ret;
> +}
> +
> +module_init(pruss_suart_init);
> +
> +static void __exit pruss_suart_exit(void)
> +{
> + platform_driver_unregister(&serial_pruss_driver);
> + uart_unregister_driver(&pruss_suart_reg);
> + pr_debug("SUART serial driver unloaded\n");
> +}
> +
> +module_exit(pruss_suart_exit);
> +
> +/* Module information */
> +MODULE_AUTHOR("Subhasish Ghosh <subhasish@...tralsolutions.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION(DRV_DESC);
> diff --git a/drivers/tty/serial/pruss_suart.h
> b/drivers/tty/serial/pruss_suart.h
> new file mode 100644
> index 0000000..8e0b40d
> --- /dev/null
> +++ b/drivers/tty/serial/pruss_suart.h
> @@ -0,0 +1,1081 @@
> +/*
> + * Copyright (C) 2010 Texas Instruments Incorporated
> + * Author: Jitendra Kumar <jitendra@...tralsolutions.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation version 2.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
> + * whether express or implied; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#ifndef _SUART_API_H_
> +#define _SUART_API_H_
> +
> +#include <linux/types.h>
> +#include <linux/bitops.h>
> +#include <linux/io.h>
> +#include <linux/mfd/da8xx/da8xx_pru.h>
> +
> +#define SINGLE_PRU 0
> +#define BOTH_PRU 1
> +#define PRU_ACTIVE BOTH_PRU
> +#define PRU_CLK_228 228
> +#define PRU_CLK_186 186
> +
> +#define PRU_SUART_SERIALIZER_0 (0u)
> +#define PRU_SUART_SERIALIZER_1 (1u)
> +#define PRU_SUART_SERIALIZER_2 (2u)
> +#define PRU_SUART_SERIALIZER_3 (3u)
> +#define PRU_SUART_SERIALIZER_4 (4u)
> +#define PRU_SUART_SERIALIZER_5 (5u)
> +#define PRU_SUART_SERIALIZER_6 (6u)
> +#define PRU_SUART_SERIALIZER_7 (7u)
> +#define PRU_SUART_SERIALIZER_8 (8u)
> +#define PRU_SUART_SERIALIZER_9 (9u)
> +#define PRU_SUART_SERIALIZER_10 (10u)
> +#define PRU_SUART_SERIALIZER_11 (11u)
> +#define PRU_SUART_SERIALIZER_12 (12u)
> +#define PRU_SUART_SERIALIZER_13 (13u)
> +#define PRU_SUART_SERIALIZER_14 (14u)
> +#define PRU_SUART_SERIALIZER_15 (15u)
> +#define PRU_SUART_SERIALIZER_NONE (16u)
> +
> +#define PRU_SUART_UART1 (1u)
> +#define PRU_SUART_UART2 (2u)
> +#define PRU_SUART_UART3 (3u)
> +#define PRU_SUART_UART4 (4u)
> +#define PRU_SUART_UART5 (5u)
> +#define PRU_SUART_UART6 (6u)
> +#define PRU_SUART_UART7 (7u)
> +#define PRU_SUART_UART8 (8u)
> +#define PRU_SUART_UARTx_INVALID (9u)
> +
> +#define PRU_SUART_HALF_TX (1u)
> +#define PRU_SUART_HALF_RX (2u)
> +#define PRU_SUART_HALF_TX_DISABLED (4u)
> +#define PRU_SUART_HALF_RX_DISABLED (8u)
> +
> +#define PRU_SUART0_CONFIG_DUPLEX (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#define PRU_SUART0_CONFIG_RX_SER (PRU_SUART_SERIALIZER_NONE)
> +#define PRU_SUART0_CONFIG_TX_SER (PRU_SUART_SERIALIZER_NONE)
> +
> +#define PRU_SUART1_CONFIG_DUPLEX (PRU_SUART_HALF_TX | \
> + PRU_SUART_HALF_RX)
> +#define PRU_SUART1_CONFIG_RX_SER (PRU_SUART_SERIALIZER_7)
> +#define PRU_SUART1_CONFIG_TX_SER (PRU_SUART_SERIALIZER_8)
> +
> +#define PRU_SUART2_CONFIG_DUPLEX (PRU_SUART_HALF_TX | \
> + PRU_SUART_HALF_RX)
> +#define PRU_SUART2_CONFIG_RX_SER (PRU_SUART_SERIALIZER_9)
> +#define PRU_SUART2_CONFIG_TX_SER (PRU_SUART_SERIALIZER_10)
> +
> +#define PRU_SUART3_CONFIG_DUPLEX (PRU_SUART_HALF_TX | \
> + PRU_SUART_HALF_RX)
> +#define PRU_SUART3_CONFIG_RX_SER (PRU_SUART_SERIALIZER_13)
> +#define PRU_SUART3_CONFIG_TX_SER (PRU_SUART_SERIALIZER_14)
> +
> +#define PRU_SUART4_CONFIG_DUPLEX (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#define PRU_SUART4_CONFIG_RX_SER (PRU_SUART_SERIALIZER_NONE)
> +#define PRU_SUART4_CONFIG_TX_SER (PRU_SUART_SERIALIZER_NONE)
> +
> +#define PRU_SUART5_CONFIG_DUPLEX (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#define PRU_SUART5_CONFIG_RX_SER (PRU_SUART_SERIALIZER_NONE)
> +#define PRU_SUART5_CONFIG_TX_SER (PRU_SUART_SERIALIZER_NONE)
> +
> +#define PRU_SUART6_CONFIG_DUPLEX (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#define PRU_SUART6_CONFIG_RX_SER (PRU_SUART_SERIALIZER_NONE)
> +#define PRU_SUART6_CONFIG_TX_SER (PRU_SUART_SERIALIZER_NONE)
> +
> +#define PRU_SUART7_CONFIG_DUPLEX (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#define PRU_SUART7_CONFIG_RX_SER (PRU_SUART_SERIALIZER_NONE)
> +#define PRU_SUART7_CONFIG_TX_SER (PRU_SUART_SERIALIZER_NONE)
> +
> +#define SUART_NUM_OF_CHANNELS_PER_SUART 2
> +#define SUART_NUM_OF_BYTES_PER_CHANNEL 16
> +
> +#define PRU_TX_INTR 1
> +#define PRU_RX_INTR 2
> +
> +#define CHN_TXRX_STATUS_TIMEOUT BIT(6)
> +#define CHN_TXRX_STATUS_BI BIT(5)
> +#define CHN_TXRX_STATUS_FE BIT(4)
> +#define CHN_TXRX_STATUS_UNERR BIT(3)
> +#define CHN_TXRX_STATUS_OVRNERR BIT(3)
> +#define CHN_TXRX_STATUS_ERR BIT(2)
> +#define CHN_TXRX_STATUS_CMPLT BIT(1)
> +#define CHN_TXRX_STATUS_RDY BIT(0)
> +
> +#define CHN_TXRX_IE_MASK_TIMEOUT BIT(14)
> +#define CHN_TXRX_IE_MASK_BI BIT(13)
> +#define CHN_TXRX_IE_MASK_FE BIT(12)
> +#define CHN_TXRX_IE_MASK_CMPLT BIT(1)
> +
> +#define SUART_GBL_INTR_ERR_MASK BIT(9)
> +#define SUART_PRU_ID_MASK 0xFF
> +
> +#define SUART_FIFO_LEN 15
> +#define SUART_8X_OVRSMPL 1
> +#define SUART_16X_OVRSMPL 2
> +#define SUART_DEFAULT_OVRSMPL SUART_8X_OVRSMPL
> +
> +#define SUART_DEFAULT_OVRSMPL_OFFSET 26
> +#define SUART_CHN_OFFSET 31
> +#define SERIALIZER_OFFSET 8
> +
> +#if (SUART_DEFAULT_OVRSMPL == SUART_16X_OVRSMPL)
> +#define SUART_DEFAULT_BAUD 57600
> +#else
> +#define SUART_DEFAULT_BAUD 115200
> +#endif
> +
> +#define PRU_MODE_INVALID 0x0
> +#define PRU_MODE_TX_ONLY 0x1
> +#define PRU_MODE_RX_ONLY 0x2
> +#define PRU_MODE_RX_TX_BOTH 0x3
> +
> +#if (PRU_ACTIVE == BOTH_PRU)
> +#define PRU0_MODE PRU_MODE_RX_ONLY
> +#define PRU1_MODE PRU_MODE_TX_ONLY
> +#elif (PRU_ACTIVE == SINGLE_PRU)
> +#define PRU0_MODE PRU_MODE_RX_TX_BOTH
> +#define PRU1_MODE PRU_MODE_INVALID
> +#else
> +#define PRU0_MODE PRU_MODE_INVALID
> +#define PRU1_MODE PRU_MODE_INVALID
> +#endif
> +
> +#define MCASP_XBUF_BASE_ADDR (0x01d00200)
> +#define MCASP_RBUF_BASE_ADDR (0x01d00280)
> +#define MCASP_SRCTL_BASE_ADDR (0x01d00180)
> +
> +#define MCASP_SRCTL_TX_MODE (0x000D)
> +#define MCASP_SRCTL_RX_MODE (0x000E)
> +
> +/* Since only PRU0 can work as RX */
> +#define RX_DEFAULT_DATA_DUMP_ADDR (0x00001FC)
> +#define PRU_NUM_OF_CHANNELS (16)
> +
> +/* MCASP */
> +
> +#define OMAPL_MCASP_PFUNC_AFSR_MASK (0x80000000u)
> +#define OMAPL_MCASP_PFUNC_AFSR_SHIFT (0x0000001Fu)
> +#define OMAPL_MCASP_PFUNC_AFSR_RESETVAL (0x00000000u)
> +/* AFSR Tokens */
> +#define OMAPL_MCASP_PFUNC_AFSR_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AFSR_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AHCLKR_MASK (0x40000000u)
> +#define OMAPL_MCASP_PFUNC_AHCLKR_SHIFT (0x0000001Eu)
> +#define OMAPL_MCASP_PFUNC_AHCLKR_RESETVAL (0x00000000u)
> +/* AHCLKR Tokens */
> +#define OMAPL_MCASP_PFUNC_AHCLKR_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AHCLKR_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_ACLKR_MASK (0x20000000u)
> +#define OMAPL_MCASP_PFUNC_ACLKR_SHIFT (0x0000001Du)
> +#define OMAPL_MCASP_PFUNC_ACLKR_RESETVAL (0x00000000u)
> +/* ACLKR Tokens */
> +#define OMAPL_MCASP_PFUNC_ACLKR_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_ACLKR_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AFSX_MASK (0x10000000u)
> +#define OMAPL_MCASP_PFUNC_AFSX_SHIFT (0x0000001Cu)
> +#define OMAPL_MCASP_PFUNC_AFSX_RESETVAL (0x00000000u)
> +/* AFSX Tokens */
> +#define OMAPL_MCASP_PFUNC_AFSX_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AFSX_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AHCLKX_MASK (0x08000000u)
> +#define OMAPL_MCASP_PFUNC_AHCLKX_SHIFT (0x0000001Bu)
> +#define OMAPL_MCASP_PFUNC_AHCLKX_RESETVAL (0x00000000u)
> +/* AHCLKX Tokens */
> +#define OMAPL_MCASP_PFUNC_AHCLKX_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AHCLKX_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_ACLKX_MASK (0x04000000u)
> +#define OMAPL_MCASP_PFUNC_ACLKX_SHIFT (0x0000001Au)
> +#define OMAPL_MCASP_PFUNC_ACLKX_RESETVAL (0x00000000u)
> +/* ACLKX Tokens */
> +#define OMAPL_MCASP_PFUNC_ACLKX_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_ACLKX_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AMUTE_MASK (0x02000000u)
> +#define OMAPL_MCASP_PFUNC_AMUTE_SHIFT (0x00000019u)
> +#define OMAPL_MCASP_PFUNC_AMUTE_RESETVAL (0x00000000u)
> +/* AMUTE Tokens */
> +#define OMAPL_MCASP_PFUNC_AMUTE_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AMUTE_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR15_MASK (0x00008000u)
> +#define OMAPL_MCASP_PFUNC_AXR15_SHIFT (0x0000000Fu)
> +#define OMAPL_MCASP_PFUNC_AXR15_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR15_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR15_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR14_MASK (0x00004000u)
> +#define OMAPL_MCASP_PFUNC_AXR14_SHIFT (0x0000000Eu)
> +#define OMAPL_MCASP_PFUNC_AXR14_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR14_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR14_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR13_MASK (0x00002000u)
> +#define OMAPL_MCASP_PFUNC_AXR13_SHIFT (0x0000000Du)
> +#define OMAPL_MCASP_PFUNC_AXR13_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR13_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR13_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR12_MASK (0x00001000u)
> +#define OMAPL_MCASP_PFUNC_AXR12_SHIFT (0x0000000Cu)
> +#define OMAPL_MCASP_PFUNC_AXR12_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR12_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR12_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR11_MASK (0x00000800u)
> +#define OMAPL_MCASP_PFUNC_AXR11_SHIFT (0x0000000Bu)
> +#define OMAPL_MCASP_PFUNC_AXR11_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR11_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR11_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR10_MASK (0x00000400u)
> +#define OMAPL_MCASP_PFUNC_AXR10_SHIFT (0x0000000Au)
> +#define OMAPL_MCASP_PFUNC_AXR10_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR10_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR10_GPIO (0x00000001u)
> +#define OMAPL_MCASP_PFUNC_AXR9_MASK (0x00000200u)
> +#define OMAPL_MCASP_PFUNC_AXR9_SHIFT (0x00000009u)
> +#define OMAPL_MCASP_PFUNC_AXR9_RESETVAL (0x00000000u)
> +/* AXR9 Token */
> +#define OMAPL_MCASP_PFUNC_AXR9_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR9_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR8_MASK (0x00000100u)
> +#define OMAPL_MCASP_PFUNC_AXR8_SHIFT (0x00000008u)
> +#define OMAPL_MCASP_PFUNC_AXR8_RESETVAL (0x00000000u)
> +/* AXR8 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR8_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR8_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR7_MASK (0x00000080u)
> +#define OMAPL_MCASP_PFUNC_AXR7_SHIFT (0x00000007u)
> +#define OMAPL_MCASP_PFUNC_AXR7_RESETVAL (0x00000000u)
> +/* AXR7 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR7_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR7_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR6_MASK (0x00000040u)
> +#define OMAPL_MCASP_PFUNC_AXR6_SHIFT (0x00000006u)
> +#define OMAPL_MCASP_PFUNC_AXR6_RESETVAL (0x00000000u)
> +/* AXR6 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR6_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR6_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR5_MASK (0x00000020u)
> +#define OMAPL_MCASP_PFUNC_AXR5_SHIFT (0x00000005u)
> +#define OMAPL_MCASP_PFUNC_AXR5_RESETVAL (0x00000000u)
> +/* AXR5 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR5_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR5_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR4_MASK (0x00000010u)
> +#define OMAPL_MCASP_PFUNC_AXR4_SHIFT (0x00000004u)
> +#define OMAPL_MCASP_PFUNC_AXR4_RESETVAL (0x00000000u)
> +/* AXR4 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR4_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR4_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR3_MASK (0x00000008u)
> +#define OMAPL_MCASP_PFUNC_AXR3_SHIFT (0x00000003u)
> +#define OMAPL_MCASP_PFUNC_AXR3_RESETVAL (0x00000000u)
> +/* AXR3 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR3_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR3_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR2_MASK (0x00000004u)
> +#define OMAPL_MCASP_PFUNC_AXR2_SHIFT (0x00000002u)
> +#define OMAPL_MCASP_PFUNC_AXR2_RESETVAL (0x00000000u)
> +/* AXR2 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR2_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR2_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR1_MASK (0x00000002u)
> +#define OMAPL_MCASP_PFUNC_AXR1_SHIFT (0x00000001u)
> +#define OMAPL_MCASP_PFUNC_AXR1_RESETVAL (0x00000000u)
> +/* AXR1 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR1_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR1_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR0_MASK (0x00000001u)
> +#define OMAPL_MCASP_PFUNC_AXR0_SHIFT (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR0_RESETVAL (0x00000000u)
> +/* AXR0 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR0_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR0_GPIO (0x00000001u)
> +#define OMAPL_MCASP_PFUNC_RESETVAL (0x00000000u)
> +
> +#define OMAPL_MCASP_PDIR_AFSR_MASK (0x80000000u)
> +#define OMAPL_MCASP_PDIR_AFSR_SHIFT (0x0000001Fu)
> +#define OMAPL_MCASP_PDIR_AFSR_RESETVAL (0x00000000u)
> +/* AFSR Tokens */
> +#define OMAPL_MCASP_PDIR_AFSR_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AFSR_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AHCLKR_MASK (0x40000000u)
> +#define OMAPL_MCASP_PDIR_AHCLKR_SHIFT (0x0000001Eu)
> +#define OMAPL_MCASP_PDIR_AHCLKR_RESETVAL (0x00000000u)
> +/* AHCLKR Tokens */
> +#define OMAPL_MCASP_PDIR_AHCLKR_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AHCLKR_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_ACLKR_MASK (0x20000000u)
> +#define OMAPL_MCASP_PDIR_ACLKR_SHIFT (0x0000001Du)
> +#define OMAPL_MCASP_PDIR_ACLKR_RESETVAL (0x00000000u)
> +/* ACLKR Tokens */
> +#define OMAPL_MCASP_PDIR_ACLKR_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_ACLKR_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AFSX_MASK (0x10000000u)
> +#define OMAPL_MCASP_PDIR_AFSX_SHIFT (0x0000001Cu)
> +#define OMAPL_MCASP_PDIR_AFSX_RESETVAL (0x00000000u)
> +/* AFSX Tokens */
> +#define OMAPL_MCASP_PDIR_AFSX_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AFSX_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AHCLKX_MASK (0x08000000u)
> +#define OMAPL_MCASP_PDIR_AHCLKX_SHIFT (0x0000001Bu)
> +#define OMAPL_MCASP_PDIR_AHCLKX_RESETVAL (0x00000000u)
> +/* AHCLKX Tokens */
> +#define OMAPL_MCASP_PDIR_AHCLKX_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AHCLKX_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_ACLKX_MASK (0x04000000u)
> +#define OMAPL_MCASP_PDIR_ACLKX_SHIFT (0x0000001Au)
> +#define OMAPL_MCASP_PDIR_ACLKX_RESETVAL (0x00000000u)
> +/* ACLKX Tokens */
> +#define OMAPL_MCASP_PDIR_ACLKX_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_ACLKX_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AMUTE_MASK (0x02000000u)
> +#define OMAPL_MCASP_PDIR_AMUTE_SHIFT (0x00000019u)
> +#define OMAPL_MCASP_PDIR_AMUTE_RESETVAL (0x00000000u)
> +/* AMUTE Tokens */
> +#define OMAPL_MCASP_PDIR_AMUTE_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AMUTE_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR15_MASK (0x00008000u)
> +#define OMAPL_MCASP_PDIR_AXR15_SHIFT (0x0000000Fu)
> +#define OMAPL_MCASP_PDIR_AXR15_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR15_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR15_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR14_MASK (0x00004000u)
> +#define OMAPL_MCASP_PDIR_AXR14_SHIFT (0x0000000Eu)
> +#define OMAPL_MCASP_PDIR_AXR14_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR14_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR14_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR13_MASK (0x00002000u)
> +#define OMAPL_MCASP_PDIR_AXR13_SHIFT (0x0000000Du)
> +#define OMAPL_MCASP_PDIR_AXR13_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR13_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR13_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR12_MASK (0x00001000u)
> +#define OMAPL_MCASP_PDIR_AXR12_SHIFT (0x0000000Cu)
> +#define OMAPL_MCASP_PDIR_AXR12_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR12_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR12_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR11_MASK (0x00000800u)
> +#define OMAPL_MCASP_PDIR_AXR11_SHIFT (0x0000000Bu)
> +#define OMAPL_MCASP_PDIR_AXR11_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR11_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR11_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR10_MASK (0x00000400u)
> +#define OMAPL_MCASP_PDIR_AXR10_SHIFT (0x0000000Au)
> +#define OMAPL_MCASP_PDIR_AXR10_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR10_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR10_OUTPUT (0x00000001u)
> +#define OMAPL_MCASP_PDIR_AXR9_MASK (0x00000200u)
> +#define OMAPL_MCASP_PDIR_AXR9_SHIFT (0x00000009u)
> +#define OMAPL_MCASP_PDIR_AXR9_RESETVAL (0x00000000u)
> +/* AXR9 Tokens */
> +#define OMAPL_MCASP_PDIR_AXR9_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR9_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR8_MASK (0x00000100u)
> +#define OMAPL_MCASP_PDIR_AXR8_SHIFT (0x00000008u)
> +#define OMAPL_MCASP_PDIR_AXR8_RESETVAL (0x00000000u)
> +/* AXR8 Tokens */
> +#define OMAPL_MCASP_PDIR_AXR8_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR8_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR7_MASK (0x00000080u)
> +#define OMAPL_MCASP_PDIR_AXR7_SHIFT (0x00000007u)
> +#define OMAPL_MCASP_PDIR_AXR7_RESETVAL (0x00000000u)
> +/*----AXR7 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR7_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR7_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR6_MASK (0x00000040u)
> +#define OMAPL_MCASP_PDIR_AXR6_SHIFT (0x00000006u)
> +#define OMAPL_MCASP_PDIR_AXR6_RESETVAL (0x00000000u)
> +/*----AXR6 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR6_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR6_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR5_MASK (0x00000020u)
> +#define OMAPL_MCASP_PDIR_AXR5_SHIFT (0x00000005u)
> +#define OMAPL_MCASP_PDIR_AXR5_RESETVAL (0x00000000u)
> +/*----AXR5 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR5_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR5_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR4_MASK (0x00000010u)
> +#define OMAPL_MCASP_PDIR_AXR4_SHIFT (0x00000004u)
> +#define OMAPL_MCASP_PDIR_AXR4_RESETVAL (0x00000000u)
> +/*----AXR4 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR4_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR4_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR3_MASK (0x00000008u)
> +#define OMAPL_MCASP_PDIR_AXR3_SHIFT (0x00000003u)
> +#define OMAPL_MCASP_PDIR_AXR3_RESETVAL (0x00000000u)
> +/*----AXR3 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR3_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR3_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR2_MASK (0x00000004u)
> +#define OMAPL_MCASP_PDIR_AXR2_SHIFT (0x00000002u)
> +#define OMAPL_MCASP_PDIR_AXR2_RESETVAL (0x00000000u)
> +/*----AXR2 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR2_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR2_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR1_MASK (0x00000002u)
> +#define OMAPL_MCASP_PDIR_AXR1_SHIFT (0x00000001u)
> +#define OMAPL_MCASP_PDIR_AXR1_RESETVAL (0x00000000u)
> +/*----AXR1 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR1_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR1_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR0_MASK (0x00000001u)
> +#define OMAPL_MCASP_PDIR_AXR0_SHIFT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR0_RESETVAL (0x00000000u)
> +/*----AXR0 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR0_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR0_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_RESETVAL (0x00000000u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_MASK (0x00000080u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_SHIFT (0x00000007u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_RESETVAL (0x00000000u)
> +/*----CLKXP Tokens----*/
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_RISINGEDGE (0x00000000u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_FALLINGEDGE (0x00000001u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_MASK (0x00000040u)
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_SHIFT (0x00000006u)
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_RESETVAL (0x00000001u)
> +/*----ASYNC Tokens----*/
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_SYNC (0x00000000u)
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_ASYNC (0x00000001u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_MASK (0x00000020u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_SHIFT (0x00000005u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_RESETVAL (0x00000001u)
> +/*----CLKXM Tokens----*/
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_EXTERNAL (0x00000000u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_INTERNAL (0x00000001u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_CLKXDIV_MASK (0x0000001Fu)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT (0x00000000u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXDIV_RESETVAL (0x00000000u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_RESETVAL (0x00000060u)
> +
> +/* AHCLKXCTL */
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_MASK (0x00008000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_SHIFT (0x0000000Fu)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_RESETVAL (0x00000001u)
> +/*----HCLKXM Tokens----*/
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_EXTERNAL (0x00000000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_INTERNAL (0x00000001u)
> +
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_MASK (0x00004000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_SHIFT (0x0000000Eu)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_RESETVAL (0x00000000u)
> +/*----HCLKXP Tokens----*/
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_NOTINVERTED (0x00000000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_INVERTED (0x00000001u)
> +
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_MASK (0x00000FFFu)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT (0x00000000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_RESETVAL (0x00000000u)
> +
> +#define OMAPL_MCASP_AHCLKXCTL_RESETVAL (0x00008000u)
> +
> +#define MCASP_SUART_GBLCTL (0X00000000)
> +#define MCASP_SUART_RGBLCTL (0X00000000)
> +#define MCASP_SUART_XGBLCTL (0X00000000)
> +#define MCASP_SUART_RMASK_8 (0x000000FF)
> +#define MCASP_SUART_RMASK_16 (0x0000FFFF)
> +#define MCASP_SUART_RFMT_8 (0x0000A038)
> +#define MCASP_SUART_RFMT_16 (0x0000A078)
> +#define MCASP_SUART_FSRM (0X00000002)
> +#define MCASP_SUART_CLKRM_CLKRP (0X000000A0)
> +#define MCASP_SUART_HCLKRP (0X00008000)
> +#define MCASP_SUART_RTDMS0 (0X00000001)
> +#define MCASP_SUART_RSYNCERR (0X00000002)
> +#define MCASP_SUART_RMAX_RPS_256 (0x00FF0008)
> +#define MCASP_SUART_XMASK_0_31 (0X0000FFFF)
> +#define MCASP_SUART_XBUSEL_XSSZ_16_XPAD_0 (0x00002078)
> +#define MCASP_SUART_FSXM (0x00000002)
> +#define MCASP_SUART_CLKXM_ASYNC_CLKXP (0x000000E0)
> +#define MCASP_SUART_HCLKXM (0x00008000)
> +#define MCASP_SUART_XTDMS0 (0X00000001)
> +#define MCASP_SUART_XSYNCERR (0x00000002)
> +#define MCASP_SUART_XMAX_XPS_256 (0x00FF0008)
> +#define MCASP_SUART_SRCTL_DISMOD (0x0000000c)
> +#define MCASP_SUART_DIT_DISABLE (0X00000000)
> +#define MCASP_SUART_LOOPBACK_DISABLE (0x00000000)
> +#define MCASP_SUART_AMUTE_DISABLE (0X00000000)
> +#define MCASP_SUART_XSTAT (0x0000FFFF)
> +#define MCASP_SUART_RSTAT (0x0000FFFF)
> +
> +/* SUART REGS */
> +
> +/* PRU0 DATA RAM base address */
> +#define PRU0_DATARAM_OFFSET (0x0000u)
> +/* PRU1 DATA RAM base address */
> +#define PRU1_DATARAM_OFFSET (0x2000u)
> +
> +/* PRU0 DATA RAM size */
> +#define PRU0_DATARAM_SIZE (0x200u)
> +/* PRU1 DATA RAM size */
> +#define PRU1_DATARAM_SIZE (0x200u)
> +
> +#define PRU_SUART_PRU0_CH0_OFFSET (0x0000)
> +#define PRU_SUART_PRU0_CH1_OFFSET (0x0010)
> +#define PRU_SUART_PRU0_CH2_OFFSET (0x0020)
> +#define PRU_SUART_PRU0_CH3_OFFSET (0x0030)
> +#define PRU_SUART_PRU0_CH4_OFFSET (0x0040)
> +#define PRU_SUART_PRU0_CH5_OFFSET (0x0050)
> +#define PRU_SUART_PRU0_CH6_OFFSET (0x0060)
> +#define PRU_SUART_PRU0_CH7_OFFSET (0x0070)
> +#define PRU_SUART_PRU0_IMR_OFFSET (0x0080)
> +/* Interrupt Mask Register */
> +#define PRU_SUART_PRU0_ISR_OFFSET (0x0082)
> +/* Interrupt Status Register */
> +#define PRU_SUART_PRU0_ID_ADDR (0x0084)
> +/* PRU ID Register */
> +#define PRU_SUART_PRU0_RX_TX_MODE (0x0085)
> +#define PRU_SUART_PRU0_DELAY_OFFSET (0x0086)
> +#define PRU_SUART_PRU0_IDLE_TIMEOUT_OFFSET (0x0088)
> +
> +/* PRU 1 Macros */
> +#define PRU_SUART_PRU1_CH0_OFFSET (0x2000)
> +#define PRU_SUART_PRU1_CH1_OFFSET (0x2010)
> +#define PRU_SUART_PRU1_CH2_OFFSET (0x2020)
> +#define PRU_SUART_PRU1_CH3_OFFSET (0x2030)
> +#define PRU_SUART_PRU1_CH4_OFFSET (0x2040)
> +#define PRU_SUART_PRU1_CH5_OFFSET (0x2050)
> +#define PRU_SUART_PRU1_CH6_OFFSET (0x2060)
> +#define PRU_SUART_PRU1_CH7_OFFSET (0x2070)
> +#define PRU_SUART_PRU1_IMR_OFFSET (0x2080)
> +#define PRU_SUART_PRU1_ISR_OFFSET (0x2082)
> +#define PRU_SUART_PRU1_ID_ADDR (0x2084)
> +#define PRU_SUART_PRU1_RX_TX_MODE (0x2085)
> +#define PRU_SUART_PRU1_DELAY_OFFSET (0x2086)
> +#define PRU_SUART_PRU1_IDLE_TIMEOUT_OFFSET (0x2088)
> +
> +/* SUART Channel Control Register bit descriptions */
> +#define PRU_SUART_CH_CTRL_MODE_SHIFT 0x0000
> +#define PRU_SUART_CH_CTRL_MODE_MASK 0x0003
> +#define PRU_SUART_CH_CTRL_TX_MODE 0x0001
> +#define PRU_SUART_CH_CTRL_RX_MODE 0x0002
> +
> +/* Service Request */
> +#define PRU_SUART_CH_CTRL_SREQ_SHIFT 0x0002
> +#define PRU_SUART_CH_CTRL_SREQ_MASK 0x0004
> +#define PRU_SUART_CH_CTRL_SREQ 0x0001
> +
> +/* McASP Instance */
> +#define PRU_SUART_CH_CTRL_MCASP_SHIFT 0x0003
> +#define PRU_SUART_CH_CTRL_MCASP_MASK 0x0018
> +#define PRU_SUART_CH_CTRL_SR_SHIFT 0x0008
> +#define PRU_SUART_CH_CTRL_SR_MASK 0x0F00
> +
> +/* SUART channel configuration1 register descriptions */
> +
> +/* clock divisor - relative baud value */
> +#define PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT 0x0000
> +#define PRU_SUART_CH_CONFIG1_DIVISOR_MASK 0x03FF
> +/* oversampling */
> +#define PRU_SUART_CH_CONFIG1_OVS_SHIFT 0x000A
> +#define PRU_SUART_CH_CONFIG1_OVS_MASK 0x0C00
> +
> +/* SUART channel configuration2 register descriptions */
> +/* Bits per character */
> +#define PRU_SUART_CH_CONFIG2_BITPERCHAR_SHIFT 0x0000
> +#define PRU_SUART_CH_CONFIG2_BITPERCHAR_MASK 0x000F
> +
> +/* Bits per character */
> +#define PRU_SUART_CH_CONFIG2_DATALEN_SHIFT 0x0008
> +#define PRU_SUART_CH_CONFIG2_DATALEN_MASK 0x0F00
> +
> +/* SUART Channel STATUS Register*/
> +#define PRU_SUART_CH_STATUS_EN_BIT_MASK 0x8000
> +
> +/* SUART Channel register offsets */
> +#define PRU_SUART_CH_CTRL_OFFSET 0x00
> +#define PRU_SUART_CH_CONFIG1_OFFSET 0x02
> +#define PRU_SUART_CH_CONFIG2_OFFSET 0x04
> +#define PRU_SUART_CH_TXRXSTATUS_OFFSET 0x06
> +#define PRU_SUART_CH_TXRXDATA_OFFSET 0x08
> +#define PRU_SUART_CH_BYTESDONECNTR_OFFSET 0x0C
> +
> +/* SUART Event Numbers macros */
> +#define PRU_SUART0_TX_EVT 34
> +#define PRU_SUART0_RX_EVT 35
> +#define PRU_SUART1_TX_EVT 36
> +#define PRU_SUART1_RX_EVT 37
> +#define PRU_SUART2_TX_EVT 38
> +#define PRU_SUART2_RX_EVT 39
> +#define PRU_SUART3_TX_EVT 40
> +#define PRU_SUART3_RX_EVT 41
> +#define PRU_SUART4_TX_EVT 42
> +#define PRU_SUART4_RX_EVT 43
> +#define PRU_SUART5_TX_EVT 44
> +#define PRU_SUART5_RX_EVT 45
> +#define PRU_SUART6_TX_EVT 46
> +#define PRU_SUART6_RX_EVT 47
> +#define PRU_SUART7_TX_EVT 48
> +#define PRU_SUART7_RX_EVT 49
> +
> +#define PRU_SUART0_TX_EVT_BIT BIT(2)
> +#define PRU_SUART0_RX_EVT_BIT BIT(3)
> +#define PRU_SUART1_TX_EVT_BIT BIT(4)
> +#define PRU_SUART1_RX_EVT_BIT BIT(5)
> +#define PRU_SUART2_TX_EVT_BIT BIT(6)
> +#define PRU_SUART2_RX_EVT_BIT BIT(7)
> +#define PRU_SUART3_TX_EVT_BIT BIT(8)
> +#define PRU_SUART3_RX_EVT_BIT BIT(9)
> +#define PRU_SUART4_TX_EVT_BIT BIT(10)
> +#define PRU_SUART4_RX_EVT_BIT BIT(11)
> +#define PRU_SUART5_TX_EVT_BIT BIT(12)
> +#define PRU_SUART5_RX_EVT_BIT BIT(13)
> +#define PRU_SUART6_TX_EVT_BIT BIT(14)
> +#define PRU_SUART6_RX_EVT_BIT BIT(15)
> +#define PRU_SUART7_TX_EVT_BIT BIT(16)
> +#define PRU_SUART7_RX_EVT_BIT BIT(17)
> +
> +/* Total number of baud rates supported */
> +#define SUART_NUM_OF_BAUDS_SUPPORTED 13
> +
> +#define MCASP_PDIR_VAL ( \
> + OMAPL_MCASP_PDIR_AFSR_OUTPUT<<OMAPL_MCASP_PDIR_AFSR_SHIFT | \
> + OMAPL_MCASP_PDIR_AHCLKR_OUTPUT<<OMAPL_MCASP_PDIR_AHCLKR_SHIFT | \
> + OMAPL_MCASP_PDIR_ACLKR_OUTPUT<<OMAPL_MCASP_PDIR_ACLKR_SHIFT | \
> + OMAPL_MCASP_PDIR_AFSX_OUTPUT<<OMAPL_MCASP_PDIR_AFSX_SHIFT | \
> + OMAPL_MCASP_PDIR_AHCLKX_OUTPUT<<OMAPL_MCASP_PDIR_AHCLKX_SHIFT | \
> + OMAPL_MCASP_PDIR_ACLKX_OUTPUT<<OMAPL_MCASP_PDIR_ACLKX_SHIFT)
> +
> +/*
> + * This enum is used to specify the direction of the channel in UART
> + */
> +enum SUART_CHN_DIR {
> + SUART_CHN_TX = 1,
> + SUART_CHN_RX = 2
> +};
> +
> +/*
> + * This enum is used to specify the state of the channel in UART. It
> + * is either enabled or disabled.
> + */
> +enum SUART_CHN_STATE {
> + SUART_CHN_DISABLED = 0,
> + SUART_CHN_ENABLED = 1
> +};
> +
> +enum SUART_EN_BITSPERCHAR {
> + ePRU_SUART_DATA_BITS6 = 8,
> + ePRU_SUART_DATA_BITS7,
> + ePRU_SUART_DATA_BITS8,
> + ePRU_SUART_DATA_BITS9,
> + ePRU_SUART_DATA_BITS10,
> + ePRU_SUART_DATA_BITS11,
> + ePRU_SUART_DATA_BITS12
> +};
> +
> +enum SUART_EN_UARTNUM {
> + ePRU_SUART_NUM_1 = 1,
> + ePRU_SUART_NUM_2,
> + ePRU_SUART_NUM_3,
> + ePRU_SUART_NUM_4,
> + ePRU_SUART_NUM_5,
> + ePRU_SUART_NUM_6,
> + ePRU_SUART_NUM_7,
> + ePRU_SUART_NUM_8
> +};
> +
> +enum SUART_EN_UARTTYPE {
> + ePRU_SUART_HALF_TX = 1,
> + ePRU_SUART_HALF_RX,
> + ePRU_SUART_FULL_TX_RX,
> + ePRU_SUART_HALF_TX_DISABLED = 4,
> + ePRU_SUART_HALF_RX_DISABLED = 8
> +};
> +
> +enum SUART_EN_TXCHANNEL {
> + ePRU_SUART_TX_CH0 = 0,
> + ePRU_SUART_TX_CH1,
> + ePRU_SUART_TX_CH2,
> + ePRU_SUART_TX_CH3,
> + ePRU_SUART_TX_CH4,
> + ePRU_SUART_TX_CH5,
> + ePRU_SUART_TX_CH6,
> + ePRU_SUART_TX_CH7
> +};
> +
> +enum SUART_EN_RXCHANNEL {
> + ePRU_SUART_RX_CH0 = 0,
> + ePRU_SUART_RX_CH1,
> + ePRU_SUART_RX_CH2,
> + ePRU_SUART_RX_CH3,
> + ePRU_SUART_RX_CH4,
> + ePRU_SUART_RX_CH5,
> + ePRU_SUART_RX_CH6,
> + ePRU_SUART_RX_CH7
> +};
> +
> +enum SUART_EN_UART_STATUS {
> + ePRU_SUART_UART_FREE = 0,
> + ePRU_SUART_UART_IN_USE
> +};
> +
> +struct pru_suart_cnh_cntrl_config1 {
> + u32 mode:2;
> + u32 service_req:1;
> + u32 asp_id:2;
> + u32 reserved1:3;
> + u32 serializer_num:4;
> + u32 reserved2:4;
> + u32 presacler:10;
> + u32 over_sampling:2;
> + u32 framing_mask:1;
> + u32 break_mask:1;
> + u32 timeout_mask:1;
> + u32 reserved3:1;
> +};
> +
> +struct pru_suart_chn_config2_status {
> + u32 bits_per_char:4;
> + u32 reserved1:4;
> + u32 data_len:4;
> + u32 reserved2:4;
> + u32 txrx_ready:1;
> + u32 txrx_complete:1;
> + u32 txrx_error:1;
> + u32 txrx_underrun:1;
> + u32 framing_error:1;
> + u32 break_error:1;
> + u32 timeout_error:1;
> + u32 reserved3:8;
> + u32 chn_state:1;
> +};
> +
> +struct pru_suart_regs_ovly {
> + struct pru_suart_cnh_cntrl_config1 ch_ctrl_config1;
> + struct pru_suart_chn_config2_status ch_config2_txrx_status;
> + u32 ch_txrx_data;
> + u32 reserved1;
> +};
> +
> +struct pru_suart_tx_cntx_priv {
> + u32 asp_xsrctl_base;
> + u32 asp_xbuf_base;
> + u16 buff_addr;
> + u8 buff_size;
> + u8 bits_loaded;
> +};
> +
> +struct pru_suart_rx_cntx_priv {
> + u32 asp_rbuf_base;
> + u32 asp_rsrctl_base;
> + u32 reserved1;
> + u32 reserved2;
> + u32 reserved3;
> + u32 reserved4;
> +};
> +
> +struct suart_config {
> + u8 tx_serializer;
> + u8 rx_serializer;
> + u16 tx_clk_divisor;
> + u16 rx_clk_divisor;
> + u8 tx_bits_per_char;
> + u8 rx_bits_per_char;
> + u8 oversampling;
> + u8 bi_inter_mask;
> + u8 fe_intr_mask;
> +};
> +
> +struct suart_handle {
> + u16 uart_num;
> + u16 uart_type;
> + u16 uart_tx_channel;
> + u16 uart_rx_channel;
> + u16 uart_status;
> +};
> +
> +struct pruss_suart_iomap {
> + void *mcasp_io_addr;
> + void *p_fifo_buff_phys_base;
> + void *p_fifo_buff_virt_base;
> + u32 pru_clk_freq;
> +};
> +
> +/* MCASP */
> +struct omapl_mcasp_regs_ovly {
> + u32 REVID;
> + u32 RSVD0[3];
> + u32 PFUNC;
> + u32 PDIR;
> + u32 PDOUT;
> + u32 PDIN;
> + u32 PDCLR;
> + u32 RSVD1[8];
> + u32 GBLCTL;
> + u32 AMUTE;
> + u32 DLBCTL;
> + u32 DITCTL;
> + u32 RSVD2[3];
> + u32 RGBLCTL;
> + u32 RMASK;
> + u32 RFMT;
> + u32 AFSRCTL;
> + u32 ACLKRCTL;
> + u32 AHCLKRCTL;
> + u32 RTDM;
> + u32 RINTCTL;
> + u32 RSTAT;
> + u32 RSLOT;
> + u32 RCLKCHK;
> + u32 REVTCTL;
> + u32 RSVD3[4];
> + u32 XGBLCTL;
> + u32 XMASK;
> + u32 XFMT;
> + u32 AFSXCTL;
> + u32 ACLKXCTL;
> + u32 AHCLKXCTL;
> + u32 XTDM;
> + u32 XINTCTL;
> + u32 XSTAT;
> + u32 XSLOT;
> + u32 XCLKCHK;
> + u32 XEVTCTL;
> + u32 RSVD4[12];
> + u32 DITCSRA0;
> + u32 DITCSRA1;
> + u32 DITCSRA2;
> + u32 DITCSRA3;
> + u32 DITCSRA4;
> + u32 DITCSRA5;
> + u32 DITCSRB0;
> + u32 DITCSRB1;
> + u32 DITCSRB2;
> + u32 DITCSRB3;
> + u32 DITCSRB4;
> + u32 DITCSRB5;
> + u32 DITUDRA0;
> + u32 DITUDRA1;
> + u32 DITUDRA2;
> + u32 DITUDRA3;
> + u32 DITUDRA4;
> + u32 DITUDRA5;
> + u32 DITUDRB0;
> + u32 DITUDRB1;
> + u32 DITUDRB2;
> + u32 DITUDRB3;
> + u32 DITUDRB4;
> + u32 DITUDRB5;
> + u32 RSVD5[8];
> + u32 SRCTL0;
> + u32 SRCTL1;
> + u32 SRCTL2;
> + u32 SRCTL3;
> + u32 SRCTL4;
> + u32 SRCTL5;
> + u32 SRCTL6;
> + u32 SRCTL7;
> + u32 SRCTL8;
> + u32 SRCTL9;
> + u32 SRCTL10;
> + u32 SRCTL11;
> + u32 SRCTL12;
> + u32 SRCTL13;
> + u32 SRCTL14;
> + u32 SRCTL15;
> + u32 RSVD6[16];
> + u32 XBUF0;
> + u32 XBUF1;
> + u32 XBUF2;
> + u32 XBUF3;
> + u32 XBUF4;
> + u32 XBUF5;
> + u32 XBUF6;
> + u32 XBUF7;
> + u32 XBUF8;
> + u32 XBUF9;
> + u32 XBUF10;
> + u32 XBUF11;
> + u32 XBUF12;
> + u32 XBUF13;
> + u32 XBUF14;
> + u32 XBUF15;
> + u32 RSVD7[16];
> + u32 RBUF0;
> + u32 RBUF1;
> + u32 RBUF2;
> + u32 RBUF3;
> + u32 RBUF4;
> + u32 RBUF5;
> + u32 RBUF6;
> + u32 RBUF7;
> + u32 RBUF8;
> + u32 RBUF9;
> + u32 RBUF10;
> + u32 RBUF11;
> + u32 RBUF12;
> + u32 RBUF13;
> + u32 RBUF14;
> + u32 RBUF15;
> +};
> +
> +/*
> + * SUART Config regs
> + */
> +struct suart_struct_pru_regs {
> + u16 chn_ctrl;
> + u16 chn_config1;
> + u16 chn_config2;
> + u16 chn_txrx_status;
> + u32 chn_txrx_data;
> +};
> +
> +extern s16 pru_softuart_init(struct device *dev, u32 tx_baud_value,
> + u32 rx_baud_value, u32 oversampling,
> + u8 *pru_suart_emu_code, u32 fw_size,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern s16 pru_softuart_open(struct suart_handle *h_suart);
> +
> +extern s16 pru_softuart_close(struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_setbaud(struct device *dev,
> + struct suart_handle *h_uart,
> + u16 tx_clk_divisor, u16 rx_clk_divisor);
> +
> +extern s16 pru_softuart_setdatabits(struct device *dev,
> + struct suart_handle *h_uart,
> + u16 tx_data_bits, u16 rx_data_bits);
> +
> +extern s16 pru_softuart_setconfig(struct device *dev,
> + struct suart_handle *h_uart,
> + struct suart_config *config_uart);
> +
> +extern s16 pru_softuart_getconfig(struct device *dev,
> + struct suart_handle *h_uart,
> + struct suart_config *config_uart);
> +
> +extern s32 pru_softuart_pending_tx_request(struct device *dev);
> +
> +extern s16 pru_softuart_write(struct device *dev,
> + struct suart_handle *h_uart,
> + u32 *pt_tx_data_buf, u16 data_len);
> +
> +extern s16 pru_softuart_read(struct device *dev,
> + struct suart_handle *h_uart,
> + u32 *pt_data_buf, u16 data_len);
> +
> +extern s32 suart_intr_clrmask(struct device *dev, u16 uart_num,
> + u32 txrxmode,
> + u32 intrmask);
> +
> +extern s16 pru_softuart_clr_tx_status(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_get_tx_status(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_clr_rx_status(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_get_rx_status(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_get_isrstatus(struct device *dev, u16 uart_num,
> + u16 *txrx_flag);
> +
> +extern s32 pru_intr_clr_isrstatus(struct device *dev, u16 uart_num,
> + u32 txrxmode);
> +
> +extern s32 suart_intr_getmask(struct device *dev, u16 uart_num,
> + u32 txrxmode,
> + u32 intrmask);
> +
> +extern s32 suart_intr_setmask(struct device *dev, u16 uart_num,
> + u32 txrxmode, u32 intrmask);
> +
> +extern s16 pru_softuart_get_tx_data_len(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_get_rx_data_len(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 suart_arm_to_pru_intr(struct device *dev, u16 uart_num);
> +
> +extern void pru_mcasp_deinit(void);
> +
> +extern s16 pru_softuart_read_data(struct device *dev,
> + struct suart_handle *h_uart,
> + u8 *p_data_buffer, s32 max_len,
> + u32 *pdata_read);
> +
> +extern s16 pru_softuart_stop_receive(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s32 suart_pru_to_host_intr_enable(struct device *dev,
> + u16 uart_num,
> + u32 txrxmode, s32 flag);
> +
> +extern void pru_set_fifo_timeout(struct device *dev, s16 timeout);
> +
> +extern void suart_mcasp_config(u32 tx_baud_value,
> + u32 rx_baud_value, u32 oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern void suart_mcasp_reset(struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern short suart_asp_baud_set(u32 tx_baud_value,
> + u32 rx_baud_value, u32 oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern short suart_asp_serializer_deactivate(u16 sr_num,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern void suart_mcasp_tx_serialzier_set(u32 serializer_num,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +#endif
> diff --git a/drivers/tty/serial/pruss_suart_api.c
> b/drivers/tty/serial/pruss_suart_api.c
> new file mode 100644
> index 0000000..b483b90
> --- /dev/null
> +++ b/drivers/tty/serial/pruss_suart_api.c
> @@ -0,0 +1,1757 @@
> +/*
> + * Copyright (C) 2010 Texas Instruments Incorporated
> + * Author: Jitendra Kumar <jitendra@...tralsolutions.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation version 2.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
> + * whether express or implied; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#include <linux/types.h>
> +#include <linux/mfd/da8xx/da8xx_pru.h>
> +#include <linux/io.h>
> +#include <mach/hardware.h>
> +#include "pruss_suart.h"
> +
> +static u8 uart_statu_table[8];
> +static struct pruss_suart_iomap suart_iomap;
> +
> +static u32 uart_rx[8] = {PRU_SUART0_CONFIG_RX_SER,
> PRU_SUART1_CONFIG_RX_SER,
> + PRU_SUART2_CONFIG_RX_SER, PRU_SUART3_CONFIG_RX_SER,
> + PRU_SUART4_CONFIG_RX_SER, PRU_SUART5_CONFIG_RX_SER,
> + PRU_SUART6_CONFIG_RX_SER, PRU_SUART7_CONFIG_RX_SER};
> +
> +static u32 uart_tx[8] = {PRU_SUART0_CONFIG_TX_SER,
> PRU_SUART1_CONFIG_TX_SER,
> + PRU_SUART2_CONFIG_TX_SER, PRU_SUART3_CONFIG_TX_SER,
> + PRU_SUART4_CONFIG_TX_SER, PRU_SUART5_CONFIG_TX_SER,
> + PRU_SUART6_CONFIG_TX_SER, PRU_SUART7_CONFIG_TX_SER};
> +
> +static u32 uart_config[8] = {PRU_SUART0_CONFIG_DUPLEX,
> PRU_SUART1_CONFIG_DUPLEX,
> + PRU_SUART2_CONFIG_DUPLEX, PRU_SUART3_CONFIG_DUPLEX,
> + PRU_SUART4_CONFIG_DUPLEX, PRU_SUART5_CONFIG_DUPLEX,
> + PRU_SUART6_CONFIG_DUPLEX, PRU_SUART7_CONFIG_DUPLEX};
> +
> +static s16 pru_softuart_clr_rx_fifo(struct device *dev,
> + struct suart_handle *h_uart);
> +static s16 arm_to_pru_intr_init(struct device *dev);
> +
> +#if (PRU_ACTIVE == BOTH_PRU)
> +static void pru_set_ram_data(struct device *dev,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + u32 datatowrite;
> + u32 i;
> + struct pru_suart_regs_ovly *pru_suart_regs = PRU0_DATARAM_OFFSET;
> + u32 *p_sr_ctl_addr = (u32 *)(pruss_ioaddr->mcasp_io_addr + 0x180);
> + struct pru_suart_tx_cntx_priv *pru_suart_tx_priv = NULL;
> + struct pru_suart_rx_cntx_priv *pru_suart_rx_priv = NULL;
> +
> + /* RX PRU - 0 Chanel 0-7 context information */
> + for (i = 0; i < 8; i++, pru_suart_regs++) {
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + 0x3, SUART_CHN_RX);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0xF << SERIALIZER_OFFSET),
> + ((0xF & uart_rx[i]) << SERIALIZER_OFFSET));
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
> + (SUART_DEFAULT_OVRSMPL <<
> + SUART_DEFAULT_OVRSMPL_OFFSET));
> + pruss_rmwl(dev,
> + (u32) &pru_suart_regs->ch_config2_txrx_status,
> + 0xF, 8);
> + if ((uart_config[i] & PRU_SUART_HALF_RX_DISABLED) ==
> + PRU_SUART_HALF_RX_DISABLED) {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_DISABLED << SUART_CHN_OFFSET));
> + } else {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_ENABLED << SUART_CHN_OFFSET));
> + __raw_writel(MCASP_SRCTL_RX_MODE, p_sr_ctl_addr +
> + uart_rx[i]);
> + }
> + /*
> + * RX is active by default, write the dummy received data at
> + * PRU RAM addr 0x1FC to avoid memory corruption.
> + */
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_txrx_data,
> + 0xFFFF, RX_DEFAULT_DATA_DUMP_ADDR);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
> + 0xFFFF, 0);
> + /* SUART1 RX context base addr */
> + pru_suart_rx_priv = (struct pru_suart_rx_cntx_priv *)
> + (PRU0_DATARAM_OFFSET + (0x090 + (i * 0x020)));
> + datatowrite = (MCASP_RBUF_BASE_ADDR + (uart_rx[i] << 2));
> + pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rbuf_base,
> + &datatowrite, 1);
> + datatowrite = (MCASP_SRCTL_BASE_ADDR + (uart_rx[i] << 2));
> + pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rsrctl_base,
> + &datatowrite, 1);
> + }
> +
> + /* ****************** PRU1 RAM BASE ADDR ************************ */
> + pru_suart_regs = (struct pru_suart_regs_ovly *) PRU1_DATARAM_OFFSET;
> +
> + /* ******************* TX PRU - 1 *********************** */
> + /* Channel 0-7 context information */
> + for (i = 0; i < 8; i++, pru_suart_regs++) {
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + 0x3, SUART_CHN_TX);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0xF << SERIALIZER_OFFSET),
> + ((0xF & uart_tx[i]) << SERIALIZER_OFFSET));
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
> + (SUART_DEFAULT_OVRSMPL <<
> + SUART_DEFAULT_OVRSMPL_OFFSET));
> + pruss_rmwl(dev,
> + (u32) &pru_suart_regs->ch_config2_txrx_status,
> + 0xF, 8);
> + if ((uart_config[i] & PRU_SUART_HALF_TX_DISABLED) ==
> + PRU_SUART_HALF_TX_DISABLED) {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_DISABLED << SUART_CHN_OFFSET));
> + } else {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_ENABLED << SUART_CHN_OFFSET));
> + __raw_writel(MCASP_SRCTL_TX_MODE,
> + p_sr_ctl_addr + uart_tx[i]);
> + }
> + pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
> + 0xFFFF, 1);
> + /* SUART1 TX context base addr */
> + pru_suart_tx_priv = (struct pru_suart_tx_cntx_priv *)
> + (PRU1_DATARAM_OFFSET + (0x0B0 + (i * 0x02C)));
> + datatowrite = (MCASP_SRCTL_BASE_ADDR + (uart_tx[i] << 2));
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xsrctl_base,
> + &datatowrite, 1);
> + datatowrite = (MCASP_XBUF_BASE_ADDR + (uart_tx[i] << 2));
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xbuf_base,
> + &datatowrite, 1);
> + /* SUART1 TX formatted data base addr */
> + datatowrite = (0x0090 + (i * 0x002C));
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->buff_addr,
> + &datatowrite, 1);
> + }
> +}
> +#else
> +static void pru_set_ram_data(struct device *dev,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> +
> + struct pru_suart_regs_ovly *pru_suart_regs =
> + (struct pru_suart_regs_ovly *)pruss_ioaddr->pru_io_addr;
> + u32 i;
> + u32 *p_sr_ctl_addr = (u32 *)(pruss_ioaddr->mcasp_io_addr + 0x180);
> + struct pru_suart_tx_cntx_priv *pru_suart_tx_priv = NULL;
> + struct pru_suart_rx_cntx_priv *pru_suart_rx_priv = NULL;
> +
> + /* ***************** UART 0 ************************ */
> + /* Channel 0 context information is Tx */
> + for (i = 0; i < 4; i++, pru_suart_regs++) {
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + 0x3, SUART_CHN_TX);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0xF << SERIALIZER_OFFSET),
> + ((0xF & uart_tx[i]) << SERIALIZER_OFFSET));
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
> + (SUART_DEFAULT_OVRSMPL <<
> + SUART_DEFAULT_OVRSMPL_OFFSET));
> + pruss_rmwl(dev,
> + (u32) &pru_suart_regs->ch_config2_txrx_status,
> + 0xF, 8);
> + if ((uart_config[i] & PRU_SUART_HALF_TX_DISABLED) ==
> + PRU_SUART_HALF_TX_DISABLED){
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_DISABLED << SUART_CHN_OFFSET));
> + } else {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_ENABLED << SUART_CHN_OFFSET));
> + __raw_writel(MCASP_SRCTL_TX_MODE,
> + p_sr_ctl_addr + uart_tx[i]);
> + }
> + pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
> + 0xFFFF, 1);
> + /* SUART1 TX context base addr */
> + pru_suart_tx_priv = (struct pru_suart_tx_cntx_priv *)
> + (PRU0_DATARAM_OFFSET + (0x0B0 + (i * 0x50)));
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xsrctl_base,
> + (MCASP_SRCTL_BASE_ADDR + (uart_tx[i] << 2)), 1);
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xbuf_base,
> + (MCASP_XBUF_BASE_ADDR + (uart_tx[i] << 2)), 1);
> + /* SUART1 TX formatted data base addr */
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->buff_addr,
> + (0x0090 + (i * 0x050)), 1);
> +
> + /* Channel 1 is Rx context information */
> + pru_suart_regs++;
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + 0x3, SUART_CHN_RX);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0xF << SERIALIZER_OFFSET),
> + ((0xF & uart_rx[i]) << SERIALIZER_OFFSET));
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
> + (SUART_DEFAULT_OVRSMPL <<
> + SUART_DEFAULT_OVRSMPL_OFFSET));
> + pruss_rmwl(dev,
> + (u32) &pru_suart_regs->ch_config2_txrx_status,
> + 0xF, 8);
> +
> + if ((uart_config[i] & PRU_SUART_HALF_RX_DISABLED) ==
> + PRU_SUART_HALF_RX_DISABLED) {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_DISABLED << SUART_CHN_OFFSET));
> + } else {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_ENABLED << SUART_CHN_OFFSET));
> + __raw_writel(MCASP_SRCTL_RX_MODE,
> + p_sr_ctl_addr + uart_rx[i]);
> + }
> + /* RX is active by default, write the dummy received data
> + * at PRU RAM addr 0x1FC to avoid memory corruption
> + */
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_txrx_data,
> + 0xFFFF, RX_DEFAULT_DATA_DUMP_ADDR);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
> + 0xFFFF, 0);
> + /* SUART1 RX context base addr */
> + pru_suart_rx_priv = (struct pru_suart_rx_cntx_priv *)
> + (PRU0_DATARAM_OFFSET + (0x0C0 + (i * 0x50)));
> + pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rbuf_base,
> + (MCASP_RBUF_BASE_ADDR + (uart_rx[i] << 2)), 1);
> + pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rsrctl_base,
> + (MCASP_SRCTL_BASE_ADDR + (uart_rx[i] << 2)), 1);
> + }
> +}
> +#endif
> +
> +static void pru_set_rx_tx_mode(struct device *dev, u32 pru_mode, u32
> pru_num)
> +{
> +
> + u32 pru_offset;
> +
> + if (pru_num == PRUSS_NUM0)
> + pru_offset = PRU_SUART_PRU0_RX_TX_MODE;
> + else if (pru_num == PRUSS_NUM1)
> + pru_offset = PRU_SUART_PRU1_RX_TX_MODE;
> + else
> + return;
> + pruss_writeb(dev, pru_offset, (u8 *) &pru_mode, 1);
> +}
> +
> +static void pru_set_delay_count(struct device *dev, u32 pru_freq)
> +{
> + u32 delay_cnt;
> +
> + if (pru_freq == PRU_CLK_228)
> + delay_cnt = 5;
> + else if (pru_freq == PRU_CLK_186)
> + delay_cnt = 5;
> + else
> + delay_cnt = 3;
> +
> + /* PRU 0 */
> + pruss_writeb(dev, PRU_SUART_PRU0_DELAY_OFFSET,
> + (u8 *) &delay_cnt, 1);
> +
> + /* PRU 1 */
> + pruss_writeb(dev, PRU_SUART_PRU1_DELAY_OFFSET,
> + (u8 *) &delay_cnt, 1);
> +}
> +
> +static s32 suart_set_pru_id(struct device *dev, u32 pru_no)
> +{
> + u32 offset;
> + u8 reg_val = 0;
> +
> + if (PRUSS_NUM0 == pru_no)
> + offset = PRU_SUART_PRU0_ID_ADDR;
> + else if (PRUSS_NUM1 == pru_no)
> + offset = PRU_SUART_PRU1_ID_ADDR;
> + else
> + return -EINVAL;
> +
> + reg_val = pru_no;
> + pruss_writeb(dev, offset, (u8 *) ®_val, 1);
> +
> + return 0;
> +}
> +
> +/*
> + * suart Initialization routine
> + */
> +s16 pru_softuart_init(struct device *dev, u32 tx_baud_value,
> + u32 rx_baud_value, u32 oversampling,
> + u8 *pru_suart_emu_code, u32 fw_size,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + u32 datatowrite[128] = {0};
> + s16 status = 0;
> + s16 idx;
> + s16 retval;
> +
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) &&
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH))
> + return -EINVAL;
> +
> + suart_iomap.mcasp_io_addr = pruss_ioaddr->mcasp_io_addr;
> + suart_iomap.p_fifo_buff_phys_base =
> + pruss_ioaddr->p_fifo_buff_phys_base;
> + suart_iomap.p_fifo_buff_virt_base =
> + pruss_ioaddr->p_fifo_buff_virt_base;
> + suart_iomap.pru_clk_freq = pruss_ioaddr->pru_clk_freq;
> + /* Configure McASP0 */
> + suart_mcasp_config(tx_baud_value,
> + rx_baud_value, oversampling, pruss_ioaddr);
> + pruss_enable(dev, PRUSS_NUM0);
> +
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_enable(dev, PRUSS_NUM1);
> +
> + /* Reset PRU RAM */
> + pruss_writel(dev, PRU0_DATARAM_OFFSET, datatowrite,
> + (PRU0_DATARAM_SIZE / sizeof(int)));
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_writel(dev, PRU1_DATARAM_OFFSET, datatowrite,
> + (PRU1_DATARAM_SIZE / sizeof(int)));
> +
> + pruss_load(dev, PRUSS_NUM0, (u32 *)pru_suart_emu_code,
> + (fw_size / sizeof(u32)));
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_load(dev, PRUSS_NUM1, (u32 *)pru_suart_emu_code,
> + (fw_size / sizeof(u32)));
> +
> + retval = arm_to_pru_intr_init(dev);
> + if (-1 == retval)
> + return status;
> + pru_set_delay_count(dev, pruss_ioaddr->pru_clk_freq);
> + suart_set_pru_id(dev, PRUSS_NUM0);
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + suart_set_pru_id(dev, PRUSS_NUM1);
> +
> + pru_set_rx_tx_mode(dev, PRU0_MODE, PRUSS_NUM0);
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pru_set_rx_tx_mode(dev, PRU1_MODE, PRUSS_NUM1);
> +
> + pru_set_ram_data(dev, pruss_ioaddr);
> + pruss_run(dev, PRUSS_NUM0);
> +
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_run(dev, PRUSS_NUM1);
> +
> + /* Initialize uart_statu_table */
> + for (idx = 0; idx < 8; idx++)
> + uart_statu_table[idx] = ePRU_SUART_UART_FREE;
> +
> + return status;
> +}
> +
> +void pru_set_fifo_timeout(struct device *dev, s16 timeout)
> +{
> + pruss_writew(dev, PRU_SUART_PRU0_IDLE_TIMEOUT_OFFSET,
> + &timeout, 1);
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_writew(dev, PRU_SUART_PRU1_IDLE_TIMEOUT_OFFSET,
> + &timeout, 1);
> +}
> +
> +void pru_mcasp_deinit(void)
> +{
> + suart_mcasp_reset(&suart_iomap);
> +}
> +
> +/* suart Instance open routine */
> +s16 pru_softuart_open(struct suart_handle *h_suart)
> +{
> + s16 status = 0;
> + u16 uart_num = h_suart->uart_num - 1;
> +
> + if (uart_statu_table[h_suart->uart_num - 1] ==
> + ePRU_SUART_UART_IN_USE) {
> + status = EUSERS;
> + return status;
> + } else {
> + h_suart->uart_type = uart_config[uart_num];
> + h_suart->uart_tx_channel = uart_tx[uart_num];
> + h_suart->uart_rx_channel = uart_rx[uart_num];
> + h_suart->uart_status = ePRU_SUART_UART_IN_USE;
> + uart_statu_table[h_suart->uart_num - 1] =
> + ePRU_SUART_UART_IN_USE;
> + }
> + return status;
> +}
> +
> +/* suart instance close routine */
> +s16 pru_softuart_close(struct suart_handle *h_uart)
> +{
> + s16 status = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + } else {
> + uart_statu_table[h_uart->uart_num - 1] =
> + ePRU_SUART_UART_FREE;
> + /* Reset the Instance to Invalid */
> + h_uart->uart_num = PRU_SUART_UARTx_INVALID;
> + h_uart->uart_status = ePRU_SUART_UART_FREE;
> + }
> + return status;
> +}
> +
> +static s16 search_chnum(u16 uart_num, u16 *ch_num, u32 *pru_offset, u16
> mode)
> +{
> + *ch_num = uart_num - 1;
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + *ch_num = (uart_num *
> + SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> + if (uart_num <= 4) {
> + *pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else {
> + *pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + *ch_num -= 8;
> + }
> + if (mode == 2)
> + *ch_num = *ch_num + 1;
> +
> + } else if ((mode == 1) || (mode == 2)) {
> + if (mode == 1) {
> + if (PRU0_MODE == PRU_MODE_TX_ONLY)
> + *pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + else if (PRU1_MODE == PRU_MODE_TX_ONLY)
> + *pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if (mode == 2) {
> + if (PRU0_MODE == PRU_MODE_RX_ONLY)
> + *pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + else if (PRU1_MODE == PRU_MODE_RX_ONLY)
> + *pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + }
> + } else {
> + return 0;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * suart routine for setting relative baud rate
> + */
> +s16 pru_softuart_setbaud(struct device *dev, struct suart_handle *h_uart,
> + u16 tx_clk_divisor, u16 rx_clk_divisor)
> +{
> + u32 offset;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u16 regval = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + /* Set the clock divisor value s32o the McASP */
> + if ((tx_clk_divisor > 385) || (tx_clk_divisor == 0))
> + return -EINVAL;
> + if ((rx_clk_divisor > 385) || (rx_clk_divisor == 0))
> + return -EINVAL;
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + if (tx_clk_divisor != 0) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®val, 2);
> + regval &= (~0x3FF);
> + regval |= tx_clk_divisor;
> + pruss_writeb(dev, offset, (u8 *) ®val, 2);
> + }
> + if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + ch_num++;
> + } else {
> + return 0;
> + }
> + regval = 0;
> + if (rx_clk_divisor != 0) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®val, 2);
> + regval &= (~0x3FF);
> + regval |= tx_clk_divisor;
> + pruss_writeb(dev, offset, (u8 *) ®val, 2);
> + }
> + return status;
> +}
> +
> +/*
> + * suart routine for setting number of bits per character for a specific
> uart
> + */
> +s16 pru_softuart_setdatabits(struct device *dev, struct suart_handle
> *h_uart,
> + u16 tx_data_bits, u16 rx_data_bits)
> +{
> + u32 offset;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u32 reg_val;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + /*
> + * NOTE:
> + * The supported data bits are 6,7,8,9,10,11,12 bits per character
> + */
> +
> + if ((tx_data_bits < ePRU_SUART_DATA_BITS6)
> + || (tx_data_bits > ePRU_SUART_DATA_BITS12))
> + return -EINVAL;
> +
> + if ((rx_data_bits < ePRU_SUART_DATA_BITS6)
> + || (rx_data_bits > ePRU_SUART_DATA_BITS12))
> + return -EINVAL;
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + if (tx_data_bits != 0) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 1);
> + reg_val &= ~(0xF);
> + reg_val |= tx_data_bits;
> + pruss_writeb(dev, offset, (u8 *) ®_val, 1);
> + }
> + if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + ch_num++;
> + } else {
> + return 0;
> + }
> + if (rx_data_bits != 0) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 1);
> + reg_val &= ~(0xF);
> + reg_val |= rx_data_bits;
> + pruss_writeb(dev, offset, (u8 *) &rx_data_bits, 1);
> + }
> +
> + return status;
> +}
> +
> +/*
> + * suart routine to configure specific uart
> + */
> +s16 pru_softuart_setconfig(struct device *dev, struct suart_handle
> *h_uart,
> + struct suart_config *config_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u16 reg_val = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + /*
> + * NOTE:
> + * Dependent baud rate for the given UART,the value MUST BE LESS THAN OR
> + * EQUAL TO 64, preScalarValue <= 64
> + */
> + if ((config_uart->tx_clk_divisor > 384)
> + || (config_uart->rx_clk_divisor > 384)) {
> + return -EINVAL;
> + }
> + if ((config_uart->tx_bits_per_char < 8)
> + || (config_uart->tx_bits_per_char > 14)) {
> + return -EINVAL;
> + }
> + if ((config_uart->rx_bits_per_char < 8)
> + || (config_uart->rx_bits_per_char > 14)) {
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + /* Configuring the Transmit part of the given UART */
> + /* Serializer has been as TX in mcasp config, by writing 1 in bits
> + * corresponding to tx serializer in PFUNC regsiter ie already set
> + * to GPIO mode PRU code will set then back to MCASP mode once TX
> + * request for that serializer is posted.It is required because at this
> + * pos32 Mcasp is accessed by both PRU and DSP have lower priority for
> + * Mcasp in comparison to PRU and DPS keeps on looping there only
> + */
> + /*
> + * suart_mcasp_tx_serialzier_set
> + * (config_uart->tx_serializer, &suart_iomap);
> + */
> + /* Configuring TX serializer */
> + if (config_uart->tx_serializer != PRU_SUART_SERIALIZER_NONE) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val = reg_val | (config_uart->tx_serializer <<
> + PRU_SUART_CH_CTRL_SR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val = reg_val | (config_uart->tx_clk_divisor <<
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val = reg_val | (config_uart->tx_bits_per_char <<
> + PRU_SUART_CH_CONFIG2_BITPERCHAR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> + }
> +
> + if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + ch_num++;
> + } else {
> + return 0;
> + }
> +
> + /* Configuring the Transmit part of the given UART */
> + if (config_uart->rx_serializer != PRU_SUART_SERIALIZER_NONE) {
> + /* Configuring RX serializer */
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val = reg_val | (config_uart->rx_serializer <<
> + PRU_SUART_CH_CTRL_SR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> +
> + /* Configuring RX prescalar value and Oversampling */
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val = reg_val | (config_uart->rx_clk_divisor <<
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT) |
> + (config_uart->oversampling <<
> + PRU_SUART_CH_CONFIG1_OVS_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> +
> + /* Configuring RX bits per character value */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val = reg_val | (config_uart->rx_bits_per_char <<
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> + }
> + return status;
> +}
> +
> +/*
> + * suart routine for getting the number of bytes transfered
> + */
> +s16 pru_softuart_get_tx_data_len(struct device *dev,
> + struct suart_handle *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 read_value = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &read_value, 2);
> + read_value = ((read_value & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
> + >> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
> + return read_value;
> +}
> +
> +/*
> + * suart routine for getting the number of bytes received
> + */
> +s16 pru_softuart_get_rx_data_len(struct device *dev,
> + struct suart_handle *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 read_value = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &read_value, 2);
> + read_value = ((read_value & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
> + >> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
> +
> + return read_value;
> +}
> +
> +/*
> + * suart routine to get the configuration information from a specific
> uart
> + */
> +s16 pru_softuart_getconfig(struct device *dev,
> + struct suart_handle *h_uart,
> + struct suart_config *config_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 reg_val = 0;
> + s16 status = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + /*
> + * NOTE:
> + * Dependent baud rate for the given UART,the value MUST BE LESS THAN OR
> + * EQUAL TO 64, preScalarValue <= 64
> + */
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + /* Configuring the Transmit part of the given UART */
> + /* Configuring TX serializer */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + config_uart->tx_serializer = ((reg_val & PRU_SUART_CH_CTRL_SR_MASK) >>
> + PRU_SUART_CH_CTRL_SR_SHIFT);
> + /* Configuring TX prescalar value */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + config_uart->tx_clk_divisor = ((reg_val &
> + PRU_SUART_CH_CONFIG1_DIVISOR_MASK) >>
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> +
> + /* Configuring TX bits per character value */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + config_uart->tx_bits_per_char = ((reg_val &
> + PRU_SUART_CH_CONFIG1_DIVISOR_MASK) >>
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> +
> + if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + ch_num++;
> + } else {
> + return 0;
> + }
> + /* Configuring the Transmit part of the given UART */
> + /* Configuring RX serializer */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + config_uart->rx_serializer = ((reg_val & PRU_SUART_CH_CTRL_SR_MASK) >>
> + PRU_SUART_CH_CTRL_SR_SHIFT);
> +
> + /* Configuring RX prescalar value and oversampling */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + config_uart->rx_clk_divisor = ((reg_val &
> + PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
> + >> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> + config_uart->oversampling = ((reg_val &
> + PRU_SUART_CH_CONFIG1_OVS_MASK) >>
> + PRU_SUART_CH_CONFIG1_OVS_SHIFT);
> +
> + /* Configuring RX bits per character value */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + config_uart->rx_bits_per_char = ((reg_val &
> + PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
> + >> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> +
> + return status;
> +}
> +
> +s32 pru_softuart_pending_tx_request(struct device *dev)
> +{
> + u32 offset = 0;
> + u32 ISR_value = 0;
> +
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + return 0;
> + } else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
> + /* Read PRU Interrupt Status Register from PRU */
> + offset = (u32) (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
> + pruss_readl(dev, offset, (u32 *)&ISR_value, 1);
> + if ((ISR_value & 0x1) == 0x1)
> + return -EINVAL;
> + } else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
> + /* Read PRU Interrupt Status Register from PRU */
> + offset = (u32) (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
> + pruss_readl(dev, offset, (u32 *)&ISR_value, 1);
> + if ((ISR_value & 0x2) == 0x2)
> + return -EINVAL;
> + } else {
> + return 0;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * suart data transmit routine
> + */
> +s16 pru_softuart_write(struct device *dev, struct suart_handle *h_uart,
> + u32 *pt_tx_data_buf, u16 data_len)
> +{
> + u32 offset = 0;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u16 reg_val = 0;
> + u16 pru_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH))
> + pru_num = h_uart->uart_num;
> + else if (PRU0_MODE == PRU_MODE_TX_ONLY)
> + pru_num = 0;
> + else if (PRU1_MODE == PRU_MODE_TX_ONLY)
> + pru_num = 1;
> + else
> + return 0;
> +
> + /* Writing data length to SUART channel register */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val &= ~PRU_SUART_CH_CONFIG2_DATALEN_MASK;
> + reg_val = reg_val | (data_len << PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> +
> + /* Writing the data pos32er to channel TX data pointer */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXDATA_OFFSET;
> + pruss_writeb(dev, offset, (u8 *) pt_tx_data_buf, 4);
> +
> + /* Service Request to PRU */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val &= ~(PRU_SUART_CH_CTRL_MODE_MASK |
> + PRU_SUART_CH_CTRL_SREQ_MASK);
> + reg_val |= (PRU_SUART_CH_CTRL_TX_MODE <<
> + PRU_SUART_CH_CTRL_MODE_SHIFT) | (PRU_SUART_CH_CTRL_SREQ <<
> + PRU_SUART_CH_CTRL_SREQ_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> +
> + /* generate ARM->PRU event */
> + suart_arm_to_pru_intr(dev, pru_num);
> +
> + return status;
> +}
> +
> +/*
> + * suart data receive routine
> + */
> +s16 pru_softuart_read(struct device *dev, struct suart_handle *h_uart,
> + u32 *ptDataBuf, u16 data_len)
> +{
> + u32 offset = 0;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u16 reg_val = 0;
> + u16 pru_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + /* channel starts from 0 and uart instance starts from 1 */
> + ch_num = (h_uart->uart_num *
> + SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> + pru_num = h_uart->uart_num;
> + } else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_num = 0;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_num = 1;
> + } else {
> + return 0;
> + }
> + /* Writing data length to SUART channel register */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val &= ~PRU_SUART_CH_CONFIG2_DATALEN_MASK;
> + reg_val = reg_val | (data_len << PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> +
> + /* Writing the data pos32er to channel RX data pointer */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXDATA_OFFSET;
> + pruss_writeb(dev, offset, (u8 *) ptDataBuf, 4);
> +
> + /* Service Request to PRU */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val &= ~(PRU_SUART_CH_CTRL_MODE_MASK |
> + PRU_SUART_CH_CTRL_SREQ_MASK);
> + reg_val |= (PRU_SUART_CH_CTRL_RX_MODE <<
> + PRU_SUART_CH_CTRL_MODE_SHIFT) | (PRU_SUART_CH_CTRL_SREQ <<
> + PRU_SUART_CH_CTRL_SREQ_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> +
> + /* enable the timeout s32errupt */
> + suart_intr_setmask(dev, h_uart->uart_num, PRU_RX_INTR,
> + CHN_TXRX_IE_MASK_TIMEOUT);
> +
> + /* generate ARM->PRU event */
> + suart_arm_to_pru_intr(dev, pru_num);
> +
> + return status;
> +}
> +
> +/*
> + * suart routine to read the data from the RX FIFO
> + */
> +s16 pru_softuart_read_data(struct device *dev, struct suart_handle
> *h_uart,
> + u8 *p_data_buffer, s32 max_len,
> + u32 *pdata_read)
> +{
> + s16 ret_val = 0;
> + u8 *psrc_addr = NULL;
> + u32 data_read = 0;
> + u32 data_len = 0;
> + u32 char_len = 0;
> + u32 offset = 0;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 status = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + /* Get the data pos32er from channel RX data pointer */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXDATA_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &psrc_addr, 4);
> +
>+ /* Reading data length from SUART channel register */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &data_len, 2);
> +
> + /* read the character length */
> + char_len = data_len & PRU_SUART_CH_CONFIG2_BITPERCHAR_MASK;
> + char_len -= 2; /* remove the START & STOP bit */
> +
> + data_len &= PRU_SUART_CH_CONFIG2_DATALEN_MASK;
> + data_len = data_len >> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT;
> + data_len++;
> +
> + /* if the character length is greater than 8, then the size doubles */
> + if (char_len > 8)
> + data_len *= 2;
> +
> + /* Check if the time-out had occured. If, yes, then we need to find the
> + * number of bytes read from PRU. Else, we need to
> + * read the requested bytes
> + */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + if (CHN_TXRX_STATUS_TIMEOUT == (status & CHN_TXRX_STATUS_TIMEOUT)) {
> + /* determine the number of bytes read s32o the FIFO */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_BYTESDONECNTR_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &data_read, 1);
> +
> + /* if the character length is greater than 8,
> + then the size doubles */
> + if (char_len > 8)
> + data_read *= 2;
> +
> +/*
> + * the data corresponding is loaded in second
> + * half during the timeout
> + */
> + if (data_read > data_len) {
> + data_read -= data_len;
> + psrc_addr += data_len;
> + }
> +
> + pru_softuart_clr_rx_fifo(dev, h_uart);
> + } else {
> + data_read = data_len;
> +/*
> + * if the bit is set, the data is in the first
> + * half of the FIFO else the data is in the second half
> + */
> + /* Determine the buffer index by reading FIFO_OddEven flag*/
> + if (status & CHN_TXRX_STATUS_CMPLT)
> + psrc_addr += data_len;
> + }
> +
> + /* we should be copying only max len given by the application */
> + if (data_read > max_len)
> + data_read = max_len;
> +
> +/* evaluate the virtual address of the FIFO address
> + * based on the physical addr
> + */
> + psrc_addr = (u8 *)((u32) psrc_addr -
> + (u32) suart_iomap.p_fifo_buff_phys_base +
> + (u32) suart_iomap.p_fifo_buff_virt_base);
> +
> + /* Now we have both the data length and the source address. copy */
> + for (offset = 0; offset < data_read; offset++)
> + *p_data_buffer++ = *psrc_addr++;
> + *pdata_read = data_read;
> + ret_val = 0;
> +
> + return ret_val;
> +}
> +
> +/*
> + * suart routine to disable the receive functionality.
> + * This routine stops the PRU from receiving on selected
> + * UART and also disables the McASP serializer corresponding
> + * to this UART Rx line.
> + */
> +s16 pru_softuart_stop_receive(struct device *dev, struct suart_handle
> *h_uart)
> +{
> + u16 ret_status = 0;
> + u32 offset;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 status;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + /* read the existing value of status flag */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> +
> + /* we need to clear the busy bit corresponding to receive channel */
> + status &= ~(CHN_TXRX_STATUS_RDY);
> + pruss_writeb(dev, offset, (u8 *) &status, 1);
> +
> + /* get the serizlizer number being used for this Rx channel */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 2);
> + status &= PRU_SUART_CH_CTRL_SR_MASK;
> + status = status >> PRU_SUART_CH_CTRL_SR_SHIFT;
> +
> + /* we need to de-activate the serializer corresponding to this rx */
> + ret_status = suart_asp_serializer_deactivate(status, &suart_iomap);
> +
> + return ret_status;
> +}
> +
> +/*
> + * suart routine to get the tx status for a specific uart
> + */
> +s16 pru_softuart_get_tx_status(struct device *dev, struct suart_handle
> *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + return status;
> +}
> +
> +s16 pru_softuart_clr_tx_status(struct device *dev, struct suart_handle
> *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + status &= ~(0x2);
> + pruss_writeb(dev, offset, (u8 *) &status, 1);
> + return status;
> +}
> +
> +/*
> + * suart routine to get the rx status for a specific uart
> + */
> +s16 pru_softuart_get_rx_status(struct device *dev, struct suart_handle
> *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + return status;
> +}
> +
> +static s16 pru_softuart_clr_rx_fifo(struct device *dev,
> + struct suart_handle *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> + u16 reg_val;
> + u16 uart_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + uart_num = h_uart->uart_num;
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> + if (PRU0_MODE == PRU_MODE_RX_ONLY)
> + uart_num = 0;
> + else if (PRU1_MODE == PRU_MODE_RX_ONLY)
> + uart_num = 1;
> +
> + /* Reset the number of bytes read into the FIFO */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_BYTESDONECNTR_OFFSET;
> + pruss_readw(dev, offset, (u16 *) ®_val, 1);
> + reg_val &= 0x00;
> + pruss_writew(dev, offset, (u16 *) ®_val, 1);
> +
> +
> + /* Service Request to PRU */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) ®_val, 2);
> + reg_val &= ~(PRU_SUART_CH_CTRL_MODE_MASK | PRU_SUART_CH_CTRL_SREQ_MASK);
> + reg_val |= (PRU_SUART_CH_CTRL_RX_MODE << PRU_SUART_CH_CTRL_MODE_SHIFT) |
> + (PRU_SUART_CH_CTRL_SREQ << PRU_SUART_CH_CTRL_SREQ_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) ®_val, 2);
> + suart_intr_setmask(dev, h_uart->uart_num, PRU_RX_INTR,
> + CHN_TXRX_IE_MASK_TIMEOUT);
> +
> + /* generate ARM->PRU event */
> + suart_arm_to_pru_intr(dev, uart_num);
> +
> + return status;
> +}
> +
> +s16 pru_softuart_clr_rx_status(struct device *dev, struct suart_handle
> *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + status &= ~(0x3C);
> + pruss_writeb(dev, offset, (u8 *) &status, 1);
> + return status;
> +}
> +
> +/*
> + * suart_s32r_status_read: Gets the Global Interrupt status register
> + * for the specified SUART.
> + * uart_num < 1 to 6 >
> + * txrx_flag < Indicates TX or RX s32errupt for the uart >
> + */
> +s16 pru_softuart_get_isrstatus(struct device *dev, u16 uart_num, u16
> *txrx_flag)
> +{
> + u32 intc_offset;
> + u32 ch_num = 0xFF;
> + u32 reg_val = 0;
> + u32 reg_val2 = 0;
> + u32 ISR_value = 0;
> + u32 ack_reg_val = 0;
> + u32 stat_inx_clr_regoffset = 0;
> +
> + /* initialize the status & Flag to known value */
> + *txrx_flag = 0;
> +
> + stat_inx_clr_regoffset = (u32) (PRUSS_INTC_STATIDXCLR & 0xFFFF);
> +
> + /* Read PRU Interrupt Status Register from PRU */
> + intc_offset = (u32) (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
> +
> + pruss_readl(dev, intc_offset, (u32 *)&ISR_value, 1);
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + /* Check if the interrupt occured for Tx */
> + ch_num = uart_num * 2 - 2;
> + reg_val2 = PRU_SUART0_TX_EVT_BIT << ((uart_num - 1) * 2);
> + if (ISR_value & reg_val2) {
> + /* interupt occured for TX */
> + *txrx_flag |= PRU_TX_INTR;
> + /* acknowledge the RX interrupt */
> + ack_reg_val = ch_num + PRU_SUART0_TX_EVT;
> + pruss_writel(dev, stat_inx_clr_regoffset,
> + (u32 *)&ack_reg_val, 1);
> + }
> +
> + /* Check if the interrupt occured for Rx */
> + reg_val2 = PRU_SUART0_RX_EVT_BIT << ((uart_num - 1) * 2);
> + pruss_readl(dev, intc_offset, (u32 *)&ISR_value, 1);
> + if (ISR_value & reg_val2) {
> + /* interupt occured for RX */
> + *txrx_flag |= PRU_RX_INTR;
> + ch_num += 1;
> +
> + /* acknowledge the RX interrupt */
> + ack_reg_val = ch_num + PRU_SUART0_TX_EVT;
> + pruss_writel(dev, stat_inx_clr_regoffset,
> + (u32 *)&ack_reg_val, 1);
> + }
> + } else {
> + ch_num = uart_num - 1;
> + if ((ISR_value & 0x03FC) != 0) {
> + reg_val2 = 1 << (uart_num + 1);
> + if (ISR_value & reg_val2) {
> + /* acknowledge the s32errupt */
> + ack_reg_val = ch_num + PRU_SUART0_TX_EVT;
> + pruss_writel(dev, stat_inx_clr_regoffset,
> + (u32 *)&ack_reg_val, 1);
> + *txrx_flag |= PRU_RX_INTR;
> + }
> + }
> + pruss_readl(dev, intc_offset, (u32 *)&ISR_value, 1);
> + if (ISR_value & 0x3FC00) {
> + reg_val2 = 1 << (uart_num + 9);
> + if (ISR_value & reg_val2) {
> + /* acknowledge the s32errupt */
> + ack_reg_val = ch_num + PRU_SUART4_TX_EVT;
> + pruss_writel(dev, stat_inx_clr_regoffset,
> + (u32 *)&ack_reg_val, 1);
> + *txrx_flag |= PRU_TX_INTR;
> + }
> + }
> + }
> + return reg_val;
> +}
> +
> +s32 pru_intr_clr_isrstatus(struct device *dev, u16 uart_num, u32
> txrxmode)
> +{
> + u32 offset;
> + u16 txrx_flag = 0;
> + u16 chn_num;
> +
> + chn_num = uart_num - 1;
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + /* channel starts from 0 and uart instance starts from 1 */
> + chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> + if (uart_num <= 4) {
> + /* PRU0 */
> + offset = PRU_SUART_PRU0_ISR_OFFSET + 1;
> + } else {
> + /* PRU1 */
> + offset = PRU_SUART_PRU1_ISR_OFFSET + 1;
> + /* First 8 channel corresponds to PRU0 */
> + chn_num -= 8;
> + }
> + if (2 == txrxmode)
> + chn_num++;
> + } else if (PRU0_MODE == txrxmode) {
> + offset = PRU_SUART_PRU0_ISR_OFFSET + 1;
> + } else if (PRU1_MODE == txrxmode) {
> + offset = PRU_SUART_PRU1_ISR_OFFSET + 1;
> + } else {
> + return 0;
> + }
> +
> + pruss_readb(dev, offset, (u8 *) &txrx_flag, 1);
> + txrx_flag &= ~(0x2);
> + pruss_writeb(dev, offset, (u8 *) &txrx_flag, 1);
> +
> + return 0;
> +}
> +
> +s16 suart_arm_to_pru_intr(struct device *dev, u16 uart_num)
> +{
> + u32 offset;
> + u32 value;
> + s16 retval;
> +
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + if ((uart_num > 0) && (uart_num <= 4)) {
> + /* PRU0 SYS_EVT32 */
> + value = 0x20;
> + } else if ((uart_num > 4) && (uart_num <= 8)) {
> + /* PRU1 SYS_EVT33 */
> + value = 0x21;
> + } else {
> + return -EINVAL;
> + }
> + }
> +
> + if ((PRU0_MODE == PRU_MODE_RX_ONLY) || (PRU1_MODE == PRU_MODE_RX_ONLY)
> + || (PRU0_MODE == PRU_MODE_TX_ONLY)
> + || (PRU1_MODE == PRU_MODE_TX_ONLY)) {
> + if (uart_num == PRUSS_NUM0) {
> + /* PRU0 SYS_EVT32 */
> + value = 0x20;
> + }
> +
> + if (uart_num == PRUSS_NUM1) {
> + /* PRU0 SYS_EVT33 */
> + value = 0x21;
> + }
> + }
> +
> + offset = (u32) (PRUSS_INTC_STATIDXSET & 0xFFFF);
> + retval = pruss_writel(dev, offset, (u32 *)&value, 1);
> + if (retval == -1)
> + return -1;
> + return 0;
> +}
> +
> +static s16 arm_to_pru_intr_init(struct device *dev)
> +{
> + u32 value;
> + u32 int_offset;
> +
> + /* Clear all the host interrupts */
> + for (int_offset = 0; int_offset <= PRUSS_INTC_HOSTINTLVL_MAX;
> + int_offset++)
> + pruss_idx_writel(dev, PRUSS_INTC_HSTINTENIDXCLR, int_offset);
> +
> + /* Enable the global s32errupt */
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_GLBLEN & 0xFFFF), 0, 1);
> +
> + /* Enable the Host interrupts for all host channels */
> + for (int_offset = 0; int_offset <= PRUSS_INTC_HOSTINTLVL_MAX;
> + int_offset++)
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_HSTINTENIDXSET & 0xFFFF),
> + 0, int_offset);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_HOSTMAP0 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_HOSTMAP0_CHAN);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_HOSTMAP1 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_HOSTMAP1_CHAN);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_HOSTMAP2 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_HOSTMAP2_CHAN);
> +
> + /* MAP Channel 0 to SYS_EVT31 */
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP7 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP7_SYS_EVT31);
> +
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + /* Sets the channels for the system interrupt */
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP8 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP8_FULL);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP9 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP9_FULL);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP10 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP10_FULL);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP11 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP11_FULL);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP12 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP12_FULL);
> + }
> + if ((PRU0_MODE == PRU_MODE_RX_ONLY) || (PRU1_MODE == PRU_MODE_RX_ONLY)
> + || (PRU0_MODE == PRU_MODE_TX_ONLY)
> + || (PRU1_MODE == PRU_MODE_TX_ONLY)) {
> +
> + /* Sets the channels for the system interrupt */
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP8 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP8_HALF);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP9 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP9_HALF);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP10 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP10_HALF);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP11 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP11_HALF);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP12 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP12_HALF);
> + }
> +
> + /* Clear required set of system events
> + * and enable them using indexed register
> + */
> + for (int_offset = 0; int_offset < 18; int_offset++) {
> + value = 32 + int_offset;
> + pruss_idx_writel(dev, PRUSS_INTC_STATIDXCLR, value);
> + }
> +
> + /* enable only the HOST to PRU interrupts and let the PRU to Host events
> + * enabled by the separate API on demand basis.
> + */
> + pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 31);
> + pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 32);
> + pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 33);
> + pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 50);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_GLBLEN & 0xFFFF), 0, 1);
> +
> + /* Enable the Host interrupts for all host channels */
> + for (int_offset = 0; int_offset <= PRUSS_INTC_HOSTINTLVL_MAX;
> + int_offset++)
> + pruss_idx_writel(dev, PRUSS_INTC_HSTINTENIDXSET, int_offset);
> +
> + return 0;
> +}
> +
> +s32 suart_pru_to_host_intr_enable(struct device *dev, u16 uart_num,
> + u32 txrxmode, s32 flag)
> +{
> + s32 ret_val = 0;
> + u32 offset;
> + u32 chn_num;
> + u32 value;
> + s16 retval = 0;
> +
> + if (uart_num > 8)
> + return -EINVAL;
> +
> + chn_num = uart_num - 1;
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + chn_num = (uart_num * 2) - 2;
> + if (2 == txrxmode) /* Rx mode */
> + chn_num++;
> + value = 34 + chn_num;
> + } else if ((PRU_MODE_RX_ONLY == txrxmode)
> + && (PRU0_MODE == PRU_MODE_RX_ONLY))
> + value = 34 + chn_num;
> + else if ((PRU_MODE_RX_ONLY == txrxmode)
> + && (PRU1_MODE == PRU_MODE_RX_ONLY))
> + value = 42 + chn_num;
> + else if ((PRU_MODE_TX_ONLY == txrxmode)
> + && (PRU0_MODE == PRU_MODE_TX_ONLY))
> + value = 34 + chn_num;
> + else if ((PRU_MODE_TX_ONLY == txrxmode)
> + && (PRU1_MODE == PRU_MODE_TX_ONLY))
> + value = 42 + chn_num;
> + else
> + return -1;
> +
> + if (true == flag) {
> + offset = (u32) (PRUSS_INTC_ENIDXSET & 0xFFFF);
> + retval = pruss_writel(dev, offset, (u32 *)&value, 1);
> + if (retval == -1)
> + return -1;
> + } else {
> + offset = (u32) (PRUSS_INTC_ENIDXCLR & 0xFFFF);
> + retval = pruss_writel(dev, offset, (u32 *)&value, 1);
> + if (retval == -1)
> + return -1;
> + }
> + return ret_val;
> +}
> +
> +s32 suart_intr_setmask(struct device *dev, u16 uart_num,
> + u32 txrxmode, u32 rmask)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u32 regval = 0;
> + u32 chn_num;
> +
> + chn_num = uart_num - 1;
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + /* channel starts from 0 and uart instance starts from 1 */
> + chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> +
> + if ((uart_num > 0) && (uart_num <= 4)) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if ((uart_num > 4) && (uart_num <= 8)) {
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + chn_num -= 8;
> + } else {
> + return -EINVAL;
> + }
> + if (2 == txrxmode) { /* rx mode */
> + chn_num++;
> + }
> + } else if (PRU0_MODE == txrxmode) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if (PRU1_MODE == txrxmode) {
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else {
> + return 0;
> + }
> + regval = 1 << chn_num;
> + if (CHN_TXRX_IE_MASK_CMPLT == (rmask & CHN_TXRX_IE_MASK_CMPLT))
> + pruss_rmww(dev, offset, regval, regval);
> +
> + if ((rmask & SUART_GBL_INTR_ERR_MASK) ==
> + SUART_GBL_INTR_ERR_MASK) {
> + regval = SUART_GBL_INTR_ERR_MASK;
> + pruss_rmww(dev, offset, regval, regval);
> + }
> +
> + offset = pru_offset +
> + (chn_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_CONFIG1_OFFSET;
> + /* Framing Error Interrupt Masked */
> + if ((rmask & CHN_TXRX_IE_MASK_FE) == CHN_TXRX_IE_MASK_FE) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) ®val, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_FE);
> + regval |= CHN_TXRX_IE_MASK_FE;
> + pruss_writeb(dev, offset, (u8 *) ®val, 2);
> + }
> +
> + /* Break Indicator Interrupt Masked */
> + if (CHN_TXRX_IE_MASK_BI == (rmask & CHN_TXRX_IE_MASK_BI)) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) ®val, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_BI);
> + regval |= CHN_TXRX_IE_MASK_BI;
> + pruss_writeb(dev, offset, (u8 *) ®val, 2);
> + }
> +
> + /* Timeout error Interrupt Masked */
> + if (CHN_TXRX_IE_MASK_TIMEOUT ==
> + (rmask & CHN_TXRX_IE_MASK_TIMEOUT)) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) ®val, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_TIMEOUT);
> + regval |= CHN_TXRX_IE_MASK_TIMEOUT;
> + pruss_writeb(dev, offset, (u8 *) ®val, 2);
> + }
> + return 0;
> +}
> +
> +s32 suart_intr_clrmask(struct device *dev, u16 uart_num,
> + u32 txrxmode, u32 rmask)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 regval = 0;
> + u16 chn_num;
> +
> + chn_num = uart_num - 1;
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + /* channel starts from 0 and uart instance starts from 1 */
> + chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> + if ((uart_num > 0) && (uart_num <= 4)) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if ((uart_num > 4) && (uart_num <= 8)) {
> + /* PRU1 */
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + /* First 8 channel corresponds to PRU0 */
> + chn_num -= 8;
> + } else {
> + return -EINVAL;
> + }
> + if (2 == txrxmode) { /* rx mode */
> + chn_num++;
> + }
> + } else if (PRU0_MODE == txrxmode) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if (PRU1_MODE == txrxmode) {
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else {
> + return 0;
> + }
> + regval = 1 << chn_num;
> + if (CHN_TXRX_IE_MASK_CMPLT == (rmask & CHN_TXRX_IE_MASK_CMPLT))
> + pruss_rmww(dev, offset, regval, 0);
> +
> + if ((rmask & SUART_GBL_INTR_ERR_MASK) == SUART_GBL_INTR_ERR_MASK)
> + pruss_rmww(dev, offset, SUART_GBL_INTR_ERR_MASK, 0);
> +
> + offset = pru_offset +
> + (chn_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_CONFIG1_OFFSET;
> +
> + /* Framing Error Interrupt Masked */
> + if ((rmask & CHN_TXRX_IE_MASK_FE) == CHN_TXRX_IE_MASK_FE) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) ®val, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_FE);
> + pruss_writeb(dev, offset, (u8 *) ®val, 2);
> + }
> +
> + /* Break Indicator Interrupt Masked */
> + if (CHN_TXRX_IE_MASK_BI == (rmask & CHN_TXRX_IE_MASK_BI)) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) ®val, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_BI);
> + pruss_writeb(dev, offset, (u8 *) ®val, 2);
> + }
> +
> + /* Timeout error Interrupt Masked */
> + if (CHN_TXRX_IE_MASK_TIMEOUT ==
> + (rmask & CHN_TXRX_IE_MASK_TIMEOUT)) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) ®val, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_TIMEOUT);
> + pruss_writeb(dev, offset, (u8 *) ®val, 2);
> + }
> +
> + return 0;
> +}
> +
> +s32 suart_intr_getmask(struct device *dev, u16 uart_num, u32 txrxmode,
> + u32 rmask)
> +{
> + u16 chn_num;
> + u32 offset;
> + u16 txrx_flag;
> + u16 regval = 1;
> +
> + chn_num = uart_num - 1;
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + /* channel starts from 0 and uart instance starts from 1 */
> + chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> +
> + if ((uart_num > 0) && (uart_num <= 4)) {
> +
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if ((uart_num > 4) && (uart_num <= 8)) {
> + /* PRU1 */
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + /* First 8 channel corresponds to PRU0 */
> + chn_num -= 8;
> + } else {
> + return -EINVAL;
> + }
> +
> + if (2 == txrxmode) { /* rx mode */
> + chn_num++;
> + }
> + } else if (PRU0_MODE == txrxmode) {
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if (PRU1_MODE == txrxmode) {
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + } else {
> + return 0;
> + }
> + regval = regval << chn_num;
> + pruss_readb(dev, offset, (u8 *) &txrx_flag, 2);
> + txrx_flag &= regval;
> + if (0 == rmask) {
> + if (txrx_flag == 0)
> + return 1;
> + }
> + if (1 == rmask) {
> + if (txrx_flag == regval)
> + return 1;
> + }
> + return 0;
> +}
> diff --git a/drivers/tty/serial/pruss_suart_utils.c
> b/drivers/tty/serial/pruss_suart_utils.c
> new file mode 100644
> index 0000000..2bd6983
> --- /dev/null
> +++ b/drivers/tty/serial/pruss_suart_utils.c
> @@ -0,0 +1,391 @@
> +/*
> + * Copyright (C) 2010 Texas Instruments Incorporated
> + * Author: Jitendra Kumar <jitendra@...tralsolutions.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation version 2.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
> + * whether express or implied; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +
> +#include <linux/mfd/da8xx/da8xx_pru.h>
> +#include "pruss_suart.h"
> +
> +#define SUART_TRX_DIV_CONF_SZ 4
> +
> +static s16 suart_mcasp_tx_baud_set(u32 tx_baud_value,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +static s16 suart_mcasp_rx_baud_set(u32 rx_baud_value, u32 oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +/*
> + * Lookup table for TX baud rate
> + * The divisor value is calculated using the formula
> + *
> + * ACLKX = (AUXCLK)/(CLKXDIV * HCLKXDIV)
> + *
> + * Where
> + * CLKXDIV takes values from 1-32
> + * HCLKXDIV takes values from 1-4096
> + * Here
> + * AUXCLK = 24MHz
> + */
> +u32 lt_tx_baud_rate[][SUART_TRX_DIV_CONF_SZ] = {
> + /*BaudRate, Divisor, CLKXDIV,HCLKXDIV */
> + {300, 80000, 24, 3200},
> + {600, 40000, 15, 2500},
> + {1800, 13333, 10, 1212},
> + {2400, 10000, 4, 2000},
> + {4800, 5000, 1, 2500},
> + {7200, 3333, 0, 3333},
> + {9600, 2500, 0, 2500},
> + {14400, 1666, 0, 1666},
> + {19200, 1250, 0, 1250},
> + {38400, 625, 0, 625},
> + {57600, 416, 0, 416},
> + {115200, 208, 0, 208},
> + {230400, 104, 0, 104}
> +};
> +
> +/*
> + * Lookup table for RX baud rate for 8 bit oversampling
> + * The divisor value is calculated using the formula
> + *
> + * ACLKR = (AUXCLK)/(CLKRDIV * HCLKRDIV) * Oversampling
> + *
> + * Where
> + * CLKRDIV takes values from 1-32
> + * HCLKRDIV takes values from 1-4096
> + * Here
> + * AUXCLK = 24MHz
> + */
> +u32 lt_rx_8x_baud_rate[][SUART_TRX_DIV_CONF_SZ] = {
> +/* BaudRate, Divisor, CLKXDIV, HCLKXDIV */
> + {300, 10000, 4, 2000},
> + {600, 5000, 1, 2500},
> + {1800, 1667, 0, 1667},
> + {2400, 1250, 0, 1250},
> + {7200, 417, 0, 417},
> + {4800, 625, 0, 625},
> + {9600, 312, 0, 312},
> + {14400, 208, 0, 208},
> + {19200, 156, 0, 156},
> + {38400, 78, 0, 78},
> + {57600, 52, 0, 52},
> + {115200, 26, 0, 26},
> + {230400, 13, 0, 13}
> +};
> +
> +/*
> + * Lookup table for RX baud rate for 16 bit oversampling
> + * The divisor value is calculated using the formula
> + *
> + * ACLKR = (AUXCLK)/(CLKRDIV * HCLKRDIV) * Oversampling
> + *
> + * Where
> + * CLKRDIV takes values from 1-32
> + * HCLKRDIV takes values from 1-4096
> + * Here
> + * AUXCLK = 24MHz
> + */
> +u32 lt_rx_16x_baud_rate[][SUART_TRX_DIV_CONF_SZ] = {
> +/*BaudRate, Divisor, CLKXDIV, HCLKXDIV */
> + {300, 5000, 1, 2500},
> + {600, 2500, 0, 2500},
> + {1800, 833, 0, 833},
> + {2400, 625, 0, 625},
> + {4800, 312, 0, 312},
> + {7200, 208, 0, 208},
> + {9600, 156, 0, 156},
> + {14400, 104, 0, 104},
> + {19200, 78, 0, 78},
> + {38400, 39, 0, 39},
> + {57600, 26, 0, 26},
> + {115200, 13, 0, 13},
> + {230400, 6, 0, 6}
> +};
> +
> +/*
> + * McASP configuration routine
> + */
> +
> +void suart_mcasp_reset(struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> + (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + /* reset mcasp. */
> + __raw_writel(MCASP_SUART_GBLCTL, &mcasp0_regs->GBLCTL);
> + __raw_writel(MCASP_SUART_RGBLCTL, &mcasp0_regs->RGBLCTL);
> + __raw_writel(MCASP_SUART_XGBLCTL, &mcasp0_regs->XGBLCTL);
> + __raw_writel(MCASP_SUART_XSTAT, &mcasp0_regs->XSTAT);
> + __raw_writel(MCASP_SUART_RSTAT, &mcasp0_regs->RSTAT);
> +}
> +
> +void suart_mcasp_config(u32 tx_baud_value,
> + u32 rx_baud_value,
> + u32 oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> + (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + u32 temp_reg;
> +
> + /* reset mcasp */
> + __raw_writel(MCASP_SUART_GBLCTL, &mcasp0_regs->GBLCTL);
> + __raw_writel(MCASP_SUART_RGBLCTL, &mcasp0_regs->RGBLCTL);
> + __raw_writel(MCASP_SUART_XGBLCTL, &mcasp0_regs->XGBLCTL);
> +
> + /* configure receive registers */
> + if ((SUART_8X_OVRSMPL == oversampling) || (0 == oversampling)) {
> + __raw_writel(MCASP_SUART_RMASK_8, &mcasp0_regs->RMASK);
> + __raw_writel(MCASP_SUART_RFMT_8, &mcasp0_regs->RFMT);
> + }
> + if (SUART_16X_OVRSMPL == oversampling) {
> + __raw_writel(MCASP_SUART_RMASK_16, &mcasp0_regs->RMASK);
> + __raw_writel(MCASP_SUART_RFMT_16, &mcasp0_regs->RFMT);
> +
> + }
> +
> + __raw_writel(MCASP_SUART_FSRM, &mcasp0_regs->AFSRCTL);
> + __raw_writel(MCASP_SUART_CLKRM_CLKRP, &mcasp0_regs->ACLKRCTL);
> + __raw_writel(MCASP_SUART_HCLKRP, &mcasp0_regs->AHCLKRCTL);
> + suart_mcasp_rx_baud_set(rx_baud_value, oversampling, pruss_ioaddr);
> + __raw_writel(MCASP_SUART_RTDMS0, &mcasp0_regs->RTDM);
> + __raw_writel(MCASP_SUART_RSYNCERR, &mcasp0_regs->RINTCTL);
> + __raw_writel(MCASP_SUART_RMAX_RPS_256, &mcasp0_regs->RCLKCHK);
> +
> + /* configure transmit registers. */
> + __raw_writel(MCASP_SUART_XMASK_0_31, &mcasp0_regs->XMASK);
> + __raw_writel(MCASP_SUART_XBUSEL_XSSZ_16_XPAD_0, &mcasp0_regs->XFMT);
> + __raw_writel(MCASP_SUART_FSXM, &mcasp0_regs->AFSXCTL);
> + __raw_writel(MCASP_SUART_CLKXM_ASYNC_CLKXP, &mcasp0_regs->ACLKXCTL);
> + __raw_writel(MCASP_SUART_HCLKXM, &mcasp0_regs->AHCLKXCTL);
> +
> + suart_mcasp_tx_baud_set(tx_baud_value, pruss_ioaddr);
> + __raw_writel(MCASP_SUART_XTDMS0, &mcasp0_regs->XTDM);
> + __raw_writel(MCASP_SUART_XSYNCERR, &mcasp0_regs->XINTCTL);
> + __raw_writel(MCASP_SUART_XMAX_XPS_256, &mcasp0_regs->XCLKCHK);
> +
> + /* Serializer as a transmitter */
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL0);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL1);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL2);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL3);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL4);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL5);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL6);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL7);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL8);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL9);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL10);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL11);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL12);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL13);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL14);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL15);
> +
> + /* Configure all AXR[n] as McASP pins */
> +
> + /*
> + * Setting all TX MCASP AXR[n] Pin mapped to Even Serializer number
> + * (0,2,4,6,8,10,12,14) to GPIO Mode by default. During setting the
> + * serializer to TX mode in PRU assembly code, the MCASP AXR[n] Pin
> + * would get configured to MCASP mode of operation,
> + * before Actual Data Transfer
> + */
> +
> + /* Setting all TX Pin to GPIO Mode by default */
> + temp_reg = (OMAPL_MCASP_PFUNC_RESETVAL) |
> + (1 << PRU_SUART0_CONFIG_TX_SER) | (1 << PRU_SUART1_CONFIG_TX_SER) |
> + (1 << PRU_SUART2_CONFIG_TX_SER) | (1 << PRU_SUART3_CONFIG_TX_SER) |
> + (1 << PRU_SUART4_CONFIG_TX_SER) | (1 << PRU_SUART5_CONFIG_TX_SER) |
> + (1 << PRU_SUART6_CONFIG_TX_SER) | (1 << PRU_SUART7_CONFIG_TX_SER);
> + __raw_writel(temp_reg, &mcasp0_regs->PFUNC);
> +
> + __raw_writel(0xFFF, &mcasp0_regs->PDOUT);
> +
> + /* config pin function and direction */
> + __raw_writel(0x00000000, &mcasp0_regs->PDIR);
> + temp_reg =
> + (1 << PRU_SUART0_CONFIG_TX_SER) | (1 << PRU_SUART1_CONFIG_TX_SER) |
> + (1 << PRU_SUART2_CONFIG_TX_SER) | (1 << PRU_SUART3_CONFIG_TX_SER) |
> + (1 << PRU_SUART4_CONFIG_TX_SER) | (1 << PRU_SUART5_CONFIG_TX_SER) |
> + (1 << PRU_SUART6_CONFIG_TX_SER) | (1 << PRU_SUART7_CONFIG_TX_SER) |
> + (MCASP_PDIR_VAL);
> + __raw_writel(temp_reg, &mcasp0_regs->PDIR);
> +
> + __raw_writel(MCASP_SUART_DIT_DISABLE, &mcasp0_regs->DITCTL);
> + __raw_writel(MCASP_SUART_LOOPBACK_DISABLE, &mcasp0_regs->DLBCTL);
> + __raw_writel(MCASP_SUART_AMUTE_DISABLE, &mcasp0_regs->AMUTE);
> +
> + __raw_writel(MCASP_SUART_XSTAT, &mcasp0_regs->XSTAT);
> + __raw_writel(MCASP_SUART_RSTAT, &mcasp0_regs->RSTAT);
> +}
> +
> +void suart_mcasp_tx_serialzier_set(u32 serializer_num,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> + (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + u32 temp_reg;
> + temp_reg = mcasp0_regs->PFUNC | (0x1 << serializer_num);
> + __raw_writel(temp_reg, &mcasp0_regs->PFUNC);
> +}
> +
> +/*
> + * mcasp TX buard rate setting routine
> + */
> +s16 suart_mcasp_tx_baud_set(u32 tx_baud_value,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + u32 clk_div_val;
> + u32 loop_cnt;
> + s16 status = 0;
> + s16 found_val = false;
> +
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> + (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + u32 temp_reg;
> +
> + /* Search the supported baud rate in the table */
> + for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
> + loop_cnt++) {
> + if (tx_baud_value == lt_tx_baud_rate[loop_cnt][0]) {
> + found_val = true;
> + break;
> + }
> + }
> + if (found_val == true) {
> + clk_div_val = lt_tx_baud_rate[loop_cnt][2];
> + temp_reg = mcasp0_regs->ACLKXCTL |
> + clk_div_val << OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT;
> + __raw_writel(temp_reg, &mcasp0_regs->ACLKXCTL);
> + clk_div_val = lt_tx_baud_rate[loop_cnt][3];
> + temp_reg = mcasp0_regs->AHCLKXCTL |
> + clk_div_val << OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT;
> + __raw_writel(temp_reg, &mcasp0_regs->AHCLKXCTL);
> + } else {
> + return -EINVAL ;
> + }
> + return status;
> +}
> +
> +/*
> + * mcasp RX buard rate setting routine
> + */
> +s16 suart_mcasp_rx_baud_set(u32 rx_baud_value,
> + u32 oversampling, struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + u32 clk_div_val;
> + u32 loop_cnt;
> + s16 status = 0;
> + s16 found_val = false;
> +
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> + (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + u32 temp_reg;
> +
> + if (oversampling == SUART_8X_OVRSMPL) {
> + for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
> + loop_cnt++) {
> + if (rx_baud_value == lt_rx_8x_baud_rate[loop_cnt][0]) {
> + clk_div_val = lt_rx_8x_baud_rate[loop_cnt][2];
> + temp_reg = mcasp0_regs->ACLKRCTL | (clk_div_val
> + << OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT);
> +
> + __raw_writel(temp_reg, &mcasp0_regs->ACLKRCTL);
> +
> + clk_div_val =
> + lt_rx_8x_baud_rate[loop_cnt][3] - 1;
> +
> + temp_reg = mcasp0_regs->AHCLKRCTL | (clk_div_val
> + << OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT);
> +
> + __raw_writel(temp_reg, &mcasp0_regs->AHCLKRCTL);
> +
> + found_val = true;
> + break;
> + }
> + }
> + } else if (oversampling == SUART_16X_OVRSMPL) {
> + for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
> + loop_cnt++) {
> + if (rx_baud_value == lt_rx_16x_baud_rate[loop_cnt][0]) {
> + clk_div_val = lt_rx_16x_baud_rate[loop_cnt][2];
> + temp_reg =
> + mcasp0_regs->ACLKRCTL | (clk_div_val <<
> + OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT);
> + __raw_writel(temp_reg, &mcasp0_regs->ACLKRCTL);
> + clk_div_val = lt_rx_16x_baud_rate[loop_cnt][3];
> + temp_reg =
> + mcasp0_regs->AHCLKRCTL | (clk_div_val <<
> + OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT);
> + __raw_writel(temp_reg, &mcasp0_regs->AHCLKRCTL);
> + found_val = true;
> + break;
> + }
> + }
> + } else if (oversampling == 0) {
> + for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
> + loop_cnt++) {
> + if (rx_baud_value == lt_tx_baud_rate[loop_cnt][0]) {
> + clk_div_val = lt_tx_baud_rate[loop_cnt][2];
> + temp_reg =
> + mcasp0_regs->ACLKRCTL | (clk_div_val <<
> + OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT);
> + __raw_writel(temp_reg, &mcasp0_regs->ACLKRCTL);
> + clk_div_val = lt_tx_baud_rate[loop_cnt][3];
> + temp_reg =
> + mcasp0_regs->AHCLKRCTL | (clk_div_val <<
> + OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT);
> + __raw_writel(temp_reg, &mcasp0_regs->AHCLKRCTL);
> + found_val = true;
> + break;
> + }
> + }
> + } else {
> + return -EINVAL ;
> + }
> +
> + if (found_val != true)
> + return -EINVAL ;
> +
> + return status;
> +}
> +
> +/*
> + * mcasp buard rate setting routine
> + */
> +s16 suart_asp_baud_set(u32 tx_baud_value, u32 rx_baud_value, u32
> oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + s16 status = 0;
> +
> + status = suart_mcasp_tx_baud_set(tx_baud_value, pruss_ioaddr);
> + status = suart_mcasp_rx_baud_set(rx_baud_value, oversampling,
> + pruss_ioaddr);
> +
> + return status;
> +}
> +
> +/*
> + * mcasp deactivate the selected serializer
> + */
> +s16 suart_asp_serializer_deactivate(u16 sr_num,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + s16 status = 0;
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> + (struct omapl_mcasp_regs_ovly *)pruss_ioaddr->mcasp_io_addr;
> + if (sr_num > 15)
> + status = -EINVAL;
> + else
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL0);
> +
> + return status;
> +}
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index 758c5b0..eae37fe 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -202,6 +202,8 @@
> /* VIA VT8500 SoC */
> #define PORT_VT8500 97
>
> +#define PORT_DA8XX_PRU_SUART 98
> +
> #ifdef __KERNEL__
>
> #include <linux/compiler.h>
> --
> 1.7.2.3
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists