/*
* Freescale STMP37XX/STMP378X Application UART driver
*
* Author: dmitry pervushin <dimka@embeddedalley.com>
*
* Copyright 2008-2010 Freescale Semiconductor, Inc.
* Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/pinctrl/consumer.h>
#include <linux/of_device.h>
#include <linux/dma-mapping.h>
#include <linux/fsl/mxs-dma.h>
#include <asm/cacheflush.h>
#define MXS_AUART_PORTS 5
#define AUART_CTRL0 0x00000000
#define AUART_CTRL0_SET 0x00000004
#define AUART_CTRL0_CLR 0x00000008
#define AUART_CTRL0_TOG 0x0000000c
#define AUART_CTRL1 0x00000010
#define AUART_CTRL1_SET 0x00000014
#define AUART_CTRL1_CLR 0x00000018
#define AUART_CTRL1_TOG 0x0000001c
#define AUART_CTRL2 0x00000020
#define AUART_CTRL2_SET 0x00000024
#define AUART_CTRL2_CLR 0x00000028
#define AUART_CTRL2_TOG 0x0000002c
#define AUART_LINECTRL 0x00000030
#define AUART_LINECTRL_SET 0x00000034
#define AUART_LINECTRL_CLR 0x00000038
#define AUART_LINECTRL_TOG 0x0000003c
#define AUART_LINECTRL2 0x00000040
#define AUART_LINECTRL2_SET 0x00000044
#define AUART_LINECTRL2_CLR 0x00000048
#define AUART_LINECTRL2_TOG 0x0000004c
#define AUART_INTR 0x00000050
#define AUART_INTR_SET 0x00000054
#define AUART_INTR_CLR 0x00000058
#define AUART_INTR_TOG 0x0000005c
#define AUART_DATA 0x00000060
#define AUART_STAT 0x00000070
#define AUART_DEBUG 0x00000080
#define AUART_VERSION 0x00000090
#define AUART_AUTOBAUD 0x000000a0
#define AUART_CTRL0_SFTRST (1 << 31)
#define AUART_CTRL0_CLKGATE (1 << 30)
#define AUART_CTRL0_RXTO_ENABLE (1 << 27)
#define AUART_CTRL0_RXTIMEOUT(v) (((v) & 0x7ff) << 16)
#define AUART_CTRL0_XFER_COUNT(v) ((v) & 0xffff)
#define AUART_CTRL1_XFER_COUNT(v) ((v) & 0xffff)
#define AUART_CTRL2_DMAONERR (1 << 26)
#define AUART_CTRL2_TXDMAE (1 << 25)
#define AUART_CTRL2_RXDMAE (1 << 24)
#define AUART_CTRL2_CTSEN (1 << 15)
#define AUART_CTRL2_RTSEN (1 << 14)
#define AUART_CTRL2_RTS (1 << 11)
#define AUART_CTRL2_RXE (1 << 9)
#define AUART_CTRL2_TXE (1 << 8)
#define AUART_CTRL2_UARTEN (1 << 0)
#define AUART_LINECTRL_BAUD_DIVINT_SHIFT 16
#define AUART_LINECTRL_BAUD_DIVINT_MASK 0xffff0000
#define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16)
#define AUART_LINECTRL_BAUD_DIVFRAC_SHIFT 8
#define AUART_LINECTRL_BAUD_DIVFRAC_MASK 0x00003f00
#define AUART_LINECTRL_BAUD_DIVFRAC(v) (((v) & 0x3f) << 8)
#define AUART_LINECTRL_WLEN_MASK 0x00000060
#define AUART_LINECTRL_WLEN(v) (((v) & 0x3) << 5)
#define AUART_LINECTRL_FEN (1 << 4)
#define AUART_LINECTRL_STP2 (1 << 3)
#define AUART_LINECTRL_EPS (1 << 2)
#define AUART_LINECTRL_PEN (1 << 1)
#define AUART_LINECTRL_BRK (1 << 0)
#define AUART_INTR_RTIEN (1 << 22)
#define AUART_INTR_TXIEN (1 << 21)
#define AUART_INTR_RXIEN (1 << 20)
#define AUART_INTR_CTSMIEN (1 << 17)
#define AUART_INTR_RTIS (1 << 6)
#define AUART_INTR_TXIS (1 << 5)
#define AUART_INTR_RXIS (1 << 4)
#define AUART_INTR_CTSMIS (1 << 1)
#define AUART_STAT_BUSY (1 << 29)
#define AUART_STAT_CTS (1 << 28)
#define AUART_STAT_TXFE (1 << 27)
#define AUART_STAT_TXFF (1 << 25)
#define AUART_STAT_RXFE (1 << 24)
#define AUART_STAT_OERR (1 << 19)
#define AUART_STAT_BERR (1 << 18)
#define AUART_STAT_PERR (1 << 17)
#define AUART_STAT_FERR (1 << 16)
#define AUART_STAT_RXCOUNT_MASK 0xffff
static struct uart_driver auart_driver;
enum mxs_auart_type {
IMX23_AUART,
IMX28_AUART,
};
struct mxs_auart_port {
struct uart_port port;
#define MXS_AUART_DMA_CONFIG 0x1
#define MXS_AUART_DMA_ENABLED 0x2
#define MXS_AUART_DMA_TX_SYNC 2 /* bit 2 */
#define MXS_AUART_DMA_RX_READY 3 /* bit 3 */
unsigned long flags;
unsigned int ctrl;
enum mxs_auart_type devtype;
unsigned int irq;
struct clk *clk;
struct device *dev;
/* for DMA */
struct mxs_dma_data dma_data;
int dma_channel_rx, dma_channel_tx;
int dma_irq_rx, dma_irq_tx;
int dma_channel;
struct scatterlist tx_sgl;
struct dma_chan *tx_dma_chan;
void *tx_dma_buf;
struct scatterlist rx_sgl;
struct dma_chan *rx_dma_chan;
void *rx_dma_buf;
};
static struct platform_device_id mxs_auart_devtype[] = {
{ .name = "mxs-auart-imx23", .driver_data = IMX23_AUART },
{ .name = "mxs-auart-imx28", .driver_data = IMX28_AUART },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, mxs_auart_devtype);
static struct of_device_id mxs_auart_dt_ids[] = {
{
.compatible = "fsl,imx28-auart",
.data = &mxs_auart_devtype[IMX28_AUART]
}, {
.compatible = "fsl,imx23-auart",
.data = &