From 6a13c2c8a7f654d1160f46b14133636c9beaf316 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Mon, 25 May 2015 19:59:36 +0200 Subject: update to latest 4.0.x stable kernel --- mk/kernel-ver.mk | 6 +- target/config/Config.in.kernelversion.choice | 8 +- target/config/Config.in.kernelversion.default | 2 +- target/linux/patches/4.0.3/cris-header.patch | 12 - target/linux/patches/4.0.3/cris32-serial.patch | 2886 -------------------- .../patches/4.0.3/initramfs-nosizelimit.patch | 57 - target/linux/patches/4.0.3/startup.patch | 37 - target/linux/patches/4.0.4/cris-header.patch | 12 + target/linux/patches/4.0.4/cris32-serial.patch | 2886 ++++++++++++++++++++ .../patches/4.0.4/initramfs-nosizelimit.patch | 57 + target/linux/patches/4.0.4/startup.patch | 37 + 11 files changed, 2999 insertions(+), 3001 deletions(-) delete mode 100644 target/linux/patches/4.0.3/cris-header.patch delete mode 100644 target/linux/patches/4.0.3/cris32-serial.patch delete mode 100644 target/linux/patches/4.0.3/initramfs-nosizelimit.patch delete mode 100644 target/linux/patches/4.0.3/startup.patch create mode 100644 target/linux/patches/4.0.4/cris-header.patch create mode 100644 target/linux/patches/4.0.4/cris32-serial.patch create mode 100644 target/linux/patches/4.0.4/initramfs-nosizelimit.patch create mode 100644 target/linux/patches/4.0.4/startup.patch diff --git a/mk/kernel-ver.mk b/mk/kernel-ver.mk index 04c43dd78..4b9879917 100644 --- a/mk/kernel-ver.mk +++ b/mk/kernel-ver.mk @@ -1,8 +1,8 @@ -ifeq ($(ADK_KERNEL_VERSION_4_0_3),y) -KERNEL_VERSION:= 4.0.3 +ifeq ($(ADK_KERNEL_VERSION_4_0_4),y) +KERNEL_VERSION:= 4.0.4 KERNEL_MOD_VERSION:= $(KERNEL_VERSION) KERNEL_RELEASE:= 1 -KERNEL_HASH:= 8477fe664c14f1a139a128b1e6dfbe483aad18aaa4316045c628a1f8335e53b6 +KERNEL_HASH:= 30651ccd2cdf01ea2215cd39a94d9b684c1b3a681120f33e6605b467fe41b4c8 endif ifeq ($(ADK_KERNEL_VERSION_3_18_12),y) KERNEL_VERSION:= 3.18.12 diff --git a/target/config/Config.in.kernelversion.choice b/target/config/Config.in.kernelversion.choice index 98bbf2aec..af33a46ed 100644 --- a/target/config/Config.in.kernelversion.choice +++ b/target/config/Config.in.kernelversion.choice @@ -4,13 +4,11 @@ choice prompt "Kernel Version" depends on ADK_TARGET_KERNEL_CUSTOMISING -default ADK_KERNEL_VERSION_4_0_3 +default ADK_KERNEL_VERSION_4_0_4 -config ADK_KERNEL_VERSION_4_0_3 - bool "4.0.3" +config ADK_KERNEL_VERSION_4_0_4 + bool "4.0.4" select ADK_KERNEL_VERSION_4_0 - depends on !ADK_TARGET_SYSTEM_RASPBERRY_PI - depends on !ADK_TARGET_SYSTEM_RASPBERRY_PI2 config ADK_KERNEL_VERSION_3_18_12 bool "3.18.12" diff --git a/target/config/Config.in.kernelversion.default b/target/config/Config.in.kernelversion.default index 0c4b4bb68..d1d447245 100644 --- a/target/config/Config.in.kernelversion.default +++ b/target/config/Config.in.kernelversion.default @@ -27,7 +27,7 @@ config ADK_KERNEL_VERSION_2_6_32 config ADK_KERNEL_VERSION string - default "4.0.3" if ADK_KERNEL_VERSION_4_0 + default "4.0.4" if ADK_KERNEL_VERSION_4_0 default "3.18.12" if ADK_KERNEL_VERSION_3_18_12 default "3.14.43" if ADK_KERNEL_VERSION_3_14_43 default "3.12.40" if ADK_KERNEL_VERSION_3_12_40 diff --git a/target/linux/patches/4.0.3/cris-header.patch b/target/linux/patches/4.0.3/cris-header.patch deleted file mode 100644 index 2b5a88461..000000000 --- a/target/linux/patches/4.0.3/cris-header.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Nur linux-3.16.2.orig/arch/cris/include/arch-v10/arch/Kbuild linux-3.16.2/arch/cris/include/arch-v10/arch/Kbuild ---- linux-3.16.2.orig/arch/cris/include/arch-v10/arch/Kbuild 2014-09-06 01:37:11.000000000 +0200 -+++ linux-3.16.2/arch/cris/include/arch-v10/arch/Kbuild 2014-09-26 19:24:50.000000000 +0200 -@@ -1 +1,2 @@ - # CRISv10 arch -+header-y += ptrace.h -diff -Nur linux-3.16.2.orig/arch/cris/include/arch-v32/arch/Kbuild linux-3.16.2/arch/cris/include/arch-v32/arch/Kbuild ---- linux-3.16.2.orig/arch/cris/include/arch-v32/arch/Kbuild 2014-09-06 01:37:11.000000000 +0200 -+++ linux-3.16.2/arch/cris/include/arch-v32/arch/Kbuild 2014-09-26 19:24:31.000000000 +0200 -@@ -1 +1,2 @@ - # CRISv32 arch -+header-y += ptrace.h diff --git a/target/linux/patches/4.0.3/cris32-serial.patch b/target/linux/patches/4.0.3/cris32-serial.patch deleted file mode 100644 index 0f071cffb..000000000 --- a/target/linux/patches/4.0.3/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 - -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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 */ diff --git a/target/linux/patches/4.0.3/initramfs-nosizelimit.patch b/target/linux/patches/4.0.3/initramfs-nosizelimit.patch deleted file mode 100644 index 40d2f6bd8..000000000 --- a/target/linux/patches/4.0.3/initramfs-nosizelimit.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 9a18df7a71bfa620b1278777d64783a359d7eb4e Mon Sep 17 00:00:00 2001 -From: Thorsten Glaser -Date: Sun, 4 May 2014 01:37:54 +0200 -Subject: [PATCH] mount tmpfs-as-rootfs (initramfs) with -o - nr_blocks=0,nr_inodes=0 - -I would have preferred to write this patch to be able to pass -rootflags=nr_blocks=0,nr_inodes=0 on the kernel command line, -and then hand these rootflags over to the initramfs (tmpfs) -mount in the same way the kernel hands them over to the block -device rootfs mount. But at least the Debian/m68k initrd also -parses $rootflags from the environment and adds it to the call -to the user-space mount for the eventual root device, which -would make the kernel command line rootflags option be used in -both places (tmpfs and e.g. ext4) which is guaranteed to error -out in at least one of them. - -This change is intended to aid people in a setup where the -initrd is the final root filesystem, i.e. not mounted over. -This is especially useful in automated tests running on qemu -for boards with constrained memory (e.g. 64 MiB on sh4). - -Considering that the initramfs is normally emptied out then -overmounted, this change is probably safe for setups where -initramfs just hosts early userspace, too, since the tmpfs -backing it is not accessible any more later on, AFAICT. - -Signed-off-by: Thorsten Glaser ---- - init/do_mounts.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/init/do_mounts.c b/init/do_mounts.c -index 82f2288..55a4cfe 100644 ---- a/init/do_mounts.c -+++ b/init/do_mounts.c -@@ -594,6 +594,7 @@ out: - } - - static bool is_tmpfs; -+static char tmpfs_rootflags[] = "nr_blocks=0,nr_inodes=0"; - static struct dentry *rootfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) - { -@@ -606,6 +607,9 @@ static struct dentry *rootfs_mount(struct file_system_type *fs_type, - if (IS_ENABLED(CONFIG_TMPFS) && is_tmpfs) - fill = shmem_fill_super; - -+ if (is_tmpfs) -+ data = tmpfs_rootflags; -+ - return mount_nodev(fs_type, flags, data, fill); - } - --- -2.0.0.rc0 - diff --git a/target/linux/patches/4.0.3/startup.patch b/target/linux/patches/4.0.3/startup.patch deleted file mode 100644 index d396b75e4..000000000 --- a/target/linux/patches/4.0.3/startup.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff -Nur linux-3.13.3.orig/init/main.c linux-3.13.3/init/main.c ---- linux-3.13.3.orig/init/main.c 2014-02-13 23:00:14.000000000 +0100 -+++ linux-3.13.3/init/main.c 2014-02-17 11:35:14.000000000 +0100 -@@ -916,6 +917,8 @@ - if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) - pr_err("Warning: unable to open an initial console.\n"); - -+ printk(KERN_WARNING "Starting Linux (built with OpenADK).\n"); -+ - (void) sys_dup(0); - (void) sys_dup(0); - /* -diff -Nur linux-3.13.6.orig/init/initramfs.c linux-3.13.6/init/initramfs.c ---- linux-3.13.6.orig/init/initramfs.c 2014-03-07 07:07:02.000000000 +0100 -+++ linux-3.13.6/init/initramfs.c 2014-03-15 12:11:31.882731916 +0100 -@@ -622,6 +622,9 @@ - */ - load_default_modules(); - } -+#ifdef CONFIG_DEVTMPFS_MOUNT -+ devtmpfs_mount("dev"); -+#endif - return 0; - } - rootfs_initcall(populate_rootfs); -diff -Nur linux-3.13.6.orig/init/main.c linux-3.13.6/init/main.c ---- linux-3.13.6.orig/init/main.c 2014-03-07 07:07:02.000000000 +0100 -+++ linux-3.13.6/init/main.c 2014-03-15 12:13:16.459024452 +0100 -@@ -924,7 +924,7 @@ - */ - - if (!ramdisk_execute_command) -- ramdisk_execute_command = "/init"; -+ ramdisk_execute_command = "/sbin/init"; - - if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { - ramdisk_execute_command = NULL; diff --git a/target/linux/patches/4.0.4/cris-header.patch b/target/linux/patches/4.0.4/cris-header.patch new file mode 100644 index 000000000..2b5a88461 --- /dev/null +++ b/target/linux/patches/4.0.4/cris-header.patch @@ -0,0 +1,12 @@ +diff -Nur linux-3.16.2.orig/arch/cris/include/arch-v10/arch/Kbuild linux-3.16.2/arch/cris/include/arch-v10/arch/Kbuild +--- linux-3.16.2.orig/arch/cris/include/arch-v10/arch/Kbuild 2014-09-06 01:37:11.000000000 +0200 ++++ linux-3.16.2/arch/cris/include/arch-v10/arch/Kbuild 2014-09-26 19:24:50.000000000 +0200 +@@ -1 +1,2 @@ + # CRISv10 arch ++header-y += ptrace.h +diff -Nur linux-3.16.2.orig/arch/cris/include/arch-v32/arch/Kbuild linux-3.16.2/arch/cris/include/arch-v32/arch/Kbuild +--- linux-3.16.2.orig/arch/cris/include/arch-v32/arch/Kbuild 2014-09-06 01:37:11.000000000 +0200 ++++ linux-3.16.2/arch/cris/include/arch-v32/arch/Kbuild 2014-09-26 19:24:31.000000000 +0200 +@@ -1 +1,2 @@ + # CRISv32 arch ++header-y += ptrace.h diff --git a/target/linux/patches/4.0.4/cris32-serial.patch b/target/linux/patches/4.0.4/cris32-serial.patch new file mode 100644 index 000000000..0f071cffb --- /dev/null +++ b/target/linux/patches/4.0.4/cris32-serial.patch @@ -0,0 +1,2886 @@ +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 + +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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 */ diff --git a/target/linux/patches/4.0.4/initramfs-nosizelimit.patch b/target/linux/patches/4.0.4/initramfs-nosizelimit.patch new file mode 100644 index 000000000..40d2f6bd8 --- /dev/null +++ b/target/linux/patches/4.0.4/initramfs-nosizelimit.patch @@ -0,0 +1,57 @@ +From 9a18df7a71bfa620b1278777d64783a359d7eb4e Mon Sep 17 00:00:00 2001 +From: Thorsten Glaser +Date: Sun, 4 May 2014 01:37:54 +0200 +Subject: [PATCH] mount tmpfs-as-rootfs (initramfs) with -o + nr_blocks=0,nr_inodes=0 + +I would have preferred to write this patch to be able to pass +rootflags=nr_blocks=0,nr_inodes=0 on the kernel command line, +and then hand these rootflags over to the initramfs (tmpfs) +mount in the same way the kernel hands them over to the block +device rootfs mount. But at least the Debian/m68k initrd also +parses $rootflags from the environment and adds it to the call +to the user-space mount for the eventual root device, which +would make the kernel command line rootflags option be used in +both places (tmpfs and e.g. ext4) which is guaranteed to error +out in at least one of them. + +This change is intended to aid people in a setup where the +initrd is the final root filesystem, i.e. not mounted over. +This is especially useful in automated tests running on qemu +for boards with constrained memory (e.g. 64 MiB on sh4). + +Considering that the initramfs is normally emptied out then +overmounted, this change is probably safe for setups where +initramfs just hosts early userspace, too, since the tmpfs +backing it is not accessible any more later on, AFAICT. + +Signed-off-by: Thorsten Glaser +--- + init/do_mounts.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/init/do_mounts.c b/init/do_mounts.c +index 82f2288..55a4cfe 100644 +--- a/init/do_mounts.c ++++ b/init/do_mounts.c +@@ -594,6 +594,7 @@ out: + } + + static bool is_tmpfs; ++static char tmpfs_rootflags[] = "nr_blocks=0,nr_inodes=0"; + static struct dentry *rootfs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) + { +@@ -606,6 +607,9 @@ static struct dentry *rootfs_mount(struct file_system_type *fs_type, + if (IS_ENABLED(CONFIG_TMPFS) && is_tmpfs) + fill = shmem_fill_super; + ++ if (is_tmpfs) ++ data = tmpfs_rootflags; ++ + return mount_nodev(fs_type, flags, data, fill); + } + +-- +2.0.0.rc0 + diff --git a/target/linux/patches/4.0.4/startup.patch b/target/linux/patches/4.0.4/startup.patch new file mode 100644 index 000000000..d396b75e4 --- /dev/null +++ b/target/linux/patches/4.0.4/startup.patch @@ -0,0 +1,37 @@ +diff -Nur linux-3.13.3.orig/init/main.c linux-3.13.3/init/main.c +--- linux-3.13.3.orig/init/main.c 2014-02-13 23:00:14.000000000 +0100 ++++ linux-3.13.3/init/main.c 2014-02-17 11:35:14.000000000 +0100 +@@ -916,6 +917,8 @@ + if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) + pr_err("Warning: unable to open an initial console.\n"); + ++ printk(KERN_WARNING "Starting Linux (built with OpenADK).\n"); ++ + (void) sys_dup(0); + (void) sys_dup(0); + /* +diff -Nur linux-3.13.6.orig/init/initramfs.c linux-3.13.6/init/initramfs.c +--- linux-3.13.6.orig/init/initramfs.c 2014-03-07 07:07:02.000000000 +0100 ++++ linux-3.13.6/init/initramfs.c 2014-03-15 12:11:31.882731916 +0100 +@@ -622,6 +622,9 @@ + */ + load_default_modules(); + } ++#ifdef CONFIG_DEVTMPFS_MOUNT ++ devtmpfs_mount("dev"); ++#endif + return 0; + } + rootfs_initcall(populate_rootfs); +diff -Nur linux-3.13.6.orig/init/main.c linux-3.13.6/init/main.c +--- linux-3.13.6.orig/init/main.c 2014-03-07 07:07:02.000000000 +0100 ++++ linux-3.13.6/init/main.c 2014-03-15 12:13:16.459024452 +0100 +@@ -924,7 +924,7 @@ + */ + + if (!ramdisk_execute_command) +- ramdisk_execute_command = "/init"; ++ ramdisk_execute_command = "/sbin/init"; + + if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { + ramdisk_execute_command = NULL; -- cgit v1.2.3