* Add i.MX23/28 auart support
@ 2011-01-11 15:09 Sascha Hauer
2011-01-11 15:09 ` [PATCH 1/2] serial: Add auart driver for i.MX23/28 Sascha Hauer
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Sascha Hauer @ 2011-01-11 15:09 UTC (permalink / raw)
To: linux-arm-kernel
The following series adds support for the auart found on i.MX23/28
Sascha Hauer (2):
serial: Add auart driver for i.MX23/28
ARM i.MXS: Add auart platform support for i.MX28
arch/arm/mach-mxs/clock-mx28.c | 5 +
arch/arm/mach-mxs/devices-mx28.h | 8 +
arch/arm/mach-mxs/devices/Kconfig | 3 +
arch/arm/mach-mxs/devices/Makefile | 1 +
arch/arm/mach-mxs/devices/platform-auart.c | 54 ++
arch/arm/mach-mxs/include/mach/devices-common.h | 10 +
drivers/serial/Kconfig | 15 +
drivers/serial/Makefile | 1 +
drivers/serial/mxs-auart.c | 763 +++++++++++++++++++++++
9 files changed, 860 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-mxs/devices/platform-auart.c
create mode 100644 drivers/serial/mxs-auart.c
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] serial: Add auart driver for i.MX23/28
2011-01-11 15:09 Add i.MX23/28 auart support Sascha Hauer
@ 2011-01-11 15:09 ` Sascha Hauer
2011-01-11 16:05 ` Russell King - ARM Linux
` (2 more replies)
2011-01-11 15:09 ` [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28 Sascha Hauer
2011-01-12 5:31 ` Add i.MX23/28 auart support Shawn Guo
2 siblings, 3 replies; 12+ messages in thread
From: Sascha Hauer @ 2011-01-11 15:09 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/serial/Kconfig | 15 +
drivers/serial/Makefile | 1 +
drivers/serial/mxs-auart.c | 763 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 779 insertions(+), 0 deletions(-)
create mode 100644 drivers/serial/mxs-auart.c
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ec3c214..de37fe5 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1657,4 +1657,19 @@ 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.
+
+config SERIAL_MXS_AUART
+ depends on ARCH_MXS
+ tristate "i.MXS AUART support"
+ select SERIAL_CORE
+ help
+ This driver supports the i.MX AUART port.
+
+config SERIAL_MXS_AUART_CONSOLE
+ bool "i.MXS AUART console support"
+ depends on SERIAL_MXS_AUART=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Enable a i.MXS AUART port to be the system console.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 8ea92e9..c855071 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -92,3 +92,4 @@ 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
+obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
diff --git a/drivers/serial/mxs-auart.c b/drivers/serial/mxs-auart.c
new file mode 100644
index 0000000..dd437ea
--- /dev/null
+++ b/drivers/serial/mxs-auart.c
@@ -0,0 +1,763 @@
+/*
+ * Application UART driver for hardware found on
+ * Sigmatel STMP37XX/STMP378X and
+ * Freescale i.MX23/28
+ *
+ * Author: dmitry pervushin <dimka@embeddedalley.com>
+ *
+ * Copyright 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ * 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/device.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 <asm/cacheflush.h>
+#include <mach/mx28.h>
+
+#define MXS_AUART_PORTS 5
+
+#define UARTAPP_CTRL0 0x00000000
+#define UARTAPP_CTRL0_SET 0x00000004
+#define UARTAPP_CTRL0_CLR 0x00000008
+#define UARTAPP_CTRL0_TOG 0x0000000c
+#define UARTAPP_CTRL1 0x00000010
+#define UARTAPP_CTRL1_SET 0x00000014
+#define UARTAPP_CTRL1_CLR 0x00000018
+#define UARTAPP_CTRL1_TOG 0x0000001c
+#define UARTAPP_CTRL2 0x00000020
+#define UARTAPP_CTRL2_SET 0x00000024
+#define UARTAPP_CTRL2_CLR 0x00000028
+#define UARTAPP_CTRL2_TOG 0x0000002c
+#define UARTAPP_LINECTRL 0x00000030
+#define UARTAPP_LINECTRL_SET 0x00000034
+#define UARTAPP_LINECTRL_CLR 0x00000038
+#define UARTAPP_LINECTRL_TOG 0x0000003c
+#define UARTAPP_LINECTRL2 0x00000040
+#define UARTAPP_LINECTRL2_SET 0x00000044
+#define UARTAPP_LINECTRL2_CLR 0x00000048
+#define UARTAPP_LINECTRL2_TOG 0x0000004c
+#define UARTAPP_INTR 0x00000050
+#define UARTAPP_INTR_SET 0x00000054
+#define UARTAPP_INTR_CLR 0x00000058
+#define UARTAPP_INTR_TOG 0x0000005c
+#define UARTAPP_DATA 0x00000060
+#define UARTAPP_STAT 0x00000070
+#define UARTAPP_DEBUG 0x00000080
+#define UARTAPP_VERSION 0x00000090
+#define UARTAPP_AUTOBAUD 0x000000a0
+
+#define BM_UARTAPP_CTRL0_SFTRST (1 << 31)
+#define BM_UARTAPP_CTRL0_CLKGATE (1 << 30)
+
+
+#define BM_UARTAPP_CTRL2_CTSEN (1 << 15)
+#define BM_UARTAPP_CTRL2_RTS (1 << 11)
+#define BM_UARTAPP_CTRL2_RXE (1 << 9)
+#define BM_UARTAPP_CTRL2_TXE (1 << 8)
+#define BM_UARTAPP_CTRL2_UARTEN (1 << 0)
+
+#define BP_UARTAPP_LINECTRL_BAUD_DIVINT 16
+#define BM_UARTAPP_LINECTRL_BAUD_DIVINT 0xffff0000
+#define BF_UARTAPP_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16)
+#define BP_UARTAPP_LINECTRL_BAUD_DIVFRAC 8
+#define BM_UARTAPP_LINECTRL_BAUD_DIVFRAC 0x00003f00
+#define BF_UARTAPP_LINECTRL_BAUD_DIVFRAC(v) (((v) & 0x3f) << 8)
+#define BP_UARTAPP_LINECTRL_WLEN 5
+#define BM_UARTAPP_LINECTRL_WLEN 0x00000060
+#define BF_UARTAPP_LINECTRL_WLEN(v) (((v) & 0x3) << 5)
+#define BM_UARTAPP_LINECTRL_FEN (1 << 4)
+#define BM_UARTAPP_LINECTRL_STP2 (1 << 3)
+#define BM_UARTAPP_LINECTRL_EPS (1 << 2)
+#define BM_UARTAPP_LINECTRL_PEN (1 << 1)
+#define BM_UARTAPP_LINECTRL_BRK (1 << 0)
+
+#define BM_UARTAPP_INTR_RTIEN (1 << 22)
+#define BM_UARTAPP_INTR_TXIEN (1 << 21)
+#define BM_UARTAPP_INTR_RXIEN (1 << 20)
+#define BM_UARTAPP_INTR_CTSMIEN (1 << 17)
+#define BM_UARTAPP_INTR_RTIS (1 << 6)
+#define BM_UARTAPP_INTR_TXIS (1 << 5)
+#define BM_UARTAPP_INTR_RXIS (1 << 4)
+#define BM_UARTAPP_INTR_CTSMIS (1 << 1)
+
+#define BM_UARTAPP_STAT_BUSY (1 << 29)
+#define BM_UARTAPP_STAT_CTS (1 << 28)
+#define BM_UARTAPP_STAT_TXFE (1 << 27)
+#define BM_UARTAPP_STAT_TXFF (1 << 25)
+#define BM_UARTAPP_STAT_RXFE (1 << 24)
+#define BM_UARTAPP_STAT_OERR (1 << 19)
+#define BM_UARTAPP_STAT_BERR (1 << 18)
+#define BM_UARTAPP_STAT_PERR (1 << 17)
+#define BM_UARTAPP_STAT_FERR (1 << 16)
+
+#define MXS_AUART_MAJOR 242
+#define MXS_AUART_RX_THRESHOLD 16
+
+static struct uart_driver auart_driver;
+
+struct mxs_auart_port {
+ struct uart_port port;
+
+ unsigned int flags;
+ unsigned int ctrl;
+
+ unsigned int irq;
+
+ struct clk *clk;
+ struct device *dev;
+};
+
+static void mxs_auart_stop_tx(struct uart_port *u);
+
+#define to_auart_port(u) container_of(u, struct mxs_auart_port, port)
+
+static inline void mxs_auart_tx_chars(struct mxs_auart_port *s)
+{
+ struct circ_buf *xmit = &s->port.state->xmit;
+
+ while (!(readl(s->port.membase + UARTAPP_STAT) &
+ BM_UARTAPP_STAT_TXFF)) {
+ if (s->port.x_char) {
+ writel(s->port.x_char,
+ s->port.membase + UARTAPP_DATA);
+ s->port.x_char = 0;
+ continue;
+ }
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
+ writel(xmit->buf[xmit->tail],
+ s->port.membase + UARTAPP_DATA);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&s->port);
+ } else
+ break;
+ }
+ if (uart_circ_empty(&(s->port.state->xmit)))
+ writel(BM_UARTAPP_INTR_TXIEN,
+ s->port.membase + UARTAPP_INTR_CLR);
+ else
+ writel(BM_UARTAPP_INTR_TXIEN,
+ s->port.membase + UARTAPP_INTR_SET);
+
+ if (uart_tx_stopped(&s->port))
+ mxs_auart_stop_tx(&s->port);
+}
+
+static inline unsigned int
+mxs_auart_rx_char(struct mxs_auart_port *s, unsigned int stat, u8 c)
+{
+ int flag;
+
+ flag = TTY_NORMAL;
+ if (stat & BM_UARTAPP_STAT_BERR) {
+ stat &= ~BM_UARTAPP_STAT_BERR;
+ s->port.icount.brk++;
+ if (uart_handle_break(&s->port))
+ return stat;
+ flag = TTY_BREAK;
+ } else if (stat & BM_UARTAPP_STAT_PERR) {
+ stat &= ~BM_UARTAPP_STAT_PERR;
+ s->port.icount.parity++;
+ flag = TTY_PARITY;
+ } else if (stat & BM_UARTAPP_STAT_FERR) {
+ stat &= ~BM_UARTAPP_STAT_FERR;
+ s->port.icount.frame++;
+ flag = TTY_FRAME;
+ }
+
+ if (stat & BM_UARTAPP_STAT_OERR)
+ s->port.icount.overrun++;
+
+ if (uart_handle_sysrq_char(&s->port, c))
+ return stat;
+
+ uart_insert_char(&s->port, stat, BM_UARTAPP_STAT_OERR, c, flag);
+
+ return stat;
+}
+
+static void mxs_auart_rx_chars(struct mxs_auart_port *s)
+{
+ u8 c;
+ struct tty_struct *tty = s->port.state->port.tty;
+ u32 stat = 0;
+
+ for (;;) {
+ stat = readl(s->port.membase + UARTAPP_STAT);
+ if (stat & BM_UARTAPP_STAT_RXFE)
+ break;
+ c = readl(s->port.membase + UARTAPP_DATA);
+ stat = mxs_auart_rx_char(s, stat, c);
+ writel(stat, s->port.membase + UARTAPP_STAT);
+ }
+
+ writel(stat, s->port.membase + UARTAPP_STAT);
+ tty_flip_buffer_push(tty);
+}
+
+static int mxs_auart_request_port(struct uart_port *u)
+{
+ return 0;
+}
+
+static int mxs_auart_verify_port(struct uart_port *u,
+ struct serial_struct *ser)
+{
+ if (u->type != PORT_UNKNOWN && u->type != PORT_IMX)
+ return -EINVAL;
+ return 0;
+}
+
+static void mxs_auart_config_port(struct uart_port *u, int flags)
+{
+}
+
+static const char *mxs_auart_type(struct uart_port *u)
+{
+ struct mxs_auart_port *s = to_auart_port(u);
+
+ return dev_name(s->dev);
+}
+
+static void mxs_auart_release_port(struct uart_port *u)
+{
+}
+
+static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
+{
+ struct mxs_auart_port *s = to_auart_port(u);
+
+ u32 ctrl = readl(u->membase + UARTAPP_CTRL2);
+
+ ctrl &= ~BM_UARTAPP_CTRL2_RTS;
+ if (mctrl & TIOCM_RTS)
+ ctrl |= BM_UARTAPP_CTRL2_RTS;
+ s->ctrl = mctrl;
+ writel(ctrl, u->membase + UARTAPP_CTRL2);
+}
+
+static u32 mxs_auart_get_mctrl(struct uart_port *u)
+{
+ struct mxs_auart_port *s = to_auart_port(u);
+ u32 stat = readl(u->membase + UARTAPP_STAT);
+ int ctrl2 = readl(u->membase + UARTAPP_CTRL2);
+ u32 mctrl = s->ctrl;
+
+ mctrl &= ~TIOCM_CTS;
+ if (stat & BM_UARTAPP_STAT_CTS)
+ mctrl |= TIOCM_CTS;
+
+ if (ctrl2 & BM_UARTAPP_CTRL2_RTS)
+ mctrl |= TIOCM_RTS;
+
+ return mctrl;
+}
+
+static void mxs_auart_settermios(struct uart_port *u,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ u32 bm, ctrl, ctrl2, div;
+ unsigned int cflag, baud;
+
+ cflag = termios->c_cflag;
+
+ ctrl = BM_UARTAPP_LINECTRL_FEN;
+ ctrl2 = readl(u->membase + UARTAPP_CTRL2);
+
+ /* byte size */
+ switch (cflag & CSIZE) {
+ case CS5:
+ bm = 0;
+ break;
+ case CS6:
+ bm = 1;
+ break;
+ case CS7:
+ bm = 2;
+ break;
+ case CS8:
+ bm = 3;
+ break;
+ default:
+ return;
+ }
+
+ ctrl |= BF_UARTAPP_LINECTRL_WLEN(bm);
+
+ /* parity */
+ if (cflag & PARENB) {
+ ctrl |= BM_UARTAPP_LINECTRL_PEN;
+ if ((cflag & PARODD) == 0)
+ ctrl |= BM_UARTAPP_LINECTRL_EPS;
+ }
+
+ /* figure out the stop bits requested */
+ if (cflag & CSTOPB)
+ ctrl |= BM_UARTAPP_LINECTRL_STP2;
+
+ /* figure out the hardware flow control settings */
+ if (cflag & CRTSCTS)
+ ctrl2 |= BM_UARTAPP_CTRL2_CTSEN;
+ else
+ ctrl2 &= ~BM_UARTAPP_CTRL2_CTSEN;
+
+ /* set baud rate */
+ baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
+ div = u->uartclk * 32 / baud;
+ ctrl |= BF_UARTAPP_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
+ ctrl |= BF_UARTAPP_LINECTRL_BAUD_DIVINT(div >> 6);
+
+ if ((cflag & CREAD) != 0)
+ ctrl2 |= BM_UARTAPP_CTRL2_RXE;
+
+ writel(ctrl, u->membase + UARTAPP_LINECTRL);
+ writel(ctrl2, u->membase + UARTAPP_CTRL2);
+}
+
+static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
+{
+ u32 istatus, istat;
+ struct mxs_auart_port *s = context;
+ u32 stat = readl(s->port.membase + UARTAPP_STAT);
+
+ istatus = istat = readl(s->port.membase + UARTAPP_INTR);
+
+ if (istat & BM_UARTAPP_INTR_CTSMIS) {
+ uart_handle_cts_change(&s->port, stat & BM_UARTAPP_STAT_CTS);
+ writel(BM_UARTAPP_INTR_CTSMIS,
+ s->port.membase + UARTAPP_INTR_CLR);
+ istat &= ~BM_UARTAPP_INTR_CTSMIS;
+ }
+
+ if (istat & (BM_UARTAPP_INTR_RTIS | BM_UARTAPP_INTR_RXIS)) {
+ mxs_auart_rx_chars(s);
+ istat &= ~(BM_UARTAPP_INTR_RTIS | BM_UARTAPP_INTR_RXIS);
+ }
+
+ if (istat & BM_UARTAPP_INTR_TXIS) {
+ mxs_auart_tx_chars(s);
+ istat &= ~BM_UARTAPP_INTR_TXIS;
+ }
+
+ writel(istatus & (BM_UARTAPP_INTR_RTIS
+ | BM_UARTAPP_INTR_TXIS
+ | BM_UARTAPP_INTR_RXIS
+ | BM_UARTAPP_INTR_CTSMIS),
+ s->port.membase + UARTAPP_INTR_CLR);
+
+ return IRQ_HANDLED;
+}
+
+static void mxs_auart_reset(struct uart_port *u)
+{
+ int i;
+ unsigned int reg;
+
+ writel(BM_UARTAPP_CTRL0_SFTRST,
+ u->membase + UARTAPP_CTRL0_CLR);
+
+ for (i = 0; i < 10000; i++) {
+ reg = readl(u->membase + UARTAPP_CTRL0);
+ if (!(reg & BM_UARTAPP_CTRL0_SFTRST))
+ break;
+ udelay(3);
+ }
+
+ writel(BM_UARTAPP_CTRL0_CLKGATE,
+ u->membase + UARTAPP_CTRL0_CLR);
+}
+
+static int mxs_auart_startup(struct uart_port *u)
+{
+ struct mxs_auart_port *s = to_auart_port(u);
+
+ clk_enable(s->clk);
+
+ writel(BM_UARTAPP_CTRL2_UARTEN,
+ s->port.membase + UARTAPP_CTRL2_SET);
+
+ writel(BM_UARTAPP_INTR_RXIEN | BM_UARTAPP_INTR_RTIEN,
+ s->port.membase + UARTAPP_INTR);
+
+ writel(BM_UARTAPP_INTR_CTSMIEN,
+ s->port.membase + UARTAPP_INTR_SET);
+
+ /*
+ * Enable fifo so all four bytes of a DMA word are written to
+ * output (otherwise, only the LSB is written, ie. 1 in 4 bytes)
+ */
+ writel(BM_UARTAPP_LINECTRL_FEN,
+ s->port.membase + UARTAPP_LINECTRL_SET);
+
+ return 0;
+}
+
+static void mxs_auart_shutdown(struct uart_port *u)
+{
+ struct mxs_auart_port *s = to_auart_port(u);
+
+ writel(BM_UARTAPP_CTRL0_SFTRST,
+ s->port.membase + UARTAPP_CTRL0_SET);
+
+ writel(BM_UARTAPP_INTR_RXIEN | BM_UARTAPP_INTR_RTIEN |
+ BM_UARTAPP_INTR_CTSMIEN,
+ s->port.membase + UARTAPP_INTR_CLR);
+
+ clk_disable(s->clk);
+}
+
+static unsigned int mxs_auart_tx_empty(struct uart_port *u)
+{
+ if (readl(u->membase + UARTAPP_STAT) & BM_UARTAPP_STAT_TXFE)
+ return TIOCSER_TEMT;
+ else
+ return 0;
+}
+
+static void mxs_auart_start_tx(struct uart_port *u)
+{
+ struct mxs_auart_port *s = to_auart_port(u);
+
+ /* enable transmitter */
+ writel(BM_UARTAPP_CTRL2_TXE, u->membase + UARTAPP_CTRL2_SET);
+
+ mxs_auart_tx_chars(s);
+}
+
+static void mxs_auart_stop_tx(struct uart_port *u)
+{
+ writel(BM_UARTAPP_CTRL2_TXE, u->membase + UARTAPP_CTRL2_CLR);
+}
+
+static void mxs_auart_stop_rx(struct uart_port *u)
+{
+ writel(BM_UARTAPP_CTRL2_RXE, u->membase + UARTAPP_CTRL2_CLR);
+}
+
+static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
+{
+ if (ctl)
+ writel(BM_UARTAPP_LINECTRL_BRK,
+ u->membase + UARTAPP_LINECTRL_SET);
+ else
+ writel(BM_UARTAPP_LINECTRL_BRK,
+ u->membase + UARTAPP_LINECTRL_CLR);
+}
+
+static void mxs_auart_enable_ms(struct uart_port *port)
+{
+ /* just empty */
+}
+
+static struct uart_ops mxs_auart_ops = {
+ .tx_empty = mxs_auart_tx_empty,
+ .start_tx = mxs_auart_start_tx,
+ .stop_tx = mxs_auart_stop_tx,
+ .stop_rx = mxs_auart_stop_rx,
+ .enable_ms = mxs_auart_enable_ms,
+ .break_ctl = mxs_auart_break_ctl,
+ .set_mctrl = mxs_auart_set_mctrl,
+ .get_mctrl = mxs_auart_get_mctrl,
+ .startup = mxs_auart_startup,
+ .shutdown = mxs_auart_shutdown,
+ .set_termios = mxs_auart_settermios,
+ .type = mxs_auart_type,
+ .release_port = mxs_auart_release_port,
+ .request_port = mxs_auart_request_port,
+ .config_port = mxs_auart_config_port,
+ .verify_port = mxs_auart_verify_port,
+};
+
+static struct mxs_auart_port *auart_port[MXS_AUART_PORTS];
+
+#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
+static void mxs_auart_console_putchar(struct uart_port *port, int ch)
+{
+ unsigned int status;
+
+ do {
+ status = readl(port->membase + UARTAPP_STAT);
+ } while (status & BM_UARTAPP_STAT_TXFF);
+ writel(ch, port->membase + UARTAPP_DATA);
+}
+
+static void
+auart_console_write(struct console *co, const char *str, unsigned int count)
+{
+ struct mxs_auart_port *s;
+ struct uart_port *port;
+ unsigned int status, old_cr;
+
+ if (co->index > MXS_AUART_PORTS || co->index < 0)
+ return;
+
+ s = auart_port[co->index];
+ port = &s->port;
+
+ clk_enable(s->clk);
+
+ /* First save the CR then disable the interrupts */
+ old_cr = readl(port->membase + UARTAPP_CTRL2);
+ writel(BM_UARTAPP_CTRL2_UARTEN | BM_UARTAPP_CTRL2_TXE,
+ port->membase + UARTAPP_CTRL2_SET);
+
+ uart_console_write(port, str, count, mxs_auart_console_putchar);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the TCR
+ */
+ do {
+ status = readl(port->membase + UARTAPP_STAT);
+ } while (status & BM_UARTAPP_STAT_BUSY);
+
+ writel(old_cr, port->membase + UARTAPP_CTRL2);
+
+ clk_disable(s->clk);
+}
+
+static void __init
+auart_console_get_options(struct uart_port *port, int *baud,
+ int *parity, int *bits)
+{
+ if (readl(port->membase + UARTAPP_CTRL2)
+ & BM_UARTAPP_CTRL2_UARTEN) {
+ unsigned int lcr_h, quot;
+ lcr_h = readl(port->membase + UARTAPP_LINECTRL);
+
+ *parity = 'n';
+ if (lcr_h & BM_UARTAPP_LINECTRL_PEN) {
+ if (lcr_h & BM_UARTAPP_LINECTRL_EPS)
+ *parity = 'e';
+ else
+ *parity = 'o';
+ }
+
+ if ((lcr_h & BM_UARTAPP_LINECTRL_WLEN)
+ == BF_UARTAPP_LINECTRL_WLEN(2))
+ *bits = 7;
+ else
+ *bits = 8;
+
+ quot = (((readl(port->membase + UARTAPP_LINECTRL)
+ & BM_UARTAPP_LINECTRL_BAUD_DIVINT))
+ >> (BP_UARTAPP_LINECTRL_BAUD_DIVINT - 6))
+ | (((readl(port->membase + UARTAPP_LINECTRL)
+ & BM_UARTAPP_LINECTRL_BAUD_DIVFRAC))
+ >> BP_UARTAPP_LINECTRL_BAUD_DIVFRAC);
+ if (quot == 0)
+ quot = 1;
+ *baud = (port->uartclk << 2) / quot;
+ }
+}
+
+static int __init
+auart_console_setup(struct console *co, char *options)
+{
+ struct mxs_auart_port *s;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+ int ret;
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ if (co->index == -1 || co->index >= ARRAY_SIZE(auart_port))
+ co->index = 0;
+ s = auart_port[co->index];
+ if (!s)
+ return -ENODEV;
+
+ clk_enable(s->clk);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else
+ auart_console_get_options(&s->port, &baud, &parity, &bits);
+
+ ret = uart_set_options(&s->port, co, baud, parity, bits, flow);
+
+ clk_disable(s->clk);
+
+ return ret;
+}
+
+static struct console auart_console = {
+ .name = "ttyAPP",
+ .write = auart_console_write,
+ .device = uart_console_device,
+ .setup = auart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &auart_driver,
+};
+#endif
+
+static struct uart_driver auart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "ttyAPP",
+ .dev_name = "ttyAPP",
+ .major = 0,
+ .minor = 0,
+ .nr = MXS_AUART_PORTS,
+#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
+ .cons = &auart_console,
+#endif
+};
+
+static int __devinit mxs_auart_probe(struct platform_device *pdev)
+{
+ struct mxs_auart_port *s;
+ u32 version;
+ int ret = 0;
+ struct resource *r;
+
+ s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
+ if (!s) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ s->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(s->clk)) {
+ ret = PTR_ERR(s->clk);
+ goto out_free;
+ }
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ ret = -ENXIO;
+ goto out_free_clk;
+ }
+
+ s->port.mapbase = r->start;
+ s->port.membase = ioremap(r->start, resource_size(r));
+ s->port.ops = &mxs_auart_ops;
+ s->port.iotype = UPIO_MEM;
+ s->port.line = pdev->id < 0 ? 0 : pdev->id;
+ s->port.fifosize = 16;
+ s->port.uartclk = clk_get_rate(s->clk);
+ s->port.type = PORT_IMX;
+ s->port.dev = s->dev = get_device(&pdev->dev);
+
+ s->flags = 0;
+ s->ctrl = 0;
+
+ s->irq = platform_get_irq(pdev, 0);
+ s->port.irq = s->irq;
+ ret = request_irq(s->irq, mxs_auart_irq_handle, 0, dev_name(&pdev->dev), s);
+ if (ret)
+ goto out_free_clk;
+
+ platform_set_drvdata(pdev, s);
+
+ auart_port[pdev->id] = s;
+
+ mxs_auart_reset(&s->port);
+
+ ret = uart_add_one_port(&auart_driver, &s->port);
+ if (ret)
+ goto out_free_irq;
+
+ version = readl(s->port.membase + UARTAPP_VERSION);
+ dev_info(&pdev->dev, "Found APPUART %d.%d.%d\n",
+ (version >> 24) & 0xff,
+ (version >> 16) & 0xff, version & 0xffff);
+
+ return 0;
+
+out_free_irq:
+ auart_port[pdev->id] = NULL;
+ free_irq(s->irq, s);
+out_free_clk:
+ clk_put(s->clk);
+out_free:
+ kfree(s);
+out:
+ return ret;
+}
+
+static int __devexit mxs_auart_remove(struct platform_device *pdev)
+{
+ struct mxs_auart_port *s = platform_get_drvdata(pdev);
+
+ uart_remove_one_port(&auart_driver, &s->port);
+
+ auart_port[pdev->id] = NULL;
+
+ clk_put(s->clk);
+ free_irq(s->irq, s);
+ kfree(s);
+
+ return 0;
+}
+
+static struct platform_driver mxs_auart_driver = {
+ .probe = mxs_auart_probe,
+ .remove = __devexit_p(mxs_auart_remove),
+ .driver = {
+ .name = "mxs-auart",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mxs_auart_init(void)
+{
+ int r;
+
+ r = uart_register_driver(&auart_driver);
+ if (r)
+ goto out;
+
+ r = platform_driver_register(&mxs_auart_driver);
+ if (r)
+ goto out_err;
+
+ return 0;
+out_err:
+ uart_unregister_driver(&auart_driver);
+out:
+ return r;
+}
+
+static void __exit mxs_auart_exit(void)
+{
+ platform_driver_unregister(&mxs_auart_driver);
+ uart_unregister_driver(&auart_driver);
+}
+
+module_init(mxs_auart_init);
+module_exit(mxs_auart_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Freescale MXS application uart driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
--
1.7.2.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28
2011-01-11 15:09 Add i.MX23/28 auart support Sascha Hauer
2011-01-11 15:09 ` [PATCH 1/2] serial: Add auart driver for i.MX23/28 Sascha Hauer
@ 2011-01-11 15:09 ` Sascha Hauer
2011-01-11 15:17 ` Uwe Kleine-König
2011-01-12 6:17 ` Shawn Guo
2011-01-12 5:31 ` Add i.MX23/28 auart support Shawn Guo
2 siblings, 2 replies; 12+ messages in thread
From: Sascha Hauer @ 2011-01-11 15:09 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-mxs/clock-mx28.c | 5 ++
arch/arm/mach-mxs/devices-mx28.h | 8 +++
arch/arm/mach-mxs/devices/Kconfig | 3 +
arch/arm/mach-mxs/devices/Makefile | 1 +
arch/arm/mach-mxs/devices/platform-auart.c | 54 +++++++++++++++++++++++
arch/arm/mach-mxs/include/mach/devices-common.h | 10 ++++
6 files changed, 81 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-mxs/devices/platform-auart.c
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index 74e2103..9f65934 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -603,6 +603,11 @@ _DEFINE_CLOCK(fec_clk, ENET, DISABLE, &hbus_clk);
static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("mxs-duart.0", NULL, uart_clk)
+ _REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
+ _REGISTER_CLOCK("mxs-auart.1", NULL, uart_clk)
+ _REGISTER_CLOCK("mxs-auart.2", NULL, uart_clk)
+ _REGISTER_CLOCK("mxs-auart.3", NULL, uart_clk)
+ _REGISTER_CLOCK("mxs-auart.4", NULL, uart_clk)
_REGISTER_CLOCK("fec.0", NULL, fec_clk)
_REGISTER_CLOCK("rtc", NULL, rtc_clk)
_REGISTER_CLOCK("pll2", NULL, pll2_clk)
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
index 00b736c..a0b70df 100644
--- a/arch/arm/mach-mxs/devices-mx28.h
+++ b/arch/arm/mach-mxs/devices-mx28.h
@@ -15,6 +15,14 @@ extern const struct mxs_duart_data mx28_duart_data __initconst;
#define mx28_add_duart() \
mxs_add_duart(&mx28_duart_data)
+extern const struct mxs_auart_data mx28_auart_data[] __initconst;
+#define mx28_add_auart(id) mxs_add_auart(&mx28_auart_data[id])
+#define mx28_add_auart0() mx28_add_auart(0)
+#define mx28_add_auart1() mx28_add_auart(1)
+#define mx28_add_auart2() mx28_add_auart(2)
+#define mx28_add_auart3() mx28_add_auart(3)
+#define mx28_add_auart4() mx28_add_auart(4)
+
extern const struct mxs_fec_data mx28_fec_data[] __initconst;
#define mx28_add_fec(id, pdata) \
mxs_add_fec(&mx28_fec_data[id], pdata)
diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
index a35a2dc..9d16540 100644
--- a/arch/arm/mach-mxs/devices/Kconfig
+++ b/arch/arm/mach-mxs/devices/Kconfig
@@ -1,5 +1,8 @@
config MXS_HAVE_PLATFORM_DUART
bool
+config MXS_HAVE_PLATFORM_AUART
+ bool
+
config MXS_HAVE_PLATFORM_FEC
bool
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index 4b5266a..b46d18d 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_MXS_HAVE_PLATFORM_DUART) += platform-duart.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
diff --git a/arch/arm/mach-mxs/devices/platform-auart.c b/arch/arm/mach-mxs/devices/platform-auart.c
new file mode 100644
index 0000000..d5e6cb2
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-auart.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/sizes.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_auart_data_entry_single(soc, _id) \
+ { \
+ .id = _id, \
+ .iobase = soc ## _AUART ## _id ## _BASE_ADDR, \
+ .irq = soc ## _INT_AUART ## _id, \
+ }
+
+#define mxs_auart_data_entry(soc, _id) \
+ [_id] = mxs_auart_data_entry_single(soc, _id)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_auart_data mx28_auart_data[] __initconst = {
+#define mx28_auart_data_entry(_id) \
+ mxs_auart_data_entry(MX28, _id)
+ mx28_auart_data_entry(0),
+ mx28_auart_data_entry(1),
+ mx28_auart_data_entry(2),
+ mx28_auart_data_entry(3),
+ mx28_auart_data_entry(4),
+};
+#endif
+
+struct platform_device *__init mxs_add_auart(
+ const struct mxs_auart_data *data)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return mxs_add_platform_device_dmamask("mxs-auart", data->id,
+ res, ARRAY_SIZE(res), NULL, 0,
+ DMA_BIT_MASK(32));
+}
+
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index 3da48d4..b8ab332 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -33,6 +33,16 @@ struct mxs_duart_data {
struct platform_device *__init mxs_add_duart(
const struct mxs_duart_data *data);
+/* auart */
+struct mxs_auart_data {
+ int id;
+ resource_size_t iobase;
+ resource_size_t iosize;
+ resource_size_t irq;
+};
+struct platform_device *__init mxs_add_auart(
+ const struct mxs_auart_data *data);
+
/* fec */
#include <linux/fec.h>
struct mxs_fec_data {
--
1.7.2.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28
2011-01-11 15:09 ` [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28 Sascha Hauer
@ 2011-01-11 15:17 ` Uwe Kleine-König
2011-01-11 15:26 ` Sascha Hauer
2011-01-12 5:06 ` Shawn Guo
2011-01-12 6:17 ` Shawn Guo
1 sibling, 2 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2011-01-11 15:17 UTC (permalink / raw)
To: linux-arm-kernel
Hello Sascha,
On Tue, Jan 11, 2011 at 04:09:05PM +0100, Sascha Hauer wrote:
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> arch/arm/mach-mxs/clock-mx28.c | 5 ++
> arch/arm/mach-mxs/devices-mx28.h | 8 +++
> arch/arm/mach-mxs/devices/Kconfig | 3 +
> arch/arm/mach-mxs/devices/Makefile | 1 +
> arch/arm/mach-mxs/devices/platform-auart.c | 54 +++++++++++++++++++++++
> arch/arm/mach-mxs/include/mach/devices-common.h | 10 ++++
> 6 files changed, 81 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-mxs/devices/platform-auart.c
>
> diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
> index 74e2103..9f65934 100644
> --- a/arch/arm/mach-mxs/clock-mx28.c
> +++ b/arch/arm/mach-mxs/clock-mx28.c
> @@ -603,6 +603,11 @@ _DEFINE_CLOCK(fec_clk, ENET, DISABLE, &hbus_clk);
>
> static struct clk_lookup lookups[] = {
> _REGISTER_CLOCK("mxs-duart.0", NULL, uart_clk)
> + _REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
> + _REGISTER_CLOCK("mxs-auart.1", NULL, uart_clk)
> + _REGISTER_CLOCK("mxs-auart.2", NULL, uart_clk)
> + _REGISTER_CLOCK("mxs-auart.3", NULL, uart_clk)
> + _REGISTER_CLOCK("mxs-auart.4", NULL, uart_clk)
> _REGISTER_CLOCK("fec.0", NULL, fec_clk)
> _REGISTER_CLOCK("rtc", NULL, rtc_clk)
> _REGISTER_CLOCK("pll2", NULL, pll2_clk)
> diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
> index 00b736c..a0b70df 100644
> --- a/arch/arm/mach-mxs/devices-mx28.h
> +++ b/arch/arm/mach-mxs/devices-mx28.h
> @@ -15,6 +15,14 @@ extern const struct mxs_duart_data mx28_duart_data __initconst;
> #define mx28_add_duart() \
> mxs_add_duart(&mx28_duart_data)
>
> +extern const struct mxs_auart_data mx28_auart_data[] __initconst;
> +#define mx28_add_auart(id) mxs_add_auart(&mx28_auart_data[id])
> +#define mx28_add_auart0() mx28_add_auart(0)
> +#define mx28_add_auart1() mx28_add_auart(1)
> +#define mx28_add_auart2() mx28_add_auart(2)
> +#define mx28_add_auart3() mx28_add_auart(3)
> +#define mx28_add_auart4() mx28_add_auart(4)
I wouldn't add the mx28_add_auartX macros, only mx28_add_auart. The
former are a relict of the time when we didn't use an array to get the
data from.
> +
> extern const struct mxs_fec_data mx28_fec_data[] __initconst;
> #define mx28_add_fec(id, pdata) \
> mxs_add_fec(&mx28_fec_data[id], pdata)
> diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
> index a35a2dc..9d16540 100644
> --- a/arch/arm/mach-mxs/devices/Kconfig
> +++ b/arch/arm/mach-mxs/devices/Kconfig
> @@ -1,5 +1,8 @@
> config MXS_HAVE_PLATFORM_DUART
> bool
>
> +config MXS_HAVE_PLATFORM_AUART
> + bool
> +
This doesn't happen to be an amba device, too?
> config MXS_HAVE_PLATFORM_FEC
> bool
> diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
> index 4b5266a..b46d18d 100644
> --- a/arch/arm/mach-mxs/devices/Makefile
> +++ b/arch/arm/mach-mxs/devices/Makefile
> @@ -1,2 +1,3 @@
> obj-$(CONFIG_MXS_HAVE_PLATFORM_DUART) += platform-duart.o
> +obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
> obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
this conflicts with the "make duart use amba-pl011 driver" patch.
Also can you please keep the file sorted alphabetically?
> diff --git a/arch/arm/mach-mxs/devices/platform-auart.c b/arch/arm/mach-mxs/devices/platform-auart.c
> new file mode 100644
> index 0000000..d5e6cb2
> --- /dev/null
> +++ b/arch/arm/mach-mxs/devices/platform-auart.c
> @@ -0,0 +1,54 @@
> +/*
> + * Copyright (C) 2010 Pengutronix
> + * Sascha Hauer <s.hauer@pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or modify it under
> + * the terms of the GNU General Public License version 2 as published by the
> + * Free Software Foundation.
> + */
> +#include <asm/sizes.h>
> +#include <mach/mx28.h>
> +#include <mach/devices-common.h>
> +
> +#define mxs_auart_data_entry_single(soc, _id) \
> + { \
> + .id = _id, \
> + .iobase = soc ## _AUART ## _id ## _BASE_ADDR, \
> + .irq = soc ## _INT_AUART ## _id, \
> + }
> +
> +#define mxs_auart_data_entry(soc, _id) \
> + [_id] = mxs_auart_data_entry_single(soc, _id)
> +
> +#ifdef CONFIG_SOC_IMX28
> +const struct mxs_auart_data mx28_auart_data[] __initconst = {
> +#define mx28_auart_data_entry(_id) \
> + mxs_auart_data_entry(MX28, _id)
> + mx28_auart_data_entry(0),
> + mx28_auart_data_entry(1),
> + mx28_auart_data_entry(2),
> + mx28_auart_data_entry(3),
> + mx28_auart_data_entry(4),
> +};
> +#endif
> +
> +struct platform_device *__init mxs_add_auart(
> + const struct mxs_auart_data *data)
> +{
> + struct resource res[] = {
> + {
> + .start = data->iobase,
> + .end = data->iobase + SZ_4K - 1,
> + .flags = IORESOURCE_MEM,
> + }, {
> + .start = data->irq,
> + .end = data->irq,
> + .flags = IORESOURCE_IRQ,
> + },
> + };
> +
> + return mxs_add_platform_device_dmamask("mxs-auart", data->id,
> + res, ARRAY_SIZE(res), NULL, 0,
> + DMA_BIT_MASK(32));
> +}
> +
> diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
> index 3da48d4..b8ab332 100644
> --- a/arch/arm/mach-mxs/include/mach/devices-common.h
> +++ b/arch/arm/mach-mxs/include/mach/devices-common.h
> @@ -33,6 +33,16 @@ struct mxs_duart_data {
> struct platform_device *__init mxs_add_duart(
> const struct mxs_duart_data *data);
>
> +/* auart */
> +struct mxs_auart_data {
> + int id;
> + resource_size_t iobase;
> + resource_size_t iosize;
> + resource_size_t irq;
> +};
> +struct platform_device *__init mxs_add_auart(
> + const struct mxs_auart_data *data);
> +
> /* fec */
> #include <linux/fec.h>
> struct mxs_fec_data {
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28
2011-01-11 15:17 ` Uwe Kleine-König
@ 2011-01-11 15:26 ` Sascha Hauer
2011-01-12 5:06 ` Shawn Guo
1 sibling, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2011-01-11 15:26 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jan 11, 2011 at 04:17:25PM +0100, Uwe Kleine-K?nig wrote:
> >
> > +extern const struct mxs_auart_data mx28_auart_data[] __initconst;
> > +#define mx28_add_auart(id) mxs_add_auart(&mx28_auart_data[id])
> > +#define mx28_add_auart0() mx28_add_auart(0)
> > +#define mx28_add_auart1() mx28_add_auart(1)
> > +#define mx28_add_auart2() mx28_add_auart(2)
> > +#define mx28_add_auart3() mx28_add_auart(3)
> > +#define mx28_add_auart4() mx28_add_auart(4)
> I wouldn't add the mx28_add_auartX macros, only mx28_add_auart. The
> former are a relict of the time when we didn't use an array to get the
> data from.
With pleasure.
>
> > +
> > extern const struct mxs_fec_data mx28_fec_data[] __initconst;
> > #define mx28_add_fec(id, pdata) \
> > mxs_add_fec(&mx28_fec_data[id], pdata)
> > diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
> > index a35a2dc..9d16540 100644
> > --- a/arch/arm/mach-mxs/devices/Kconfig
> > +++ b/arch/arm/mach-mxs/devices/Kconfig
> > @@ -1,5 +1,8 @@
> > config MXS_HAVE_PLATFORM_DUART
> > bool
> >
> > +config MXS_HAVE_PLATFORM_AUART
> > + bool
> > +
> This doesn't happen to be an amba device, too?
no
>
> > config MXS_HAVE_PLATFORM_FEC
> > bool
> > diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
> > index 4b5266a..b46d18d 100644
> > --- a/arch/arm/mach-mxs/devices/Makefile
> > +++ b/arch/arm/mach-mxs/devices/Makefile
> > @@ -1,2 +1,3 @@
> > obj-$(CONFIG_MXS_HAVE_PLATFORM_DUART) += platform-duart.o
> > +obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
> > obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
> this conflicts with the "make duart use amba-pl011 driver" patch.
Nah, let the maintainer deal with it...
> Also can you please keep the file sorted alphabetically?
ok
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] serial: Add auart driver for i.MX23/28
2011-01-11 15:09 ` [PATCH 1/2] serial: Add auart driver for i.MX23/28 Sascha Hauer
@ 2011-01-11 16:05 ` Russell King - ARM Linux
2011-01-11 17:10 ` Wolfram Sang
2011-01-12 5:39 ` Shawn Guo
2 siblings, 0 replies; 12+ messages in thread
From: Russell King - ARM Linux @ 2011-01-11 16:05 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jan 11, 2011 at 04:09:04PM +0100, Sascha Hauer wrote:
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
So you don't handle any of the termios settings at all in this driver
such as ignoring parity, reading parity, framing errors, etc.
There's a reason that you're provided with read_status_mask and
ignore_status_mask.
If you don't intend to support those termios modes, ensure that you
force the termios structure to reflect what you actually do implement
so that userspace can detect the capabilities of your driver.
IOW, iflags INPCK, BRKINT, PARMRK, IGNPAR, IGNBRK and cflag CREAD.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] serial: Add auart driver for i.MX23/28
2011-01-11 15:09 ` [PATCH 1/2] serial: Add auart driver for i.MX23/28 Sascha Hauer
2011-01-11 16:05 ` Russell King - ARM Linux
@ 2011-01-11 17:10 ` Wolfram Sang
2011-01-11 17:57 ` Sascha Hauer
2011-01-12 5:39 ` Shawn Guo
2 siblings, 1 reply; 12+ messages in thread
From: Wolfram Sang @ 2011-01-11 17:10 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jan 11, 2011 at 04:09:04PM +0100, Sascha Hauer wrote:
[...]
> +#include <asm/cacheflush.h>
> +#include <mach/mx28.h>
What about MX23 and STMP3xxx?
> +
> +#define MXS_AUART_PORTS 5
MX23 has just 2. We should better adapt to that depending on the type?
Bye,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110111/e2e6b8c3/attachment.sig>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] serial: Add auart driver for i.MX23/28
2011-01-11 17:10 ` Wolfram Sang
@ 2011-01-11 17:57 ` Sascha Hauer
0 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2011-01-11 17:57 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jan 11, 2011 at 06:10:50PM +0100, Wolfram Sang wrote:
> On Tue, Jan 11, 2011 at 04:09:04PM +0100, Sascha Hauer wrote:
> [...]
> > +#include <asm/cacheflush.h>
> > +#include <mach/mx28.h>
>
> What about MX23 and STMP3xxx?
This include is not needed, will remove. Instead we need linux/io.h.
>
> > +
> > +#define MXS_AUART_PORTS 5
>
> MX23 has just 2. We should better adapt to that depending on the type?
This is just the maximum number the driver supports, it's safe to keep
it as is.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28
2011-01-11 15:17 ` Uwe Kleine-König
2011-01-11 15:26 ` Sascha Hauer
@ 2011-01-12 5:06 ` Shawn Guo
1 sibling, 0 replies; 12+ messages in thread
From: Shawn Guo @ 2011-01-12 5:06 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jan 11, 2011 at 04:17:25PM +0100, Uwe Kleine-K?nig wrote:
> Hello Sascha,
>
> On Tue, Jan 11, 2011 at 04:09:05PM +0100, Sascha Hauer wrote:
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> > arch/arm/mach-mxs/clock-mx28.c | 5 ++
> > arch/arm/mach-mxs/devices-mx28.h | 8 +++
> > arch/arm/mach-mxs/devices/Kconfig | 3 +
> > arch/arm/mach-mxs/devices/Makefile | 1 +
> > arch/arm/mach-mxs/devices/platform-auart.c | 54 +++++++++++++++++++++++
> > arch/arm/mach-mxs/include/mach/devices-common.h | 10 ++++
> > 6 files changed, 81 insertions(+), 0 deletions(-)
> > create mode 100644 arch/arm/mach-mxs/devices/platform-auart.c
> >
> > diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
> > index 74e2103..9f65934 100644
> > --- a/arch/arm/mach-mxs/clock-mx28.c
> > +++ b/arch/arm/mach-mxs/clock-mx28.c
> > @@ -603,6 +603,11 @@ _DEFINE_CLOCK(fec_clk, ENET, DISABLE, &hbus_clk);
> >
> > static struct clk_lookup lookups[] = {
> > _REGISTER_CLOCK("mxs-duart.0", NULL, uart_clk)
> > + _REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
> > + _REGISTER_CLOCK("mxs-auart.1", NULL, uart_clk)
> > + _REGISTER_CLOCK("mxs-auart.2", NULL, uart_clk)
> > + _REGISTER_CLOCK("mxs-auart.3", NULL, uart_clk)
> > + _REGISTER_CLOCK("mxs-auart.4", NULL, uart_clk)
> > _REGISTER_CLOCK("fec.0", NULL, fec_clk)
> > _REGISTER_CLOCK("rtc", NULL, rtc_clk)
> > _REGISTER_CLOCK("pll2", NULL, pll2_clk)
> > diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
> > index 00b736c..a0b70df 100644
> > --- a/arch/arm/mach-mxs/devices-mx28.h
> > +++ b/arch/arm/mach-mxs/devices-mx28.h
> > @@ -15,6 +15,14 @@ extern const struct mxs_duart_data mx28_duart_data __initconst;
> > #define mx28_add_duart() \
> > mxs_add_duart(&mx28_duart_data)
> >
> > +extern const struct mxs_auart_data mx28_auart_data[] __initconst;
> > +#define mx28_add_auart(id) mxs_add_auart(&mx28_auart_data[id])
> > +#define mx28_add_auart0() mx28_add_auart(0)
> > +#define mx28_add_auart1() mx28_add_auart(1)
> > +#define mx28_add_auart2() mx28_add_auart(2)
> > +#define mx28_add_auart3() mx28_add_auart(3)
> > +#define mx28_add_auart4() mx28_add_auart(4)
> I wouldn't add the mx28_add_auartX macros, only mx28_add_auart. The
> former are a relict of the time when we didn't use an array to get the
> data from.
>
> > +
> > extern const struct mxs_fec_data mx28_fec_data[] __initconst;
> > #define mx28_add_fec(id, pdata) \
> > mxs_add_fec(&mx28_fec_data[id], pdata)
> > diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
> > index a35a2dc..9d16540 100644
> > --- a/arch/arm/mach-mxs/devices/Kconfig
> > +++ b/arch/arm/mach-mxs/devices/Kconfig
> > @@ -1,5 +1,8 @@
> > config MXS_HAVE_PLATFORM_DUART
> > bool
> >
> > +config MXS_HAVE_PLATFORM_AUART
> > + bool
> > +
> This doesn't happen to be an amba device, too?
>
> > config MXS_HAVE_PLATFORM_FEC
> > bool
> > diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
> > index 4b5266a..b46d18d 100644
> > --- a/arch/arm/mach-mxs/devices/Makefile
> > +++ b/arch/arm/mach-mxs/devices/Makefile
> > @@ -1,2 +1,3 @@
> > obj-$(CONFIG_MXS_HAVE_PLATFORM_DUART) += platform-duart.o
> > +obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
> > obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
> this conflicts with the "make duart use amba-pl011 driver" patch.
May I know the reason that the patch is still pending for being
merged? DEBUG_SPINLOCK_SLEEP warning?
[...]
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 12+ messages in thread
* Add i.MX23/28 auart support
2011-01-11 15:09 Add i.MX23/28 auart support Sascha Hauer
2011-01-11 15:09 ` [PATCH 1/2] serial: Add auart driver for i.MX23/28 Sascha Hauer
2011-01-11 15:09 ` [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28 Sascha Hauer
@ 2011-01-12 5:31 ` Shawn Guo
2 siblings, 0 replies; 12+ messages in thread
From: Shawn Guo @ 2011-01-12 5:31 UTC (permalink / raw)
To: linux-arm-kernel
Hi Sascha,
On Tue, Jan 11, 2011 at 04:09:03PM +0100, Sascha Hauer wrote:
> The following series adds support for the auart found on i.MX23/28
>
> Sascha Hauer (2):
> serial: Add auart driver for i.MX23/28
> ARM i.MXS: Add auart platform support for i.MX28
>
> arch/arm/mach-mxs/clock-mx28.c | 5 +
> arch/arm/mach-mxs/devices-mx28.h | 8 +
> arch/arm/mach-mxs/devices/Kconfig | 3 +
> arch/arm/mach-mxs/devices/Makefile | 1 +
> arch/arm/mach-mxs/devices/platform-auart.c | 54 ++
> arch/arm/mach-mxs/include/mach/devices-common.h | 10 +
> drivers/serial/Kconfig | 15 +
> drivers/serial/Makefile | 1 +
> drivers/serial/mxs-auart.c | 763 +++++++++++++++++++++++
> 9 files changed, 860 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-mxs/devices/platform-auart.c
> create mode 100644 drivers/serial/mxs-auart.c
>
>
I just fetched the branch imx-for-2.6.38 and tried to apply the patch
set on it, but failed. What commit should I apply against?
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] serial: Add auart driver for i.MX23/28
2011-01-11 15:09 ` [PATCH 1/2] serial: Add auart driver for i.MX23/28 Sascha Hauer
2011-01-11 16:05 ` Russell King - ARM Linux
2011-01-11 17:10 ` Wolfram Sang
@ 2011-01-12 5:39 ` Shawn Guo
2 siblings, 0 replies; 12+ messages in thread
From: Shawn Guo @ 2011-01-12 5:39 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jan 11, 2011 at 04:09:04PM +0100, Sascha Hauer wrote:
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> drivers/serial/Kconfig | 15 +
> drivers/serial/Makefile | 1 +
> drivers/serial/mxs-auart.c | 763 ++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 779 insertions(+), 0 deletions(-)
> create mode 100644 drivers/serial/mxs-auart.c
>
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index ec3c214..de37fe5 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -1657,4 +1657,19 @@ 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.
> +
> +config SERIAL_MXS_AUART
> + depends on ARCH_MXS
> + tristate "i.MXS AUART support"
Can we not use i.MXS? We use i.MX23 and i.MX28 for SoC, MXS for the
arch, but never i.MXS.
> + select SERIAL_CORE
> + help
> + This driver supports the i.MX AUART port.
i.MX is being used to break the naming consistency here.
> +
> +config SERIAL_MXS_AUART_CONSOLE
> + bool "i.MXS AUART console support"
> + depends on SERIAL_MXS_AUART=y
> + select SERIAL_CORE_CONSOLE
> + help
> + Enable a i.MXS AUART port to be the system console.
> +
> endmenu
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index 8ea92e9..c855071 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -92,3 +92,4 @@ 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
> +obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
> diff --git a/drivers/serial/mxs-auart.c b/drivers/serial/mxs-auart.c
> new file mode 100644
> index 0000000..dd437ea
> --- /dev/null
> +++ b/drivers/serial/mxs-auart.c
> @@ -0,0 +1,763 @@
> +/*
> + * Application UART driver for hardware found on
> + * Sigmatel STMP37XX/STMP378X and
> + * Freescale i.MX23/28
> + *
> + * Author: dmitry pervushin <dimka@embeddedalley.com>
> + *
> + * Copyright 2010 Sascha Hauer <s.hauer@pengutronix.de>
2011?
> + * 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/device.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 <asm/cacheflush.h>
> +#include <mach/mx28.h>
> +
> +#define MXS_AUART_PORTS 5
> +
> +#define UARTAPP_CTRL0 0x00000000
> +#define UARTAPP_CTRL0_SET 0x00000004
> +#define UARTAPP_CTRL0_CLR 0x00000008
> +#define UARTAPP_CTRL0_TOG 0x0000000c
> +#define UARTAPP_CTRL1 0x00000010
> +#define UARTAPP_CTRL1_SET 0x00000014
> +#define UARTAPP_CTRL1_CLR 0x00000018
> +#define UARTAPP_CTRL1_TOG 0x0000001c
> +#define UARTAPP_CTRL2 0x00000020
> +#define UARTAPP_CTRL2_SET 0x00000024
> +#define UARTAPP_CTRL2_CLR 0x00000028
> +#define UARTAPP_CTRL2_TOG 0x0000002c
> +#define UARTAPP_LINECTRL 0x00000030
> +#define UARTAPP_LINECTRL_SET 0x00000034
> +#define UARTAPP_LINECTRL_CLR 0x00000038
> +#define UARTAPP_LINECTRL_TOG 0x0000003c
> +#define UARTAPP_LINECTRL2 0x00000040
> +#define UARTAPP_LINECTRL2_SET 0x00000044
> +#define UARTAPP_LINECTRL2_CLR 0x00000048
> +#define UARTAPP_LINECTRL2_TOG 0x0000004c
> +#define UARTAPP_INTR 0x00000050
> +#define UARTAPP_INTR_SET 0x00000054
> +#define UARTAPP_INTR_CLR 0x00000058
> +#define UARTAPP_INTR_TOG 0x0000005c
> +#define UARTAPP_DATA 0x00000060
> +#define UARTAPP_STAT 0x00000070
> +#define UARTAPP_DEBUG 0x00000080
> +#define UARTAPP_VERSION 0x00000090
> +#define UARTAPP_AUTOBAUD 0x000000a0
> +
> +#define BM_UARTAPP_CTRL0_SFTRST (1 << 31)
> +#define BM_UARTAPP_CTRL0_CLKGATE (1 << 30)
> +
> +
> +#define BM_UARTAPP_CTRL2_CTSEN (1 << 15)
> +#define BM_UARTAPP_CTRL2_RTS (1 << 11)
> +#define BM_UARTAPP_CTRL2_RXE (1 << 9)
> +#define BM_UARTAPP_CTRL2_TXE (1 << 8)
> +#define BM_UARTAPP_CTRL2_UARTEN (1 << 0)
> +
> +#define BP_UARTAPP_LINECTRL_BAUD_DIVINT 16
> +#define BM_UARTAPP_LINECTRL_BAUD_DIVINT 0xffff0000
> +#define BF_UARTAPP_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16)
> +#define BP_UARTAPP_LINECTRL_BAUD_DIVFRAC 8
> +#define BM_UARTAPP_LINECTRL_BAUD_DIVFRAC 0x00003f00
> +#define BF_UARTAPP_LINECTRL_BAUD_DIVFRAC(v) (((v) & 0x3f) << 8)
> +#define BP_UARTAPP_LINECTRL_WLEN 5
> +#define BM_UARTAPP_LINECTRL_WLEN 0x00000060
> +#define BF_UARTAPP_LINECTRL_WLEN(v) (((v) & 0x3) << 5)
> +#define BM_UARTAPP_LINECTRL_FEN (1 << 4)
> +#define BM_UARTAPP_LINECTRL_STP2 (1 << 3)
> +#define BM_UARTAPP_LINECTRL_EPS (1 << 2)
> +#define BM_UARTAPP_LINECTRL_PEN (1 << 1)
> +#define BM_UARTAPP_LINECTRL_BRK (1 << 0)
> +
> +#define BM_UARTAPP_INTR_RTIEN (1 << 22)
> +#define BM_UARTAPP_INTR_TXIEN (1 << 21)
> +#define BM_UARTAPP_INTR_RXIEN (1 << 20)
> +#define BM_UARTAPP_INTR_CTSMIEN (1 << 17)
> +#define BM_UARTAPP_INTR_RTIS (1 << 6)
> +#define BM_UARTAPP_INTR_TXIS (1 << 5)
> +#define BM_UARTAPP_INTR_RXIS (1 << 4)
> +#define BM_UARTAPP_INTR_CTSMIS (1 << 1)
> +
> +#define BM_UARTAPP_STAT_BUSY (1 << 29)
> +#define BM_UARTAPP_STAT_CTS (1 << 28)
> +#define BM_UARTAPP_STAT_TXFE (1 << 27)
> +#define BM_UARTAPP_STAT_TXFF (1 << 25)
> +#define BM_UARTAPP_STAT_RXFE (1 << 24)
> +#define BM_UARTAPP_STAT_OERR (1 << 19)
> +#define BM_UARTAPP_STAT_BERR (1 << 18)
> +#define BM_UARTAPP_STAT_PERR (1 << 17)
> +#define BM_UARTAPP_STAT_FERR (1 << 16)
> +
> +#define MXS_AUART_MAJOR 242
> +#define MXS_AUART_RX_THRESHOLD 16
> +
> +static struct uart_driver auart_driver;
> +
> +struct mxs_auart_port {
> + struct uart_port port;
> +
> + unsigned int flags;
> + unsigned int ctrl;
> +
> + unsigned int irq;
> +
> + struct clk *clk;
> + struct device *dev;
> +};
> +
> +static void mxs_auart_stop_tx(struct uart_port *u);
> +
> +#define to_auart_port(u) container_of(u, struct mxs_auart_port, port)
> +
> +static inline void mxs_auart_tx_chars(struct mxs_auart_port *s)
> +{
> + struct circ_buf *xmit = &s->port.state->xmit;
> +
> + while (!(readl(s->port.membase + UARTAPP_STAT) &
> + BM_UARTAPP_STAT_TXFF)) {
> + if (s->port.x_char) {
> + writel(s->port.x_char,
> + s->port.membase + UARTAPP_DATA);
> + s->port.x_char = 0;
> + continue;
> + }
> + if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
> + writel(xmit->buf[xmit->tail],
> + s->port.membase + UARTAPP_DATA);
> + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
> + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
> + uart_write_wakeup(&s->port);
> + } else
> + break;
> + }
> + if (uart_circ_empty(&(s->port.state->xmit)))
> + writel(BM_UARTAPP_INTR_TXIEN,
> + s->port.membase + UARTAPP_INTR_CLR);
> + else
> + writel(BM_UARTAPP_INTR_TXIEN,
> + s->port.membase + UARTAPP_INTR_SET);
> +
> + if (uart_tx_stopped(&s->port))
> + mxs_auart_stop_tx(&s->port);
> +}
> +
> +static inline unsigned int
> +mxs_auart_rx_char(struct mxs_auart_port *s, unsigned int stat, u8 c)
> +{
> + int flag;
> +
> + flag = TTY_NORMAL;
> + if (stat & BM_UARTAPP_STAT_BERR) {
> + stat &= ~BM_UARTAPP_STAT_BERR;
> + s->port.icount.brk++;
> + if (uart_handle_break(&s->port))
> + return stat;
> + flag = TTY_BREAK;
> + } else if (stat & BM_UARTAPP_STAT_PERR) {
> + stat &= ~BM_UARTAPP_STAT_PERR;
> + s->port.icount.parity++;
> + flag = TTY_PARITY;
> + } else if (stat & BM_UARTAPP_STAT_FERR) {
> + stat &= ~BM_UARTAPP_STAT_FERR;
> + s->port.icount.frame++;
> + flag = TTY_FRAME;
> + }
> +
> + if (stat & BM_UARTAPP_STAT_OERR)
> + s->port.icount.overrun++;
> +
> + if (uart_handle_sysrq_char(&s->port, c))
> + return stat;
> +
> + uart_insert_char(&s->port, stat, BM_UARTAPP_STAT_OERR, c, flag);
> +
> + return stat;
> +}
> +
> +static void mxs_auart_rx_chars(struct mxs_auart_port *s)
> +{
> + u8 c;
> + struct tty_struct *tty = s->port.state->port.tty;
> + u32 stat = 0;
> +
> + for (;;) {
> + stat = readl(s->port.membase + UARTAPP_STAT);
> + if (stat & BM_UARTAPP_STAT_RXFE)
> + break;
> + c = readl(s->port.membase + UARTAPP_DATA);
> + stat = mxs_auart_rx_char(s, stat, c);
> + writel(stat, s->port.membase + UARTAPP_STAT);
> + }
> +
> + writel(stat, s->port.membase + UARTAPP_STAT);
> + tty_flip_buffer_push(tty);
> +}
> +
> +static int mxs_auart_request_port(struct uart_port *u)
> +{
> + return 0;
> +}
> +
> +static int mxs_auart_verify_port(struct uart_port *u,
> + struct serial_struct *ser)
> +{
> + if (u->type != PORT_UNKNOWN && u->type != PORT_IMX)
> + return -EINVAL;
> + return 0;
> +}
> +
> +static void mxs_auart_config_port(struct uart_port *u, int flags)
> +{
> +}
> +
> +static const char *mxs_auart_type(struct uart_port *u)
> +{
> + struct mxs_auart_port *s = to_auart_port(u);
> +
> + return dev_name(s->dev);
> +}
> +
> +static void mxs_auart_release_port(struct uart_port *u)
> +{
> +}
> +
> +static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
> +{
> + struct mxs_auart_port *s = to_auart_port(u);
> +
> + u32 ctrl = readl(u->membase + UARTAPP_CTRL2);
> +
> + ctrl &= ~BM_UARTAPP_CTRL2_RTS;
> + if (mctrl & TIOCM_RTS)
> + ctrl |= BM_UARTAPP_CTRL2_RTS;
> + s->ctrl = mctrl;
> + writel(ctrl, u->membase + UARTAPP_CTRL2);
> +}
> +
> +static u32 mxs_auart_get_mctrl(struct uart_port *u)
> +{
> + struct mxs_auart_port *s = to_auart_port(u);
> + u32 stat = readl(u->membase + UARTAPP_STAT);
> + int ctrl2 = readl(u->membase + UARTAPP_CTRL2);
> + u32 mctrl = s->ctrl;
> +
> + mctrl &= ~TIOCM_CTS;
> + if (stat & BM_UARTAPP_STAT_CTS)
> + mctrl |= TIOCM_CTS;
> +
> + if (ctrl2 & BM_UARTAPP_CTRL2_RTS)
> + mctrl |= TIOCM_RTS;
> +
> + return mctrl;
> +}
> +
> +static void mxs_auart_settermios(struct uart_port *u,
> + struct ktermios *termios,
> + struct ktermios *old)
> +{
> + u32 bm, ctrl, ctrl2, div;
> + unsigned int cflag, baud;
> +
> + cflag = termios->c_cflag;
> +
> + ctrl = BM_UARTAPP_LINECTRL_FEN;
> + ctrl2 = readl(u->membase + UARTAPP_CTRL2);
> +
> + /* byte size */
> + switch (cflag & CSIZE) {
> + case CS5:
> + bm = 0;
> + break;
> + case CS6:
> + bm = 1;
> + break;
> + case CS7:
> + bm = 2;
> + break;
> + case CS8:
> + bm = 3;
> + break;
> + default:
> + return;
> + }
> +
> + ctrl |= BF_UARTAPP_LINECTRL_WLEN(bm);
> +
> + /* parity */
> + if (cflag & PARENB) {
> + ctrl |= BM_UARTAPP_LINECTRL_PEN;
> + if ((cflag & PARODD) == 0)
> + ctrl |= BM_UARTAPP_LINECTRL_EPS;
> + }
> +
> + /* figure out the stop bits requested */
> + if (cflag & CSTOPB)
> + ctrl |= BM_UARTAPP_LINECTRL_STP2;
> +
> + /* figure out the hardware flow control settings */
> + if (cflag & CRTSCTS)
> + ctrl2 |= BM_UARTAPP_CTRL2_CTSEN;
> + else
> + ctrl2 &= ~BM_UARTAPP_CTRL2_CTSEN;
> +
> + /* set baud rate */
> + baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
> + div = u->uartclk * 32 / baud;
> + ctrl |= BF_UARTAPP_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
> + ctrl |= BF_UARTAPP_LINECTRL_BAUD_DIVINT(div >> 6);
> +
> + if ((cflag & CREAD) != 0)
> + ctrl2 |= BM_UARTAPP_CTRL2_RXE;
> +
> + writel(ctrl, u->membase + UARTAPP_LINECTRL);
> + writel(ctrl2, u->membase + UARTAPP_CTRL2);
> +}
> +
> +static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
> +{
> + u32 istatus, istat;
> + struct mxs_auart_port *s = context;
> + u32 stat = readl(s->port.membase + UARTAPP_STAT);
> +
> + istatus = istat = readl(s->port.membase + UARTAPP_INTR);
> +
> + if (istat & BM_UARTAPP_INTR_CTSMIS) {
> + uart_handle_cts_change(&s->port, stat & BM_UARTAPP_STAT_CTS);
> + writel(BM_UARTAPP_INTR_CTSMIS,
> + s->port.membase + UARTAPP_INTR_CLR);
> + istat &= ~BM_UARTAPP_INTR_CTSMIS;
> + }
> +
> + if (istat & (BM_UARTAPP_INTR_RTIS | BM_UARTAPP_INTR_RXIS)) {
> + mxs_auart_rx_chars(s);
> + istat &= ~(BM_UARTAPP_INTR_RTIS | BM_UARTAPP_INTR_RXIS);
> + }
> +
> + if (istat & BM_UARTAPP_INTR_TXIS) {
> + mxs_auart_tx_chars(s);
> + istat &= ~BM_UARTAPP_INTR_TXIS;
> + }
> +
> + writel(istatus & (BM_UARTAPP_INTR_RTIS
> + | BM_UARTAPP_INTR_TXIS
> + | BM_UARTAPP_INTR_RXIS
> + | BM_UARTAPP_INTR_CTSMIS),
> + s->port.membase + UARTAPP_INTR_CLR);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static void mxs_auart_reset(struct uart_port *u)
> +{
> + int i;
> + unsigned int reg;
> +
> + writel(BM_UARTAPP_CTRL0_SFTRST,
> + u->membase + UARTAPP_CTRL0_CLR);
> +
> + for (i = 0; i < 10000; i++) {
> + reg = readl(u->membase + UARTAPP_CTRL0);
> + if (!(reg & BM_UARTAPP_CTRL0_SFTRST))
> + break;
> + udelay(3);
> + }
> +
> + writel(BM_UARTAPP_CTRL0_CLKGATE,
> + u->membase + UARTAPP_CTRL0_CLR);
> +}
> +
> +static int mxs_auart_startup(struct uart_port *u)
> +{
> + struct mxs_auart_port *s = to_auart_port(u);
> +
> + clk_enable(s->clk);
> +
> + writel(BM_UARTAPP_CTRL2_UARTEN,
> + s->port.membase + UARTAPP_CTRL2_SET);
> +
> + writel(BM_UARTAPP_INTR_RXIEN | BM_UARTAPP_INTR_RTIEN,
> + s->port.membase + UARTAPP_INTR);
> +
> + writel(BM_UARTAPP_INTR_CTSMIEN,
> + s->port.membase + UARTAPP_INTR_SET);
> +
> + /*
> + * Enable fifo so all four bytes of a DMA word are written to
> + * output (otherwise, only the LSB is written, ie. 1 in 4 bytes)
> + */
> + writel(BM_UARTAPP_LINECTRL_FEN,
> + s->port.membase + UARTAPP_LINECTRL_SET);
> +
> + return 0;
> +}
> +
> +static void mxs_auart_shutdown(struct uart_port *u)
> +{
> + struct mxs_auart_port *s = to_auart_port(u);
> +
> + writel(BM_UARTAPP_CTRL0_SFTRST,
> + s->port.membase + UARTAPP_CTRL0_SET);
> +
> + writel(BM_UARTAPP_INTR_RXIEN | BM_UARTAPP_INTR_RTIEN |
> + BM_UARTAPP_INTR_CTSMIEN,
> + s->port.membase + UARTAPP_INTR_CLR);
> +
> + clk_disable(s->clk);
> +}
> +
> +static unsigned int mxs_auart_tx_empty(struct uart_port *u)
> +{
> + if (readl(u->membase + UARTAPP_STAT) & BM_UARTAPP_STAT_TXFE)
> + return TIOCSER_TEMT;
> + else
> + return 0;
> +}
> +
> +static void mxs_auart_start_tx(struct uart_port *u)
> +{
> + struct mxs_auart_port *s = to_auart_port(u);
> +
> + /* enable transmitter */
> + writel(BM_UARTAPP_CTRL2_TXE, u->membase + UARTAPP_CTRL2_SET);
> +
> + mxs_auart_tx_chars(s);
> +}
> +
> +static void mxs_auart_stop_tx(struct uart_port *u)
> +{
> + writel(BM_UARTAPP_CTRL2_TXE, u->membase + UARTAPP_CTRL2_CLR);
> +}
> +
> +static void mxs_auart_stop_rx(struct uart_port *u)
> +{
> + writel(BM_UARTAPP_CTRL2_RXE, u->membase + UARTAPP_CTRL2_CLR);
> +}
> +
> +static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
> +{
> + if (ctl)
> + writel(BM_UARTAPP_LINECTRL_BRK,
> + u->membase + UARTAPP_LINECTRL_SET);
> + else
> + writel(BM_UARTAPP_LINECTRL_BRK,
> + u->membase + UARTAPP_LINECTRL_CLR);
> +}
> +
> +static void mxs_auart_enable_ms(struct uart_port *port)
> +{
> + /* just empty */
> +}
> +
> +static struct uart_ops mxs_auart_ops = {
> + .tx_empty = mxs_auart_tx_empty,
> + .start_tx = mxs_auart_start_tx,
> + .stop_tx = mxs_auart_stop_tx,
> + .stop_rx = mxs_auart_stop_rx,
> + .enable_ms = mxs_auart_enable_ms,
> + .break_ctl = mxs_auart_break_ctl,
> + .set_mctrl = mxs_auart_set_mctrl,
> + .get_mctrl = mxs_auart_get_mctrl,
> + .startup = mxs_auart_startup,
> + .shutdown = mxs_auart_shutdown,
> + .set_termios = mxs_auart_settermios,
> + .type = mxs_auart_type,
> + .release_port = mxs_auart_release_port,
> + .request_port = mxs_auart_request_port,
> + .config_port = mxs_auart_config_port,
> + .verify_port = mxs_auart_verify_port,
> +};
> +
> +static struct mxs_auart_port *auart_port[MXS_AUART_PORTS];
> +
> +#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
> +static void mxs_auart_console_putchar(struct uart_port *port, int ch)
> +{
> + unsigned int status;
> +
> + do {
> + status = readl(port->membase + UARTAPP_STAT);
> + } while (status & BM_UARTAPP_STAT_TXFF);
> + writel(ch, port->membase + UARTAPP_DATA);
> +}
> +
> +static void
> +auart_console_write(struct console *co, const char *str, unsigned int count)
> +{
> + struct mxs_auart_port *s;
> + struct uart_port *port;
> + unsigned int status, old_cr;
> +
> + if (co->index > MXS_AUART_PORTS || co->index < 0)
> + return;
> +
> + s = auart_port[co->index];
> + port = &s->port;
> +
> + clk_enable(s->clk);
> +
> + /* First save the CR then disable the interrupts */
> + old_cr = readl(port->membase + UARTAPP_CTRL2);
> + writel(BM_UARTAPP_CTRL2_UARTEN | BM_UARTAPP_CTRL2_TXE,
> + port->membase + UARTAPP_CTRL2_SET);
> +
> + uart_console_write(port, str, count, mxs_auart_console_putchar);
> +
> + /*
> + * Finally, wait for transmitter to become empty
> + * and restore the TCR
> + */
> + do {
> + status = readl(port->membase + UARTAPP_STAT);
> + } while (status & BM_UARTAPP_STAT_BUSY);
> +
> + writel(old_cr, port->membase + UARTAPP_CTRL2);
> +
> + clk_disable(s->clk);
> +}
> +
> +static void __init
> +auart_console_get_options(struct uart_port *port, int *baud,
> + int *parity, int *bits)
> +{
> + if (readl(port->membase + UARTAPP_CTRL2)
> + & BM_UARTAPP_CTRL2_UARTEN) {
> + unsigned int lcr_h, quot;
> + lcr_h = readl(port->membase + UARTAPP_LINECTRL);
> +
> + *parity = 'n';
> + if (lcr_h & BM_UARTAPP_LINECTRL_PEN) {
> + if (lcr_h & BM_UARTAPP_LINECTRL_EPS)
> + *parity = 'e';
> + else
> + *parity = 'o';
> + }
> +
> + if ((lcr_h & BM_UARTAPP_LINECTRL_WLEN)
> + == BF_UARTAPP_LINECTRL_WLEN(2))
> + *bits = 7;
> + else
> + *bits = 8;
> +
> + quot = (((readl(port->membase + UARTAPP_LINECTRL)
> + & BM_UARTAPP_LINECTRL_BAUD_DIVINT))
> + >> (BP_UARTAPP_LINECTRL_BAUD_DIVINT - 6))
> + | (((readl(port->membase + UARTAPP_LINECTRL)
> + & BM_UARTAPP_LINECTRL_BAUD_DIVFRAC))
> + >> BP_UARTAPP_LINECTRL_BAUD_DIVFRAC);
> + if (quot == 0)
> + quot = 1;
> + *baud = (port->uartclk << 2) / quot;
> + }
> +}
> +
> +static int __init
> +auart_console_setup(struct console *co, char *options)
> +{
> + struct mxs_auart_port *s;
> + int baud = 9600;
> + int bits = 8;
> + int parity = 'n';
> + int flow = 'n';
> + int ret;
> +
> + /*
> + * Check whether an invalid uart number has been specified, and
> + * if so, search for the first available port that does have
> + * console support.
> + */
> + if (co->index == -1 || co->index >= ARRAY_SIZE(auart_port))
> + co->index = 0;
> + s = auart_port[co->index];
> + if (!s)
> + return -ENODEV;
> +
> + clk_enable(s->clk);
> +
> + if (options)
> + uart_parse_options(options, &baud, &parity, &bits, &flow);
> + else
> + auart_console_get_options(&s->port, &baud, &parity, &bits);
> +
> + ret = uart_set_options(&s->port, co, baud, parity, bits, flow);
> +
> + clk_disable(s->clk);
> +
> + return ret;
> +}
> +
> +static struct console auart_console = {
> + .name = "ttyAPP",
> + .write = auart_console_write,
> + .device = uart_console_device,
> + .setup = auart_console_setup,
> + .flags = CON_PRINTBUFFER,
> + .index = -1,
> + .data = &auart_driver,
> +};
> +#endif
> +
> +static struct uart_driver auart_driver = {
> + .owner = THIS_MODULE,
> + .driver_name = "ttyAPP",
> + .dev_name = "ttyAPP",
> + .major = 0,
> + .minor = 0,
> + .nr = MXS_AUART_PORTS,
> +#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
> + .cons = &auart_console,
> +#endif
> +};
> +
> +static int __devinit mxs_auart_probe(struct platform_device *pdev)
> +{
> + struct mxs_auart_port *s;
> + u32 version;
> + int ret = 0;
> + struct resource *r;
> +
> + s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
> + if (!s) {
> + ret = -ENOMEM;
> + goto out;
> + }
> +
> + s->clk = clk_get(&pdev->dev, NULL);
> + if (IS_ERR(s->clk)) {
> + ret = PTR_ERR(s->clk);
> + goto out_free;
> + }
> +
> + r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!r) {
> + ret = -ENXIO;
> + goto out_free_clk;
> + }
> +
> + s->port.mapbase = r->start;
> + s->port.membase = ioremap(r->start, resource_size(r));
> + s->port.ops = &mxs_auart_ops;
> + s->port.iotype = UPIO_MEM;
> + s->port.line = pdev->id < 0 ? 0 : pdev->id;
> + s->port.fifosize = 16;
> + s->port.uartclk = clk_get_rate(s->clk);
> + s->port.type = PORT_IMX;
> + s->port.dev = s->dev = get_device(&pdev->dev);
> +
> + s->flags = 0;
> + s->ctrl = 0;
> +
> + s->irq = platform_get_irq(pdev, 0);
> + s->port.irq = s->irq;
> + ret = request_irq(s->irq, mxs_auart_irq_handle, 0, dev_name(&pdev->dev), s);
> + if (ret)
> + goto out_free_clk;
> +
> + platform_set_drvdata(pdev, s);
> +
> + auart_port[pdev->id] = s;
> +
> + mxs_auart_reset(&s->port);
> +
> + ret = uart_add_one_port(&auart_driver, &s->port);
> + if (ret)
> + goto out_free_irq;
> +
> + version = readl(s->port.membase + UARTAPP_VERSION);
> + dev_info(&pdev->dev, "Found APPUART %d.%d.%d\n",
> + (version >> 24) & 0xff,
> + (version >> 16) & 0xff, version & 0xffff);
> +
> + return 0;
> +
> +out_free_irq:
> + auart_port[pdev->id] = NULL;
> + free_irq(s->irq, s);
> +out_free_clk:
> + clk_put(s->clk);
> +out_free:
> + kfree(s);
> +out:
> + return ret;
> +}
> +
> +static int __devexit mxs_auart_remove(struct platform_device *pdev)
> +{
> + struct mxs_auart_port *s = platform_get_drvdata(pdev);
> +
> + uart_remove_one_port(&auart_driver, &s->port);
> +
> + auart_port[pdev->id] = NULL;
> +
> + clk_put(s->clk);
> + free_irq(s->irq, s);
> + kfree(s);
> +
> + return 0;
> +}
> +
> +static struct platform_driver mxs_auart_driver = {
> + .probe = mxs_auart_probe,
> + .remove = __devexit_p(mxs_auart_remove),
> + .driver = {
> + .name = "mxs-auart",
> + .owner = THIS_MODULE,
> + },
> +};
> +
> +static int __init mxs_auart_init(void)
> +{
> + int r;
> +
> + r = uart_register_driver(&auart_driver);
> + if (r)
> + goto out;
> +
> + r = platform_driver_register(&mxs_auart_driver);
> + if (r)
> + goto out_err;
> +
> + return 0;
> +out_err:
> + uart_unregister_driver(&auart_driver);
> +out:
> + return r;
> +}
> +
> +static void __exit mxs_auart_exit(void)
> +{
> + platform_driver_unregister(&mxs_auart_driver);
> + uart_unregister_driver(&auart_driver);
> +}
> +
> +module_init(mxs_auart_init);
> +module_exit(mxs_auart_exit);
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("Freescale MXS application uart driver");
> +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
> --
> 1.7.2.3
>
>
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28
2011-01-11 15:09 ` [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28 Sascha Hauer
2011-01-11 15:17 ` Uwe Kleine-König
@ 2011-01-12 6:17 ` Shawn Guo
1 sibling, 0 replies; 12+ messages in thread
From: Shawn Guo @ 2011-01-12 6:17 UTC (permalink / raw)
To: linux-arm-kernel
Hi Sascha,
On Tue, Jan 11, 2011 at 04:09:05PM +0100, Sascha Hauer wrote:
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> arch/arm/mach-mxs/clock-mx28.c | 5 ++
> arch/arm/mach-mxs/devices-mx28.h | 8 +++
> arch/arm/mach-mxs/devices/Kconfig | 3 +
> arch/arm/mach-mxs/devices/Makefile | 1 +
> arch/arm/mach-mxs/devices/platform-auart.c | 54 +++++++++++++++++++++++
> arch/arm/mach-mxs/include/mach/devices-common.h | 10 ++++
> 6 files changed, 81 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-mxs/devices/platform-auart.c
>
[...]
> +struct platform_device *__init mxs_add_auart(
> + const struct mxs_auart_data *data)
> +{
> + struct resource res[] = {
> + {
> + .start = data->iobase,
> + .end = data->iobase + SZ_4K - 1,
The io size here is supposed to mean the space for holding the
current defined registers or the memory map size for this block
given by SoC design? If it's the latter, the size should be SZ_8K.
> + .flags = IORESOURCE_MEM,
> + }, {
> + .start = data->irq,
> + .end = data->irq,
> + .flags = IORESOURCE_IRQ,
> + },
> + };
> +
> + return mxs_add_platform_device_dmamask("mxs-auart", data->id,
> + res, ARRAY_SIZE(res), NULL, 0,
> + DMA_BIT_MASK(32));
> +}
> +
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2011-01-12 6:17 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-11 15:09 Add i.MX23/28 auart support Sascha Hauer
2011-01-11 15:09 ` [PATCH 1/2] serial: Add auart driver for i.MX23/28 Sascha Hauer
2011-01-11 16:05 ` Russell King - ARM Linux
2011-01-11 17:10 ` Wolfram Sang
2011-01-11 17:57 ` Sascha Hauer
2011-01-12 5:39 ` Shawn Guo
2011-01-11 15:09 ` [PATCH 2/2] ARM i.MXS: Add auart platform support for i.MX28 Sascha Hauer
2011-01-11 15:17 ` Uwe Kleine-König
2011-01-11 15:26 ` Sascha Hauer
2011-01-12 5:06 ` Shawn Guo
2011-01-12 6:17 ` Shawn Guo
2011-01-12 5:31 ` Add i.MX23/28 auart support Shawn Guo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).