summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2015-05-26 07:29:03 (GMT)
committerWaldemar Brodkorb <wbx@openadk.org>2015-05-26 07:29:03 (GMT)
commitc40a49d923bd449d0246f647e6bad9dc9f0c3e5f (patch)
treed4993e955c5c40d64c31b49d40c6a231812abf03
parent1f58dbe349cc60bf3302fb4a1b058ead8808fdf1 (diff)
remove patch, it is already in just need to activate internal dtb
-rw-r--r--target/linux/patches/4.0.4/cris32-serial.patch2886
1 files changed, 0 insertions, 2886 deletions
diff --git a/target/linux/patches/4.0.4/cris32-serial.patch b/target/linux/patches/4.0.4/cris32-serial.patch
deleted file mode 100644
index 0f071cf..0000000
--- a/target/linux/patches/4.0.4/cris32-serial.patch
+++ /dev/null
@@ -1,2886 +0,0 @@
-diff -Nur linux-4.0.3.orig/arch/cris/arch-v32/drivers/Kconfig linux-4.0.3/arch/cris/arch-v32/drivers/Kconfig
---- linux-4.0.3.orig/arch/cris/arch-v32/drivers/Kconfig 2015-05-13 14:14:53.000000000 +0200
-+++ linux-4.0.3/arch/cris/arch-v32/drivers/Kconfig 2015-05-25 17:20:55.000000000 +0200
-@@ -49,24 +49,261 @@
- if you do not need DMA to something else.
- ser0 can use dma4 or dma6 for output and dma5 or dma7 for input.
-
-+choice
-+ prompt "Ser0 default port type "
-+ depends on ETRAX_SERIAL_PORT0
-+ default ETRAX_SERIAL_PORT0_TYPE_232
-+ help
-+ Type of serial port.
-+
-+config ETRAX_SERIAL_PORT0_TYPE_232
-+ bool "Ser0 is a RS-232 port"
-+ help
-+ Configure serial port 0 to be a RS-232 port.
-+
-+config ETRAX_SERIAL_PORT0_TYPE_485HD
-+ bool "Ser0 is a half duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 0 to be a half duplex (two wires) RS-485 port.
-+
-+config ETRAX_SERIAL_PORT0_TYPE_485FD
-+ bool "Ser0 is a full duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 0 to be a full duplex (four wires) RS-485 port.
-+endchoice
-+
-+config ETRAX_SER0_DTR_BIT
-+ string "Ser 0 DTR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT0
-+
-+config ETRAX_SER0_RI_BIT
-+ string "Ser 0 RI bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT0
-+
-+config ETRAX_SER0_DSR_BIT
-+ string "Ser 0 DSR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT0
-+
-+config ETRAX_SER0_CD_BIT
-+ string "Ser 0 CD bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT0
-+
- config ETRAX_SERIAL_PORT1
- bool "Serial port 1 enabled"
- depends on ETRAXFS_SERIAL
- help
- Enables the ETRAX FS serial driver for ser1 (ttyS1).
-
-+choice
-+ prompt "Ser1 default port type"
-+ depends on ETRAX_SERIAL_PORT1
-+ default ETRAX_SERIAL_PORT1_TYPE_232
-+ help
-+ Type of serial port.
-+
-+config ETRAX_SERIAL_PORT1_TYPE_232
-+ bool "Ser1 is a RS-232 port"
-+ help
-+ Configure serial port 1 to be a RS-232 port.
-+
-+config ETRAX_SERIAL_PORT1_TYPE_485HD
-+ bool "Ser1 is a half duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 1 to be a half duplex (two wires) RS-485 port.
-+
-+config ETRAX_SERIAL_PORT1_TYPE_485FD
-+ bool "Ser1 is a full duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 1 to be a full duplex (four wires) RS-485 port.
-+endchoice
-+
-+config ETRAX_SER1_DTR_BIT
-+ string "Ser 1 DTR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT1
-+
-+config ETRAX_SER1_RI_BIT
-+ string "Ser 1 RI bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT1
-+
-+config ETRAX_SER1_DSR_BIT
-+ string "Ser 1 DSR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT1
-+
-+config ETRAX_SER1_CD_BIT
-+ string "Ser 1 CD bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT1
-+
- config ETRAX_SERIAL_PORT2
- bool "Serial port 2 enabled"
- depends on ETRAXFS_SERIAL
- help
- Enables the ETRAX FS serial driver for ser2 (ttyS2).
-
-+choice
-+ prompt "Ser2 default port type"
-+ depends on ETRAX_SERIAL_PORT2
-+ default ETRAX_SERIAL_PORT2_TYPE_232
-+ help
-+ What DMA channel to use for ser2
-+
-+config ETRAX_SERIAL_PORT2_TYPE_232
-+ bool "Ser2 is a RS-232 port"
-+ help
-+ Configure serial port 2 to be a RS-232 port.
-+
-+config ETRAX_SERIAL_PORT2_TYPE_485HD
-+ bool "Ser2 is a half duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 2 to be a half duplex (two wires) RS-485 port.
-+
-+config ETRAX_SERIAL_PORT2_TYPE_485FD
-+ bool "Ser2 is a full duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 2 to be a full duplex (four wires) RS-485 port.
-+endchoice
-+
-+
-+config ETRAX_SER2_DTR_BIT
-+ string "Ser 2 DTR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT2
-+
-+config ETRAX_SER2_RI_BIT
-+ string "Ser 2 RI bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT2
-+
-+config ETRAX_SER2_DSR_BIT
-+ string "Ser 2 DSR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT2
-+
-+config ETRAX_SER2_CD_BIT
-+ string "Ser 2 CD bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT2
-+
- config ETRAX_SERIAL_PORT3
- bool "Serial port 3 enabled"
- depends on ETRAXFS_SERIAL
- help
- Enables the ETRAX FS serial driver for ser3 (ttyS3).
-
-+choice
-+ prompt "Ser3 default port type"
-+ depends on ETRAX_SERIAL_PORT3
-+ default ETRAX_SERIAL_PORT3_TYPE_232
-+ help
-+ What DMA channel to use for ser3.
-+
-+config ETRAX_SERIAL_PORT3_TYPE_232
-+ bool "Ser3 is a RS-232 port"
-+ help
-+ Configure serial port 3 to be a RS-232 port.
-+
-+config ETRAX_SERIAL_PORT3_TYPE_485HD
-+ bool "Ser3 is a half duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 3 to be a half duplex (two wires) RS-485 port.
-+
-+config ETRAX_SERIAL_PORT3_TYPE_485FD
-+ bool "Ser3 is a full duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 3 to be a full duplex (four wires) RS-485 port.
-+endchoice
-+
-+config ETRAX_SER3_DTR_BIT
-+ string "Ser 3 DTR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT3
-+
-+config ETRAX_SER3_RI_BIT
-+ string "Ser 3 RI bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT3
-+
-+config ETRAX_SER3_DSR_BIT
-+ string "Ser 3 DSR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT3
-+
-+config ETRAX_SER3_CD_BIT
-+ string "Ser 3 CD bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT3
-+
-+config ETRAX_SERIAL_PORT4
-+ bool "Serial port 4 enabled"
-+ depends on ETRAXFS_SERIAL && CRIS_MACH_ARTPEC3
-+ help
-+ Enables the ETRAX FS serial driver for ser4 (ttyS4).
-+
-+choice
-+ prompt "Ser4 default port type"
-+ depends on ETRAX_SERIAL_PORT4
-+ default ETRAX_SERIAL_PORT4_TYPE_232
-+ help
-+ What DMA channel to use for ser4.
-+
-+config ETRAX_SERIAL_PORT4_TYPE_232
-+ bool "Ser4 is a RS-232 port"
-+ help
-+ Configure serial port 4 to be a RS-232 port.
-+
-+config ETRAX_SERIAL_PORT4_TYPE_485HD
-+ bool "Ser4 is a half duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 4 to be a half duplex (two wires) RS-485 port.
-+
-+config ETRAX_SERIAL_PORT4_TYPE_485FD
-+ bool "Ser4 is a full duplex RS-485 port"
-+ depends on ETRAX_RS485
-+ help
-+ Configure serial port 4 to be a full duplex (four wires) RS-485 port.
-+endchoice
-+
-+choice
-+ prompt "Ser4 DMA in channel "
-+ depends on ETRAX_SERIAL_PORT4
-+ default ETRAX_SERIAL_PORT4_NO_DMA_IN
-+ help
-+ What DMA channel to use for ser4.
-+
-+
-+config ETRAX_SERIAL_PORT4_NO_DMA_IN
-+ bool "Ser4 uses no DMA for input"
-+ help
-+ Do not use DMA for ser4 input.
-+
-+config ETRAX_SERIAL_PORT4_DMA9_IN
-+ bool "Ser4 uses DMA9 for input"
-+ depends on ETRAX_SERIAL_PORT4
-+ help
-+ Enables the DMA9 input channel for ser4 (ttyS4).
-+ If you do not enable DMA, an interrupt for each character will be
-+ used when receiving data.
-+ Normally you want to use DMA, unless you use the DMA channel for
-+ something else.
-+
-+endchoice
-+
-+config ETRAX_SER4_DTR_BIT
-+ string "Ser 4 DTR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT4
-+
-+config ETRAX_SER4_RI_BIT
-+ string "Ser 4 RI bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT4
-+
-+config ETRAX_SER4_DSR_BIT
-+ string "Ser 4 DSR bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT4
-+
-+config ETRAX_SER4_CD_BIT
-+ string "Ser 4 CD bit (empty = not used)"
-+ depends on ETRAX_SERIAL_PORT4
-+
- config ETRAX_SYNCHRONOUS_SERIAL
- bool "Synchronous serial-port support"
- depends on ETRAX_ARCH_V32
-diff -Nur linux-4.0.3.orig/arch/cris/include/uapi/asm/ioctls.h linux-4.0.3/arch/cris/include/uapi/asm/ioctls.h
---- linux-4.0.3.orig/arch/cris/include/uapi/asm/ioctls.h 2015-05-13 14:14:53.000000000 +0200
-+++ linux-4.0.3/arch/cris/include/uapi/asm/ioctls.h 2015-05-25 17:20:56.000000000 +0200
-@@ -5,6 +5,10 @@
- #define TIOCSERSETRS485 0x5461 /* enable rs-485 (deprecated) */
- #define TIOCSERWRRS485 0x5462 /* write rs-485 */
- #define TIOCSRS485 0x5463 /* enable rs-485 */
-+#define TIOCSERSETRS485FD 0x5464 /* set rs-485 full/half duplex mode */
-+
-+
-+#define TIOCSERSETDIVISOR 0x5465 /* set the divisor for non standard bauds */
-
- #include <asm-generic/ioctls.h>
-
-diff -Nur linux-4.0.3.orig/drivers/tty/serial/crisv32.c linux-4.0.3/drivers/tty/serial/crisv32.c
---- linux-4.0.3.orig/drivers/tty/serial/crisv32.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-4.0.3/drivers/tty/serial/crisv32.c 2015-05-25 17:20:56.000000000 +0200
-@@ -0,0 +1,2581 @@
-+/* $Id: crisv32.c,v 1.109 2010-07-09 15:00:44 jespern Exp $
-+ *
-+ * Serial port driver for the ETRAX FS chip
-+ *
-+ * Copyright (C) 1998-2006 Axis Communications AB
-+ *
-+ * Many, many authors. Based once upon a time on serial.c for 16x50.
-+ *
-+ * Johan Adolfsson - port to ETRAX FS
-+ * Mikael Starvik - port to serial_core framework
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/console.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/serial_core.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <linux/tty_flip.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+
-+#include <dma.h>
-+#include <arch/system.h>
-+#include <mach/pinmux.h>
-+#include <hwregs/dma.h>
-+#include <hwregs/reg_rdwr.h>
-+#include <hwregs/ser_defs.h>
-+#include <hwregs/dma_defs.h>
-+#include <hwregs/gio_defs.h>
-+#include <hwregs/intr_vect_defs.h>
-+#include <hwregs/reg_map.h>
-+
-+#define UART_NR CONFIG_ETRAX_SERIAL_PORTS + 1 /* Ports + dummy port */
-+#define SERIAL_RECV_DESCRIPTORS 8
-+
-+/* We only buffer 255 characters here, no need for more tx descriptors. */
-+#define SERIAL_TX_DESCRIPTORS 4
-+
-+/* Kept for experimental purposes. */
-+#define SERIAL_DESCR_BUF_SIZE 256
-+#define regi_NULL 0
-+#define DMA_WAIT_UNTIL_RESET(inst) \
-+ do { \
-+ reg_dma_rw_stat r; \
-+ do { \
-+ r = REG_RD(dma, (inst), rw_stat); \
-+ } while (r.mode != regk_dma_rst); \
-+ } while (0)
-+
-+#define __DMA(ch) regi_dma##ch
-+#define DMA(ch) __DMA(ch)
-+#define DMA_IRQ(ch) (DMA0_INTR_VECT + (ch))
-+
-+/* Macro to set up control lines for a port. */
-+#define SETUP_PINS(port) \
-+ if (serial_cris_ports[port].used) { \
-+ if (strcmp(CONFIG_ETRAX_SER##port##_DTR_BIT, "")) \
-+ crisv32_io_get_name(&serial_cris_ports[port].dtr_pin, \
-+ CONFIG_ETRAX_SER##port##_DTR_BIT); \
-+ else \
-+ serial_cris_ports[port].dtr_pin = dummy_pin; \
-+ if (strcmp(CONFIG_ETRAX_SER##port##_DSR_BIT, "")) \
-+ crisv32_io_get_name(&serial_cris_ports[port].dsr_pin, \
-+ CONFIG_ETRAX_SER##port##_DSR_BIT); \
-+ else \
-+ serial_cris_ports[port].dsr_pin = dummy_pin; \
-+ if (strcmp(CONFIG_ETRAX_SER##port##_RI_BIT, "")) \
-+ crisv32_io_get_name(&serial_cris_ports[port].ri_pin, \
-+ CONFIG_ETRAX_SER##port##_RI_BIT); \
-+ else \
-+ serial_cris_ports[port].ri_pin = dummy_pin; \
-+ if (strcmp(CONFIG_ETRAX_SER##port##_CD_BIT, "")) \
-+ crisv32_io_get_name(&serial_cris_ports[port].cd_pin, \
-+ CONFIG_ETRAX_SER##port##_CD_BIT); \
-+ else \
-+ serial_cris_ports[port].cd_pin = dummy_pin; \
-+ }
-+
-+/* Set a serial port register if anything has changed. */
-+#define MODIFY_REG(instance, reg, var) \
-+ if (REG_RD_INT(ser, instance, reg) \
-+ != REG_TYPE_CONV(int, reg_ser_##reg, var)) \
-+ REG_WR(ser, instance, reg, var);
-+
-+/*
-+ * Regarding RS485 operation in crisv32 serial driver.
-+ * ---------------------------------------------------
-+ * RS485 can be run in two modes, full duplex using four wires (485FD) and
-+ * half duplex using two wires (485HD). The default mode of each serial port
-+ * is configured in the kernel configuration. The available modes are:
-+ * RS-232, RS-485 half duplex, and RS-485 full duplex.
-+ *
-+ * In the 485HD mode the direction of the data bus must be able to switch.
-+ * The direction of the transceiver is controlled by the RTS signal. Hence
-+ * the auto_rts function in the ETRAX FS chip is enabled in this mode, which
-+ * automatically toggle RTS when transmitting. The initial direction of the
-+ * port is receiving.
-+ *
-+ * In the 485FD mode two transceivers will be used, one in each direction.
-+ * Usually the hardware can handle both 485HD and 485FD, which implies that
-+ * one of the transceivers can change direction. Consequently that transceiver
-+ * must be tied to operate in the opposite direction of the other one, setting
-+ * and keeping RTS to a fixed value do this.
-+ *
-+ * There are two special "ioctl" that can configure the ports. These two are
-+ * left for backward compatible with older applications. The effects of using
-+ * them are described below:
-+ * The TIOCSERSETRS485:
-+ * This ioctl sets a serial port in 232 mode to 485HD mode or vise versa. The
-+ * state of the port is kept when closing the port. Note that this ioctl has no
-+ * effect on a serial port in the 485FD mode.
-+ * The TIOCSERWRRS485:
-+ * This ioctl set a serial port in 232 mode to 485HD mode and writes the data
-+ * "included" in the ioctl to the port. The port will then stay in 485HD mode.
-+ * Using this ioctl on a serial port in the 485HD mode will transmit the data
-+ * without changing the mode. Using this ioctl on a serial port in 485FD mode
-+ * will not change the mode and simply send the data using the 485FD mode.
-+ */
-+
-+#define TYPE_232 0
-+#define TYPE_485HD 1
-+#define TYPE_485FD 2
-+
-+struct etrax_recv_buffer {
-+ struct etrax_recv_buffer *next;
-+ unsigned short length;
-+ unsigned char error;
-+ unsigned char pad;
-+
-+ unsigned char buffer[0];
-+};
-+
-+struct uart_cris_port {
-+ struct uart_port port;
-+
-+ int initialized;
-+ int used;
-+ int irq;
-+
-+ /* Used to check if port enabled as well by testing for zero. */
-+ reg_scope_instances regi_ser;
-+ reg_scope_instances regi_dmain;
-+ reg_scope_instances regi_dmaout;
-+
-+ struct crisv32_iopin dtr_pin;
-+ struct crisv32_iopin dsr_pin;
-+ struct crisv32_iopin ri_pin;
-+ struct crisv32_iopin cd_pin;
-+
-+ struct dma_descr_context tr_context_descr
-+ __attribute__ ((__aligned__(32)));
-+ struct dma_descr_data tr_descr[SERIAL_TX_DESCRIPTORS]
-+ __attribute__ ((__aligned__(32)));
-+ struct dma_descr_context rec_context_descr
-+ __attribute__ ((__aligned__(32)));
-+ struct dma_descr_data rec_descr[SERIAL_RECV_DESCRIPTORS]
-+ __attribute__ ((__aligned__(32)));
-+
-+ /* This is the first one in the list the HW is working on now. */
-+ struct dma_descr_data* first_tx_descr;
-+
-+ /* This is the last one in the list the HW is working on now. */
-+ struct dma_descr_data* last_tx_descr;
-+
-+ /* This is how many characters the HW is working on now. */
-+ unsigned int tx_pending_chars;
-+
-+ int tx_started;
-+ unsigned int cur_rec_descr;
-+ struct etrax_recv_buffer *first_recv_buffer;
-+ struct etrax_recv_buffer *last_recv_buffer;
-+
-+ unsigned int recv_cnt;
-+ unsigned int max_recv_cnt;
-+
-+ /* The time for 1 char, in usecs. */
-+ unsigned long char_time_usec;
-+
-+ /* Last tx usec in the jiffies. */
-+ unsigned long last_tx_active_usec;
-+
-+ /* Last tx time in jiffies. */
-+ unsigned long last_tx_active;
-+
-+ /* Last rx usec in the jiffies. */
-+ unsigned long last_rx_active_usec;
-+
-+ /* Last rx time in jiffies. */
-+ unsigned long last_rx_active;
-+
-+#ifdef CONFIG_ETRAX_RS485
-+ /* RS-485 support, duh. */
-+ struct rs485_control rs485;
-+#endif
-+ int port_type;
-+ int write_ongoing;
-+};
-+
-+extern struct uart_driver serial_cris_driver;
-+static struct uart_port *console_port;
-+static int console_baud = 115200;
-+static struct uart_cris_port serial_cris_ports[UART_NR] = {
-+{
-+#ifdef CONFIG_ETRAX_SERIAL_PORT0
-+ .used = 1,
-+ .irq = SER0_INTR_VECT,
-+ .regi_ser = regi_ser0,
-+ /*
-+ * We initialize the dma stuff like this to get a compiler error
-+ * if a CONFIG is missing
-+ */
-+ .regi_dmain =
-+# ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
-+ regi_dma7,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT0_DMA1_IN)
-+ regi_dma1,
-+# elif defined CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_IN
-+ regi_NULL,
-+# endif
-+
-+ .regi_dmaout =
-+# ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
-+ regi_dma6,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT0_DMA7_OUT)
-+ regi_dma7,
-+# else
-+ regi_NULL,
-+# endif
-+
-+# ifdef CONFIG_ETRAX_RS485
-+# ifdef CONFIG_ETRAX_SERIAL_PORT0_TYPE_485HD
-+ .port_type = TYPE_485HD,
-+# endif
-+# ifdef CONFIG_ETRAX_SERIAL_PORT0_TYPE_485FD
-+ .port_type = TYPE_485FD,
-+# endif
-+# endif
-+#else
-+ .regi_ser = regi_NULL,
-+ .regi_dmain = regi_NULL,
-+ .regi_dmaout = regi_NULL,
-+#endif
-+ .write_ongoing = 0
-+}, /* ttyS0 */
-+{
-+#ifdef CONFIG_ETRAX_SERIAL_PORT1
-+ .used = 1,
-+ .irq = SER1_INTR_VECT,
-+ .regi_ser = regi_ser1,
-+ .regi_dmain =
-+# ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA5_IN
-+ regi_dma5,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_IN)
-+ regi_NULL,
-+# endif
-+
-+ .regi_dmaout =
-+# ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA4_OUT
-+ regi_dma4,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_OUT)
-+ regi_NULL,
-+# endif
-+
-+# ifdef CONFIG_ETRAX_RS485
-+# ifdef CONFIG_ETRAX_SERIAL_PORT1_TYPE_485HD
-+ .port_type = TYPE_485HD,
-+# endif
-+# ifdef CONFIG_ETRAX_SERIAL_PORT1_TYPE_485FD
-+ .port_type = TYPE_485FD,
-+# endif
-+# endif
-+#else
-+ .regi_ser = regi_NULL,
-+ .regi_dmain = regi_NULL,
-+ .regi_dmaout = regi_NULL,
-+#endif
-+ .write_ongoing = 0
-+}, /* ttyS1 */
-+{
-+#ifdef CONFIG_ETRAX_SERIAL_PORT2
-+ .used = 1,
-+ .irq = SER2_INTR_VECT,
-+ .regi_ser = regi_ser2,
-+ .regi_dmain =
-+# ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
-+ regi_dma3,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT2_DMA7_IN)
-+ regi_dma7,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_IN)
-+ regi_NULL,
-+# endif
-+
-+ .regi_dmaout =
-+# ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
-+ regi_dma2,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT2_DMA6_OUT)
-+ regi_dma6,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_OUT)
-+ regi_NULL,
-+# endif
-+
-+# ifdef CONFIG_ETRAX_RS485
-+# ifdef CONFIG_ETRAX_SERIAL_PORT2_TYPE_485HD
-+ .port_type = TYPE_485HD,
-+# endif
-+# ifdef CONFIG_ETRAX_SERIAL_PORT2_TYPE_485FD
-+ .port_type = TYPE_485FD,
-+# endif
-+# endif
-+#else
-+ .regi_ser = regi_NULL,
-+ .regi_dmain = regi_NULL,
-+ .regi_dmaout = regi_NULL,
-+#endif
-+ .write_ongoing = 0
-+}, /* ttyS2 */
-+{
-+#ifdef CONFIG_ETRAX_SERIAL_PORT3
-+ .used = 1,
-+ .irq = SER3_INTR_VECT,
-+ .regi_ser = regi_ser3,
-+ .regi_dmain =
-+# ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA9_IN
-+ regi_dma9,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT3_DMA4_IN)
-+ regi_dma3,
-+# else
-+ regi_NULL,
-+# endif
-+
-+ .regi_dmaout =
-+# ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA8_OUT
-+ regi_dma8,
-+# elif defined(CONFIG_ETRAX_SERIAL_PORT3_DMA2_OUT)
-+ regi_dma2,
-+# else
-+ regi_NULL,
-+# endif
-+# ifdef CONFIG_ETRAX_RS485
-+# ifdef CONFIG_ETRAX_SERIAL_PORT3_TYPE_485HD
-+ .port_type = TYPE_485HD,
-+# endif
-+# ifdef CONFIG_ETRAX_SERIAL_PORT3_TYPE_485FD
-+ .port_type = TYPE_485FD,
-+# endif
-+# endif
-+#else
-+ .regi_ser = regi_NULL,
-+ .regi_dmain = regi_NULL,
-+ .regi_dmaout = regi_NULL,
-+#endif
-+ .write_ongoing = 0
-+}, /* ttyS3 */
-+#if CONFIG_ETRAX_SERIAL_PORTS == 5
-+{
-+#ifdef CONFIG_ETRAX_SERIAL_PORT4
-+ .used = 1,
-+ .irq = SER4_INTR_VECT,
-+ .regi_ser = regi_ser4,
-+ .regi_dmain =
-+# ifdef CONFIG_ETRAX_SERIAL_PORT4_DMA9_IN
-+ regi_dma9,
-+# else
-+ regi_NULL,
-+# endif
-+
-+ .regi_dmaout = regi_NULL,
-+# ifdef CONFIG_ETRAX_RS485
-+# ifdef CONFIG_ETRAX_SERIAL_PORT4_TYPE_485HD
-+ .port_type = TYPE_485HD,
-+# endif
-+# ifdef CONFIG_ETRAX_SERIAL_PORT4_TYPE_485FD
-+ .port_type = TYPE_485FD,
-+# endif
-+# endif
-+#else
-+ .regi_ser = regi_NULL,
-+ .regi_dmain = regi_NULL,
-+ .regi_dmaout = regi_NULL,
-+#endif
-+ .write_ongoing = 0
-+}, /* ttyS4 */
-+#endif
-+{
-+#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL
-+ .used = 1,
-+#endif
-+ .regi_ser = regi_NULL,
-+ .write_ongoing = 0
-+} /* Dummy console port */
-+
-+};
-+
-+/* Dummy pin used for unused CD, DSR, DTR and RI signals. */
-+static unsigned long io_dummy;
-+static struct crisv32_ioport dummy_port =
-+{
-+ &io_dummy,
-+ &io_dummy,
-+ &io_dummy,
-+ 32
-+};
-+static struct crisv32_iopin dummy_pin =
-+{
-+ &dummy_port,
-+ 0
-+};
-+
-+static int selected_console =
-+#if defined(CONFIG_ETRAX_DEBUG_PORT0)
-+0;
-+#elif defined(CONFIG_ETRAX_DEBUG_PORT1)
-+1;
-+#elif defined(CONFIG_ETRAX_DEBUG_PORT2)
-+2;
-+#elif defined(CONFIG_ETRAX_DEBUG_PORT3)
-+3;
-+#elif defined(CONFIG_ETRAX_DEBUG_PORT4)
-+4;
-+#else /* CONFIG_ETRAX_DEBUG_PORT_NULL */
-+#if CONFIG_ETRAX_SERIAL_PORTS == 5
-+5;
-+#else
-+4;
-+#endif
-+#endif
-+
-+extern void reset_watchdog(void);
-+
-+static void serial_cris_stop_rx(struct uart_port *port);
-+
-+/*
-+ * Interrupts are disabled on entering
-+ */
-+#ifndef CONFIG_ETRAX_VCS_SIM
-+static void
-+cris_console_write(struct console *co, const char *s, unsigned int count)
-+{
-+ struct uart_cris_port *up;
-+ int i;
-+ reg_ser_r_stat_din stat;
-+ reg_ser_rw_tr_dma_en tr_dma_en, old;
-+
-+ up = &serial_cris_ports[selected_console];
-+
-+ /*
-+ * This function isn't covered by the struct uart_ops, so we
-+ * have to check manually that the port really is there,
-+ * configured and live.
-+ */
-+ if (!up->regi_ser)
-+ return;
-+
-+ /* Switch to manual mode. */
-+ tr_dma_en = old = REG_RD (ser, up->regi_ser, rw_tr_dma_en);
-+ if (tr_dma_en.en == regk_ser_yes) {
-+ tr_dma_en.en = regk_ser_no;
-+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, tr_dma_en);
-+ }
-+
-+ /* Send data. */
-+ for (i = 0; i < count; i++) {
-+ /* LF -> CRLF */
-+ if (s[i] == '\n') {
-+ do {
-+ stat = REG_RD (ser, up->regi_ser, r_stat_din);
-+ } while (!stat.tr_rdy);
-+ REG_WR_INT (ser, up->regi_ser, rw_dout, '\r');
-+ }
-+ /* Wait until transmitter is ready and send. */
-+ do {
-+ stat = REG_RD (ser, up->regi_ser, r_stat_din);
-+ } while (!stat.tr_rdy);
-+ REG_WR_INT (ser, up->regi_ser, rw_dout, s[i]);
-+
-+ /* Feed watchdog, because this may take looong time. */
-+ reset_watchdog();
-+ }
-+
-+ /* Restore mode. */
-+ if (tr_dma_en.en != old.en)
-+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, old);
-+}
-+#else
-+
-+extern void print_str( const char *str );
-+static char buffer[1024];
-+static char msg[] = "Debug: ";
-+static int buffer_pos = sizeof(msg) - 1;
-+
-+static void
-+cris_console_write(struct console *co, const char *buf, unsigned int len)
-+{
-+ char* pos;
-+ pos = memchr(buf, '\n', len);
-+ if (pos) {
-+ int l = ++pos - buf;
-+ memcpy(buffer + buffer_pos, buf, l);
-+ memcpy(buffer, msg, sizeof(msg) - 1);
-+ buffer[buffer_pos + l] = '\0';
-+ print_str(buffer);
-+ buffer_pos = sizeof(msg) - 1;
-+ if (pos - buf != len) {
-+ memcpy(buffer + buffer_pos, pos, len - l);
-+ buffer_pos += len - l;
-+ }
-+ } else {
-+ memcpy(buffer + buffer_pos, buf, len);
-+ buffer_pos += len;
-+ }
-+}
-+#endif
-+
-+static void cris_serial_port_init(struct uart_port *port, int line);
-+static int __init
-+cris_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 115200;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ if (co->index >= UART_NR)
-+ co->index = 0;
-+ if (options)
-+ selected_console = co->index;
-+ port = &serial_cris_ports[selected_console].port;
-+ console_port = port;
-+
-+ co->flags |= CON_CONSDEV;
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ console_baud = baud;
-+ cris_serial_port_init(port, selected_console);
-+ co->index = port->line;
-+ uart_set_options(port, co, baud, parity, bits, flow);
-+
-+ return 0;
-+}
-+
-+static struct tty_driver*
-+cris_console_device(struct console* co, int *index)
-+{
-+ struct uart_driver *p = co->data;
-+ *index = selected_console;
-+ return p->tty_driver;
-+}
-+
-+static struct console cris_console = {
-+ .name = "ttyS",
-+ .write = cris_console_write,
-+ .device = cris_console_device,
-+ .setup = cris_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+ .data = &serial_cris_driver,
-+};
-+
-+#define SERIAL_CRIS_CONSOLE &cris_console
-+
-+struct uart_driver serial_cris_driver = {
-+ .owner = THIS_MODULE,
-+ .driver_name = "serial",
-+ .dev_name = "ttyS",
-+ .major = TTY_MAJOR,
-+ .minor = 64,
-+ .nr = UART_NR,
-+ .cons = SERIAL_CRIS_CONSOLE,
-+};
-+
-+static int inline crisv32_serial_get_rts(struct uart_cris_port *up)
-+{
-+ reg_scope_instances regi_ser = up->regi_ser;
-+ /*
-+ * Return what the user has controlled rts to or
-+ * what the pin is? (if auto_rts is used it differs during tx)
-+ */
-+ reg_ser_r_stat_din rstat = REG_RD(ser, regi_ser, r_stat_din);
-+ return !(rstat.rts_n == regk_ser_active);
-+}
-+
-+/*
-+ * A set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive
-+ * 0=0V , 1=3.3V
-+ */
-+static inline void crisv32_serial_set_rts(struct uart_cris_port *up, int set, int force)
-+{
-+ reg_scope_instances regi_ser = up->regi_ser;
-+
-+#ifdef CONFIG_ETRAX_RS485
-+ /* Never toggle RTS if port is in 485 mode. If port is in 485FD mode we
-+ * do not want to send with the reciever and for 485HD mode auto_rts
-+ * take care of the RTS for us.
-+ */
-+ if (force || !up->rs485.enabled) {
-+#else
-+ {
-+#endif
-+ unsigned long flags;
-+ reg_ser_rw_rec_ctrl rec_ctrl;
-+
-+ local_irq_save(flags);
-+ rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
-+
-+ if (set)
-+ rec_ctrl.rts_n = regk_ser_active;
-+ else
-+ rec_ctrl.rts_n = regk_ser_inactive;
-+ REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
-+ local_irq_restore(flags);
-+ }
-+}
-+
-+/* Input */
-+static int inline crisv32_serial_get_cts(struct uart_cris_port *up)
-+{
-+ reg_scope_instances regi_ser = up->regi_ser;
-+ reg_ser_r_stat_din rstat = REG_RD(ser, regi_ser, r_stat_din);
-+ return (rstat.cts_n == regk_ser_active);
-+}
-+
-+/*
-+ * Send a single character for XON/XOFF purposes. We do it in this separate
-+ * function instead of the alternative support port.x_char, in the ...start_tx
-+ * function, so we don't mix up this case with possibly enabling transmission
-+ * of queued-up data (in case that's disabled after *receiving* an XOFF or
-+ * negative CTS). This function is used for both DMA and non-DMA case; see HW
-+ * docs specifically blessing sending characters manually when DMA for
-+ * transmission is enabled and running. We may be asked to transmit despite
-+ * the transmitter being disabled by a ..._stop_tx call so we need to enable
-+ * it temporarily but restore the state afterwards.
-+ *
-+ * Beware: I'm not sure how the RS-485 stuff is supposed to work. Using
-+ * XON/XOFF seems problematic if there are several controllers, but if it's
-+ * actually RS-422 (multi-drop; one sender and multiple receivers), it might
-+ * Just Work, so don't bail out just because it looks a little suspicious.
-+ */
-+
-+void serial_cris_send_xchar(struct uart_port *port, char ch)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ reg_ser_rw_dout dout = { .data = ch };
-+ reg_ser_rw_ack_intr ack_intr = { .tr_rdy = regk_ser_yes };
-+ reg_ser_r_stat_din rstat;
-+ reg_ser_rw_tr_ctrl prev_tr_ctrl, tr_ctrl;
-+ reg_scope_instances regi_ser = up->regi_ser;
-+ unsigned long flags;
-+
-+ /*
-+ * Wait for tr_rdy in case a character is already being output. Make
-+ * sure we have integrity between the register reads and the writes
-+ * below, but don't busy-wait with interrupts off and the port lock
-+ * taken.
-+ */
-+ spin_lock_irqsave(&port->lock, flags);
-+ do {
-+ spin_unlock_irqrestore(&port->lock, flags);
-+ spin_lock_irqsave(&port->lock, flags);
-+ prev_tr_ctrl = tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
-+ rstat = REG_RD(ser, regi_ser, r_stat_din);
-+ } while (!rstat.tr_rdy);
-+
-+ /*
-+ * Ack an interrupt if one was just issued for the previous character
-+ * that was output. This is required for non-DMA as the interrupt is
-+ * used as the only indicator that the transmitter is ready and it
-+ * isn't while this x_char is being transmitted.
-+ */
-+ REG_WR(ser, regi_ser, rw_ack_intr, ack_intr);
-+
-+ /* Enable the transmitter in case it was disabled. */
-+ tr_ctrl.stop = 0;
-+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
-+
-+ /*
-+ * Finally, send the blessed character; nothing should stop it now,
-+ * except for an xoff-detected state, which we'll handle below.
-+ */
-+ REG_WR(ser, regi_ser, rw_dout, dout);
-+ up->port.icount.tx++;
-+
-+ /* There might be an xoff state to clear. */
-+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
-+
-+ /*
-+ * Clear any xoff state that *may* have been there to
-+ * inhibit transmission of the character.
-+ */
-+ if (rstat.xoff_detect) {
-+ reg_ser_rw_xoff_clr xoff_clr = { .clr = 1 };
-+ reg_ser_rw_tr_dma_en tr_dma_en;
-+ REG_WR(ser, regi_ser, rw_xoff_clr, xoff_clr);
-+ tr_dma_en = REG_RD(ser, regi_ser, rw_tr_dma_en);
-+
-+ /*
-+ * If we had an xoff state but cleared it, instead sneak in a
-+ * disabled state for the transmitter, after the character we
-+ * sent. Thus we keep the port disabled, just as if the xoff
-+ * state was still in effect (or actually, as if stop_tx had
-+ * been called, as we stop DMA too).
-+ */
-+ prev_tr_ctrl.stop = 1;
-+
-+ tr_dma_en.en = 0;
-+ REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en);
-+ }
-+
-+ /* Restore "previous" enabled/disabled state of the transmitter. */
-+ REG_WR(ser, regi_ser, rw_tr_ctrl, prev_tr_ctrl);
-+
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static void transmit_chars_dma(struct uart_cris_port *up);
-+
-+/*
-+ * Do not spin_lock_irqsave or disable interrupts by other means here; it's
-+ * already done by the caller.
-+ */
-+
-+static void serial_cris_start_tx(struct uart_port *port)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ reg_scope_instances regi_ser = up->regi_ser;
-+ reg_ser_rw_tr_ctrl tr_ctrl;
-+
-+ /* we have already done below if a write is ongoing */
-+ if (!up->regi_dmaout && up->write_ongoing)
-+ return;
-+
-+#ifdef CONFIG_ETRAX_RS485
-+ if (up->rs485.enabled)
-+ {
-+ /* If we are in RS-485 mode, we need to toggle RTS and disable
-+ * the receiver before initiating a DMA transfer
-+ */
-+
-+ if (up->rs485.delay_rts_before_send > 0) {
-+ reg_ser_rw_tr_ctrl tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
-+ tr_ctrl.auto_rts = regk_ser_no;
-+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
-+ crisv32_serial_set_rts(up, up->rs485.rts_on_send, 1);
-+ msleep(up->rs485.delay_rts_before_send);
-+ tr_ctrl.auto_rts = regk_ser_yes;
-+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
-+ crisv32_serial_set_rts(up, !up->rs485.rts_on_send, 1);
-+ }
-+ }
-+#endif
-+
-+ tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
-+ tr_ctrl.stop = regk_ser_no;
-+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
-+ if (!up->regi_dmaout) {
-+ reg_ser_rw_intr_mask intr_mask =
-+ REG_RD(ser, regi_ser, rw_intr_mask);
-+ intr_mask.tr_rdy = regk_ser_yes;
-+ REG_WR(ser, regi_ser, rw_intr_mask, intr_mask);
-+ up->write_ongoing = 1;
-+ } else {
-+ /*
-+ * We're called possibly to re-enable transmission after it
-+ * has been disabled. If so, DMA needs to be re-enabled.
-+ */
-+ reg_ser_rw_tr_dma_en tr_dma_en = { .en = 1 };
-+ REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en);
-+ transmit_chars_dma(up);
-+ }
-+}
-+
-+/*
-+ * This function handles both the DMA and non-DMA case by ordering the
-+ * transmitter to stop of after the current character. We don't need to wait
-+ * for any such character to be completely transmitted; we do that where it
-+ * matters, like in serial_cris_set_termios. Don't busy-wait here; see
-+ * Documentation/serial/driver: this function is called within
-+ * spin_lock_irq{,save} and thus separate ones would be disastrous (when SMP).
-+ * There's no documented need to set the txd pin to any particular value;
-+ * break setting is controlled solely by serial_cris_break_ctl.
-+ */
-+
-+static void serial_cris_stop_tx(struct uart_port *port)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ reg_scope_instances regi_ser = up->regi_ser;
-+ reg_ser_rw_tr_ctrl tr_ctrl;
-+ reg_ser_rw_intr_mask intr_mask;
-+ reg_ser_rw_tr_dma_en tr_dma_en = {0};
-+ reg_ser_rw_xoff_clr xoff_clr = {0};
-+
-+ /*
-+ * For the non-DMA case, we'd get a tr_rdy interrupt that we're not
-+ * interested in as we're not transmitting any characters. For the
-+ * DMA case, that interrupt is already turned off, but no reason to
-+ * waste code on conditionals here.
-+ */
-+ intr_mask = REG_RD(ser, regi_ser, rw_intr_mask);
-+ intr_mask.tr_rdy = regk_ser_no;
-+ REG_WR(ser, regi_ser, rw_intr_mask, intr_mask);
-+
-+ tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
-+ tr_ctrl.stop = 1;
-+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
-+
-+ /*
-+ * Always clear possible hardware xoff-detected state here, no need to
-+ * unnecessary consider mctrl settings and when they change. We clear
-+ * it here rather than in start_tx: both functions are called as the
-+ * effect of XOFF processing, but start_tx is also called when upper
-+ * levels tell the driver that there are more characters to send, so
-+ * avoid adding code there.
-+ */
-+ xoff_clr.clr = 1;
-+ REG_WR(ser, regi_ser, rw_xoff_clr, xoff_clr);
-+
-+ /*
-+ * Disable transmitter DMA, so that if we're in XON/XOFF, we can send
-+ * those single characters without also giving go-ahead for queued up
-+ * DMA data.
-+ */
-+ tr_dma_en.en = 0;
-+ REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en);
-+}
-+
-+static void serial_cris_stop_rx(struct uart_port *port)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ reg_scope_instances regi_ser = up->regi_ser;
-+ reg_ser_rw_rec_ctrl rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
-+
-+ rec_ctrl.en = regk_ser_no;
-+ REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
-+}
-+
-+static void serial_cris_enable_ms(struct uart_port *port)
-+{
-+}
-+
-+static void check_modem_status(struct uart_cris_port *up)
-+{
-+}
-+
-+static unsigned int serial_cris_tx_empty(struct uart_port *port)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ unsigned long flags;
-+ unsigned int ret;
-+ reg_ser_r_stat_din rstat = {0};
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ if (up->regi_dmaout) {
-+ /*
-+ * For DMA, before looking at r_stat, we need to check that we
-+ * either haven't actually started or that end-of-list is
-+ * reached, else a tr_empty indication is just an internal
-+ * state. The caller qualifies, if needed, that the
-+ * port->info.xmit buffer is empty, so we don't need to
-+ * check that.
-+ */
-+ reg_dma_rw_stat status = REG_RD(dma, up->regi_dmaout, rw_stat);
-+
-+ if (!up->tx_started) {
-+ ret = 1;
-+ goto done;
-+ }
-+
-+ if (status.list_state != regk_dma_data_at_eol) {
-+ ret = 0;
-+ goto done;
-+ }
-+ }
-+
-+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
-+ ret = rstat.tr_empty ? TIOCSER_TEMT : 0;
-+
-+ done:
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+ return ret;
-+}
-+static unsigned int serial_cris_get_mctrl(struct uart_port *port)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ unsigned int ret;
-+
-+ ret = 0;
-+ if (crisv32_serial_get_rts(up))
-+ ret |= TIOCM_RTS;
-+ /* DTR is active low */
-+ if (!crisv32_io_rd(&up->dtr_pin))
-+ ret |= TIOCM_DTR;
-+ /* CD is active low */
-+ if (!crisv32_io_rd(&up->cd_pin))
-+ ret |= TIOCM_CD;
-+ /* RI is active low */
-+ if (!crisv32_io_rd(&up->ri_pin))
-+ ret |= TIOCM_RI;
-+ /* DSR is active low */
-+ if (!crisv32_io_rd(&up->dsr_pin))
-+ ret |= TIOCM_DSR;
-+ if (crisv32_serial_get_cts(up))
-+ ret |= TIOCM_CTS;
-+ return ret;
-+}
-+
-+static void serial_cris_set_mctrl(struct uart_port *port, unsigned int mctrl)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+
-+ crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0);
-+ /* DTR is active low */
-+ crisv32_io_set(&up->dtr_pin, mctrl & TIOCM_DTR ? 0 : 1);
-+ /* RI is active low */
-+ crisv32_io_set(&up->ri_pin, mctrl & TIOCM_RNG ? 0 : 1);
-+ /* CD is active low */
-+ crisv32_io_set(&up->cd_pin, mctrl & TIOCM_CD ? 0 : 1);
-+}
-+
-+static void serial_cris_break_ctl(struct uart_port *port, int break_state)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ unsigned long flags;
-+ reg_ser_rw_tr_ctrl tr_ctrl;
-+ reg_ser_rw_tr_dma_en tr_dma_en;
-+ reg_ser_rw_intr_mask intr_mask;
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ tr_ctrl = REG_RD(ser, up->regi_ser, rw_tr_ctrl);
-+ tr_dma_en = REG_RD(ser, up->regi_ser, rw_tr_dma_en);
-+ intr_mask = REG_RD(ser, up->regi_ser, rw_intr_mask);
-+
-+ if (break_state != 0) { /* Send break */
-+ /*
-+ * We need to disable DMA (if used) or tr_rdy interrupts if no
-+ * DMA. No need to make this conditional on use of DMA;
-+ * disabling will be a no-op for the other mode.
-+ */
-+ intr_mask.tr_rdy = regk_ser_no;
-+ tr_dma_en.en = 0;
-+
-+ /*
-+ * Stop transmission and set the txd pin to 0 after the
-+ * current character. The txd setting will take effect after
-+ * any current transmission has completed.
-+ */
-+ tr_ctrl.stop = 1;
-+ tr_ctrl.txd = 0;
-+ } else {
-+ /* Re-enable either transmit DMA or the serial interrupt. */
-+ if (up->regi_dmaout)
-+ tr_dma_en.en = 1;
-+ else
-+ intr_mask.tr_rdy = regk_ser_yes;
-+
-+
-+ tr_ctrl.stop = 0;
-+ tr_ctrl.txd = 1;
-+ }
-+ REG_WR(ser, up->regi_ser, rw_tr_ctrl, tr_ctrl);
-+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, tr_dma_en);
-+ REG_WR(ser, up->regi_ser, rw_intr_mask, intr_mask);
-+
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+}
-+
-+/*
-+ * The output DMA channel is free - use it to send as many chars as
-+ * possible.
-+ */
-+
-+static void
-+transmit_chars_dma(struct uart_cris_port *up)
-+{
-+ struct dma_descr_data *descr, *pending_descr, *dmapos;
-+ struct dma_descr_data *last_tx_descr;
-+ struct circ_buf *xmit = &up->port.state->xmit;
-+ unsigned int sentl = 0;
-+ reg_dma_rw_ack_intr ack_intr = { .data = regk_dma_yes };
-+ reg_dma_rw_stat status;
-+ reg_scope_instances regi_dmaout = up->regi_dmaout;
-+ unsigned int chars_in_q;
-+ unsigned int chars_to_send;
-+
-+ /* Acknowledge dma data descriptor irq, if there was one. */
-+ REG_WR(dma, regi_dmaout, rw_ack_intr, ack_intr);
-+
-+ /*
-+ * First get the amount of bytes sent during the last DMA transfer,
-+ * and update xmit accordingly.
-+ */
-+ status = REG_RD(dma, regi_dmaout, rw_stat);
-+ if (status.list_state == regk_dma_data_at_eol || !up->tx_started)
-+ dmapos = phys_to_virt((int)up->last_tx_descr->next);
-+ else
-+ dmapos = phys_to_virt(REG_RD_INT(dma, regi_dmaout, rw_data));
-+
-+ pending_descr = up->first_tx_descr;
-+ while (pending_descr != dmapos) {
-+ sentl += pending_descr->after - pending_descr->buf;
-+ pending_descr->after = pending_descr->buf = NULL;
-+ pending_descr = phys_to_virt((int)pending_descr->next);
-+ }
-+
-+ up->first_tx_descr = pending_descr;
-+ last_tx_descr = up->last_tx_descr;
-+
-+ /* Update stats. */
-+ up->port.icount.tx += sentl;
-+
-+ up->tx_pending_chars -= sentl;
-+
-+ /* Update xmit buffer. */
-+ xmit->tail = (xmit->tail + sentl) & (UART_XMIT_SIZE - 1);
-+
-+ /*
-+ * Find out the largest amount of consecutive bytes we want to send
-+ * now.
-+ */
-+ chars_in_q = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
-+
-+ if (chars_in_q == 0)
-+ /* Tell upper layers that we're now idle. */
-+ goto done;
-+
-+ /* Some of those characters are actually pending output. */
-+ chars_to_send = chars_in_q - up->tx_pending_chars;
-+
-+ /*
-+ * Clamp the new number of pending chars to the advertised
-+ * one.
-+ */
-+ if (chars_to_send + up->tx_pending_chars > up->port.fifosize)
-+ chars_to_send = up->port.fifosize - up->tx_pending_chars;
-+
-+ /* If we don't want to send any, we're done. */
-+ if (chars_to_send == 0)
-+ goto done;
-+
-+ descr = phys_to_virt((int)last_tx_descr->next);
-+
-+ /*
-+ * We can't send anything if we could make the condition in
-+ * the while-loop above (reaping finished descriptors) be met
-+ * immediately before the first iteration. However, don't
-+ * mistake the full state for the empty state.
-+ */
-+ if ((descr == up->first_tx_descr && up->tx_pending_chars != 0)
-+ || descr->next == up->first_tx_descr)
-+ goto done;
-+
-+ /* Set up the descriptor for output. */
-+ descr->buf = (void*)virt_to_phys(xmit->buf + xmit->tail
-+ + up->tx_pending_chars);
-+ descr->after = descr->buf + chars_to_send;
-+ descr->eol = 1;
-+ descr->out_eop = 0;
-+ descr->intr = 1;
-+ descr->wait = 0;
-+ descr->in_eop = 0;
-+ descr->md = 0;
-+ /*
-+ * Make sure GCC doesn't move this eol clear before the eol set
-+ * above.
-+ */
-+ barrier();
-+ last_tx_descr->eol = 0;
-+
-+ up->last_tx_descr = descr;
-+ up->tx_pending_chars += chars_to_send;
-+
-+ if (!up->tx_started) {
-+ up->tx_started = 1;
-+ up->tr_context_descr.next = 0;
-+ up->tr_context_descr.saved_data
-+ = (dma_descr_data*)virt_to_phys(descr);
-+ up->tr_context_descr.saved_data_buf = descr->buf;
-+ DMA_START_CONTEXT(regi_dmaout,
-+ virt_to_phys(&up->tr_context_descr));
-+ } else
-+ DMA_CONTINUE_DATA(regi_dmaout);
-+
-+ /* DMA is now running (hopefully). */
-+
-+ done:
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(&up->port);
-+}
-+
-+static void
-+transmit_chars_no_dma(struct uart_cris_port *up)
-+{
-+ int max_count;
-+ struct circ_buf *xmit = &up->port.state->xmit;
-+
-+ reg_scope_instances regi_ser = up->regi_ser;
-+ reg_ser_r_stat_din rstat;
-+ reg_ser_rw_ack_intr ack_intr = { .tr_rdy = regk_ser_yes };
-+
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-+ /* No more to send, so disable the interrupt. */
-+ reg_ser_rw_intr_mask intr_mask;
-+ intr_mask = REG_RD(ser, regi_ser, rw_intr_mask);
-+ intr_mask.tr_rdy = 0;
-+ intr_mask.tr_empty = 0;
-+ REG_WR(ser, regi_ser, rw_intr_mask, intr_mask);
-+ up->write_ongoing=0;
-+ return;
-+ }
-+
-+ /* If the serport is fast, we send up to max_count bytes before
-+ exiting the loop. */
-+ max_count = 64;
-+ do {
-+ reg_ser_rw_dout dout = { .data = xmit->buf[xmit->tail] };
-+ REG_WR(ser, regi_ser, rw_dout, dout);
-+ REG_WR(ser, regi_ser, rw_ack_intr, ack_intr);
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
-+ up->port.icount.tx++;
-+ if (xmit->head == xmit->tail)
-+ break;
-+ rstat = REG_RD(ser, regi_ser, r_stat_din);
-+ } while ((--max_count > 0) && rstat.tr_rdy);
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(&up->port);
-+} /* transmit_chars_no_dma */
-+
-+static struct etrax_recv_buffer *
-+alloc_recv_buffer(unsigned int size)
-+{
-+ struct etrax_recv_buffer *buffer;
-+
-+ if (!(buffer = kmalloc(sizeof *buffer + size, GFP_ATOMIC)))
-+ panic("%s: Could not allocate %d bytes buffer\n",
-+ __FUNCTION__, size);
-+
-+ buffer->next = NULL;
-+ buffer->length = 0;
-+ buffer->error = TTY_NORMAL;
-+
-+ return buffer;
-+}
-+
-+static void
-+append_recv_buffer(struct uart_cris_port *up,
-+ struct etrax_recv_buffer *buffer)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ if (!up->first_recv_buffer)
-+ up->first_recv_buffer = buffer;
-+ else
-+ up->last_recv_buffer->next = buffer;
-+
-+ up->last_recv_buffer = buffer;
-+
-+ up->recv_cnt += buffer->length;
-+ if (up->recv_cnt > up->max_recv_cnt)
-+ up->max_recv_cnt = up->recv_cnt;
-+
-+ local_irq_restore(flags);
-+}
-+
-+static int
-+add_char_and_flag(struct uart_cris_port *up, unsigned char data,
-+ unsigned char flag)
-+{
-+ struct etrax_recv_buffer *buffer;
-+
-+ buffer = alloc_recv_buffer(4);
-+ buffer->length = 1;
-+ buffer->error = flag;
-+ buffer->buffer[0] = data;
-+
-+ append_recv_buffer(up, buffer);
-+
-+ up->port.icount.rx++;
-+
-+ return 1;
-+}
-+
-+static void
-+flush_to_flip_buffer(struct uart_cris_port *up)
-+{
-+ struct etrax_recv_buffer *buffer;
-+
-+ if (!up->first_recv_buffer)
-+ return;
-+
-+ while ((buffer = up->first_recv_buffer)) {
-+ unsigned int count = (unsigned int)
-+ tty_insert_flip_string(&up->port.state->port,
-+ buffer->buffer,
-+ buffer->length);
-+
-+ up->recv_cnt -= count;
-+
-+ if (count == buffer->length) {
-+ up->first_recv_buffer = buffer->next;
-+ kfree(buffer);
-+ } else {
-+ buffer->length -= count;
-+ memmove(buffer->buffer, buffer->buffer + count,
-+ buffer->length);
-+ buffer->error = TTY_NORMAL;
-+ }
-+ }
-+
-+ if (!up->first_recv_buffer)
-+ up->last_recv_buffer = NULL;
-+
-+ /* This call includes a check for low-latency. */
-+ tty_flip_buffer_push(&up->port.state->port);
-+}
-+
-+static unsigned int
-+handle_descr_data(struct uart_cris_port *up, struct dma_descr_data *descr,
-+ unsigned int recvl)
-+{
-+ struct etrax_recv_buffer *buffer
-+ = phys_to_virt((unsigned long)descr->buf) - sizeof *buffer;
-+
-+ if (up->recv_cnt + recvl > 65536) {
-+ printk(KERN_ERR "Too much pending incoming data on %s!"
-+ " Dropping %u bytes.\n", up->port.state->port.tty->name,
-+ recvl);
-+ return 0;
-+ }
-+
-+ buffer->length = recvl;
-+
-+ append_recv_buffer(up, buffer);
-+
-+ flush_to_flip_buffer(up);
-+
-+ buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE);
-+ descr->buf = (void*)virt_to_phys(buffer->buffer);
-+ descr->after = descr->buf + SERIAL_DESCR_BUF_SIZE;
-+
-+ return recvl;
-+}
-+
-+static unsigned int
-+handle_all_descr_data(struct uart_cris_port *up)
-+{
-+ struct dma_descr_data *descr
-+ = &up->rec_descr[(up->cur_rec_descr - 1)
-+ % SERIAL_RECV_DESCRIPTORS];
-+ struct dma_descr_data *prev_descr;
-+ unsigned int recvl;
-+ unsigned int ret = 0;
-+ reg_scope_instances regi_dmain = up->regi_dmain;
-+
-+ while (1) {
-+ prev_descr = descr;
-+ descr = &up->rec_descr[up->cur_rec_descr];
-+
-+ if (descr == phys_to_virt(REG_RD(dma, regi_dmain, rw_data)))
-+ break;
-+
-+ if (++up->cur_rec_descr == SERIAL_RECV_DESCRIPTORS)
-+ up->cur_rec_descr = 0;
-+
-+ /* Find out how many bytes were read. */
-+ recvl = descr->after - descr->buf;
-+
-+ /* Update stats. */
-+ up->port.icount.rx += recvl;
-+
-+ ret += handle_descr_data(up, descr, recvl);
-+ descr->eol = 1;
-+ /*
-+ * Make sure GCC doesn't move this eol clear before the
-+ * eol set above.
-+ */
-+ barrier();
-+ prev_descr->eol = 0;
-+ flush_dma_descr(descr,1); // Cache bug workaround
-+ flush_dma_descr(prev_descr,0); // Cache bug workaround
-+ }
-+
-+ return ret;
-+}
-+
-+static void
-+receive_chars_dma(struct uart_cris_port *up)
-+{
-+ reg_ser_r_stat_din rstat;
-+ reg_dma_rw_ack_intr ack_intr = {0};
-+
-+ /* Acknowledge both dma_descr and dma_eop irq. */
-+ ack_intr.data = 1;
-+ ack_intr.in_eop = 1;
-+ REG_WR(dma, up->regi_dmain, rw_ack_intr, ack_intr);
-+
-+ handle_all_descr_data(up);
-+
-+ /* Read the status register to detect errors. */
-+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
-+
-+ if (rstat.framing_err | rstat.par_err | rstat.orun) {
-+ /*
-+ * If we got an error, we must reset it by reading the
-+ * rs_stat_din register and put the data in buffer manually.
-+ */
-+ reg_ser_rs_stat_din stat_din;
-+ stat_din = REG_RD(ser, up->regi_ser, rs_stat_din);
-+
-+ if (stat_din.par_err)
-+ add_char_and_flag(up, stat_din.data, TTY_PARITY);
-+ else if (stat_din.orun)
-+ add_char_and_flag(up, stat_din.data, TTY_OVERRUN);
-+ else if (stat_din.framing_err)
-+ add_char_and_flag(up, stat_din.data, TTY_FRAME);
-+ }
-+
-+ /* Restart the receiving DMA, in case it got stuck on an EOL. */
-+ DMA_CONTINUE_DATA(up->regi_dmain);
-+}
-+
-+void receive_chars_no_dma(struct uart_cris_port *up)
-+{
-+ reg_ser_rs_stat_din stat_din;
-+ reg_ser_r_stat_din rstat;
-+ struct uart_icount *icount;
-+ int max_count = 16;
-+ char flag;
-+ reg_ser_rw_ack_intr ack_intr = { 0 };
-+
-+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
-+ up->last_rx_active_usec = GET_JIFFIES_USEC();
-+ up->last_rx_active = jiffies;
-+ icount = &up->port.icount;
-+
-+ do {
-+ stat_din = REG_RD(ser, up->regi_ser, rs_stat_din);
-+
-+ flag = TTY_NORMAL;
-+ ack_intr.dav = 1;
-+ REG_WR(ser, up->regi_ser, rw_ack_intr, ack_intr);
-+ icount->rx++;
-+
-+ if (stat_din.framing_err | stat_din.par_err | stat_din.orun) {
-+ if (stat_din.data == 0x00 &&
-+ stat_din.framing_err) {
-+ /* Most likely a break. */
-+ flag = TTY_BREAK;
-+ icount->brk++;
-+ } else if (stat_din.par_err) {
-+ flag = TTY_PARITY;
-+ icount->parity++;
-+ } else if (stat_din.orun) {
-+ flag = TTY_OVERRUN;
-+ icount->overrun++;
-+ } else if (stat_din.framing_err) {
-+ flag = TTY_FRAME;
-+ icount->frame++;
-+ }
-+ }
-+
-+ /*
-+ * If this becomes important, we probably *could* handle this
-+ * gracefully by keeping track of the unhandled character.
-+ */
-+ if (!tty_insert_flip_char(&up->port.state->port, stat_din.data, flag))
-+ panic("%s: No tty buffer space", __FUNCTION__);
-+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
-+ } while (rstat.dav && (max_count-- > 0));
-+ spin_unlock(&up->port.lock);
-+ tty_flip_buffer_push(&up->port.state->port);
-+ spin_lock(&up->port.lock);
-+} /* receive_chars_no_dma */
-+
-+/*
-+ * DMA output channel interrupt handler.
-+ * this interrupt is called from DMA2(ser2), DMA8(ser3), DMA6(ser0) or
-+ * DMA4(ser1) when they have finished a descriptor with the intr flag set.
-+ */
-+static irqreturn_t dma_tr_interrupt(int irq, void *dev_id)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)dev_id;
-+ reg_dma_r_masked_intr masked_intr;
-+ reg_scope_instances regi_dmaout;
-+ int handled = 0;
-+
-+ spin_lock(&up->port.lock);
-+ regi_dmaout = up->regi_dmaout;
-+ if (!regi_dmaout) {
-+ spin_unlock(&up->port.lock);
-+ return IRQ_NONE;
-+ }
-+
-+ /*
-+ * Check for dma_descr (don't need to check for dma_eop in
-+ * output DMA for serial).
-+ */
-+ masked_intr = REG_RD(dma, regi_dmaout, r_masked_intr);
-+
-+ if (masked_intr.data) {
-+ /* We can send a new dma bunch. make it so. */
-+
-+ /*
-+ * Read jiffies_usec first.
-+ * We want this time to be as late as possible.
-+ */
-+ up->last_tx_active_usec = GET_JIFFIES_USEC();
-+ up->last_tx_active = jiffies;
-+ transmit_chars_dma(up);
-+ handled = 1;
-+ }
-+ check_modem_status(up);
-+ spin_unlock(&up->port.lock);
-+ return IRQ_RETVAL(handled);
-+}
-+
-+/* DMA input channel interrupt handler. */
-+
-+static irqreturn_t
-+dma_rec_interrupt(int irq, void *dev_id)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)dev_id;
-+ reg_dma_r_masked_intr masked_intr;
-+ reg_scope_instances regi_dmain;
-+ int handled = 0;
-+
-+ spin_lock(&up->port.lock);
-+ regi_dmain = up->regi_dmain;
-+ if (!regi_dmain) {
-+ spin_unlock(&up->port.lock);
-+ return IRQ_NONE;
-+ }
-+
-+ /* Check for both dma_eop and dma_descr for the input dma channel. */
-+ masked_intr = REG_RD(dma, regi_dmain, r_masked_intr);
-+ if (masked_intr.data || masked_intr.in_eop) {
-+ /* We have received something. */
-+ receive_chars_dma(up);
-+ handled = 1;
-+ }
-+ check_modem_status(up);
-+ spin_unlock(&up->port.lock);
-+ return IRQ_RETVAL(handled);
-+}
-+
-+/* "Normal" serial port interrupt handler - both rx and tx. */
-+
-+static irqreturn_t
-+ser_interrupt(int irq, void *dev_id)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)dev_id;
-+ reg_scope_instances regi_ser;
-+ int handled = 0;
-+
-+ spin_lock(&up->port.lock);
-+ if (up->regi_dmain && up->regi_dmaout) {
-+ spin_unlock(&up->port.lock);
-+ return IRQ_NONE;
-+ }
-+
-+ regi_ser = up->regi_ser;
-+
-+ if (regi_ser) {
-+ reg_ser_r_masked_intr masked_intr;
-+ masked_intr = REG_RD(ser, regi_ser, r_masked_intr);
-+ /*
-+ * Check what interrupts are active before taking
-+ * actions. If DMA is used the interrupt shouldn't
-+ * be enabled.
-+ */
-+ if (masked_intr.dav) {
-+ receive_chars_no_dma(up);
-+ handled = 1;
-+ }
-+ check_modem_status(up);
-+
-+ if (masked_intr.tr_rdy) {
-+ transmit_chars_no_dma(up);
-+ handled = 1;
-+ }
-+ }
-+ spin_unlock(&up->port.lock);
-+ return IRQ_RETVAL(handled);
-+} /* ser_interrupt */
-+
-+static int start_recv_dma(struct uart_cris_port *up)
-+{
-+ struct dma_descr_data *descr = up->rec_descr;
-+ struct etrax_recv_buffer *buffer;
-+ int i;
-+
-+ /* Set up the receiving descriptors. */
-+ for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) {
-+ buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE);
-+ descr[i].next = (void*)virt_to_phys(&descr[i+1]);
-+ descr[i].buf = (void*)virt_to_phys(buffer->buffer);
-+ descr[i].after = descr[i].buf + SERIAL_DESCR_BUF_SIZE;
-+ descr[i].eol = 0;
-+ descr[i].out_eop = 0;
-+ descr[i].intr = 1;
-+ descr[i].wait = 0;
-+ descr[i].in_eop = 0;
-+ descr[i].md = 0;
-+
-+ }
-+
-+ /* Link the last descriptor to the first. */
-+ descr[i-1].next = (void*)virt_to_phys(&descr[0]);
-+
-+ /* And mark it as end of list. */
-+ descr[i-1].eol = 1;
-+
-+ /* Start with the first descriptor in the list. */
-+ up->cur_rec_descr = 0;
-+ up->rec_context_descr.next = 0;
-+ up->rec_context_descr.saved_data
-+ = (dma_descr_data *)virt_to_phys(&descr[up->cur_rec_descr]);
-+ up->rec_context_descr.saved_data_buf = descr[up->cur_rec_descr].buf;
-+
-+ /* Start the DMA. */
-+ DMA_START_CONTEXT(up->regi_dmain,
-+ virt_to_phys(&up->rec_context_descr));
-+
-+ /* Input DMA should be running now. */
-+ return 1;
-+}
-+
-+#ifdef CONFIG_CONSOLE_POLL
-+/*
-+ * Console polling routines for writing and reading from the uart while
-+ * in an interrupt or debug context.
-+ */
-+
-+static int serial_artpec_get_poll_char(struct uart_port *port)
-+{
-+ reg_ser_rs_stat_din stat;
-+ reg_ser_rw_ack_intr ack_intr = { 0 };
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+
-+ do {
-+ stat = REG_RD(ser, up->regi_ser, rs_stat_din);
-+ } while (!stat.dav);
-+
-+ /* Ack the data_avail interrupt. */
-+ ack_intr.dav = 1;
-+ REG_WR(ser, up->regi_ser, rw_ack_intr, ack_intr);
-+
-+ return stat.data;
-+}
-+
-+static void serial_artpec_put_poll_char(struct uart_port *port,
-+ unsigned char c)
-+{
-+ reg_ser_r_stat_din stat;
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+
-+ do {
-+ stat = REG_RD (ser, up->regi_ser, r_stat_din);
-+ } while (!stat.tr_rdy);
-+ REG_WR_INT (ser, up->regi_ser, rw_dout, c);
-+}
-+#endif /* CONFIG_CONSOLE_POLL */
-+
-+static void start_receive(struct uart_cris_port *up)
-+{
-+ reg_scope_instances regi_dmain = up->regi_dmain;
-+ if (regi_dmain) {
-+ start_recv_dma(up);
-+ }
-+}
-+
-+
-+static void start_transmitter(struct uart_cris_port *up)
-+{
-+ int i;
-+ reg_scope_instances regi_dmaout = up->regi_dmaout;
-+ if (regi_dmaout) {
-+ for (i = 0; i < SERIAL_TX_DESCRIPTORS; i++) {
-+ memset(&up->tr_descr[i], 0, sizeof(up->tr_descr[i]));
-+ up->tr_descr[i].eol = 1;
-+ up->tr_descr[i].intr = 1;
-+ up->tr_descr[i].next = (dma_descr_data *)
-+ virt_to_phys(&up->tr_descr[i+1]);
-+ }
-+ up->tr_descr[i-1].next = (dma_descr_data *)
-+ virt_to_phys(&up->tr_descr[0]);
-+ up->first_tx_descr = &up->tr_descr[0];
-+
-+ /*
-+ * We'll be counting up to up->last_tx_descr->next from
-+ * up->first_tx_descr when starting DMA, so we should make
-+ * them the same for the very first round. If instead we'd
-+ * set last_tx_descr = first_tx_descr, we'd rely on
-+ * accidentally working code and data as we'd take a pass over
-+ * the first, unused, descriptor.
-+ */
-+ up->last_tx_descr = &up->tr_descr[i-1];
-+ up->tx_started = 0;
-+ up->tx_pending_chars = 0;
-+ }
-+}
-+
-+static int serial_cris_startup(struct uart_port *port)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ unsigned long flags;
-+ reg_ser_rw_intr_mask ser_intr_mask = {0};
-+ reg_dma_rw_intr_mask dmain_intr_mask = {0};
-+ reg_dma_rw_intr_mask dmaout_intr_mask = {0};
-+ reg_dma_rw_cfg cfg = {.en = 1};
-+ reg_scope_instances regi_dma;
-+
-+ /* We dont disable interrupts here because request_irq should
-+ not be called with ints disabled. */
-+ spin_lock(&up->port.lock);
-+
-+ dmain_intr_mask.data = dmain_intr_mask.in_eop = regk_dma_yes;
-+ dmaout_intr_mask.data = regk_dma_yes;
-+ if (!up->regi_dmain)
-+ ser_intr_mask.dav = regk_ser_yes;
-+
-+ if (port->line == 0) {
-+ if (request_irq(SER0_INTR_VECT, ser_interrupt,
-+ IRQF_DISABLED, "ser0",
-+ &serial_cris_ports[0]))
-+ panic("irq ser0");
-+ /* Port ser0 can use dma6 for tx and dma7 for rx. */
-+#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
-+ if (request_irq(DMA6_INTR_VECT, dma_tr_interrupt,
-+ IRQF_DISABLED, "serial 0 dma tr",
-+ &serial_cris_ports[0]))
-+ panic("irq ser0txdma");
-+ crisv32_request_dma(6, "ser0", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser0);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
-+ if (request_irq(DMA7_INTR_VECT, dma_rec_interrupt,
-+ IRQF_DISABLED, "serial 0 dma rec",
-+ &serial_cris_ports[0]))
-+ panic("irq ser0rxdma");
-+ crisv32_request_dma(7, "ser0", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser0);
-+#endif
-+ } else if (port->line == 1) {
-+ if (request_irq(SER1_INTR_VECT, ser_interrupt,
-+ IRQF_DISABLED, "ser1",
-+ &serial_cris_ports[1]))
-+ panic("irq ser1");
-+
-+ /* Port ser1 can use dma4 for tx and dma5 for rx. */
-+#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA4_OUT
-+ if (request_irq(DMA4_INTR_VECT, dma_tr_interrupt,
-+ IRQF_DISABLED, "serial 1 dma tr",
-+ &serial_cris_ports[1]))
-+ panic("irq ser1txdma");
-+ crisv32_request_dma(4, "ser1", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser1);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA5_IN
-+ if (request_irq(DMA5_INTR_VECT, dma_rec_interrupt,
-+ IRQF_DISABLED, "serial 1 dma rec",
-+ &serial_cris_ports[1]))
-+ panic("irq ser1rxdma");
-+ crisv32_request_dma(5, "ser1", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser1);
-+#endif
-+ } else if (port->line == 2) {
-+ if (request_irq(SER2_INTR_VECT, ser_interrupt,
-+ IRQF_DISABLED, "ser2",
-+ &serial_cris_ports[2]))
-+ panic("irq ser2");
-+
-+ /* Port ser2 can use dma2 for tx and dma3 for rx. */
-+#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
-+ if (request_irq(DMA2_INTR_VECT, dma_tr_interrupt,
-+ IRQF_DISABLED, "serial 2 dma tr",
-+ &serial_cris_ports[2]))
-+ panic("irq ser2txdma");
-+ crisv32_request_dma(2, "ser2", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser2);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
-+ if (request_irq(DMA3_INTR_VECT, dma_rec_interrupt,
-+ IRQF_DISABLED, "serial 2 dma rec",
-+ &serial_cris_ports[2]))
-+ panic("irq ser2rxdma");
-+ crisv32_request_dma(3, "ser2", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser2);
-+#endif
-+ } else if (port->line == 3) {
-+ if (request_irq(SER3_INTR_VECT, ser_interrupt,
-+ IRQF_DISABLED, "ser3",
-+ &serial_cris_ports[3]))
-+ panic("irq ser3" );
-+
-+ /* Port ser3 can use dma8 for tx and dma9 for rx. */
-+#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA8_OUT
-+ if (request_irq(DMA8_INTR_VECT, dma_tr_interrupt,
-+ IRQF_DISABLED, "serial 3 dma tr",
-+ &serial_cris_ports[3]))
-+ panic("irq ser3txdma");
-+ crisv32_request_dma(8, "ser3", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser3);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA9_IN
-+ if (request_irq(DMA9_INTR_VECT, dma_rec_interrupt,
-+ IRQF_DISABLED, "serial 3 dma rec",
-+ &serial_cris_ports[3]))
-+ panic("irq ser3rxdma");
-+ crisv32_request_dma(9, "ser3", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser3);
-+#endif
-+ }
-+#if CONFIG_ETRAX_SERIAL_PORTS == 5
-+ else if (port->line == 4) {
-+ if (request_irq(SER4_INTR_VECT, ser_interrupt,
-+ IRQF_DISABLED, "ser4",
-+ &serial_cris_ports[4]))
-+ panic("irq ser4" );
-+
-+#ifdef CONFIG_ETRAX_SERIAL_PORT4_DMA_OUT
-+ if (request_irq(DMA4_INTR_VECT, dma_tr_interrupt,
-+ IRQF_DISABLED, "serial 4 dma tr",
-+ &serial_cris_ports[4]))
-+ panic("irq ser4txdma");
-+ crisv32_request_dma(5, "ser4", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser4);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT4_DMA_IN
-+ if (request_irq(DMA5_INTR_VECT, dma_rec_interrupt,
-+ IRQF_DISABLED, "serial 4 dma rec",
-+ &serial_cris_ports[4]))
-+ panic("irq ser4rxdma");
-+ crisv32_request_dma(5, "ser4", DMA_PANIC_ON_ERROR, 0,
-+ dma_ser4);
-+#endif
-+ }
-+#endif
-+
-+ local_irq_save(flags);
-+
-+ /*
-+ * Reset the DMA channels and make sure their interrupts are cleared.
-+ */
-+
-+ regi_dma = up->regi_dmain;
-+ if (regi_dma) {
-+ reg_dma_rw_ack_intr ack_intr = { 0 };
-+ DMA_RESET(regi_dma);
-+ /* Wait until reset cycle is complete. */
-+ DMA_WAIT_UNTIL_RESET(regi_dma);
-+ REG_WR(dma, regi_dma, rw_cfg, cfg);
-+ /* Make sure the irqs are cleared. */
-+ ack_intr.group = 1;
-+ ack_intr.ctxt = 1;
-+ ack_intr.data = 1;
-+ ack_intr.in_eop = 1;
-+ ack_intr.stream_cmd = 1;
-+ REG_WR(dma, regi_dma, rw_ack_intr, ack_intr);
-+ }
-+ regi_dma = up->regi_dmaout;
-+ if (regi_dma) {
-+ reg_dma_rw_ack_intr ack_intr = { 0 };
-+ DMA_RESET(regi_dma);
-+ /* Wait until reset cycle is complete. */
-+ DMA_WAIT_UNTIL_RESET(regi_dma);
-+ REG_WR(dma, regi_dma, rw_cfg, cfg);
-+ /* Make sure the irqs are cleared. */
-+ ack_intr.group = 1;
-+ ack_intr.ctxt = 1;
-+ ack_intr.data = 1;
-+ ack_intr.in_eop = 1;
-+ ack_intr.stream_cmd = 1;
-+ REG_WR(dma, regi_dma, rw_ack_intr, ack_intr);
-+ }
-+
-+ REG_WR(ser, up->regi_ser, rw_intr_mask, ser_intr_mask);
-+ if (up->regi_dmain)
-+ REG_WR(dma, up->regi_dmain, rw_intr_mask, dmain_intr_mask);
-+ if (up->regi_dmaout)
-+ REG_WR(dma, up->regi_dmaout, rw_intr_mask, dmaout_intr_mask);
-+
-+ start_receive(up);
-+ start_transmitter(up);
-+
-+ serial_cris_set_mctrl(&up->port, up->port.mctrl);
-+
-+ local_irq_restore(flags);
-+ spin_unlock(&up->port.lock);
-+
-+ return 0;
-+}
-+
-+static void serial_cris_shutdown(struct uart_port *port)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+
-+ serial_cris_stop_tx(port);
-+ serial_cris_stop_rx(port);
-+
-+ if (port->line == 0) {
-+ free_irq(SER0_INTR_VECT, &serial_cris_ports[0]);
-+#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
-+ crisv32_free_dma(6);
-+ free_irq(DMA6_INTR_VECT, &serial_cris_ports[0]);
-+#elif defined(CONFIG_ETRAX_SERIAL_PORT0_DMA0_OUT)
-+ crisv32_free_dma(0);
-+ free_irq(DMA0_INTR_VECT, &serial_cris_ports[0]);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
-+ crisv32_free_dma(7);
-+ free_irq(DMA7_INTR_VECT, &serial_cris_ports[0]);
-+#elif defined(CONFIG_ETRAX_SERIAL_PORT0_DMA1_IN)
-+ crisv32_free_dma(1);
-+ free_irq(DMA1_INTR_VECT, &serial_cris_ports[0]);
-+#endif
-+ } else if (port->line == 1) {
-+ free_irq(SER1_INTR_VECT, &serial_cris_ports[1]);
-+#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA4_OUT
-+ crisv32_free_dma(4);
-+ free_irq(DMA4_INTR_VECT, &serial_cris_ports[1]);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA5_IN
-+ crisv32_free_dma(5);
-+ free_irq(DMA5_INTR_VECT, &serial_cris_ports[1]);
-+#endif
-+ } else if (port->line == 2) {
-+ free_irq(SER2_INTR_VECT, &serial_cris_ports[2]);
-+#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
-+ crisv32_free_dma(2);
-+ free_irq(DMA2_INTR_VECT, &serial_cris_ports[2]);
-+#elif defined(CONFIG_ETRAX_SERIAL_PORT2_DMA6_OUT)
-+ crisv32_free_dma(6);
-+ free_irq(DMA6_INTR_VECT, &serial_cris_ports[2]);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
-+ crisv32_free_dma(3);
-+ free_irq(DMA3_INTR_VECT, &serial_cris_ports[2]);
-+#elif defined(CONFIG_ETRAX_SERIAL_PORT2_DMA7_IN)
-+ crisv32_free_dma(7);
-+ free_irq(DMA7_INTR_VECT, &serial_cris_ports[2]);
-+#endif
-+ } else if (port->line == 3) {
-+ free_irq(SER3_INTR_VECT, &serial_cris_ports[3]);
-+#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA8_OUT
-+ crisv32_free_dma(8);
-+ free_irq(DMA8_INTR_VECT, &serial_cris_ports[3]);
-+#elif defined(CONFIG_ETRAX_SERIAL_PORT3_DMA2_OUT)
-+ crisv32_free_dma(2);
-+ free_irq(DMA2_INTR_VECT, &serial_cris_ports[3]);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA9_IN
-+ crisv32_free_dma(9);
-+ free_irq(DMA9_INTR_VECT, &serial_cris_ports[3]);
-+#elif defined(CONFIG_ETRAX_SERIAL_PORT3_DMA3_IN)
-+ crisv32_free_dma(3);
-+ free_irq(DMA3_INTR_VECT, &serial_cris_ports[3]);
-+#endif
-+ }
-+#if CONFIG_ETRAX_SERIAL_PORTS == 5
-+ else if (port->line == 4) {
-+ free_irq(SER4_INTR_VECT, &serial_cris_ports[4]);
-+#ifdef CONFIG_ETRAX_SERIAL_PORT4_DMA9_IN
-+ crisv32_free_dma(9);
-+ free_irq(DMA9_INTR_VECT, &serial_cris_ports[4]);
-+#endif
-+ }
-+#endif
-+
-+ serial_cris_set_mctrl(&up->port, up->port.mctrl);
-+
-+ if (up->regi_dmain) {
-+ struct etrax_recv_buffer *rb;
-+ struct etrax_recv_buffer *rb_next;
-+ int i;
-+ struct dma_descr_data *descr;
-+
-+ /*
-+ * In case of DMA and receive errors, there might be pending
-+ * receive buffers still linked here and not flushed upwards.
-+ * Release them.
-+ */
-+ for (rb = up->first_recv_buffer; rb != NULL; rb = rb_next) {
-+ rb_next = rb->next;
-+ kfree (rb);
-+ }
-+ up->first_recv_buffer = NULL;
-+ up->last_recv_buffer = NULL;
-+
-+ /*
-+ * Also release buffers that were attached to the DMA
-+ * before we shut down the hardware above.
-+ */
-+ for (i = 0, descr = up->rec_descr;
-+ i < SERIAL_RECV_DESCRIPTORS;
-+ i++)
-+ if (descr[i].buf) {
-+ rb = phys_to_virt((u32) descr[i].buf)
-+ - sizeof *rb;
-+ kfree(rb);
-+ descr[i].buf = NULL;
-+ }
-+ }
-+
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+}
-+
-+static void
-+serial_cris_set_termios(struct uart_port *port, struct ktermios *termios,
-+ struct ktermios *old)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ unsigned long flags;
-+ reg_ser_rw_xoff xoff;
-+ reg_ser_rw_xoff_clr xoff_clr = {0};
-+ reg_ser_rw_tr_ctrl tx_ctrl = {0};
-+ reg_ser_rw_tr_dma_en tx_dma_en = {0};
-+ reg_ser_rw_rec_ctrl rx_ctrl = {0};
-+ reg_ser_rw_tr_baud_div tx_baud_div = {0};
-+ reg_ser_rw_rec_baud_div rx_baud_div = {0};
-+ reg_ser_r_stat_din rstat;
-+ int baud;
-+
-+ if (old &&
-+ termios->c_cflag == old->c_cflag &&
-+ termios->c_iflag == old->c_iflag)
-+ return;
-+
-+ /* Start with default settings and then fill in changes. */
-+
-+ /* Tx: 8 bit, no/even parity, 1 stop bit, no cts. */
-+ tx_ctrl.base_freq = regk_ser_f29_493;
-+ tx_ctrl.en = 0;
-+ tx_ctrl.stop = 0;
-+#ifdef CONFIG_ETRAX_RS485
-+ if (up->rs485.enabled && (up->port_type != TYPE_485FD)) {
-+ tx_ctrl.auto_rts = regk_ser_yes;
-+ tx_ctrl.rts_setup = regk_ser_bits2;
-+
-+ if (termios->c_cflag & CSTOPB) {
-+ /* 2 stop bits. */
-+ tx_ctrl.rts_delay = regk_ser_del2;
-+ }
-+ else {
-+ /* 1 stop bits. */
-+ tx_ctrl.rts_delay = regk_ser_del1;
-+ }
-+ } else
-+#endif
-+ tx_ctrl.auto_rts = regk_ser_no;
-+ tx_ctrl.txd = 1;
-+ tx_ctrl.auto_cts = 0;
-+ /* Rx: 8 bit, no/even parity. */
-+ if (up->regi_dmain) {
-+ rx_ctrl.dma_mode = 1;
-+ rx_ctrl.auto_eop = 1;
-+ }
-+ rx_ctrl.dma_err = regk_ser_stop;
-+ rx_ctrl.sampling = regk_ser_majority;
-+ rx_ctrl.timeout = 1;
-+
-+#ifdef CONFIG_ETRAX_RS485
-+ if (up->rs485.enabled && (up->port_type != TYPE_485FD)) {
-+# ifdef CONFIG_ETRAX_RS485_DISABLE_RECEIVER
-+ rx_ctrl.half_duplex = regk_ser_yes;
-+# endif
-+ rx_ctrl.rts_n = up->rs485.rts_after_sent ?
-+ regk_ser_active : regk_ser_inactive;
-+ } else if (up->port_type == TYPE_485FD) {
-+ rx_ctrl.rts_n = regk_ser_active;
-+ } else
-+#endif
-+ rx_ctrl.rts_n = regk_ser_inactive;
-+
-+ /* Common for tx and rx: 8N1. */
-+ tx_ctrl.data_bits = regk_ser_bits8;
-+ rx_ctrl.data_bits = regk_ser_bits8;
-+ tx_ctrl.par = regk_ser_even;
-+ rx_ctrl.par = regk_ser_even;
-+ tx_ctrl.par_en = regk_ser_no;
-+ rx_ctrl.par_en = regk_ser_no;
-+
-+ tx_ctrl.stop_bits = regk_ser_bits1;
-+
-+
-+ /* Change baud-rate and write it to the hardware. */
-+
-+ /* baud_clock = base_freq / (divisor*8)
-+ * divisor = base_freq / (baud_clock * 8)
-+ * base_freq is either:
-+ * off, ext, 29.493MHz, 32.000 MHz, 32.768 MHz or 100 MHz
-+ * 20.493MHz is used for standard baudrates
-+ */
-+
-+ /*
-+ * For the console port we keep the original baudrate here. Not very
-+ * beautiful.
-+ */
-+ if ((port != console_port) || old)
-+ baud = uart_get_baud_rate(port, termios, old, 0,
-+ port->uartclk / 8);
-+ else
-+ baud = console_baud;
-+
-+ tx_baud_div.div = 29493000 / (8 * baud);
-+ /* Rx uses same as tx. */
-+ rx_baud_div.div = tx_baud_div.div;
-+ rx_ctrl.base_freq = tx_ctrl.base_freq;
-+
-+ if ((termios->c_cflag & CSIZE) == CS7) {
-+ /* Set 7 bit mode. */
-+ tx_ctrl.data_bits = regk_ser_bits7;
-+ rx_ctrl.data_bits = regk_ser_bits7;
-+ }
-+
-+ if (termios->c_cflag & CSTOPB) {
-+ /* Set 2 stop bit mode. */
-+ tx_ctrl.stop_bits = regk_ser_bits2;
-+ }
-+
-+ if (termios->c_cflag & PARENB) {
-+ /* Enable parity. */
-+ tx_ctrl.par_en = regk_ser_yes;
-+ rx_ctrl.par_en = regk_ser_yes;
-+ }
-+
-+ if (termios->c_cflag & CMSPAR) {
-+ if (termios->c_cflag & PARODD) {
-+ /* Set mark parity if PARODD and CMSPAR. */
-+ tx_ctrl.par = regk_ser_mark;
-+ rx_ctrl.par = regk_ser_mark;
-+ } else {
-+ tx_ctrl.par = regk_ser_space;
-+ rx_ctrl.par = regk_ser_space;
-+ }
-+ } else {
-+ if (termios->c_cflag & PARODD) {
-+ /* Set odd parity. */
-+ tx_ctrl.par = regk_ser_odd;
-+ rx_ctrl.par = regk_ser_odd;
-+ }
-+ }
-+
-+ if (termios->c_cflag & CRTSCTS) {
-+ /* Enable automatic CTS handling. */
-+ tx_ctrl.auto_cts = regk_ser_yes;
-+ }
-+
-+ /* Make sure the tx and rx are enabled. */
-+ tx_ctrl.en = regk_ser_yes;
-+ rx_ctrl.en = regk_ser_yes;
-+
-+ /*
-+ * Wait for tr_idle in case a character is being output, so it won't
-+ * be damaged by the changes we do below. It seems the termios
-+ * changes "sometimes" (we can't see e.g. a tcsetattr TCSANOW
-+ * parameter here) should take place no matter what state. However,
-+ * in case we should wait, we may have a non-empty transmitter state
-+ * as we tell the upper layers that we're all done when we've passed
-+ * characters to the hardware, but we don't wait for them being
-+ * actually shifted out.
-+ */
-+ spin_lock_irqsave(&port->lock, flags);
-+
-+ /*
-+ * None of our interrupts re-enable DMA, so it's thankfully ok to
-+ * disable it once, outside the loop.
-+ */
-+ tx_dma_en.en = 0;
-+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en);
-+ do {
-+ /*
-+ * Make sure we have integrity between the read r_stat status
-+ * and us writing the registers below, but don't busy-wait
-+ * with interrupts off. We need to keep the port lock though
-+ * (if we go SMP), so nobody else writes characters.
-+ */
-+ local_irq_restore(flags);
-+ local_irq_save(flags);
-+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
-+ } while (!rstat.tr_idle);
-+
-+ /* Actually write the control regs (if modified) to the hardware. */
-+
-+ uart_update_timeout(port, termios->c_cflag, port->uartclk/8);
-+ MODIFY_REG(up->regi_ser, rw_rec_baud_div, rx_baud_div);
-+ MODIFY_REG(up->regi_ser, rw_rec_ctrl, rx_ctrl);
-+
-+ MODIFY_REG(up->regi_ser, rw_tr_baud_div, tx_baud_div);
-+ MODIFY_REG(up->regi_ser, rw_tr_ctrl, tx_ctrl);
-+
-+ tx_dma_en.en = up->regi_dmaout != 0;
-+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en);
-+
-+ xoff = REG_RD(ser, up->regi_ser, rw_xoff);
-+
-+ if (up->port.state && up->port.state->port.tty &&
-+ (termios->c_iflag & IXON)) {
-+ xoff.chr = STOP_CHAR(up->port.state->port.tty);
-+ xoff.automatic = regk_ser_yes;
-+ } else
-+ xoff.automatic = regk_ser_no;
-+
-+ MODIFY_REG(up->regi_ser, rw_xoff, xoff);
-+
-+ /*
-+ * Make sure we don't start in an automatically shut-off state due to
-+ * a previous early exit.
-+ */
-+ xoff_clr.clr = 1;
-+ REG_WR(ser, up->regi_ser, rw_xoff_clr, xoff_clr);
-+
-+ serial_cris_set_mctrl(&up->port, up->port.mctrl);
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+}
-+
-+static const char *
-+serial_cris_type(struct uart_port *port)
-+{
-+ return "CRISv32";
-+}
-+
-+static void serial_cris_release_port(struct uart_port *port)
-+{
-+}
-+
-+static int serial_cris_request_port(struct uart_port *port)
-+{
-+ return 0;
-+}
-+
-+static void serial_cris_config_port(struct uart_port *port, int flags)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ up->port.type = PORT_CRIS;
-+}
-+
-+#if defined(CONFIG_ETRAX_RS485)
-+
-+static void cris_set_rs485_mode(struct uart_cris_port* up) {
-+ reg_ser_rw_tr_ctrl tr_ctrl;
-+ reg_ser_rw_rec_ctrl rec_ctrl;
-+ reg_scope_instances regi_ser = up->regi_ser;
-+
-+ if (up->port_type == TYPE_485FD)
-+ /* We do not want to change anything if we are in 485FD mode */
-+ return;
-+
-+ tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
-+ rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
-+
-+ /* Set port in RS-485 mode */
-+ if (up->rs485.enabled) {
-+ tr_ctrl.auto_rts = regk_ser_yes;
-+ rec_ctrl.rts_n = up->rs485.rts_after_sent ?
-+ regk_ser_active : regk_ser_inactive;
-+ }
-+ /* Set port to RS-232 mode */
-+ else {
-+ rec_ctrl.rts_n = regk_ser_inactive;
-+ tr_ctrl.auto_rts = regk_ser_no;
-+ rec_ctrl.half_duplex = regk_ser_no;
-+ }
-+
-+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
-+ REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
-+}
-+
-+/* Enable/disable RS-485 mode on selected port. */
-+static int
-+cris_enable_rs485(struct uart_cris_port* up, struct rs485_control *r)
-+{
-+ if (up->port_type == TYPE_485FD)
-+ /* Port in 485FD mode can not chage mode */
-+ goto out;
-+
-+ up->rs485.enabled = 0x1 & r->enabled;
-+ up->rs485.rts_on_send = 0x01 & r->rts_on_send;
-+ up->rs485.rts_after_sent = 0x01 & r->rts_after_sent;
-+ up->rs485.delay_rts_before_send = r->delay_rts_before_send;
-+
-+ cris_set_rs485_mode(up);
-+ out:
-+ return 0;
-+}
-+
-+
-+/* Enable RS485 mode on port and send the data. Port will stay
-+ * in 485 mode after the data has been sent.
-+ */
-+static int
-+cris_write_rs485(struct uart_cris_port *up, const unsigned char* buf, int count)
-+{
-+ up->rs485.enabled = 1;
-+
-+ /* Set the port in RS485 mode */
-+ cris_set_rs485_mode(up);
-+
-+ /* Send the data */
-+ count = serial_cris_driver.tty_driver->ops->write(up->port.state->port.tty, buf, count);
-+
-+ return count;
-+}
-+
-+#endif /* CONFIG_ETRAX_RS485 */
-+
-+static int serial_cris_ioctl(struct uart_port *port, unsigned int cmd,
-+ unsigned long arg)
-+{
-+#if defined(CONFIG_ETRAX_RS485)
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+
-+ switch (cmd) {
-+ case TIOCSRS485: {
-+ struct serial_rs485 in;
-+ struct rs485_control rs485ctrl;
-+ if (copy_from_user(&in, (struct serial_rs485 *)cmd,
-+ sizeof(rs485ctrl)))
-+ return -EFAULT;
-+ rs485ctrl.rts_on_send = in.flags & SER_RS485_RTS_ON_SEND;
-+ rs485ctrl.rts_after_sent = in.flags & SER_RS485_RTS_AFTER_SEND;
-+ rs485ctrl.enabled = in.flags & SER_RS485_ENABLED;
-+ rs485ctrl.delay_rts_before_send = in.delay_rts_before_send;
-+
-+ return cris_enable_rs485(up, &rs485ctrl);
-+ }
-+
-+ case TIOCSERSETRS485: {
-+ struct rs485_control rs485ctrl;
-+ if (copy_from_user(&rs485ctrl, (struct rs485_control*) arg,
-+ sizeof(rs485ctrl)))
-+ return -EFAULT;
-+
-+ return cris_enable_rs485(up, &rs485ctrl);
-+ }
-+
-+ case TIOCSERWRRS485: {
-+ struct rs485_write rs485wr;
-+ if (copy_from_user(&rs485wr, (struct rs485_write*)arg,
-+ sizeof(rs485wr)))
-+ return -EFAULT;
-+
-+ return cris_write_rs485(up, rs485wr.outc, rs485wr.outc_size);
-+ }
-+
-+ case TIOCSERSETRS485FD: {
-+ reg_scope_instances regi_ser = up->regi_ser;
-+ reg_ser_rw_rec_ctrl rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
-+
-+ if (arg)
-+ rec_ctrl.half_duplex = regk_ser_no;
-+ else
-+ rec_ctrl.half_duplex = regk_ser_yes;
-+
-+ REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
-+ return 0;
-+ }
-+
-+ case TIOCSERSETDIVISOR: {
-+ reg_ser_rw_tr_baud_div tx_baud_div = {0};
-+ reg_ser_rw_rec_baud_div rx_baud_div = {0};
-+
-+ /* divisor must be >= 8 */
-+ if (arg < 8)
-+ return -EINVAL;
-+
-+ tx_baud_div.div = arg;
-+ rx_baud_div.div = tx_baud_div.div; /* same as tx. */
-+
-+ MODIFY_REG(up->regi_ser, rw_rec_baud_div, rx_baud_div);
-+ MODIFY_REG(up->regi_ser, rw_tr_baud_div, tx_baud_div);
-+
-+ return 0;
-+ }
-+
-+ default:
-+ return -ENOIOCTLCMD;
-+ }
-+
-+ return 0;
-+#else
-+ return -ENOIOCTLCMD;
-+#endif
-+}
-+
-+static const struct uart_ops serial_cris_pops = {
-+ .tx_empty = serial_cris_tx_empty,
-+ .set_mctrl = serial_cris_set_mctrl,
-+ .get_mctrl = serial_cris_get_mctrl,
-+ .stop_tx = serial_cris_stop_tx,
-+ .start_tx = serial_cris_start_tx,
-+ .send_xchar = serial_cris_send_xchar,
-+ .stop_rx = serial_cris_stop_rx,
-+ .enable_ms = serial_cris_enable_ms,
-+ .break_ctl = serial_cris_break_ctl,
-+ .startup = serial_cris_startup,
-+ .shutdown = serial_cris_shutdown,
-+ .set_termios = serial_cris_set_termios,
-+ .type = serial_cris_type,
-+ .release_port = serial_cris_release_port,
-+ .request_port = serial_cris_request_port,
-+ .config_port = serial_cris_config_port,
-+ .ioctl = serial_cris_ioctl,
-+#ifdef CONFIG_CONSOLE_POLL
-+ .poll_get_char = serial_artpec_get_poll_char,
-+ .poll_put_char = serial_artpec_put_poll_char,
-+#endif
-+};
-+
-+/*
-+ * It's too easy to break CONFIG_ETRAX_DEBUG_PORT_NULL and the
-+ * no-config choices by adding and moving code to before a necessary
-+ * early exit in all functions for the special case of
-+ * up->regi_ser == 0. This collection of dummy functions lets us
-+ * avoid that. Maybe there should be a generic table of dummy serial
-+ * functions?
-+ */
-+
-+static unsigned int serial_cris_tx_empty_dummy(struct uart_port *port)
-+{
-+ return TIOCSER_TEMT;
-+}
-+
-+static void serial_cris_set_mctrl_dummy(struct uart_port *port,
-+ unsigned int mctrl)
-+{
-+}
-+
-+static unsigned int serial_cris_get_mctrl_dummy(struct uart_port *port)
-+{
-+ return 0;
-+}
-+
-+static void serial_cris_stop_tx_dummy(struct uart_port *port)
-+{
-+}
-+
-+static void serial_cris_start_tx_dummy(struct uart_port *port)
-+{
-+ /* Discard outbound characters. */
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ struct circ_buf *xmit = &up->port.state->xmit;
-+ xmit->tail = xmit->head;
-+ uart_write_wakeup(port);
-+}
-+
-+#define serial_cris_stop_rx_dummy serial_cris_stop_tx_dummy
-+
-+#define serial_cris_enable_ms_dummy serial_cris_stop_tx_dummy
-+
-+static void serial_cris_break_ctl_dummy(struct uart_port *port,
-+ int break_state)
-+{
-+}
-+
-+static int serial_cris_startup_dummy(struct uart_port *port)
-+{
-+ return 0;
-+}
-+
-+#define serial_cris_shutdown_dummy serial_cris_stop_tx_dummy
-+
-+static void
-+serial_cris_set_termios_dummy(struct uart_port *port, struct ktermios *termios,
-+ struct ktermios *old)
-+{
-+}
-+
-+#define serial_cris_release_port_dummy serial_cris_stop_tx_dummy
-+#define serial_cris_request_port_dummy serial_cris_startup_dummy
-+
-+static const struct uart_ops serial_cris_dummy_pops = {
-+ /*
-+ * We *could* save one or two of those with different
-+ * signature by casting and knowledge of the ABI, but it's
-+ * just not worth the maintenance headache.
-+ * For the ones we don't define here, the default (usually meaning
-+ * "unimplemented") makes sense.
-+ */
-+ .tx_empty = serial_cris_tx_empty_dummy,
-+ .set_mctrl = serial_cris_set_mctrl_dummy,
-+ .get_mctrl = serial_cris_get_mctrl_dummy,
-+ .stop_tx = serial_cris_stop_tx_dummy,
-+ .start_tx = serial_cris_start_tx_dummy,
-+ .stop_rx = serial_cris_stop_rx_dummy,
-+ .enable_ms = serial_cris_enable_ms_dummy,
-+ .break_ctl = serial_cris_break_ctl_dummy,
-+ .startup = serial_cris_startup_dummy,
-+ .shutdown = serial_cris_shutdown_dummy,
-+ .set_termios = serial_cris_set_termios_dummy,
-+
-+ /* This one we keep the same. */
-+ .type = serial_cris_type,
-+
-+ .release_port = serial_cris_release_port_dummy,
-+ .request_port = serial_cris_request_port_dummy,
-+
-+ /*
-+ * This one we keep the same too, as long as it doesn't do
-+ * anything else but to set the type.
-+ */
-+ .config_port = serial_cris_config_port,
-+};
-+
-+static void cris_serial_port_init(struct uart_port *port, int line)
-+{
-+ struct uart_cris_port *up = (struct uart_cris_port *)port;
-+ static int first = 1;
-+
-+ if (up->initialized)
-+ return;
-+ up->initialized = 1;
-+ port->line = line;
-+ spin_lock_init(&port->lock);
-+ port->ops =
-+ up->regi_ser == 0 ? &serial_cris_dummy_pops :
-+ &serial_cris_pops;
-+ port->irq = up->irq;
-+ port->iobase = up->regi_ser ? up->regi_ser : 1;
-+ port->uartclk = 29493000;
-+
-+ /*
-+ * We can't fit any more than 255 here (unsigned char), though
-+ * actually UART_XMIT_SIZE characters could be pending output (if it
-+ * wasn't for the single test in transmit_chars_dma). At time of this
-+ * writing, the definition of "fifosize" is here the amount of
-+ * characters that can be pending output after a start_tx call until
-+ * tx_empty returns 1: see serial_core.c:uart_wait_until_sent. This
-+ * matters for timeout calculations unfortunately, but keeping larger
-+ * amounts at the DMA wouldn't win much so let's just play nice.
-+ */
-+ port->fifosize = 255;
-+ port->flags = UPF_BOOT_AUTOCONF;
-+
-+#ifdef CONFIG_ETRAX_RS485
-+ /* Set sane defaults. */
-+ up->rs485.rts_on_send = 0;
-+ up->rs485.rts_after_sent = 1;
-+ up->rs485.delay_rts_before_send = 0;
-+ if (up->port_type > TYPE_232)
-+ up->rs485.enabled = 1;
-+ else
-+ up->rs485.enabled = 0;
-+#endif
-+
-+ if (first) {
-+ first = 0;
-+#ifdef CONFIG_ETRAX_SERIAL_PORT0
-+ SETUP_PINS(0);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT1
-+ SETUP_PINS(1);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT2
-+ SETUP_PINS(2);
-+#endif
-+#ifdef CONFIG_ETRAX_SERIAL_PORT3
-+ SETUP_PINS(3);
-+#endif
-+ }
-+}
-+
-+static int __init serial_cris_init(void)
-+{
-+ int ret, i;
-+ printk(KERN_INFO "Serial: CRISv32 driver $Revision: 1.109 $ ");
-+
-+ ret = uart_register_driver(&serial_cris_driver);
-+ if (ret)
-+ goto out;
-+
-+ for (i = 0; i < UART_NR; i++) {
-+ if (serial_cris_ports[i].used) {
-+ struct uart_port *port;
-+#ifdef CONFIG_ETRAX_RS485
-+ reg_ser_rw_rec_ctrl rec_ctrl;
-+
-+ /* Make sure that the RTS pin stays low when allocating
-+ * pins for a port in 485 mode.
-+ */
-+ if (serial_cris_ports[i].port_type > TYPE_232) {
-+ rec_ctrl = REG_RD(ser, serial_cris_ports[i].regi_ser, rw_rec_ctrl);
-+ rec_ctrl.rts_n = regk_ser_active;
-+ REG_WR(ser, serial_cris_ports[i].regi_ser, rw_rec_ctrl, rec_ctrl);
-+ }
-+#endif
-+ switch (serial_cris_ports[i].regi_ser) {
-+ case regi_ser0:
-+ break;
-+ case regi_ser1:
-+ if (crisv32_pinmux_alloc_fixed(pinmux_ser1)) {
-+ printk("Failed to allocate pins for ser1, disable port\n");
-+ serial_cris_ports[i].used = 0;
-+ continue;
-+ }
-+ break;
-+ case regi_ser2:
-+ if (crisv32_pinmux_alloc_fixed(pinmux_ser2)) {
-+ printk("Failed to allocate pins for ser2, disable port\n");
-+ serial_cris_ports[i].used = 0;
-+ continue;
-+ }
-+ break;
-+ case regi_ser3:
-+ if (crisv32_pinmux_alloc_fixed(pinmux_ser3)) {
-+ printk("Failed to allocate pins for ser3, disable port\n");
-+ serial_cris_ports[i].used = 0;
-+ continue;
-+ }
-+ break;
-+#if CONFIG_ETRAX_SERIAL_PORTS == 5
-+ case regi_ser4:
-+ if (crisv32_pinmux_alloc_fixed(pinmux_ser4)) {
-+ printk("Failed to allocate pins for ser4, disable port\n");
-+ serial_cris_ports[i].used = 0;
-+ continue;
-+ }
-+ break;
-+#endif
-+ default:
-+ printk("Error: No such serial port (%d) \n", serial_cris_ports[i].regi_ser);
-+ serial_cris_ports[i].used = 0;
-+ break;
-+ }
-+
-+ port = &serial_cris_ports[i].port;
-+ cris_console.index = i;
-+ cris_serial_port_init(port, i);
-+ uart_add_one_port(&serial_cris_driver, port);
-+ }
-+ }
-+
-+out:
-+ return ret;
-+}
-+
-+static void __exit serial_cris_exit(void)
-+{
-+ int i;
-+ for (i = 0; i < UART_NR; i++)
-+ if (serial_cris_ports[i].used) {
-+ switch (serial_cris_ports[i].regi_ser) {
-+ case regi_ser1:
-+ crisv32_pinmux_dealloc_fixed(pinmux_ser1);
-+ break;
-+ case regi_ser2:
-+ crisv32_pinmux_dealloc_fixed(pinmux_ser2);
-+ break;
-+ case regi_ser3:
-+ crisv32_pinmux_dealloc_fixed(pinmux_ser3);
-+ break;
-+#if CONFIG_ETRAX_SERIAL_PORTS == 5
-+ case regi_ser4:
-+ crisv32_pinmux_dealloc_fixed(pinmux_ser4);
-+ break;
-+#endif
-+ default:
-+ printk("Error: No such serial port (%d) \n", serial_cris_ports[i].regi_ser);
-+ serial_cris_ports[i].used = 0;
-+ break;
-+ }
-+ uart_remove_one_port(&serial_cris_driver,
-+ &serial_cris_ports[i].port);
-+ }
-+ uart_unregister_driver(&serial_cris_driver);
-+}
-+
-+module_init(serial_cris_init);
-+module_exit(serial_cris_exit);
-diff -Nur linux-4.0.3.orig/drivers/tty/serial/Makefile linux-4.0.3/drivers/tty/serial/Makefile
---- linux-4.0.3.orig/drivers/tty/serial/Makefile 2015-05-13 14:14:53.000000000 +0200
-+++ linux-4.0.3/drivers/tty/serial/Makefile 2015-05-25 17:21:47.000000000 +0200
-@@ -51,6 +51,7 @@
- obj-$(CONFIG_SERIAL_MESON) += meson_uart.o
- obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
- obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
-+obj-$(CONFIG_ETRAXFS_SERIAL) += crisv32.o
- obj-$(CONFIG_SERIAL_ETRAXFS) += etraxfs-uart.o
- obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
- obj-$(CONFIG_SERIAL_SC16IS7XX) += sc16is7xx.o
-diff -Nur linux-4.0.3.orig/include/uapi/linux/serial_core.h linux-4.0.3/include/uapi/linux/serial_core.h
---- linux-4.0.3.orig/include/uapi/linux/serial_core.h 2015-05-13 14:14:53.000000000 +0200
-+++ linux-4.0.3/include/uapi/linux/serial_core.h 2015-05-25 17:20:56.000000000 +0200
-@@ -258,4 +258,7 @@
- /* Cris v10 / v32 SoC */
- #define PORT_CRIS 112
-
-+/* Cris v10 / v32 SoC */
-+#define PORT_CRIS 109
-+
- #endif /* _UAPILINUX_SERIAL_CORE_H */