* [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5
@ 2014-09-21 16:27 Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 1/8] cris: Add support for early console Guenter Roeck
` (7 more replies)
0 siblings, 8 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 16:27 UTC (permalink / raw)
To: linux-kernel
Cc: Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
The following series of patches is needed to boot a crisv32 image with qemu
into a serial console.
The resulting image was built with a toolchain built with gcc 4.7.4 (with a
minor fix backported from mainline gcc) and uclibc 0.9.33 using a patched
version of buildroot. Root file system is initramfs built from latest busybox
sources.
The qemu command used to start the image is as follows.
qemu-system-cris -serial stdio -kernel vmlinux -monitor none \
-nographic -append "console=ttyS0,115200,N,8 rdinit=/sbin/init"
This still causes the following (non-fatal) traceback, but at least it works.
WARNING: CPU: 0 PID: 188 at kernel/softirq.c:146 0xc000ef4e()
Modules linked in:
CPU: 0 PID: 188 Comm: init Not tainted 3.17.0-rc5-00008-g5f5d649 #93
Analysis shows that interupts are disabled when _local_bh_enable() is called.
The patches in this series are not intended for immediate acceptance into the
upstream kernel and should instead be seen as a report on the state of the
architecture in general. Having said this, the following patches should
nevertheless be in acceptable state for upstream integration.
cris: Add support for early console
cris: Add dummy free_initrd_mem
cris: time.c: Add missing include file to fix compile
Patch 6/8 ("tty: crisv32: Coding style cleanup, delete dead code") isn't
really worth much by itself and can be omitted when testing the series.
Patch 7/8 of the series ("resource: Add NULL check in next_resource")
was submitted separately as non-RFC patch.
Patch 8/8 ('Revert "percpu: free percpu allocation info for uniprocessor
system"') is presumably only needed for cris. I have no idea why the call to
pcpu_free_alloc_info() fails; maybe memory is not initialized correctly
by the cris architecture code.
Patch 7/8 and 8/8 are only needed when applying the patch series to the latest
upstream kernel (v3.17-rcX). For v3.16 kernels, Patches 1-6 (or 1-5, strictly
speaking) are sufficient.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH 1/8] cris: Add support for early console
2014-09-21 16:27 [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5 Guenter Roeck
@ 2014-09-21 16:27 ` Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 2/8] cris: Add serial driver for Cris v32 Guenter Roeck
` (6 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 16:27 UTC (permalink / raw)
To: linux-kernel
Cc: Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
arch/cris/arch-v32/kernel/debugport.c | 41 +++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/arch/cris/arch-v32/kernel/debugport.c b/arch/cris/arch-v32/kernel/debugport.c
index 610909b..7e46d87 100644
--- a/arch/cris/arch-v32/kernel/debugport.c
+++ b/arch/cris/arch-v32/kernel/debugport.c
@@ -4,6 +4,7 @@
#include <linux/console.h>
#include <linux/init.h>
+
#include <hwregs/reg_rdwr.h>
#include <hwregs/reg_map.h>
#include <hwregs/ser_defs.h>
@@ -190,12 +191,52 @@ putDebugChar(int val)
}
#endif /* CONFIG_ETRAX_KGDB */
+static void __init early_putch(int c)
+{
+ reg_ser_r_stat_din stat;
+ /* Wait until transmitter is ready and send. */
+ do
+ stat = REG_RD(ser, port->instance, r_stat_din);
+ while (!stat.tr_rdy);
+ REG_WR_INT(ser, port->instance, rw_dout, c);
+}
+
+static void __init
+early_console_write(struct console *con, const char *s, unsigned n)
+{
+ extern void reset_watchdog(void);
+ int i;
+
+ /* Send data. */
+ for (i = 0; i < n; i++) {
+ /*
+ * TODO: the '\n' -> '\n\r' translation should be done at the
+ * receiver. Remove it when the serial driver removes it.
+ */
+ if (s[i] == '\n')
+ early_putch('\r');
+ early_putch(s[i]);
+ reset_watchdog();
+ }
+}
+
+static struct console early_console_dev __initdata = {
+ .name = "early",
+ .write = early_console_write,
+ .flags = CON_PRINTBUFFER | CON_BOOT,
+ .index = -1
+};
+
/* Register console for printk's, etc. */
int __init
init_etrax_debug(void)
{
start_port(port);
+ /* Register an early console if a debug port was chosen */
+ if (port)
+ register_console(&early_console_dev);
+
#ifdef CONFIG_ETRAX_KGDB
start_port(kgdb_port);
#endif /* CONFIG_ETRAX_KGDB */
--
1.9.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 2/8] cris: Add serial driver for Cris v32
2014-09-21 16:27 [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5 Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 1/8] cris: Add support for early console Guenter Roeck
@ 2014-09-21 16:27 ` Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 3/8] cris: Add dummy free_initrd_mem Guenter Roeck
` (5 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 16:27 UTC (permalink / raw)
To: linux-kernel
Cc: Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
arch/cris/arch-v32/drivers/Kconfig | 237 ++++
arch/cris/include/uapi/asm/ioctls.h | 4 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/crisv32.c | 2581 +++++++++++++++++++++++++++++++++++
include/uapi/linux/serial_core.h | 3 +
5 files changed, 2826 insertions(+)
create mode 100644 drivers/tty/serial/crisv32.c
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 15a9ed1..f5e3333 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -49,24 +49,261 @@ config ETRAX_SERIAL_PORT0
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 --git a/arch/cris/include/uapi/asm/ioctls.h b/arch/cris/include/uapi/asm/ioctls.h
index 488fbb3..22b9a61 100644
--- a/arch/cris/include/uapi/asm/ioctls.h
+++ b/arch/cris/include/uapi/asm/ioctls.h
@@ -5,6 +5,10 @@
#define TIOCSERSETRS485 0x5461 /* enable rs-485 (deprecated) */
#define TIOCSERWRRS485 0x5462 /* write rs-485 */
#define TIOCSRS485 0x5463 /* enable rs-485 */
+#define TIOCSERSETRS485FD 0x5464 /* set rs-485 full/half duplex mode */
+
+
+#define TIOCSERSETDIVISOR 0x5465 /* set the divisor for non standard bauds */
#include <asm-generic/ioctls.h>
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 0080cc3..79bae96 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
+obj-$(CONFIG_ETRAXFS_SERIAL) += crisv32.o
obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
obj-$(CONFIG_SERIAL_SC16IS7XX) += sc16is7xx.o
obj-$(CONFIG_SERIAL_JSM) += jsm/
diff --git a/drivers/tty/serial/crisv32.c b/drivers/tty/serial/crisv32.c
new file mode 100644
index 0000000..a69f131
--- /dev/null
+++ b/drivers/tty/serial/crisv32.c
@@ -0,0 +1,2581 @@
+/* $Id: crisv32.c,v 1.109 2010-07-09 15:00:44 jespern Exp $
+ *
+ * Serial port driver for the ETRAX FS chip
+ *
+ * Copyright (C) 1998-2006 Axis Communications AB
+ *
+ * Many, many authors. Based once upon a time on serial.c for 16x50.
+ *
+ * Johan Adolfsson - port to ETRAX FS
+ * Mikael Starvik - port to serial_core framework
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/serial_core.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/tty_flip.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include <dma.h>
+#include <arch/system.h>
+#include <mach/pinmux.h>
+#include <hwregs/dma.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/ser_defs.h>
+#include <hwregs/dma_defs.h>
+#include <hwregs/gio_defs.h>
+#include <hwregs/intr_vect_defs.h>
+#include <hwregs/reg_map.h>
+
+#define UART_NR CONFIG_ETRAX_SERIAL_PORTS + 1 /* Ports + dummy port */
+#define SERIAL_RECV_DESCRIPTORS 8
+
+/* We only buffer 255 characters here, no need for more tx descriptors. */
+#define SERIAL_TX_DESCRIPTORS 4
+
+/* Kept for experimental purposes. */
+#define SERIAL_DESCR_BUF_SIZE 256
+#define regi_NULL 0
+#define DMA_WAIT_UNTIL_RESET(inst) \
+ do { \
+ reg_dma_rw_stat r; \
+ do { \
+ r = REG_RD(dma, (inst), rw_stat); \
+ } while (r.mode != regk_dma_rst); \
+ } while (0)
+
+#define __DMA(ch) regi_dma##ch
+#define DMA(ch) __DMA(ch)
+#define DMA_IRQ(ch) (DMA0_INTR_VECT + (ch))
+
+/* Macro to set up control lines for a port. */
+#define SETUP_PINS(port) \
+ if (serial_cris_ports[port].used) { \
+ if (strcmp(CONFIG_ETRAX_SER##port##_DTR_BIT, "")) \
+ crisv32_io_get_name(&serial_cris_ports[port].dtr_pin, \
+ CONFIG_ETRAX_SER##port##_DTR_BIT); \
+ else \
+ serial_cris_ports[port].dtr_pin = dummy_pin; \
+ if (strcmp(CONFIG_ETRAX_SER##port##_DSR_BIT, "")) \
+ crisv32_io_get_name(&serial_cris_ports[port].dsr_pin, \
+ CONFIG_ETRAX_SER##port##_DSR_BIT); \
+ else \
+ serial_cris_ports[port].dsr_pin = dummy_pin; \
+ if (strcmp(CONFIG_ETRAX_SER##port##_RI_BIT, "")) \
+ crisv32_io_get_name(&serial_cris_ports[port].ri_pin, \
+ CONFIG_ETRAX_SER##port##_RI_BIT); \
+ else \
+ serial_cris_ports[port].ri_pin = dummy_pin; \
+ if (strcmp(CONFIG_ETRAX_SER##port##_CD_BIT, "")) \
+ crisv32_io_get_name(&serial_cris_ports[port].cd_pin, \
+ CONFIG_ETRAX_SER##port##_CD_BIT); \
+ else \
+ serial_cris_ports[port].cd_pin = dummy_pin; \
+ }
+
+/* Set a serial port register if anything has changed. */
+#define MODIFY_REG(instance, reg, var) \
+ if (REG_RD_INT(ser, instance, reg) \
+ != REG_TYPE_CONV(int, reg_ser_##reg, var)) \
+ REG_WR(ser, instance, reg, var);
+
+/*
+ * Regarding RS485 operation in crisv32 serial driver.
+ * ---------------------------------------------------
+ * RS485 can be run in two modes, full duplex using four wires (485FD) and
+ * half duplex using two wires (485HD). The default mode of each serial port
+ * is configured in the kernel configuration. The available modes are:
+ * RS-232, RS-485 half duplex, and RS-485 full duplex.
+ *
+ * In the 485HD mode the direction of the data bus must be able to switch.
+ * The direction of the transceiver is controlled by the RTS signal. Hence
+ * the auto_rts function in the ETRAX FS chip is enabled in this mode, which
+ * automatically toggle RTS when transmitting. The initial direction of the
+ * port is receiving.
+ *
+ * In the 485FD mode two transceivers will be used, one in each direction.
+ * Usually the hardware can handle both 485HD and 485FD, which implies that
+ * one of the transceivers can change direction. Consequently that transceiver
+ * must be tied to operate in the opposite direction of the other one, setting
+ * and keeping RTS to a fixed value do this.
+ *
+ * There are two special "ioctl" that can configure the ports. These two are
+ * left for backward compatible with older applications. The effects of using
+ * them are described below:
+ * The TIOCSERSETRS485:
+ * This ioctl sets a serial port in 232 mode to 485HD mode or vise versa. The
+ * state of the port is kept when closing the port. Note that this ioctl has no
+ * effect on a serial port in the 485FD mode.
+ * The TIOCSERWRRS485:
+ * This ioctl set a serial port in 232 mode to 485HD mode and writes the data
+ * "included" in the ioctl to the port. The port will then stay in 485HD mode.
+ * Using this ioctl on a serial port in the 485HD mode will transmit the data
+ * without changing the mode. Using this ioctl on a serial port in 485FD mode
+ * will not change the mode and simply send the data using the 485FD mode.
+ */
+
+#define TYPE_232 0
+#define TYPE_485HD 1
+#define TYPE_485FD 2
+
+struct etrax_recv_buffer {
+ struct etrax_recv_buffer *next;
+ unsigned short length;
+ unsigned char error;
+ unsigned char pad;
+
+ unsigned char buffer[0];
+};
+
+struct uart_cris_port {
+ struct uart_port port;
+
+ int initialized;
+ int used;
+ int irq;
+
+ /* Used to check if port enabled as well by testing for zero. */
+ reg_scope_instances regi_ser;
+ reg_scope_instances regi_dmain;
+ reg_scope_instances regi_dmaout;
+
+ struct crisv32_iopin dtr_pin;
+ struct crisv32_iopin dsr_pin;
+ struct crisv32_iopin ri_pin;
+ struct crisv32_iopin cd_pin;
+
+ struct dma_descr_context tr_context_descr
+ __attribute__ ((__aligned__(32)));
+ struct dma_descr_data tr_descr[SERIAL_TX_DESCRIPTORS]
+ __attribute__ ((__aligned__(32)));
+ struct dma_descr_context rec_context_descr
+ __attribute__ ((__aligned__(32)));
+ struct dma_descr_data rec_descr[SERIAL_RECV_DESCRIPTORS]
+ __attribute__ ((__aligned__(32)));
+
+ /* This is the first one in the list the HW is working on now. */
+ struct dma_descr_data* first_tx_descr;
+
+ /* This is the last one in the list the HW is working on now. */
+ struct dma_descr_data* last_tx_descr;
+
+ /* This is how many characters the HW is working on now. */
+ unsigned int tx_pending_chars;
+
+ int tx_started;
+ unsigned int cur_rec_descr;
+ struct etrax_recv_buffer *first_recv_buffer;
+ struct etrax_recv_buffer *last_recv_buffer;
+
+ unsigned int recv_cnt;
+ unsigned int max_recv_cnt;
+
+ /* The time for 1 char, in usecs. */
+ unsigned long char_time_usec;
+
+ /* Last tx usec in the jiffies. */
+ unsigned long last_tx_active_usec;
+
+ /* Last tx time in jiffies. */
+ unsigned long last_tx_active;
+
+ /* Last rx usec in the jiffies. */
+ unsigned long last_rx_active_usec;
+
+ /* Last rx time in jiffies. */
+ unsigned long last_rx_active;
+
+#ifdef CONFIG_ETRAX_RS485
+ /* RS-485 support, duh. */
+ struct rs485_control rs485;
+#endif
+ int port_type;
+ int write_ongoing;
+};
+
+extern struct uart_driver serial_cris_driver;
+static struct uart_port *console_port;
+static int console_baud = 115200;
+static struct uart_cris_port serial_cris_ports[UART_NR] = {
+{
+#ifdef CONFIG_ETRAX_SERIAL_PORT0
+ .used = 1,
+ .irq = SER0_INTR_VECT,
+ .regi_ser = regi_ser0,
+ /*
+ * We initialize the dma stuff like this to get a compiler error
+ * if a CONFIG is missing
+ */
+ .regi_dmain =
+# ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
+ regi_dma7,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT0_DMA1_IN)
+ regi_dma1,
+# elif defined CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_IN
+ regi_NULL,
+# endif
+
+ .regi_dmaout =
+# ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
+ regi_dma6,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT0_DMA7_OUT)
+ regi_dma7,
+# else
+ regi_NULL,
+# endif
+
+# ifdef CONFIG_ETRAX_RS485
+# ifdef CONFIG_ETRAX_SERIAL_PORT0_TYPE_485HD
+ .port_type = TYPE_485HD,
+# endif
+# ifdef CONFIG_ETRAX_SERIAL_PORT0_TYPE_485FD
+ .port_type = TYPE_485FD,
+# endif
+# endif
+#else
+ .regi_ser = regi_NULL,
+ .regi_dmain = regi_NULL,
+ .regi_dmaout = regi_NULL,
+#endif
+ .write_ongoing = 0
+}, /* ttyS0 */
+{
+#ifdef CONFIG_ETRAX_SERIAL_PORT1
+ .used = 1,
+ .irq = SER1_INTR_VECT,
+ .regi_ser = regi_ser1,
+ .regi_dmain =
+# ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA5_IN
+ regi_dma5,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_IN)
+ regi_NULL,
+# endif
+
+ .regi_dmaout =
+# ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA4_OUT
+ regi_dma4,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_OUT)
+ regi_NULL,
+# endif
+
+# ifdef CONFIG_ETRAX_RS485
+# ifdef CONFIG_ETRAX_SERIAL_PORT1_TYPE_485HD
+ .port_type = TYPE_485HD,
+# endif
+# ifdef CONFIG_ETRAX_SERIAL_PORT1_TYPE_485FD
+ .port_type = TYPE_485FD,
+# endif
+# endif
+#else
+ .regi_ser = regi_NULL,
+ .regi_dmain = regi_NULL,
+ .regi_dmaout = regi_NULL,
+#endif
+ .write_ongoing = 0
+}, /* ttyS1 */
+{
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
+ .used = 1,
+ .irq = SER2_INTR_VECT,
+ .regi_ser = regi_ser2,
+ .regi_dmain =
+# ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
+ regi_dma3,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT2_DMA7_IN)
+ regi_dma7,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_IN)
+ regi_NULL,
+# endif
+
+ .regi_dmaout =
+# ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
+ regi_dma2,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT2_DMA6_OUT)
+ regi_dma6,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_OUT)
+ regi_NULL,
+# endif
+
+# ifdef CONFIG_ETRAX_RS485
+# ifdef CONFIG_ETRAX_SERIAL_PORT2_TYPE_485HD
+ .port_type = TYPE_485HD,
+# endif
+# ifdef CONFIG_ETRAX_SERIAL_PORT2_TYPE_485FD
+ .port_type = TYPE_485FD,
+# endif
+# endif
+#else
+ .regi_ser = regi_NULL,
+ .regi_dmain = regi_NULL,
+ .regi_dmaout = regi_NULL,
+#endif
+ .write_ongoing = 0
+}, /* ttyS2 */
+{
+#ifdef CONFIG_ETRAX_SERIAL_PORT3
+ .used = 1,
+ .irq = SER3_INTR_VECT,
+ .regi_ser = regi_ser3,
+ .regi_dmain =
+# ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA9_IN
+ regi_dma9,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT3_DMA4_IN)
+ regi_dma3,
+# else
+ regi_NULL,
+# endif
+
+ .regi_dmaout =
+# ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA8_OUT
+ regi_dma8,
+# elif defined(CONFIG_ETRAX_SERIAL_PORT3_DMA2_OUT)
+ regi_dma2,
+# else
+ regi_NULL,
+# endif
+# ifdef CONFIG_ETRAX_RS485
+# ifdef CONFIG_ETRAX_SERIAL_PORT3_TYPE_485HD
+ .port_type = TYPE_485HD,
+# endif
+# ifdef CONFIG_ETRAX_SERIAL_PORT3_TYPE_485FD
+ .port_type = TYPE_485FD,
+# endif
+# endif
+#else
+ .regi_ser = regi_NULL,
+ .regi_dmain = regi_NULL,
+ .regi_dmaout = regi_NULL,
+#endif
+ .write_ongoing = 0
+}, /* ttyS3 */
+#if CONFIG_ETRAX_SERIAL_PORTS == 5
+{
+#ifdef CONFIG_ETRAX_SERIAL_PORT4
+ .used = 1,
+ .irq = SER4_INTR_VECT,
+ .regi_ser = regi_ser4,
+ .regi_dmain =
+# ifdef CONFIG_ETRAX_SERIAL_PORT4_DMA9_IN
+ regi_dma9,
+# else
+ regi_NULL,
+# endif
+
+ .regi_dmaout = regi_NULL,
+# ifdef CONFIG_ETRAX_RS485
+# ifdef CONFIG_ETRAX_SERIAL_PORT4_TYPE_485HD
+ .port_type = TYPE_485HD,
+# endif
+# ifdef CONFIG_ETRAX_SERIAL_PORT4_TYPE_485FD
+ .port_type = TYPE_485FD,
+# endif
+# endif
+#else
+ .regi_ser = regi_NULL,
+ .regi_dmain = regi_NULL,
+ .regi_dmaout = regi_NULL,
+#endif
+ .write_ongoing = 0
+}, /* ttyS4 */
+#endif
+{
+#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL
+ .used = 1,
+#endif
+ .regi_ser = regi_NULL,
+ .write_ongoing = 0
+} /* Dummy console port */
+
+};
+
+/* Dummy pin used for unused CD, DSR, DTR and RI signals. */
+static unsigned long io_dummy;
+static struct crisv32_ioport dummy_port =
+{
+ &io_dummy,
+ &io_dummy,
+ &io_dummy,
+ 32
+};
+static struct crisv32_iopin dummy_pin =
+{
+ &dummy_port,
+ 0
+};
+
+static int selected_console =
+#if defined(CONFIG_ETRAX_DEBUG_PORT0)
+0;
+#elif defined(CONFIG_ETRAX_DEBUG_PORT1)
+1;
+#elif defined(CONFIG_ETRAX_DEBUG_PORT2)
+2;
+#elif defined(CONFIG_ETRAX_DEBUG_PORT3)
+3;
+#elif defined(CONFIG_ETRAX_DEBUG_PORT4)
+4;
+#else /* CONFIG_ETRAX_DEBUG_PORT_NULL */
+#if CONFIG_ETRAX_SERIAL_PORTS == 5
+5;
+#else
+4;
+#endif
+#endif
+
+extern void reset_watchdog(void);
+
+static void serial_cris_stop_rx(struct uart_port *port);
+
+/*
+ * Interrupts are disabled on entering
+ */
+#ifndef CONFIG_ETRAX_VCS_SIM
+static void
+cris_console_write(struct console *co, const char *s, unsigned int count)
+{
+ struct uart_cris_port *up;
+ int i;
+ reg_ser_r_stat_din stat;
+ reg_ser_rw_tr_dma_en tr_dma_en, old;
+
+ up = &serial_cris_ports[selected_console];
+
+ /*
+ * This function isn't covered by the struct uart_ops, so we
+ * have to check manually that the port really is there,
+ * configured and live.
+ */
+ if (!up->regi_ser)
+ return;
+
+ /* Switch to manual mode. */
+ tr_dma_en = old = REG_RD (ser, up->regi_ser, rw_tr_dma_en);
+ if (tr_dma_en.en == regk_ser_yes) {
+ tr_dma_en.en = regk_ser_no;
+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, tr_dma_en);
+ }
+
+ /* Send data. */
+ for (i = 0; i < count; i++) {
+ /* LF -> CRLF */
+ if (s[i] == '\n') {
+ do {
+ stat = REG_RD (ser, up->regi_ser, r_stat_din);
+ } while (!stat.tr_rdy);
+ REG_WR_INT (ser, up->regi_ser, rw_dout, '\r');
+ }
+ /* Wait until transmitter is ready and send. */
+ do {
+ stat = REG_RD (ser, up->regi_ser, r_stat_din);
+ } while (!stat.tr_rdy);
+ REG_WR_INT (ser, up->regi_ser, rw_dout, s[i]);
+
+ /* Feed watchdog, because this may take looong time. */
+ reset_watchdog();
+ }
+
+ /* Restore mode. */
+ if (tr_dma_en.en != old.en)
+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, old);
+}
+#else
+
+extern void print_str( const char *str );
+static char buffer[1024];
+static char msg[] = "Debug: ";
+static int buffer_pos = sizeof(msg) - 1;
+
+static void
+cris_console_write(struct console *co, const char *buf, unsigned int len)
+{
+ char* pos;
+ pos = memchr(buf, '\n', len);
+ if (pos) {
+ int l = ++pos - buf;
+ memcpy(buffer + buffer_pos, buf, l);
+ memcpy(buffer, msg, sizeof(msg) - 1);
+ buffer[buffer_pos + l] = '\0';
+ print_str(buffer);
+ buffer_pos = sizeof(msg) - 1;
+ if (pos - buf != len) {
+ memcpy(buffer + buffer_pos, pos, len - l);
+ buffer_pos += len - l;
+ }
+ } else {
+ memcpy(buffer + buffer_pos, buf, len);
+ buffer_pos += len;
+ }
+}
+#endif
+
+static void cris_serial_port_init(struct uart_port *port, int line);
+static int __init
+cris_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index >= UART_NR)
+ co->index = 0;
+ if (options)
+ selected_console = co->index;
+ port = &serial_cris_ports[selected_console].port;
+ console_port = port;
+
+ co->flags |= CON_CONSDEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ console_baud = baud;
+ cris_serial_port_init(port, selected_console);
+ co->index = port->line;
+ uart_set_options(port, co, baud, parity, bits, flow);
+
+ return 0;
+}
+
+static struct tty_driver*
+cris_console_device(struct console* co, int *index)
+{
+ struct uart_driver *p = co->data;
+ *index = selected_console;
+ return p->tty_driver;
+}
+
+static struct console cris_console = {
+ .name = "ttyS",
+ .write = cris_console_write,
+ .device = cris_console_device,
+ .setup = cris_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &serial_cris_driver,
+};
+
+#define SERIAL_CRIS_CONSOLE &cris_console
+
+struct uart_driver serial_cris_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "serial",
+ .dev_name = "ttyS",
+ .major = TTY_MAJOR,
+ .minor = 64,
+ .nr = UART_NR,
+ .cons = SERIAL_CRIS_CONSOLE,
+};
+
+static int inline crisv32_serial_get_rts(struct uart_cris_port *up)
+{
+ reg_scope_instances regi_ser = up->regi_ser;
+ /*
+ * Return what the user has controlled rts to or
+ * what the pin is? (if auto_rts is used it differs during tx)
+ */
+ reg_ser_r_stat_din rstat = REG_RD(ser, regi_ser, r_stat_din);
+ return !(rstat.rts_n == regk_ser_active);
+}
+
+/*
+ * A set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive
+ * 0=0V , 1=3.3V
+ */
+static inline void crisv32_serial_set_rts(struct uart_cris_port *up, int set, int force)
+{
+ reg_scope_instances regi_ser = up->regi_ser;
+
+#ifdef CONFIG_ETRAX_RS485
+ /* Never toggle RTS if port is in 485 mode. If port is in 485FD mode we
+ * do not want to send with the reciever and for 485HD mode auto_rts
+ * take care of the RTS for us.
+ */
+ if (force || !up->rs485.enabled) {
+#else
+ {
+#endif
+ unsigned long flags;
+ reg_ser_rw_rec_ctrl rec_ctrl;
+
+ local_irq_save(flags);
+ rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
+
+ if (set)
+ rec_ctrl.rts_n = regk_ser_active;
+ else
+ rec_ctrl.rts_n = regk_ser_inactive;
+ REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
+ local_irq_restore(flags);
+ }
+}
+
+/* Input */
+static int inline crisv32_serial_get_cts(struct uart_cris_port *up)
+{
+ reg_scope_instances regi_ser = up->regi_ser;
+ reg_ser_r_stat_din rstat = REG_RD(ser, regi_ser, r_stat_din);
+ return (rstat.cts_n == regk_ser_active);
+}
+
+/*
+ * Send a single character for XON/XOFF purposes. We do it in this separate
+ * function instead of the alternative support port.x_char, in the ...start_tx
+ * function, so we don't mix up this case with possibly enabling transmission
+ * of queued-up data (in case that's disabled after *receiving* an XOFF or
+ * negative CTS). This function is used for both DMA and non-DMA case; see HW
+ * docs specifically blessing sending characters manually when DMA for
+ * transmission is enabled and running. We may be asked to transmit despite
+ * the transmitter being disabled by a ..._stop_tx call so we need to enable
+ * it temporarily but restore the state afterwards.
+ *
+ * Beware: I'm not sure how the RS-485 stuff is supposed to work. Using
+ * XON/XOFF seems problematic if there are several controllers, but if it's
+ * actually RS-422 (multi-drop; one sender and multiple receivers), it might
+ * Just Work, so don't bail out just because it looks a little suspicious.
+ */
+
+void serial_cris_send_xchar(struct uart_port *port, char ch)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ reg_ser_rw_dout dout = { .data = ch };
+ reg_ser_rw_ack_intr ack_intr = { .tr_rdy = regk_ser_yes };
+ reg_ser_r_stat_din rstat;
+ reg_ser_rw_tr_ctrl prev_tr_ctrl, tr_ctrl;
+ reg_scope_instances regi_ser = up->regi_ser;
+ unsigned long flags;
+
+ /*
+ * Wait for tr_rdy in case a character is already being output. Make
+ * sure we have integrity between the register reads and the writes
+ * below, but don't busy-wait with interrupts off and the port lock
+ * taken.
+ */
+ spin_lock_irqsave(&port->lock, flags);
+ do {
+ spin_unlock_irqrestore(&port->lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
+ prev_tr_ctrl = tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
+ rstat = REG_RD(ser, regi_ser, r_stat_din);
+ } while (!rstat.tr_rdy);
+
+ /*
+ * Ack an interrupt if one was just issued for the previous character
+ * that was output. This is required for non-DMA as the interrupt is
+ * used as the only indicator that the transmitter is ready and it
+ * isn't while this x_char is being transmitted.
+ */
+ REG_WR(ser, regi_ser, rw_ack_intr, ack_intr);
+
+ /* Enable the transmitter in case it was disabled. */
+ tr_ctrl.stop = 0;
+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
+
+ /*
+ * Finally, send the blessed character; nothing should stop it now,
+ * except for an xoff-detected state, which we'll handle below.
+ */
+ REG_WR(ser, regi_ser, rw_dout, dout);
+ up->port.icount.tx++;
+
+ /* There might be an xoff state to clear. */
+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
+
+ /*
+ * Clear any xoff state that *may* have been there to
+ * inhibit transmission of the character.
+ */
+ if (rstat.xoff_detect) {
+ reg_ser_rw_xoff_clr xoff_clr = { .clr = 1 };
+ reg_ser_rw_tr_dma_en tr_dma_en;
+ REG_WR(ser, regi_ser, rw_xoff_clr, xoff_clr);
+ tr_dma_en = REG_RD(ser, regi_ser, rw_tr_dma_en);
+
+ /*
+ * If we had an xoff state but cleared it, instead sneak in a
+ * disabled state for the transmitter, after the character we
+ * sent. Thus we keep the port disabled, just as if the xoff
+ * state was still in effect (or actually, as if stop_tx had
+ * been called, as we stop DMA too).
+ */
+ prev_tr_ctrl.stop = 1;
+
+ tr_dma_en.en = 0;
+ REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en);
+ }
+
+ /* Restore "previous" enabled/disabled state of the transmitter. */
+ REG_WR(ser, regi_ser, rw_tr_ctrl, prev_tr_ctrl);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void transmit_chars_dma(struct uart_cris_port *up);
+
+/*
+ * Do not spin_lock_irqsave or disable interrupts by other means here; it's
+ * already done by the caller.
+ */
+
+static void serial_cris_start_tx(struct uart_port *port)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ reg_scope_instances regi_ser = up->regi_ser;
+ reg_ser_rw_tr_ctrl tr_ctrl;
+
+ /* we have already done below if a write is ongoing */
+ if (!up->regi_dmaout && up->write_ongoing)
+ return;
+
+#ifdef CONFIG_ETRAX_RS485
+ if (up->rs485.enabled)
+ {
+ /* If we are in RS-485 mode, we need to toggle RTS and disable
+ * the receiver before initiating a DMA transfer
+ */
+
+ if (up->rs485.delay_rts_before_send > 0) {
+ reg_ser_rw_tr_ctrl tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
+ tr_ctrl.auto_rts = regk_ser_no;
+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
+ crisv32_serial_set_rts(up, up->rs485.rts_on_send, 1);
+ msleep(up->rs485.delay_rts_before_send);
+ tr_ctrl.auto_rts = regk_ser_yes;
+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
+ crisv32_serial_set_rts(up, !up->rs485.rts_on_send, 1);
+ }
+ }
+#endif
+
+ tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
+ tr_ctrl.stop = regk_ser_no;
+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
+ if (!up->regi_dmaout) {
+ reg_ser_rw_intr_mask intr_mask =
+ REG_RD(ser, regi_ser, rw_intr_mask);
+ intr_mask.tr_rdy = regk_ser_yes;
+ REG_WR(ser, regi_ser, rw_intr_mask, intr_mask);
+ up->write_ongoing = 1;
+ } else {
+ /*
+ * We're called possibly to re-enable transmission after it
+ * has been disabled. If so, DMA needs to be re-enabled.
+ */
+ reg_ser_rw_tr_dma_en tr_dma_en = { .en = 1 };
+ REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en);
+ transmit_chars_dma(up);
+ }
+}
+
+/*
+ * This function handles both the DMA and non-DMA case by ordering the
+ * transmitter to stop of after the current character. We don't need to wait
+ * for any such character to be completely transmitted; we do that where it
+ * matters, like in serial_cris_set_termios. Don't busy-wait here; see
+ * Documentation/serial/driver: this function is called within
+ * spin_lock_irq{,save} and thus separate ones would be disastrous (when SMP).
+ * There's no documented need to set the txd pin to any particular value;
+ * break setting is controlled solely by serial_cris_break_ctl.
+ */
+
+static void serial_cris_stop_tx(struct uart_port *port)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ reg_scope_instances regi_ser = up->regi_ser;
+ reg_ser_rw_tr_ctrl tr_ctrl;
+ reg_ser_rw_intr_mask intr_mask;
+ reg_ser_rw_tr_dma_en tr_dma_en = {0};
+ reg_ser_rw_xoff_clr xoff_clr = {0};
+
+ /*
+ * For the non-DMA case, we'd get a tr_rdy interrupt that we're not
+ * interested in as we're not transmitting any characters. For the
+ * DMA case, that interrupt is already turned off, but no reason to
+ * waste code on conditionals here.
+ */
+ intr_mask = REG_RD(ser, regi_ser, rw_intr_mask);
+ intr_mask.tr_rdy = regk_ser_no;
+ REG_WR(ser, regi_ser, rw_intr_mask, intr_mask);
+
+ tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
+ tr_ctrl.stop = 1;
+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
+
+ /*
+ * Always clear possible hardware xoff-detected state here, no need to
+ * unnecessary consider mctrl settings and when they change. We clear
+ * it here rather than in start_tx: both functions are called as the
+ * effect of XOFF processing, but start_tx is also called when upper
+ * levels tell the driver that there are more characters to send, so
+ * avoid adding code there.
+ */
+ xoff_clr.clr = 1;
+ REG_WR(ser, regi_ser, rw_xoff_clr, xoff_clr);
+
+ /*
+ * Disable transmitter DMA, so that if we're in XON/XOFF, we can send
+ * those single characters without also giving go-ahead for queued up
+ * DMA data.
+ */
+ tr_dma_en.en = 0;
+ REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en);
+}
+
+static void serial_cris_stop_rx(struct uart_port *port)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ reg_scope_instances regi_ser = up->regi_ser;
+ reg_ser_rw_rec_ctrl rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
+
+ rec_ctrl.en = regk_ser_no;
+ REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
+}
+
+static void serial_cris_enable_ms(struct uart_port *port)
+{
+}
+
+static void check_modem_status(struct uart_cris_port *up)
+{
+}
+
+static unsigned int serial_cris_tx_empty(struct uart_port *port)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ unsigned long flags;
+ unsigned int ret;
+ reg_ser_r_stat_din rstat = {0};
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->regi_dmaout) {
+ /*
+ * For DMA, before looking at r_stat, we need to check that we
+ * either haven't actually started or that end-of-list is
+ * reached, else a tr_empty indication is just an internal
+ * state. The caller qualifies, if needed, that the
+ * port->info.xmit buffer is empty, so we don't need to
+ * check that.
+ */
+ reg_dma_rw_stat status = REG_RD(dma, up->regi_dmaout, rw_stat);
+
+ if (!up->tx_started) {
+ ret = 1;
+ goto done;
+ }
+
+ if (status.list_state != regk_dma_data_at_eol) {
+ ret = 0;
+ goto done;
+ }
+ }
+
+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
+ ret = rstat.tr_empty ? TIOCSER_TEMT : 0;
+
+ done:
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return ret;
+}
+static unsigned int serial_cris_get_mctrl(struct uart_port *port)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ unsigned int ret;
+
+ ret = 0;
+ if (crisv32_serial_get_rts(up))
+ ret |= TIOCM_RTS;
+ /* DTR is active low */
+ if (!crisv32_io_rd(&up->dtr_pin))
+ ret |= TIOCM_DTR;
+ /* CD is active low */
+ if (!crisv32_io_rd(&up->cd_pin))
+ ret |= TIOCM_CD;
+ /* RI is active low */
+ if (!crisv32_io_rd(&up->ri_pin))
+ ret |= TIOCM_RI;
+ /* DSR is active low */
+ if (!crisv32_io_rd(&up->dsr_pin))
+ ret |= TIOCM_DSR;
+ if (crisv32_serial_get_cts(up))
+ ret |= TIOCM_CTS;
+ return ret;
+}
+
+static void serial_cris_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+
+ crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0);
+ /* DTR is active low */
+ crisv32_io_set(&up->dtr_pin, mctrl & TIOCM_DTR ? 0 : 1);
+ /* RI is active low */
+ crisv32_io_set(&up->ri_pin, mctrl & TIOCM_RNG ? 0 : 1);
+ /* CD is active low */
+ crisv32_io_set(&up->cd_pin, mctrl & TIOCM_CD ? 0 : 1);
+}
+
+static void serial_cris_break_ctl(struct uart_port *port, int break_state)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ unsigned long flags;
+ reg_ser_rw_tr_ctrl tr_ctrl;
+ reg_ser_rw_tr_dma_en tr_dma_en;
+ reg_ser_rw_intr_mask intr_mask;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ tr_ctrl = REG_RD(ser, up->regi_ser, rw_tr_ctrl);
+ tr_dma_en = REG_RD(ser, up->regi_ser, rw_tr_dma_en);
+ intr_mask = REG_RD(ser, up->regi_ser, rw_intr_mask);
+
+ if (break_state != 0) { /* Send break */
+ /*
+ * We need to disable DMA (if used) or tr_rdy interrupts if no
+ * DMA. No need to make this conditional on use of DMA;
+ * disabling will be a no-op for the other mode.
+ */
+ intr_mask.tr_rdy = regk_ser_no;
+ tr_dma_en.en = 0;
+
+ /*
+ * Stop transmission and set the txd pin to 0 after the
+ * current character. The txd setting will take effect after
+ * any current transmission has completed.
+ */
+ tr_ctrl.stop = 1;
+ tr_ctrl.txd = 0;
+ } else {
+ /* Re-enable either transmit DMA or the serial interrupt. */
+ if (up->regi_dmaout)
+ tr_dma_en.en = 1;
+ else
+ intr_mask.tr_rdy = regk_ser_yes;
+
+
+ tr_ctrl.stop = 0;
+ tr_ctrl.txd = 1;
+ }
+ REG_WR(ser, up->regi_ser, rw_tr_ctrl, tr_ctrl);
+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, tr_dma_en);
+ REG_WR(ser, up->regi_ser, rw_intr_mask, intr_mask);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+/*
+ * The output DMA channel is free - use it to send as many chars as
+ * possible.
+ */
+
+static void
+transmit_chars_dma(struct uart_cris_port *up)
+{
+ struct dma_descr_data *descr, *pending_descr, *dmapos;
+ struct dma_descr_data *last_tx_descr;
+ struct circ_buf *xmit = &up->port.state->xmit;
+ unsigned int sentl = 0;
+ reg_dma_rw_ack_intr ack_intr = { .data = regk_dma_yes };
+ reg_dma_rw_stat status;
+ reg_scope_instances regi_dmaout = up->regi_dmaout;
+ unsigned int chars_in_q;
+ unsigned int chars_to_send;
+
+ /* Acknowledge dma data descriptor irq, if there was one. */
+ REG_WR(dma, regi_dmaout, rw_ack_intr, ack_intr);
+
+ /*
+ * First get the amount of bytes sent during the last DMA transfer,
+ * and update xmit accordingly.
+ */
+ status = REG_RD(dma, regi_dmaout, rw_stat);
+ if (status.list_state == regk_dma_data_at_eol || !up->tx_started)
+ dmapos = phys_to_virt((int)up->last_tx_descr->next);
+ else
+ dmapos = phys_to_virt(REG_RD_INT(dma, regi_dmaout, rw_data));
+
+ pending_descr = up->first_tx_descr;
+ while (pending_descr != dmapos) {
+ sentl += pending_descr->after - pending_descr->buf;
+ pending_descr->after = pending_descr->buf = NULL;
+ pending_descr = phys_to_virt((int)pending_descr->next);
+ }
+
+ up->first_tx_descr = pending_descr;
+ last_tx_descr = up->last_tx_descr;
+
+ /* Update stats. */
+ up->port.icount.tx += sentl;
+
+ up->tx_pending_chars -= sentl;
+
+ /* Update xmit buffer. */
+ xmit->tail = (xmit->tail + sentl) & (UART_XMIT_SIZE - 1);
+
+ /*
+ * Find out the largest amount of consecutive bytes we want to send
+ * now.
+ */
+ chars_in_q = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+
+ if (chars_in_q == 0)
+ /* Tell upper layers that we're now idle. */
+ goto done;
+
+ /* Some of those characters are actually pending output. */
+ chars_to_send = chars_in_q - up->tx_pending_chars;
+
+ /*
+ * Clamp the new number of pending chars to the advertised
+ * one.
+ */
+ if (chars_to_send + up->tx_pending_chars > up->port.fifosize)
+ chars_to_send = up->port.fifosize - up->tx_pending_chars;
+
+ /* If we don't want to send any, we're done. */
+ if (chars_to_send == 0)
+ goto done;
+
+ descr = phys_to_virt((int)last_tx_descr->next);
+
+ /*
+ * We can't send anything if we could make the condition in
+ * the while-loop above (reaping finished descriptors) be met
+ * immediately before the first iteration. However, don't
+ * mistake the full state for the empty state.
+ */
+ if ((descr == up->first_tx_descr && up->tx_pending_chars != 0)
+ || descr->next == up->first_tx_descr)
+ goto done;
+
+ /* Set up the descriptor for output. */
+ descr->buf = (void*)virt_to_phys(xmit->buf + xmit->tail
+ + up->tx_pending_chars);
+ descr->after = descr->buf + chars_to_send;
+ descr->eol = 1;
+ descr->out_eop = 0;
+ descr->intr = 1;
+ descr->wait = 0;
+ descr->in_eop = 0;
+ descr->md = 0;
+ /*
+ * Make sure GCC doesn't move this eol clear before the eol set
+ * above.
+ */
+ barrier();
+ last_tx_descr->eol = 0;
+
+ up->last_tx_descr = descr;
+ up->tx_pending_chars += chars_to_send;
+
+ if (!up->tx_started) {
+ up->tx_started = 1;
+ up->tr_context_descr.next = 0;
+ up->tr_context_descr.saved_data
+ = (dma_descr_data*)virt_to_phys(descr);
+ up->tr_context_descr.saved_data_buf = descr->buf;
+ DMA_START_CONTEXT(regi_dmaout,
+ virt_to_phys(&up->tr_context_descr));
+ } else
+ DMA_CONTINUE_DATA(regi_dmaout);
+
+ /* DMA is now running (hopefully). */
+
+ done:
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&up->port);
+}
+
+static void
+transmit_chars_no_dma(struct uart_cris_port *up)
+{
+ int max_count;
+ struct circ_buf *xmit = &up->port.state->xmit;
+
+ reg_scope_instances regi_ser = up->regi_ser;
+ reg_ser_r_stat_din rstat;
+ reg_ser_rw_ack_intr ack_intr = { .tr_rdy = regk_ser_yes };
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+ /* No more to send, so disable the interrupt. */
+ reg_ser_rw_intr_mask intr_mask;
+ intr_mask = REG_RD(ser, regi_ser, rw_intr_mask);
+ intr_mask.tr_rdy = 0;
+ intr_mask.tr_empty = 0;
+ REG_WR(ser, regi_ser, rw_intr_mask, intr_mask);
+ up->write_ongoing=0;
+ return;
+ }
+
+ /* If the serport is fast, we send up to max_count bytes before
+ exiting the loop. */
+ max_count = 64;
+ do {
+ reg_ser_rw_dout dout = { .data = xmit->buf[xmit->tail] };
+ REG_WR(ser, regi_ser, rw_dout, dout);
+ REG_WR(ser, regi_ser, rw_ack_intr, ack_intr);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
+ up->port.icount.tx++;
+ if (xmit->head == xmit->tail)
+ break;
+ rstat = REG_RD(ser, regi_ser, r_stat_din);
+ } while ((--max_count > 0) && rstat.tr_rdy);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&up->port);
+} /* transmit_chars_no_dma */
+
+static struct etrax_recv_buffer *
+alloc_recv_buffer(unsigned int size)
+{
+ struct etrax_recv_buffer *buffer;
+
+ if (!(buffer = kmalloc(sizeof *buffer + size, GFP_ATOMIC)))
+ panic("%s: Could not allocate %d bytes buffer\n",
+ __FUNCTION__, size);
+
+ buffer->next = NULL;
+ buffer->length = 0;
+ buffer->error = TTY_NORMAL;
+
+ return buffer;
+}
+
+static void
+append_recv_buffer(struct uart_cris_port *up,
+ struct etrax_recv_buffer *buffer)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (!up->first_recv_buffer)
+ up->first_recv_buffer = buffer;
+ else
+ up->last_recv_buffer->next = buffer;
+
+ up->last_recv_buffer = buffer;
+
+ up->recv_cnt += buffer->length;
+ if (up->recv_cnt > up->max_recv_cnt)
+ up->max_recv_cnt = up->recv_cnt;
+
+ local_irq_restore(flags);
+}
+
+static int
+add_char_and_flag(struct uart_cris_port *up, unsigned char data,
+ unsigned char flag)
+{
+ struct etrax_recv_buffer *buffer;
+
+ buffer = alloc_recv_buffer(4);
+ buffer->length = 1;
+ buffer->error = flag;
+ buffer->buffer[0] = data;
+
+ append_recv_buffer(up, buffer);
+
+ up->port.icount.rx++;
+
+ return 1;
+}
+
+static void
+flush_to_flip_buffer(struct uart_cris_port *up)
+{
+ struct etrax_recv_buffer *buffer;
+
+ if (!up->first_recv_buffer)
+ return;
+
+ while ((buffer = up->first_recv_buffer)) {
+ unsigned int count = (unsigned int)
+ tty_insert_flip_string(&up->port.state->port,
+ buffer->buffer,
+ buffer->length);
+
+ up->recv_cnt -= count;
+
+ if (count == buffer->length) {
+ up->first_recv_buffer = buffer->next;
+ kfree(buffer);
+ } else {
+ buffer->length -= count;
+ memmove(buffer->buffer, buffer->buffer + count,
+ buffer->length);
+ buffer->error = TTY_NORMAL;
+ }
+ }
+
+ if (!up->first_recv_buffer)
+ up->last_recv_buffer = NULL;
+
+ /* This call includes a check for low-latency. */
+ tty_flip_buffer_push(&up->port.state->port);
+}
+
+static unsigned int
+handle_descr_data(struct uart_cris_port *up, struct dma_descr_data *descr,
+ unsigned int recvl)
+{
+ struct etrax_recv_buffer *buffer
+ = phys_to_virt((unsigned long)descr->buf) - sizeof *buffer;
+
+ if (up->recv_cnt + recvl > 65536) {
+ printk(KERN_ERR "Too much pending incoming data on %s!"
+ " Dropping %u bytes.\n", up->port.state->port.tty->name,
+ recvl);
+ return 0;
+ }
+
+ buffer->length = recvl;
+
+ append_recv_buffer(up, buffer);
+
+ flush_to_flip_buffer(up);
+
+ buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE);
+ descr->buf = (void*)virt_to_phys(buffer->buffer);
+ descr->after = descr->buf + SERIAL_DESCR_BUF_SIZE;
+
+ return recvl;
+}
+
+static unsigned int
+handle_all_descr_data(struct uart_cris_port *up)
+{
+ struct dma_descr_data *descr
+ = &up->rec_descr[(up->cur_rec_descr - 1)
+ % SERIAL_RECV_DESCRIPTORS];
+ struct dma_descr_data *prev_descr;
+ unsigned int recvl;
+ unsigned int ret = 0;
+ reg_scope_instances regi_dmain = up->regi_dmain;
+
+ while (1) {
+ prev_descr = descr;
+ descr = &up->rec_descr[up->cur_rec_descr];
+
+ if (descr == phys_to_virt(REG_RD(dma, regi_dmain, rw_data)))
+ break;
+
+ if (++up->cur_rec_descr == SERIAL_RECV_DESCRIPTORS)
+ up->cur_rec_descr = 0;
+
+ /* Find out how many bytes were read. */
+ recvl = descr->after - descr->buf;
+
+ /* Update stats. */
+ up->port.icount.rx += recvl;
+
+ ret += handle_descr_data(up, descr, recvl);
+ descr->eol = 1;
+ /*
+ * Make sure GCC doesn't move this eol clear before the
+ * eol set above.
+ */
+ barrier();
+ prev_descr->eol = 0;
+ flush_dma_descr(descr,1); // Cache bug workaround
+ flush_dma_descr(prev_descr,0); // Cache bug workaround
+ }
+
+ return ret;
+}
+
+static void
+receive_chars_dma(struct uart_cris_port *up)
+{
+ reg_ser_r_stat_din rstat;
+ reg_dma_rw_ack_intr ack_intr = {0};
+
+ /* Acknowledge both dma_descr and dma_eop irq. */
+ ack_intr.data = 1;
+ ack_intr.in_eop = 1;
+ REG_WR(dma, up->regi_dmain, rw_ack_intr, ack_intr);
+
+ handle_all_descr_data(up);
+
+ /* Read the status register to detect errors. */
+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
+
+ if (rstat.framing_err | rstat.par_err | rstat.orun) {
+ /*
+ * If we got an error, we must reset it by reading the
+ * rs_stat_din register and put the data in buffer manually.
+ */
+ reg_ser_rs_stat_din stat_din;
+ stat_din = REG_RD(ser, up->regi_ser, rs_stat_din);
+
+ if (stat_din.par_err)
+ add_char_and_flag(up, stat_din.data, TTY_PARITY);
+ else if (stat_din.orun)
+ add_char_and_flag(up, stat_din.data, TTY_OVERRUN);
+ else if (stat_din.framing_err)
+ add_char_and_flag(up, stat_din.data, TTY_FRAME);
+ }
+
+ /* Restart the receiving DMA, in case it got stuck on an EOL. */
+ DMA_CONTINUE_DATA(up->regi_dmain);
+}
+
+void receive_chars_no_dma(struct uart_cris_port *up)
+{
+ reg_ser_rs_stat_din stat_din;
+ reg_ser_r_stat_din rstat;
+ struct uart_icount *icount;
+ int max_count = 16;
+ char flag;
+ reg_ser_rw_ack_intr ack_intr = { 0 };
+
+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
+ up->last_rx_active_usec = GET_JIFFIES_USEC();
+ up->last_rx_active = jiffies;
+ icount = &up->port.icount;
+
+ do {
+ stat_din = REG_RD(ser, up->regi_ser, rs_stat_din);
+
+ flag = TTY_NORMAL;
+ ack_intr.dav = 1;
+ REG_WR(ser, up->regi_ser, rw_ack_intr, ack_intr);
+ icount->rx++;
+
+ if (stat_din.framing_err | stat_din.par_err | stat_din.orun) {
+ if (stat_din.data == 0x00 &&
+ stat_din.framing_err) {
+ /* Most likely a break. */
+ flag = TTY_BREAK;
+ icount->brk++;
+ } else if (stat_din.par_err) {
+ flag = TTY_PARITY;
+ icount->parity++;
+ } else if (stat_din.orun) {
+ flag = TTY_OVERRUN;
+ icount->overrun++;
+ } else if (stat_din.framing_err) {
+ flag = TTY_FRAME;
+ icount->frame++;
+ }
+ }
+
+ /*
+ * If this becomes important, we probably *could* handle this
+ * gracefully by keeping track of the unhandled character.
+ */
+ if (!tty_insert_flip_char(&up->port.state->port, stat_din.data, flag))
+ panic("%s: No tty buffer space", __FUNCTION__);
+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
+ } while (rstat.dav && (max_count-- > 0));
+ spin_unlock(&up->port.lock);
+ tty_flip_buffer_push(&up->port.state->port);
+ spin_lock(&up->port.lock);
+} /* receive_chars_no_dma */
+
+/*
+ * DMA output channel interrupt handler.
+ * this interrupt is called from DMA2(ser2), DMA8(ser3), DMA6(ser0) or
+ * DMA4(ser1) when they have finished a descriptor with the intr flag set.
+ */
+static irqreturn_t dma_tr_interrupt(int irq, void *dev_id)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)dev_id;
+ reg_dma_r_masked_intr masked_intr;
+ reg_scope_instances regi_dmaout;
+ int handled = 0;
+
+ spin_lock(&up->port.lock);
+ regi_dmaout = up->regi_dmaout;
+ if (!regi_dmaout) {
+ spin_unlock(&up->port.lock);
+ return IRQ_NONE;
+ }
+
+ /*
+ * Check for dma_descr (don't need to check for dma_eop in
+ * output DMA for serial).
+ */
+ masked_intr = REG_RD(dma, regi_dmaout, r_masked_intr);
+
+ if (masked_intr.data) {
+ /* We can send a new dma bunch. make it so. */
+
+ /*
+ * Read jiffies_usec first.
+ * We want this time to be as late as possible.
+ */
+ up->last_tx_active_usec = GET_JIFFIES_USEC();
+ up->last_tx_active = jiffies;
+ transmit_chars_dma(up);
+ handled = 1;
+ }
+ check_modem_status(up);
+ spin_unlock(&up->port.lock);
+ return IRQ_RETVAL(handled);
+}
+
+/* DMA input channel interrupt handler. */
+
+static irqreturn_t
+dma_rec_interrupt(int irq, void *dev_id)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)dev_id;
+ reg_dma_r_masked_intr masked_intr;
+ reg_scope_instances regi_dmain;
+ int handled = 0;
+
+ spin_lock(&up->port.lock);
+ regi_dmain = up->regi_dmain;
+ if (!regi_dmain) {
+ spin_unlock(&up->port.lock);
+ return IRQ_NONE;
+ }
+
+ /* Check for both dma_eop and dma_descr for the input dma channel. */
+ masked_intr = REG_RD(dma, regi_dmain, r_masked_intr);
+ if (masked_intr.data || masked_intr.in_eop) {
+ /* We have received something. */
+ receive_chars_dma(up);
+ handled = 1;
+ }
+ check_modem_status(up);
+ spin_unlock(&up->port.lock);
+ return IRQ_RETVAL(handled);
+}
+
+/* "Normal" serial port interrupt handler - both rx and tx. */
+
+static irqreturn_t
+ser_interrupt(int irq, void *dev_id)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)dev_id;
+ reg_scope_instances regi_ser;
+ int handled = 0;
+
+ spin_lock(&up->port.lock);
+ if (up->regi_dmain && up->regi_dmaout) {
+ spin_unlock(&up->port.lock);
+ return IRQ_NONE;
+ }
+
+ regi_ser = up->regi_ser;
+
+ if (regi_ser) {
+ reg_ser_r_masked_intr masked_intr;
+ masked_intr = REG_RD(ser, regi_ser, r_masked_intr);
+ /*
+ * Check what interrupts are active before taking
+ * actions. If DMA is used the interrupt shouldn't
+ * be enabled.
+ */
+ if (masked_intr.dav) {
+ receive_chars_no_dma(up);
+ handled = 1;
+ }
+ check_modem_status(up);
+
+ if (masked_intr.tr_rdy) {
+ transmit_chars_no_dma(up);
+ handled = 1;
+ }
+ }
+ spin_unlock(&up->port.lock);
+ return IRQ_RETVAL(handled);
+} /* ser_interrupt */
+
+static int start_recv_dma(struct uart_cris_port *up)
+{
+ struct dma_descr_data *descr = up->rec_descr;
+ struct etrax_recv_buffer *buffer;
+ int i;
+
+ /* Set up the receiving descriptors. */
+ for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) {
+ buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE);
+ descr[i].next = (void*)virt_to_phys(&descr[i+1]);
+ descr[i].buf = (void*)virt_to_phys(buffer->buffer);
+ descr[i].after = descr[i].buf + SERIAL_DESCR_BUF_SIZE;
+ descr[i].eol = 0;
+ descr[i].out_eop = 0;
+ descr[i].intr = 1;
+ descr[i].wait = 0;
+ descr[i].in_eop = 0;
+ descr[i].md = 0;
+
+ }
+
+ /* Link the last descriptor to the first. */
+ descr[i-1].next = (void*)virt_to_phys(&descr[0]);
+
+ /* And mark it as end of list. */
+ descr[i-1].eol = 1;
+
+ /* Start with the first descriptor in the list. */
+ up->cur_rec_descr = 0;
+ up->rec_context_descr.next = 0;
+ up->rec_context_descr.saved_data
+ = (dma_descr_data *)virt_to_phys(&descr[up->cur_rec_descr]);
+ up->rec_context_descr.saved_data_buf = descr[up->cur_rec_descr].buf;
+
+ /* Start the DMA. */
+ DMA_START_CONTEXT(up->regi_dmain,
+ virt_to_phys(&up->rec_context_descr));
+
+ /* Input DMA should be running now. */
+ return 1;
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static int serial_artpec_get_poll_char(struct uart_port *port)
+{
+ reg_ser_rs_stat_din stat;
+ reg_ser_rw_ack_intr ack_intr = { 0 };
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+
+ do {
+ stat = REG_RD(ser, up->regi_ser, rs_stat_din);
+ } while (!stat.dav);
+
+ /* Ack the data_avail interrupt. */
+ ack_intr.dav = 1;
+ REG_WR(ser, up->regi_ser, rw_ack_intr, ack_intr);
+
+ return stat.data;
+}
+
+static void serial_artpec_put_poll_char(struct uart_port *port,
+ unsigned char c)
+{
+ reg_ser_r_stat_din stat;
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+
+ do {
+ stat = REG_RD (ser, up->regi_ser, r_stat_din);
+ } while (!stat.tr_rdy);
+ REG_WR_INT (ser, up->regi_ser, rw_dout, c);
+}
+#endif /* CONFIG_CONSOLE_POLL */
+
+static void start_receive(struct uart_cris_port *up)
+{
+ reg_scope_instances regi_dmain = up->regi_dmain;
+ if (regi_dmain) {
+ start_recv_dma(up);
+ }
+}
+
+
+static void start_transmitter(struct uart_cris_port *up)
+{
+ int i;
+ reg_scope_instances regi_dmaout = up->regi_dmaout;
+ if (regi_dmaout) {
+ for (i = 0; i < SERIAL_TX_DESCRIPTORS; i++) {
+ memset(&up->tr_descr[i], 0, sizeof(up->tr_descr[i]));
+ up->tr_descr[i].eol = 1;
+ up->tr_descr[i].intr = 1;
+ up->tr_descr[i].next = (dma_descr_data *)
+ virt_to_phys(&up->tr_descr[i+1]);
+ }
+ up->tr_descr[i-1].next = (dma_descr_data *)
+ virt_to_phys(&up->tr_descr[0]);
+ up->first_tx_descr = &up->tr_descr[0];
+
+ /*
+ * We'll be counting up to up->last_tx_descr->next from
+ * up->first_tx_descr when starting DMA, so we should make
+ * them the same for the very first round. If instead we'd
+ * set last_tx_descr = first_tx_descr, we'd rely on
+ * accidentally working code and data as we'd take a pass over
+ * the first, unused, descriptor.
+ */
+ up->last_tx_descr = &up->tr_descr[i-1];
+ up->tx_started = 0;
+ up->tx_pending_chars = 0;
+ }
+}
+
+static int serial_cris_startup(struct uart_port *port)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ unsigned long flags;
+ reg_ser_rw_intr_mask ser_intr_mask = {0};
+ reg_dma_rw_intr_mask dmain_intr_mask = {0};
+ reg_dma_rw_intr_mask dmaout_intr_mask = {0};
+ reg_dma_rw_cfg cfg = {.en = 1};
+ reg_scope_instances regi_dma;
+
+ /* We dont disable interrupts here because request_irq should
+ not be called with ints disabled. */
+ spin_lock(&up->port.lock);
+
+ dmain_intr_mask.data = dmain_intr_mask.in_eop = regk_dma_yes;
+ dmaout_intr_mask.data = regk_dma_yes;
+ if (!up->regi_dmain)
+ ser_intr_mask.dav = regk_ser_yes;
+
+ if (port->line == 0) {
+ if (request_irq(SER0_INTR_VECT, ser_interrupt,
+ IRQF_DISABLED, "ser0",
+ &serial_cris_ports[0]))
+ panic("irq ser0");
+ /* Port ser0 can use dma6 for tx and dma7 for rx. */
+#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
+ if (request_irq(DMA6_INTR_VECT, dma_tr_interrupt,
+ IRQF_DISABLED, "serial 0 dma tr",
+ &serial_cris_ports[0]))
+ panic("irq ser0txdma");
+ crisv32_request_dma(6, "ser0", DMA_PANIC_ON_ERROR, 0,
+ dma_ser0);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
+ if (request_irq(DMA7_INTR_VECT, dma_rec_interrupt,
+ IRQF_DISABLED, "serial 0 dma rec",
+ &serial_cris_ports[0]))
+ panic("irq ser0rxdma");
+ crisv32_request_dma(7, "ser0", DMA_PANIC_ON_ERROR, 0,
+ dma_ser0);
+#endif
+ } else if (port->line == 1) {
+ if (request_irq(SER1_INTR_VECT, ser_interrupt,
+ IRQF_DISABLED, "ser1",
+ &serial_cris_ports[1]))
+ panic("irq ser1");
+
+ /* Port ser1 can use dma4 for tx and dma5 for rx. */
+#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA4_OUT
+ if (request_irq(DMA4_INTR_VECT, dma_tr_interrupt,
+ IRQF_DISABLED, "serial 1 dma tr",
+ &serial_cris_ports[1]))
+ panic("irq ser1txdma");
+ crisv32_request_dma(4, "ser1", DMA_PANIC_ON_ERROR, 0,
+ dma_ser1);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA5_IN
+ if (request_irq(DMA5_INTR_VECT, dma_rec_interrupt,
+ IRQF_DISABLED, "serial 1 dma rec",
+ &serial_cris_ports[1]))
+ panic("irq ser1rxdma");
+ crisv32_request_dma(5, "ser1", DMA_PANIC_ON_ERROR, 0,
+ dma_ser1);
+#endif
+ } else if (port->line == 2) {
+ if (request_irq(SER2_INTR_VECT, ser_interrupt,
+ IRQF_DISABLED, "ser2",
+ &serial_cris_ports[2]))
+ panic("irq ser2");
+
+ /* Port ser2 can use dma2 for tx and dma3 for rx. */
+#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
+ if (request_irq(DMA2_INTR_VECT, dma_tr_interrupt,
+ IRQF_DISABLED, "serial 2 dma tr",
+ &serial_cris_ports[2]))
+ panic("irq ser2txdma");
+ crisv32_request_dma(2, "ser2", DMA_PANIC_ON_ERROR, 0,
+ dma_ser2);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
+ if (request_irq(DMA3_INTR_VECT, dma_rec_interrupt,
+ IRQF_DISABLED, "serial 2 dma rec",
+ &serial_cris_ports[2]))
+ panic("irq ser2rxdma");
+ crisv32_request_dma(3, "ser2", DMA_PANIC_ON_ERROR, 0,
+ dma_ser2);
+#endif
+ } else if (port->line == 3) {
+ if (request_irq(SER3_INTR_VECT, ser_interrupt,
+ IRQF_DISABLED, "ser3",
+ &serial_cris_ports[3]))
+ panic("irq ser3" );
+
+ /* Port ser3 can use dma8 for tx and dma9 for rx. */
+#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA8_OUT
+ if (request_irq(DMA8_INTR_VECT, dma_tr_interrupt,
+ IRQF_DISABLED, "serial 3 dma tr",
+ &serial_cris_ports[3]))
+ panic("irq ser3txdma");
+ crisv32_request_dma(8, "ser3", DMA_PANIC_ON_ERROR, 0,
+ dma_ser3);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA9_IN
+ if (request_irq(DMA9_INTR_VECT, dma_rec_interrupt,
+ IRQF_DISABLED, "serial 3 dma rec",
+ &serial_cris_ports[3]))
+ panic("irq ser3rxdma");
+ crisv32_request_dma(9, "ser3", DMA_PANIC_ON_ERROR, 0,
+ dma_ser3);
+#endif
+ }
+#if CONFIG_ETRAX_SERIAL_PORTS == 5
+ else if (port->line == 4) {
+ if (request_irq(SER4_INTR_VECT, ser_interrupt,
+ IRQF_DISABLED, "ser4",
+ &serial_cris_ports[4]))
+ panic("irq ser4" );
+
+#ifdef CONFIG_ETRAX_SERIAL_PORT4_DMA_OUT
+ if (request_irq(DMA4_INTR_VECT, dma_tr_interrupt,
+ IRQF_DISABLED, "serial 4 dma tr",
+ &serial_cris_ports[4]))
+ panic("irq ser4txdma");
+ crisv32_request_dma(5, "ser4", DMA_PANIC_ON_ERROR, 0,
+ dma_ser4);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT4_DMA_IN
+ if (request_irq(DMA5_INTR_VECT, dma_rec_interrupt,
+ IRQF_DISABLED, "serial 4 dma rec",
+ &serial_cris_ports[4]))
+ panic("irq ser4rxdma");
+ crisv32_request_dma(5, "ser4", DMA_PANIC_ON_ERROR, 0,
+ dma_ser4);
+#endif
+ }
+#endif
+
+ local_irq_save(flags);
+
+ /*
+ * Reset the DMA channels and make sure their interrupts are cleared.
+ */
+
+ regi_dma = up->regi_dmain;
+ if (regi_dma) {
+ reg_dma_rw_ack_intr ack_intr = { 0 };
+ DMA_RESET(regi_dma);
+ /* Wait until reset cycle is complete. */
+ DMA_WAIT_UNTIL_RESET(regi_dma);
+ REG_WR(dma, regi_dma, rw_cfg, cfg);
+ /* Make sure the irqs are cleared. */
+ ack_intr.group = 1;
+ ack_intr.ctxt = 1;
+ ack_intr.data = 1;
+ ack_intr.in_eop = 1;
+ ack_intr.stream_cmd = 1;
+ REG_WR(dma, regi_dma, rw_ack_intr, ack_intr);
+ }
+ regi_dma = up->regi_dmaout;
+ if (regi_dma) {
+ reg_dma_rw_ack_intr ack_intr = { 0 };
+ DMA_RESET(regi_dma);
+ /* Wait until reset cycle is complete. */
+ DMA_WAIT_UNTIL_RESET(regi_dma);
+ REG_WR(dma, regi_dma, rw_cfg, cfg);
+ /* Make sure the irqs are cleared. */
+ ack_intr.group = 1;
+ ack_intr.ctxt = 1;
+ ack_intr.data = 1;
+ ack_intr.in_eop = 1;
+ ack_intr.stream_cmd = 1;
+ REG_WR(dma, regi_dma, rw_ack_intr, ack_intr);
+ }
+
+ REG_WR(ser, up->regi_ser, rw_intr_mask, ser_intr_mask);
+ if (up->regi_dmain)
+ REG_WR(dma, up->regi_dmain, rw_intr_mask, dmain_intr_mask);
+ if (up->regi_dmaout)
+ REG_WR(dma, up->regi_dmaout, rw_intr_mask, dmaout_intr_mask);
+
+ start_receive(up);
+ start_transmitter(up);
+
+ serial_cris_set_mctrl(&up->port, up->port.mctrl);
+
+ local_irq_restore(flags);
+ spin_unlock(&up->port.lock);
+
+ return 0;
+}
+
+static void serial_cris_shutdown(struct uart_port *port)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ serial_cris_stop_tx(port);
+ serial_cris_stop_rx(port);
+
+ if (port->line == 0) {
+ free_irq(SER0_INTR_VECT, &serial_cris_ports[0]);
+#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
+ crisv32_free_dma(6);
+ free_irq(DMA6_INTR_VECT, &serial_cris_ports[0]);
+#elif defined(CONFIG_ETRAX_SERIAL_PORT0_DMA0_OUT)
+ crisv32_free_dma(0);
+ free_irq(DMA0_INTR_VECT, &serial_cris_ports[0]);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
+ crisv32_free_dma(7);
+ free_irq(DMA7_INTR_VECT, &serial_cris_ports[0]);
+#elif defined(CONFIG_ETRAX_SERIAL_PORT0_DMA1_IN)
+ crisv32_free_dma(1);
+ free_irq(DMA1_INTR_VECT, &serial_cris_ports[0]);
+#endif
+ } else if (port->line == 1) {
+ free_irq(SER1_INTR_VECT, &serial_cris_ports[1]);
+#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA4_OUT
+ crisv32_free_dma(4);
+ free_irq(DMA4_INTR_VECT, &serial_cris_ports[1]);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA5_IN
+ crisv32_free_dma(5);
+ free_irq(DMA5_INTR_VECT, &serial_cris_ports[1]);
+#endif
+ } else if (port->line == 2) {
+ free_irq(SER2_INTR_VECT, &serial_cris_ports[2]);
+#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
+ crisv32_free_dma(2);
+ free_irq(DMA2_INTR_VECT, &serial_cris_ports[2]);
+#elif defined(CONFIG_ETRAX_SERIAL_PORT2_DMA6_OUT)
+ crisv32_free_dma(6);
+ free_irq(DMA6_INTR_VECT, &serial_cris_ports[2]);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
+ crisv32_free_dma(3);
+ free_irq(DMA3_INTR_VECT, &serial_cris_ports[2]);
+#elif defined(CONFIG_ETRAX_SERIAL_PORT2_DMA7_IN)
+ crisv32_free_dma(7);
+ free_irq(DMA7_INTR_VECT, &serial_cris_ports[2]);
+#endif
+ } else if (port->line == 3) {
+ free_irq(SER3_INTR_VECT, &serial_cris_ports[3]);
+#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA8_OUT
+ crisv32_free_dma(8);
+ free_irq(DMA8_INTR_VECT, &serial_cris_ports[3]);
+#elif defined(CONFIG_ETRAX_SERIAL_PORT3_DMA2_OUT)
+ crisv32_free_dma(2);
+ free_irq(DMA2_INTR_VECT, &serial_cris_ports[3]);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA9_IN
+ crisv32_free_dma(9);
+ free_irq(DMA9_INTR_VECT, &serial_cris_ports[3]);
+#elif defined(CONFIG_ETRAX_SERIAL_PORT3_DMA3_IN)
+ crisv32_free_dma(3);
+ free_irq(DMA3_INTR_VECT, &serial_cris_ports[3]);
+#endif
+ }
+#if CONFIG_ETRAX_SERIAL_PORTS == 5
+ else if (port->line == 4) {
+ free_irq(SER4_INTR_VECT, &serial_cris_ports[4]);
+#ifdef CONFIG_ETRAX_SERIAL_PORT4_DMA9_IN
+ crisv32_free_dma(9);
+ free_irq(DMA9_INTR_VECT, &serial_cris_ports[4]);
+#endif
+ }
+#endif
+
+ serial_cris_set_mctrl(&up->port, up->port.mctrl);
+
+ if (up->regi_dmain) {
+ struct etrax_recv_buffer *rb;
+ struct etrax_recv_buffer *rb_next;
+ int i;
+ struct dma_descr_data *descr;
+
+ /*
+ * In case of DMA and receive errors, there might be pending
+ * receive buffers still linked here and not flushed upwards.
+ * Release them.
+ */
+ for (rb = up->first_recv_buffer; rb != NULL; rb = rb_next) {
+ rb_next = rb->next;
+ kfree (rb);
+ }
+ up->first_recv_buffer = NULL;
+ up->last_recv_buffer = NULL;
+
+ /*
+ * Also release buffers that were attached to the DMA
+ * before we shut down the hardware above.
+ */
+ for (i = 0, descr = up->rec_descr;
+ i < SERIAL_RECV_DESCRIPTORS;
+ i++)
+ if (descr[i].buf) {
+ rb = phys_to_virt((u32) descr[i].buf)
+ - sizeof *rb;
+ kfree(rb);
+ descr[i].buf = NULL;
+ }
+ }
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+}
+
+static void
+serial_cris_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ unsigned long flags;
+ reg_ser_rw_xoff xoff;
+ reg_ser_rw_xoff_clr xoff_clr = {0};
+ reg_ser_rw_tr_ctrl tx_ctrl = {0};
+ reg_ser_rw_tr_dma_en tx_dma_en = {0};
+ reg_ser_rw_rec_ctrl rx_ctrl = {0};
+ reg_ser_rw_tr_baud_div tx_baud_div = {0};
+ reg_ser_rw_rec_baud_div rx_baud_div = {0};
+ reg_ser_r_stat_din rstat;
+ int baud;
+
+ if (old &&
+ termios->c_cflag == old->c_cflag &&
+ termios->c_iflag == old->c_iflag)
+ return;
+
+ /* Start with default settings and then fill in changes. */
+
+ /* Tx: 8 bit, no/even parity, 1 stop bit, no cts. */
+ tx_ctrl.base_freq = regk_ser_f29_493;
+ tx_ctrl.en = 0;
+ tx_ctrl.stop = 0;
+#ifdef CONFIG_ETRAX_RS485
+ if (up->rs485.enabled && (up->port_type != TYPE_485FD)) {
+ tx_ctrl.auto_rts = regk_ser_yes;
+ tx_ctrl.rts_setup = regk_ser_bits2;
+
+ if (termios->c_cflag & CSTOPB) {
+ /* 2 stop bits. */
+ tx_ctrl.rts_delay = regk_ser_del2;
+ }
+ else {
+ /* 1 stop bits. */
+ tx_ctrl.rts_delay = regk_ser_del1;
+ }
+ } else
+#endif
+ tx_ctrl.auto_rts = regk_ser_no;
+ tx_ctrl.txd = 1;
+ tx_ctrl.auto_cts = 0;
+ /* Rx: 8 bit, no/even parity. */
+ if (up->regi_dmain) {
+ rx_ctrl.dma_mode = 1;
+ rx_ctrl.auto_eop = 1;
+ }
+ rx_ctrl.dma_err = regk_ser_stop;
+ rx_ctrl.sampling = regk_ser_majority;
+ rx_ctrl.timeout = 1;
+
+#ifdef CONFIG_ETRAX_RS485
+ if (up->rs485.enabled && (up->port_type != TYPE_485FD)) {
+# ifdef CONFIG_ETRAX_RS485_DISABLE_RECEIVER
+ rx_ctrl.half_duplex = regk_ser_yes;
+# endif
+ rx_ctrl.rts_n = up->rs485.rts_after_sent ?
+ regk_ser_active : regk_ser_inactive;
+ } else if (up->port_type == TYPE_485FD) {
+ rx_ctrl.rts_n = regk_ser_active;
+ } else
+#endif
+ rx_ctrl.rts_n = regk_ser_inactive;
+
+ /* Common for tx and rx: 8N1. */
+ tx_ctrl.data_bits = regk_ser_bits8;
+ rx_ctrl.data_bits = regk_ser_bits8;
+ tx_ctrl.par = regk_ser_even;
+ rx_ctrl.par = regk_ser_even;
+ tx_ctrl.par_en = regk_ser_no;
+ rx_ctrl.par_en = regk_ser_no;
+
+ tx_ctrl.stop_bits = regk_ser_bits1;
+
+
+ /* Change baud-rate and write it to the hardware. */
+
+ /* baud_clock = base_freq / (divisor*8)
+ * divisor = base_freq / (baud_clock * 8)
+ * base_freq is either:
+ * off, ext, 29.493MHz, 32.000 MHz, 32.768 MHz or 100 MHz
+ * 20.493MHz is used for standard baudrates
+ */
+
+ /*
+ * For the console port we keep the original baudrate here. Not very
+ * beautiful.
+ */
+ if ((port != console_port) || old)
+ baud = uart_get_baud_rate(port, termios, old, 0,
+ port->uartclk / 8);
+ else
+ baud = console_baud;
+
+ tx_baud_div.div = 29493000 / (8 * baud);
+ /* Rx uses same as tx. */
+ rx_baud_div.div = tx_baud_div.div;
+ rx_ctrl.base_freq = tx_ctrl.base_freq;
+
+ if ((termios->c_cflag & CSIZE) == CS7) {
+ /* Set 7 bit mode. */
+ tx_ctrl.data_bits = regk_ser_bits7;
+ rx_ctrl.data_bits = regk_ser_bits7;
+ }
+
+ if (termios->c_cflag & CSTOPB) {
+ /* Set 2 stop bit mode. */
+ tx_ctrl.stop_bits = regk_ser_bits2;
+ }
+
+ if (termios->c_cflag & PARENB) {
+ /* Enable parity. */
+ tx_ctrl.par_en = regk_ser_yes;
+ rx_ctrl.par_en = regk_ser_yes;
+ }
+
+ if (termios->c_cflag & CMSPAR) {
+ if (termios->c_cflag & PARODD) {
+ /* Set mark parity if PARODD and CMSPAR. */
+ tx_ctrl.par = regk_ser_mark;
+ rx_ctrl.par = regk_ser_mark;
+ } else {
+ tx_ctrl.par = regk_ser_space;
+ rx_ctrl.par = regk_ser_space;
+ }
+ } else {
+ if (termios->c_cflag & PARODD) {
+ /* Set odd parity. */
+ tx_ctrl.par = regk_ser_odd;
+ rx_ctrl.par = regk_ser_odd;
+ }
+ }
+
+ if (termios->c_cflag & CRTSCTS) {
+ /* Enable automatic CTS handling. */
+ tx_ctrl.auto_cts = regk_ser_yes;
+ }
+
+ /* Make sure the tx and rx are enabled. */
+ tx_ctrl.en = regk_ser_yes;
+ rx_ctrl.en = regk_ser_yes;
+
+ /*
+ * Wait for tr_idle in case a character is being output, so it won't
+ * be damaged by the changes we do below. It seems the termios
+ * changes "sometimes" (we can't see e.g. a tcsetattr TCSANOW
+ * parameter here) should take place no matter what state. However,
+ * in case we should wait, we may have a non-empty transmitter state
+ * as we tell the upper layers that we're all done when we've passed
+ * characters to the hardware, but we don't wait for them being
+ * actually shifted out.
+ */
+ spin_lock_irqsave(&port->lock, flags);
+
+ /*
+ * None of our interrupts re-enable DMA, so it's thankfully ok to
+ * disable it once, outside the loop.
+ */
+ tx_dma_en.en = 0;
+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en);
+ do {
+ /*
+ * Make sure we have integrity between the read r_stat status
+ * and us writing the registers below, but don't busy-wait
+ * with interrupts off. We need to keep the port lock though
+ * (if we go SMP), so nobody else writes characters.
+ */
+ local_irq_restore(flags);
+ local_irq_save(flags);
+ rstat = REG_RD(ser, up->regi_ser, r_stat_din);
+ } while (!rstat.tr_idle);
+
+ /* Actually write the control regs (if modified) to the hardware. */
+
+ uart_update_timeout(port, termios->c_cflag, port->uartclk/8);
+ MODIFY_REG(up->regi_ser, rw_rec_baud_div, rx_baud_div);
+ MODIFY_REG(up->regi_ser, rw_rec_ctrl, rx_ctrl);
+
+ MODIFY_REG(up->regi_ser, rw_tr_baud_div, tx_baud_div);
+ MODIFY_REG(up->regi_ser, rw_tr_ctrl, tx_ctrl);
+
+ tx_dma_en.en = up->regi_dmaout != 0;
+ REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en);
+
+ xoff = REG_RD(ser, up->regi_ser, rw_xoff);
+
+ if (up->port.state && up->port.state->port.tty &&
+ (termios->c_iflag & IXON)) {
+ xoff.chr = STOP_CHAR(up->port.state->port.tty);
+ xoff.automatic = regk_ser_yes;
+ } else
+ xoff.automatic = regk_ser_no;
+
+ MODIFY_REG(up->regi_ser, rw_xoff, xoff);
+
+ /*
+ * Make sure we don't start in an automatically shut-off state due to
+ * a previous early exit.
+ */
+ xoff_clr.clr = 1;
+ REG_WR(ser, up->regi_ser, rw_xoff_clr, xoff_clr);
+
+ serial_cris_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static const char *
+serial_cris_type(struct uart_port *port)
+{
+ return "CRISv32";
+}
+
+static void serial_cris_release_port(struct uart_port *port)
+{
+}
+
+static int serial_cris_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+static void serial_cris_config_port(struct uart_port *port, int flags)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ up->port.type = PORT_CRIS;
+}
+
+#if defined(CONFIG_ETRAX_RS485)
+
+static void cris_set_rs485_mode(struct uart_cris_port* up) {
+ reg_ser_rw_tr_ctrl tr_ctrl;
+ reg_ser_rw_rec_ctrl rec_ctrl;
+ reg_scope_instances regi_ser = up->regi_ser;
+
+ if (up->port_type == TYPE_485FD)
+ /* We do not want to change anything if we are in 485FD mode */
+ return;
+
+ tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
+ rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
+
+ /* Set port in RS-485 mode */
+ if (up->rs485.enabled) {
+ tr_ctrl.auto_rts = regk_ser_yes;
+ rec_ctrl.rts_n = up->rs485.rts_after_sent ?
+ regk_ser_active : regk_ser_inactive;
+ }
+ /* Set port to RS-232 mode */
+ else {
+ rec_ctrl.rts_n = regk_ser_inactive;
+ tr_ctrl.auto_rts = regk_ser_no;
+ rec_ctrl.half_duplex = regk_ser_no;
+ }
+
+ REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
+ REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
+}
+
+/* Enable/disable RS-485 mode on selected port. */
+static int
+cris_enable_rs485(struct uart_cris_port* up, struct rs485_control *r)
+{
+ if (up->port_type == TYPE_485FD)
+ /* Port in 485FD mode can not chage mode */
+ goto out;
+
+ up->rs485.enabled = 0x1 & r->enabled;
+ up->rs485.rts_on_send = 0x01 & r->rts_on_send;
+ up->rs485.rts_after_sent = 0x01 & r->rts_after_sent;
+ up->rs485.delay_rts_before_send = r->delay_rts_before_send;
+
+ cris_set_rs485_mode(up);
+ out:
+ return 0;
+}
+
+
+/* Enable RS485 mode on port and send the data. Port will stay
+ * in 485 mode after the data has been sent.
+ */
+static int
+cris_write_rs485(struct uart_cris_port *up, const unsigned char* buf, int count)
+{
+ up->rs485.enabled = 1;
+
+ /* Set the port in RS485 mode */
+ cris_set_rs485_mode(up);
+
+ /* Send the data */
+ count = serial_cris_driver.tty_driver->ops->write(up->port.state->port.tty, buf, count);
+
+ return count;
+}
+
+#endif /* CONFIG_ETRAX_RS485 */
+
+static int serial_cris_ioctl(struct uart_port *port, unsigned int cmd,
+ unsigned long arg)
+{
+#if defined(CONFIG_ETRAX_RS485)
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+
+ switch (cmd) {
+ case TIOCSRS485: {
+ struct serial_rs485 in;
+ struct rs485_control rs485ctrl;
+ if (copy_from_user(&in, (struct serial_rs485 *)cmd,
+ sizeof(rs485ctrl)))
+ return -EFAULT;
+ rs485ctrl.rts_on_send = in.flags & SER_RS485_RTS_ON_SEND;
+ rs485ctrl.rts_after_sent = in.flags & SER_RS485_RTS_AFTER_SEND;
+ rs485ctrl.enabled = in.flags & SER_RS485_ENABLED;
+ rs485ctrl.delay_rts_before_send = in.delay_rts_before_send;
+
+ return cris_enable_rs485(up, &rs485ctrl);
+ }
+
+ case TIOCSERSETRS485: {
+ struct rs485_control rs485ctrl;
+ if (copy_from_user(&rs485ctrl, (struct rs485_control*) arg,
+ sizeof(rs485ctrl)))
+ return -EFAULT;
+
+ return cris_enable_rs485(up, &rs485ctrl);
+ }
+
+ case TIOCSERWRRS485: {
+ struct rs485_write rs485wr;
+ if (copy_from_user(&rs485wr, (struct rs485_write*)arg,
+ sizeof(rs485wr)))
+ return -EFAULT;
+
+ return cris_write_rs485(up, rs485wr.outc, rs485wr.outc_size);
+ }
+
+ case TIOCSERSETRS485FD: {
+ reg_scope_instances regi_ser = up->regi_ser;
+ reg_ser_rw_rec_ctrl rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
+
+ if (arg)
+ rec_ctrl.half_duplex = regk_ser_no;
+ else
+ rec_ctrl.half_duplex = regk_ser_yes;
+
+ REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
+ return 0;
+ }
+
+ case TIOCSERSETDIVISOR: {
+ reg_ser_rw_tr_baud_div tx_baud_div = {0};
+ reg_ser_rw_rec_baud_div rx_baud_div = {0};
+
+ /* divisor must be >= 8 */
+ if (arg < 8)
+ return -EINVAL;
+
+ tx_baud_div.div = arg;
+ rx_baud_div.div = tx_baud_div.div; /* same as tx. */
+
+ MODIFY_REG(up->regi_ser, rw_rec_baud_div, rx_baud_div);
+ MODIFY_REG(up->regi_ser, rw_tr_baud_div, tx_baud_div);
+
+ return 0;
+ }
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+#else
+ return -ENOIOCTLCMD;
+#endif
+}
+
+static const struct uart_ops serial_cris_pops = {
+ .tx_empty = serial_cris_tx_empty,
+ .set_mctrl = serial_cris_set_mctrl,
+ .get_mctrl = serial_cris_get_mctrl,
+ .stop_tx = serial_cris_stop_tx,
+ .start_tx = serial_cris_start_tx,
+ .send_xchar = serial_cris_send_xchar,
+ .stop_rx = serial_cris_stop_rx,
+ .enable_ms = serial_cris_enable_ms,
+ .break_ctl = serial_cris_break_ctl,
+ .startup = serial_cris_startup,
+ .shutdown = serial_cris_shutdown,
+ .set_termios = serial_cris_set_termios,
+ .type = serial_cris_type,
+ .release_port = serial_cris_release_port,
+ .request_port = serial_cris_request_port,
+ .config_port = serial_cris_config_port,
+ .ioctl = serial_cris_ioctl,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = serial_artpec_get_poll_char,
+ .poll_put_char = serial_artpec_put_poll_char,
+#endif
+};
+
+/*
+ * It's too easy to break CONFIG_ETRAX_DEBUG_PORT_NULL and the
+ * no-config choices by adding and moving code to before a necessary
+ * early exit in all functions for the special case of
+ * up->regi_ser == 0. This collection of dummy functions lets us
+ * avoid that. Maybe there should be a generic table of dummy serial
+ * functions?
+ */
+
+static unsigned int serial_cris_tx_empty_dummy(struct uart_port *port)
+{
+ return TIOCSER_TEMT;
+}
+
+static void serial_cris_set_mctrl_dummy(struct uart_port *port,
+ unsigned int mctrl)
+{
+}
+
+static unsigned int serial_cris_get_mctrl_dummy(struct uart_port *port)
+{
+ return 0;
+}
+
+static void serial_cris_stop_tx_dummy(struct uart_port *port)
+{
+}
+
+static void serial_cris_start_tx_dummy(struct uart_port *port)
+{
+ /* Discard outbound characters. */
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ struct circ_buf *xmit = &up->port.state->xmit;
+ xmit->tail = xmit->head;
+ uart_write_wakeup(port);
+}
+
+#define serial_cris_stop_rx_dummy serial_cris_stop_tx_dummy
+
+#define serial_cris_enable_ms_dummy serial_cris_stop_tx_dummy
+
+static void serial_cris_break_ctl_dummy(struct uart_port *port,
+ int break_state)
+{
+}
+
+static int serial_cris_startup_dummy(struct uart_port *port)
+{
+ return 0;
+}
+
+#define serial_cris_shutdown_dummy serial_cris_stop_tx_dummy
+
+static void
+serial_cris_set_termios_dummy(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+}
+
+#define serial_cris_release_port_dummy serial_cris_stop_tx_dummy
+#define serial_cris_request_port_dummy serial_cris_startup_dummy
+
+static const struct uart_ops serial_cris_dummy_pops = {
+ /*
+ * We *could* save one or two of those with different
+ * signature by casting and knowledge of the ABI, but it's
+ * just not worth the maintenance headache.
+ * For the ones we don't define here, the default (usually meaning
+ * "unimplemented") makes sense.
+ */
+ .tx_empty = serial_cris_tx_empty_dummy,
+ .set_mctrl = serial_cris_set_mctrl_dummy,
+ .get_mctrl = serial_cris_get_mctrl_dummy,
+ .stop_tx = serial_cris_stop_tx_dummy,
+ .start_tx = serial_cris_start_tx_dummy,
+ .stop_rx = serial_cris_stop_rx_dummy,
+ .enable_ms = serial_cris_enable_ms_dummy,
+ .break_ctl = serial_cris_break_ctl_dummy,
+ .startup = serial_cris_startup_dummy,
+ .shutdown = serial_cris_shutdown_dummy,
+ .set_termios = serial_cris_set_termios_dummy,
+
+ /* This one we keep the same. */
+ .type = serial_cris_type,
+
+ .release_port = serial_cris_release_port_dummy,
+ .request_port = serial_cris_request_port_dummy,
+
+ /*
+ * This one we keep the same too, as long as it doesn't do
+ * anything else but to set the type.
+ */
+ .config_port = serial_cris_config_port,
+};
+
+static void cris_serial_port_init(struct uart_port *port, int line)
+{
+ struct uart_cris_port *up = (struct uart_cris_port *)port;
+ static int first = 1;
+
+ if (up->initialized)
+ return;
+ up->initialized = 1;
+ port->line = line;
+ spin_lock_init(&port->lock);
+ port->ops =
+ up->regi_ser == 0 ? &serial_cris_dummy_pops :
+ &serial_cris_pops;
+ port->irq = up->irq;
+ port->iobase = up->regi_ser ? up->regi_ser : 1;
+ port->uartclk = 29493000;
+
+ /*
+ * We can't fit any more than 255 here (unsigned char), though
+ * actually UART_XMIT_SIZE characters could be pending output (if it
+ * wasn't for the single test in transmit_chars_dma). At time of this
+ * writing, the definition of "fifosize" is here the amount of
+ * characters that can be pending output after a start_tx call until
+ * tx_empty returns 1: see serial_core.c:uart_wait_until_sent. This
+ * matters for timeout calculations unfortunately, but keeping larger
+ * amounts at the DMA wouldn't win much so let's just play nice.
+ */
+ port->fifosize = 255;
+ port->flags = UPF_BOOT_AUTOCONF;
+
+#ifdef CONFIG_ETRAX_RS485
+ /* Set sane defaults. */
+ up->rs485.rts_on_send = 0;
+ up->rs485.rts_after_sent = 1;
+ up->rs485.delay_rts_before_send = 0;
+ if (up->port_type > TYPE_232)
+ up->rs485.enabled = 1;
+ else
+ up->rs485.enabled = 0;
+#endif
+
+ if (first) {
+ first = 0;
+#ifdef CONFIG_ETRAX_SERIAL_PORT0
+ SETUP_PINS(0);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT1
+ SETUP_PINS(1);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
+ SETUP_PINS(2);
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT3
+ SETUP_PINS(3);
+#endif
+ }
+}
+
+static int __init serial_cris_init(void)
+{
+ int ret, i;
+ printk(KERN_INFO "Serial: CRISv32 driver $Revision: 1.109 $ ");
+
+ ret = uart_register_driver(&serial_cris_driver);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < UART_NR; i++) {
+ if (serial_cris_ports[i].used) {
+ struct uart_port *port;
+#ifdef CONFIG_ETRAX_RS485
+ reg_ser_rw_rec_ctrl rec_ctrl;
+
+ /* Make sure that the RTS pin stays low when allocating
+ * pins for a port in 485 mode.
+ */
+ if (serial_cris_ports[i].port_type > TYPE_232) {
+ rec_ctrl = REG_RD(ser, serial_cris_ports[i].regi_ser, rw_rec_ctrl);
+ rec_ctrl.rts_n = regk_ser_active;
+ REG_WR(ser, serial_cris_ports[i].regi_ser, rw_rec_ctrl, rec_ctrl);
+ }
+#endif
+ switch (serial_cris_ports[i].regi_ser) {
+ case regi_ser0:
+ break;
+ case regi_ser1:
+ if (crisv32_pinmux_alloc_fixed(pinmux_ser1)) {
+ printk("Failed to allocate pins for ser1, disable port\n");
+ serial_cris_ports[i].used = 0;
+ continue;
+ }
+ break;
+ case regi_ser2:
+ if (crisv32_pinmux_alloc_fixed(pinmux_ser2)) {
+ printk("Failed to allocate pins for ser2, disable port\n");
+ serial_cris_ports[i].used = 0;
+ continue;
+ }
+ break;
+ case regi_ser3:
+ if (crisv32_pinmux_alloc_fixed(pinmux_ser3)) {
+ printk("Failed to allocate pins for ser3, disable port\n");
+ serial_cris_ports[i].used = 0;
+ continue;
+ }
+ break;
+#if CONFIG_ETRAX_SERIAL_PORTS == 5
+ case regi_ser4:
+ if (crisv32_pinmux_alloc_fixed(pinmux_ser4)) {
+ printk("Failed to allocate pins for ser4, disable port\n");
+ serial_cris_ports[i].used = 0;
+ continue;
+ }
+ break;
+#endif
+ default:
+ printk("Error: No such serial port (%d) \n", serial_cris_ports[i].regi_ser);
+ serial_cris_ports[i].used = 0;
+ break;
+ }
+
+ port = &serial_cris_ports[i].port;
+ cris_console.index = i;
+ cris_serial_port_init(port, i);
+ uart_add_one_port(&serial_cris_driver, port);
+ }
+ }
+
+out:
+ return ret;
+}
+
+static void __exit serial_cris_exit(void)
+{
+ int i;
+ for (i = 0; i < UART_NR; i++)
+ if (serial_cris_ports[i].used) {
+ switch (serial_cris_ports[i].regi_ser) {
+ case regi_ser1:
+ crisv32_pinmux_dealloc_fixed(pinmux_ser1);
+ break;
+ case regi_ser2:
+ crisv32_pinmux_dealloc_fixed(pinmux_ser2);
+ break;
+ case regi_ser3:
+ crisv32_pinmux_dealloc_fixed(pinmux_ser3);
+ break;
+#if CONFIG_ETRAX_SERIAL_PORTS == 5
+ case regi_ser4:
+ crisv32_pinmux_dealloc_fixed(pinmux_ser4);
+ break;
+#endif
+ default:
+ printk("Error: No such serial port (%d) \n", serial_cris_ports[i].regi_ser);
+ serial_cris_ports[i].used = 0;
+ break;
+ }
+ uart_remove_one_port(&serial_cris_driver,
+ &serial_cris_ports[i].port);
+ }
+ uart_unregister_driver(&serial_cris_driver);
+}
+
+module_init(serial_cris_init);
+module_exit(serial_cris_exit);
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 5820269..dc1d379 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -244,4 +244,7 @@
/* SC16IS74xx */
#define PORT_SC16IS7XX 108
+/* Cris v10 / v32 SoC */
+#define PORT_CRIS 109
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--
1.9.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 3/8] cris: Add dummy free_initrd_mem
2014-09-21 16:27 [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5 Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 1/8] cris: Add support for early console Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 2/8] cris: Add serial driver for Cris v32 Guenter Roeck
@ 2014-09-21 16:27 ` Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 4/8] cris: time.c: Add missing include file to fix compile error Guenter Roeck
` (4 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 16:27 UTC (permalink / raw)
To: linux-kernel
Cc: Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
to enable builds with initrd embedded in the image
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
(cherry picked from commit ee6355589ea0fcda0d19ec93015f4b61a39e8410)
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
(cherry picked from commit 7092cf61ed870897fea5c81b136a38d4a09ca09f)
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
(cherry picked from commit 8df94101f9bd48e4fa129966319f813d44d83692)
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
arch/cris/mm/init.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/cris/mm/init.c b/arch/cris/mm/init.c
index c81af5b..11d8eca 100644
--- a/arch/cris/mm/init.c
+++ b/arch/cris/mm/init.c
@@ -38,3 +38,7 @@ free_initmem(void)
{
free_initmem_default(-1);
}
+
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+}
--
1.9.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 4/8] cris: time.c: Add missing include file to fix compile error
2014-09-21 16:27 [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5 Guenter Roeck
` (2 preceding siblings ...)
2014-09-21 16:27 ` [RFC PATCH 3/8] cris: Add dummy free_initrd_mem Guenter Roeck
@ 2014-09-21 16:27 ` Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 5/8] cris: Add basic qemu_defconfig Guenter Roeck
` (3 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 16:27 UTC (permalink / raw)
To: linux-kernel
Cc: Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
Fix the following compile error.
arch/cris/arch-v32/kernel/time.c: In function ‘reset_watchdog’:
arch/cris/arch-v32/kernel/time.c:121:2:
error: implicit declaration of function ‘global_page_state’
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
arch/cris/arch-v32/kernel/time.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c
index ee66866..73745ce 100644
--- a/arch/cris/arch-v32/kernel/time.c
+++ b/arch/cris/arch-v32/kernel/time.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/threads.h>
#include <linux/cpufreq.h>
+#include <linux/mm.h>
#include <asm/types.h>
#include <asm/signal.h>
#include <asm/io.h>
--
1.9.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 5/8] cris: Add basic qemu_defconfig
2014-09-21 16:27 [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5 Guenter Roeck
` (3 preceding siblings ...)
2014-09-21 16:27 ` [RFC PATCH 4/8] cris: time.c: Add missing include file to fix compile error Guenter Roeck
@ 2014-09-21 16:27 ` Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 6/8] tty: crisv32: Coding style cleanup, delete dead code Guenter Roeck
` (2 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 16:27 UTC (permalink / raw)
To: linux-kernel
Cc: Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
Known to boot with qemu. Command line:
qemu-system-cris -serial stdio -kernel vmlinux -monitor none -nographic \
-append "console=ttyS0,115200,N,8 rdinit=/sbin/init"
ext4 needs atomic64_t which is not provided by the cris architecture
and was therefore dropped.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
(cherry picked from commit cd0ffab571f9c2097b272b1340097e0f9b833de9)
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
arch/cris/configs/qemu_defconfig | 166 +++++++++++++++++++++++++++++++++++++++
1 file changed, 166 insertions(+)
create mode 100644 arch/cris/configs/qemu_defconfig
diff --git a/arch/cris/configs/qemu_defconfig b/arch/cris/configs/qemu_defconfig
new file mode 100644
index 0000000..215e942
--- /dev/null
+++ b/arch/cris/configs/qemu_defconfig
@@ -0,0 +1,166 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="busybox-cris.cpio"
+# CONFIG_KALLSYMS is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_ETRAX_CMDLINE="root=/dev/mtdblock3 init=/linuxrc rootfstype=jffs2 mmc_core.use_spi_crc=0 mmc_spi.spi_mode=3 init=/bin/sh"
+CONFIG_ETRAX_WATCHDOG=y
+CONFIG_ETRAX_FAST_TIMER=y
+CONFIG_ETRAX_KMALLOCED_MODULES=y
+CONFIG_ETRAXFS=y
+CONFIG_ETRAX_DRAM_SIZE=32
+CONFIG_ETRAX_MEM_GRP1_CONFIG=0x40688
+CONFIG_ETRAX_MEM_GRP2_CONFIG=0x0
+CONFIG_ETRAX_MEM_GRP3_CONFIG=0x06000002
+CONFIG_ETRAX_MEM_GRP4_CONFIG=0x0
+CONFIG_ETRAX_SDRAM_GRP0_CONFIG=0x114b
+CONFIG_ETRAX_SDRAM_GRP1_CONFIG=0x0
+CONFIG_ETRAX_SDRAM_TIMING=0x424a
+CONFIG_ETRAX_SDRAM_COMMAND=0x0
+CONFIG_ETRAX_DEF_GIO_PA_OE=0x7c
+CONFIG_ETRAX_DEF_GIO_PA_OUT=0x00
+CONFIG_ETRAX_DEF_GIO_PB_OE=0x3f111
+CONFIG_ETRAX_DEF_GIO_PB_OUT=0x03000
+CONFIG_ETRAX_DEF_GIO_PC_OE=0x03330
+CONFIG_ETRAX_DEF_GIO_PC_OUT=0x00000
+CONFIG_ETRAX_DEF_GIO_PD_OE=0x0015a
+CONFIG_ETRAX_DEF_GIO_PD_OUT=0x00100
+CONFIG_ETRAX_DEF_GIO_PE_OE=0x00000
+CONFIG_ETRAX_DEF_GIO_PE_OUT=0x00000
+CONFIG_ETRAX_LED_G_NET0="PA2"
+CONFIG_ETRAX_LED_R_NET0="PA2"
+CONFIG_ETRAX_V32_LED2G="PA3"
+CONFIG_ETRAX_V32_LED2R="PA3"
+CONFIG_ETRAX_V32_LED3G="PA3"
+CONFIG_ETRAX_V32_LED3R="PA3"
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_ADVANCED is not set
+CONFIG_NETFILTER_NETLINK_LOG=y
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_MANGLE is not set
+CONFIG_IP6_NF_IPTABLES=y
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+CONFIG_IP6_NF_TARGET_LOG=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+# CONFIG_IP6_NF_MANGLE is not set
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_TBF=y
+# CONFIG_WIRELESS is not set
+CONFIG_ETRAX_ETHERNET=y
+CONFIG_ETRAX_SERIAL_PORT0=y
+CONFIG_ETRAX_SERIAL_PORT1=y
+CONFIG_ETRAX_SERIAL_PORT2=y
+CONFIG_ETRAX_SERIAL_PORT3=y
+CONFIG_ETRAX_RS485=y
+CONFIG_ETRAX_RS485_DISABLE_RECEIVER=y
+CONFIG_ETRAX_PTABLE_SECTOR=262144
+CONFIG_ETRAX_GPIO=y
+CONFIG_ETRAX_PB_CHANGEABLE_BITS=0x3f000
+CONFIG_ETRAX_ETHERNET_IFACE0=y
+CONFIG_ETRAX_ETHERNET_IFACE1=y
+CONFIG_ETRAXFS_SERIAL=y
+CONFIG_ETRAX_SER0_DTR_BIT="pb0"
+CONFIG_ETRAX_SER0_RI_BIT="pb1"
+CONFIG_ETRAX_SER0_DSR_BIT="pb2"
+CONFIG_ETRAX_SER0_CD_BIT="pb3"
+CONFIG_ETRAX_SER1_DTR_BIT="pb4"
+CONFIG_ETRAX_SER1_RI_BIT="pb5"
+CONFIG_ETRAX_SER1_DSR_BIT="pb6"
+CONFIG_ETRAX_SER1_CD_BIT="pb7"
+CONFIG_ETRAX_SER2_DTR_BIT="pb8"
+CONFIG_ETRAX_SER2_RI_BIT="pb9"
+CONFIG_ETRAX_SER2_DSR_BIT="pb10"
+CONFIG_ETRAX_SER2_CD_BIT="pb11"
+CONFIG_ETRAX_SERIAL_PORT3_TYPE_485HD=y
+CONFIG_ETRAX_AXISFLASHMAP=y
+CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE=y
+CONFIG_ETRAX_NANDFLASH=y
+CONFIG_ETRAX_NANDBOOT=y
+CONFIG_ETRAX_PD_CHANGEABLE_DIR=0x00010
+CONFIG_ETRAX_PD_CHANGEABLE_BITS=0x0011a
+CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK=y
+CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_OUT=y
+CONFIG_ETRAX_SERIAL_PORT1_DMA5_IN=y
+CONFIG_ETRAX_SERIAL_PORT1_DMA4_OUT=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD_RAM=y
+CONFIG_MTD_MTDRAM=y
+CONFIG_MTDRAM_TOTAL_SIZE=0
+CONFIG_MTDRAM_ERASE_SIZE=64
+CONFIG_MTDRAM_ABS_POS=0x0
+CONFIG_BLK_DEV_RAM=y
+CONFIG_NETDEVICES=y
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+# CONFIG_WLAN is not set
+CONFIG_I2C=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PCF8563=y
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_SYSTEM_PROFILER=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC16=y
--
1.9.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 6/8] tty: crisv32: Coding style cleanup, delete dead code
2014-09-21 16:27 [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5 Guenter Roeck
` (4 preceding siblings ...)
2014-09-21 16:27 ` [RFC PATCH 5/8] cris: Add basic qemu_defconfig Guenter Roeck
@ 2014-09-21 16:27 ` Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 7/8] resource: Add NULL check in next_resource Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system" Guenter Roeck
7 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 16:27 UTC (permalink / raw)
To: linux-kernel
Cc: Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
drivers/tty/serial/crisv32.c | 1178 ++++++++++++++++++++----------------------
1 file changed, 567 insertions(+), 611 deletions(-)
diff --git a/drivers/tty/serial/crisv32.c b/drivers/tty/serial/crisv32.c
index a69f131..fa2ab5b 100644
--- a/drivers/tty/serial/crisv32.c
+++ b/drivers/tty/serial/crisv32.c
@@ -1,4 +1,4 @@
-/* $Id: crisv32.c,v 1.109 2010-07-09 15:00:44 jespern Exp $
+/* crisv32.c 1.109 2010-07-09 15:00:44 jespern
*
* Serial port driver for the ETRAX FS chip
*
@@ -21,9 +21,9 @@
#include <linux/slab.h>
#include <linux/tty_flip.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <dma.h>
#include <arch/system.h>
@@ -36,7 +36,7 @@
#include <hwregs/intr_vect_defs.h>
#include <hwregs/reg_map.h>
-#define UART_NR CONFIG_ETRAX_SERIAL_PORTS + 1 /* Ports + dummy port */
+#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. */
@@ -45,13 +45,13 @@
/* 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_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)
@@ -60,55 +60,57 @@
/* 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; \
+ 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);
+#define MODIFY_REG(instance, reg, var) \
+ do { \
+ if (REG_RD_INT(ser, instance, reg) != \
+ REG_TYPE_CONV(int, reg_ser_##reg, var)) \
+ REG_WR(ser, instance, reg, var); \
+ } while (0)
/*
* 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.
+ * 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
+ * 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
+ * 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
+ * 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:
@@ -137,297 +139,286 @@ struct etrax_recv_buffer {
};
struct uart_cris_port {
- struct uart_port 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)));
+ 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 __aligned(32);
+ struct dma_descr_data tr_descr[SERIAL_TX_DESCRIPTORS] __aligned(32);
+ struct dma_descr_context rec_context_descr __aligned(32);
+ struct dma_descr_data rec_descr[SERIAL_RECV_DESCRIPTORS] __aligned(32);
/* This is the first one in the list the HW is working on now. */
- struct dma_descr_data* first_tx_descr;
+ 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;
+ struct dma_descr_data *last_tx_descr;
/* This is how many characters the HW is working on now. */
- unsigned int tx_pending_chars;
+ unsigned int tx_pending_chars;
- int tx_started;
- unsigned int cur_rec_descr;
+ 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;
+ unsigned int recv_cnt;
+ unsigned int max_recv_cnt;
/* The time for 1 char, in usecs. */
- unsigned long char_time_usec;
+ unsigned long char_time_usec;
/* Last tx usec in the jiffies. */
- unsigned long last_tx_active_usec;
+ unsigned long last_tx_active_usec;
/* Last tx time in jiffies. */
- unsigned long last_tx_active;
+ unsigned long last_tx_active;
/* Last rx usec in the jiffies. */
- unsigned long last_rx_active_usec;
+ unsigned long last_rx_active_usec;
/* Last rx time in jiffies. */
- unsigned long last_rx_active;
+ unsigned long last_rx_active;
#ifdef CONFIG_ETRAX_RS485
/* RS-485 support, duh. */
- struct rs485_control rs485;
+ struct rs485_control rs485;
#endif
- int port_type;
- int write_ongoing;
+ int port_type;
+ int write_ongoing;
};
-extern struct uart_driver serial_cris_driver;
+static 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
+ .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_ser = regi_NULL,
- .regi_dmain = regi_NULL,
- .regi_dmaout = regi_NULL,
+ regi_NULL,
#endif
- .write_ongoing = 0
-}, /* ttyS0 */
-{
+
+#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
+ .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,
+ .regi_ser = regi_NULL,
+ .regi_dmain = regi_NULL,
+ .regi_dmaout = regi_NULL,
#endif
- .write_ongoing = 0
-}, /* ttyS1 */
-{
+ .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
+ .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
+#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,
+ .regi_ser = regi_NULL,
+ .regi_dmain = regi_NULL,
+ .regi_dmaout = regi_NULL,
#endif
- .write_ongoing = 0
-}, /* ttyS2 */
-{
+ .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
+ .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_ser = regi_NULL,
- .regi_dmain = regi_NULL,
- .regi_dmaout = regi_NULL,
+ regi_NULL,
#endif
- .write_ongoing = 0
-}, /* ttyS3 */
+
+ .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
+ .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
+#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,
+ .regi_ser = regi_NULL,
+ .regi_dmain = regi_NULL,
+ .regi_dmaout = regi_NULL,
#endif
- .write_ongoing = 0
-}, /* ttyS4 */
+ .write_ongoing = 0}, /* ttyS4 */
#endif
-{
+ {
#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL
- .used = 1,
+ .used = 1,
#endif
- .regi_ser = regi_NULL,
- .write_ongoing = 0
-} /* Dummy console port */
+ .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 =
-{
+static struct crisv32_ioport dummy_port = {
&io_dummy,
&io_dummy,
&io_dummy,
32
};
-static struct crisv32_iopin dummy_pin =
-{
+
+static struct crisv32_iopin dummy_pin = {
&dummy_port,
0
};
static int selected_console =
#if defined(CONFIG_ETRAX_DEBUG_PORT0)
-0;
+ 0;
#elif defined(CONFIG_ETRAX_DEBUG_PORT1)
-1;
+ 1;
#elif defined(CONFIG_ETRAX_DEBUG_PORT2)
-2;
+ 2;
#elif defined(CONFIG_ETRAX_DEBUG_PORT3)
-3;
+ 3;
#elif defined(CONFIG_ETRAX_DEBUG_PORT4)
-4;
-#else /* CONFIG_ETRAX_DEBUG_PORT_NULL */
+ 4;
+#else /* CONFIG_ETRAX_DEBUG_PORT_NULL */
#if CONFIG_ETRAX_SERIAL_PORTS == 5
-5;
+ 5;
#else
-4;
+ 4;
#endif
#endif
@@ -438,7 +429,6 @@ 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)
{
@@ -458,7 +448,7 @@ cris_console_write(struct console *co, const char *s, unsigned int count)
return;
/* Switch to manual mode. */
- tr_dma_en = old = REG_RD (ser, up->regi_ser, rw_tr_dma_en);
+ 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);
@@ -469,15 +459,15 @@ cris_console_write(struct console *co, const char *s, unsigned int count)
/* LF -> CRLF */
if (s[i] == '\n') {
do {
- stat = REG_RD (ser, up->regi_ser, r_stat_din);
+ stat = REG_RD(ser, up->regi_ser, r_stat_din);
} while (!stat.tr_rdy);
- REG_WR_INT (ser, up->regi_ser, rw_dout, '\r');
+ 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);
+ 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]);
+ REG_WR_INT(ser, up->regi_ser, rw_dout, s[i]);
/* Feed watchdog, because this may take looong time. */
reset_watchdog();
@@ -487,39 +477,9 @@ cris_console_write(struct console *co, const char *s, unsigned int count)
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)
+static int __init cris_console_setup(struct console *co, char *options)
{
struct uart_port *port;
int baud = 115200;
@@ -532,7 +492,7 @@ cris_console_setup(struct console *co, char *options)
if (options)
selected_console = co->index;
port = &serial_cris_ports[selected_console].port;
- console_port = port;
+ console_port = port;
co->flags |= CON_CONSDEV;
@@ -546,8 +506,7 @@ cris_console_setup(struct console *co, char *options)
return 0;
}
-static struct tty_driver*
-cris_console_device(struct console* co, int *index)
+static struct tty_driver *cris_console_device(struct console *co, int *index)
{
struct uart_driver *p = co->data;
*index = selected_console;
@@ -555,28 +514,26 @@ cris_console_device(struct console* co, int *index)
}
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,
+ .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 struct uart_driver serial_cris_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "serial",
+ .dev_name = "ttyS",
+ .major = TTY_MAJOR,
+ .minor = 64,
+ .nr = UART_NR,
+ .cons = &cris_console,
};
-static int inline crisv32_serial_get_rts(struct uart_cris_port *up)
+static inline int crisv32_serial_get_rts(struct uart_cris_port *up)
{
reg_scope_instances regi_ser = up->regi_ser;
/*
@@ -584,6 +541,7 @@ static int inline crisv32_serial_get_rts(struct uart_cris_port *up)
* 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);
}
@@ -591,14 +549,15 @@ static int inline crisv32_serial_get_rts(struct uart_cris_port *up)
* 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)
+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.
+ * take care of the RTS for us.
*/
if (force || !up->rs485.enabled) {
#else
@@ -609,7 +568,7 @@ static inline void crisv32_serial_set_rts(struct uart_cris_port *up, int set, in
local_irq_save(flags);
rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
-
+
if (set)
rec_ctrl.rts_n = regk_ser_active;
else
@@ -620,10 +579,11 @@ static inline void crisv32_serial_set_rts(struct uart_cris_port *up, int set, in
}
/* Input */
-static int inline crisv32_serial_get_cts(struct uart_cris_port *up)
+static inline int 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);
}
@@ -646,9 +606,9 @@ static int inline crisv32_serial_get_cts(struct uart_cris_port *up)
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 };
+ 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;
@@ -695,8 +655,9 @@ void serial_cris_send_xchar(struct uart_port *port, char ch)
* inhibit transmission of the character.
*/
if (rstat.xoff_detect) {
- reg_ser_rw_xoff_clr xoff_clr = { .clr = 1 };
+ 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);
@@ -728,23 +689,23 @@ static void transmit_chars_dma(struct uart_cris_port *up);
static void serial_cris_start_tx(struct uart_port *port)
{
- struct uart_cris_port *up = (struct uart_cris_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)
+ if (!up->regi_dmaout && up->write_ongoing)
return;
#ifdef CONFIG_ETRAX_RS485
- if (up->rs485.enabled)
- {
+ 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);
+ 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);
@@ -752,16 +713,16 @@ static void serial_cris_start_tx(struct uart_port *port)
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);
+ 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;
@@ -770,7 +731,8 @@ static void serial_cris_start_tx(struct uart_port *port)
* 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_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);
}
@@ -789,12 +751,12 @@ static void serial_cris_start_tx(struct uart_port *port)
static void serial_cris_stop_tx(struct uart_port *port)
{
- struct uart_cris_port *up = (struct uart_cris_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};
+ 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
@@ -832,7 +794,7 @@ static void serial_cris_stop_tx(struct uart_port *port)
static void serial_cris_stop_rx(struct uart_port *port)
{
- struct uart_cris_port *up = (struct uart_cris_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);
@@ -850,10 +812,10 @@ 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;
+ struct uart_cris_port *up = (struct uart_cris_port *) port;
unsigned long flags;
unsigned int ret;
- reg_ser_r_stat_din rstat = {0};
+ reg_ser_r_stat_din rstat = { 0 };
spin_lock_irqsave(&up->port.lock, flags);
if (up->regi_dmaout) {
@@ -881,17 +843,18 @@ static unsigned int serial_cris_tx_empty(struct uart_port *port)
rstat = REG_RD(ser, up->regi_ser, r_stat_din);
ret = rstat.tr_empty ? TIOCSER_TEMT : 0;
- done:
+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;
+ struct uart_cris_port *up = (struct uart_cris_port *) port;
unsigned int ret;
ret = 0;
- if (crisv32_serial_get_rts(up))
+ if (crisv32_serial_get_rts(up))
ret |= TIOCM_RTS;
/* DTR is active low */
if (!crisv32_io_rd(&up->dtr_pin))
@@ -912,7 +875,7 @@ static unsigned int serial_cris_get_mctrl(struct uart_port *port)
static void serial_cris_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- struct uart_cris_port *up = (struct uart_cris_port *)port;
+ 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 */
@@ -925,7 +888,7 @@ static void serial_cris_set_mctrl(struct uart_port *port, unsigned int mctrl)
static void serial_cris_break_ctl(struct uart_port *port, int break_state)
{
- struct uart_cris_port *up = (struct uart_cris_port *)port;
+ 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;
@@ -936,7 +899,7 @@ static void serial_cris_break_ctl(struct uart_port *port, int break_state)
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 */
+ 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;
@@ -975,14 +938,13 @@ static void serial_cris_break_ctl(struct uart_port *port, int break_state)
* possible.
*/
-static void
-transmit_chars_dma(struct uart_cris_port *up)
+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_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;
@@ -997,7 +959,7 @@ transmit_chars_dma(struct uart_cris_port *up)
*/
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);
+ dmapos = phys_to_virt((int) up->last_tx_descr->next);
else
dmapos = phys_to_virt(REG_RD_INT(dma, regi_dmaout, rw_data));
@@ -1005,8 +967,8 @@ transmit_chars_dma(struct uart_cris_port *up)
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);
- }
+ pending_descr = phys_to_virt((int) pending_descr->next);
+ }
up->first_tx_descr = pending_descr;
last_tx_descr = up->last_tx_descr;
@@ -1043,7 +1005,7 @@ transmit_chars_dma(struct uart_cris_port *up)
if (chars_to_send == 0)
goto done;
- descr = phys_to_virt((int)last_tx_descr->next);
+ descr = phys_to_virt((int) last_tx_descr->next);
/*
* We can't send anything if we could make the condition in
@@ -1056,8 +1018,8 @@ transmit_chars_dma(struct uart_cris_port *up)
goto done;
/* Set up the descriptor for output. */
- descr->buf = (void*)virt_to_phys(xmit->buf + xmit->tail
- + up->tx_pending_chars);
+ 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;
@@ -1079,38 +1041,38 @@ transmit_chars_dma(struct uart_cris_port *up)
up->tx_started = 1;
up->tr_context_descr.next = 0;
up->tr_context_descr.saved_data
- = (dma_descr_data*)virt_to_phys(descr);
+ = (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
+ } else
DMA_CONTINUE_DATA(regi_dmaout);
/* DMA is now running (hopefully). */
- done:
+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)
+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 };
+ 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;
+ up->write_ongoing = 0;
return;
}
@@ -1118,10 +1080,11 @@ transmit_chars_no_dma(struct uart_cris_port *up)
exiting the loop. */
max_count = 64;
do {
- reg_ser_rw_dout dout = { .data = xmit->buf[xmit->tail] };
+ 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);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
up->port.icount.tx++;
if (xmit->head == xmit->tail)
break;
@@ -1130,16 +1093,16 @@ transmit_chars_no_dma(struct uart_cris_port *up)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&up->port);
-} /* transmit_chars_no_dma */
+} /* transmit_chars_no_dma */
-static struct etrax_recv_buffer *
-alloc_recv_buffer(unsigned int size)
+static struct etrax_recv_buffer *alloc_recv_buffer(unsigned int size)
{
struct etrax_recv_buffer *buffer;
- if (!(buffer = kmalloc(sizeof *buffer + size, GFP_ATOMIC)))
+ buffer = kmalloc(sizeof(*buffer) + size, GFP_ATOMIC);
+ if (!buffer)
panic("%s: Could not allocate %d bytes buffer\n",
- __FUNCTION__, size);
+ __func__, size);
buffer->next = NULL;
buffer->length = 0;
@@ -1149,8 +1112,7 @@ alloc_recv_buffer(unsigned int size)
}
static void
-append_recv_buffer(struct uart_cris_port *up,
- struct etrax_recv_buffer *buffer)
+append_recv_buffer(struct uart_cris_port *up, struct etrax_recv_buffer *buffer)
{
unsigned long flags;
@@ -1188,8 +1150,7 @@ add_char_and_flag(struct uart_cris_port *up, unsigned char data,
return 1;
}
-static void
-flush_to_flip_buffer(struct uart_cris_port *up)
+static void flush_to_flip_buffer(struct uart_cris_port *up)
{
struct etrax_recv_buffer *buffer;
@@ -1198,9 +1159,9 @@ flush_to_flip_buffer(struct uart_cris_port *up)
while ((buffer = up->first_recv_buffer)) {
unsigned int count = (unsigned int)
- tty_insert_flip_string(&up->port.state->port,
- buffer->buffer,
- buffer->length);
+ tty_insert_flip_string(&up->port.state->port,
+ buffer->buffer,
+ buffer->length);
up->recv_cnt -= count;
@@ -1227,12 +1188,11 @@ 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;
+ = 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);
+ pr_err("Too much pending incoming data on %s! Dropping %u bytes.\n",
+ up->port.state->port.tty->name, recvl);
return 0;
}
@@ -1243,18 +1203,16 @@ handle_descr_data(struct uart_cris_port *up, struct dma_descr_data *descr,
flush_to_flip_buffer(up);
buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE);
- descr->buf = (void*)virt_to_phys(buffer->buffer);
+ 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)
+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 *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;
@@ -1284,18 +1242,17 @@ handle_all_descr_data(struct uart_cris_port *up)
*/
barrier();
prev_descr->eol = 0;
- flush_dma_descr(descr,1); // Cache bug workaround
- flush_dma_descr(prev_descr,0); // Cache bug workaround
+ 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)
+static void receive_chars_dma(struct uart_cris_port *up)
{
reg_ser_r_stat_din rstat;
- reg_dma_rw_ack_intr ack_intr = {0};
+ reg_dma_rw_ack_intr ack_intr = { 0 };
/* Acknowledge both dma_descr and dma_eop irq. */
ack_intr.data = 1;
@@ -1313,7 +1270,8 @@ receive_chars_dma(struct uart_cris_port *up)
* 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);
+
+ 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);
@@ -1350,13 +1308,12 @@ void receive_chars_no_dma(struct uart_cris_port *up)
icount->rx++;
if (stat_din.framing_err | stat_din.par_err | stat_din.orun) {
- if (stat_din.data == 0x00 &&
- stat_din.framing_err) {
+ 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;
+ flag = TTY_PARITY;
icount->parity++;
} else if (stat_din.orun) {
flag = TTY_OVERRUN;
@@ -1371,14 +1328,15 @@ void receive_chars_no_dma(struct uart_cris_port *up)
* 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__);
+ if (!tty_insert_flip_char
+ (&up->port.state->port, stat_din.data, flag))
+ panic("%s: No tty buffer space", __func__);
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 */
+} /* receive_chars_no_dma */
/*
* DMA output channel interrupt handler.
@@ -1387,7 +1345,7 @@ void receive_chars_no_dma(struct uart_cris_port *up)
*/
static irqreturn_t dma_tr_interrupt(int irq, void *dev_id)
{
- struct uart_cris_port *up = (struct uart_cris_port *)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;
@@ -1424,10 +1382,9 @@ static irqreturn_t dma_tr_interrupt(int irq, void *dev_id)
/* DMA input channel interrupt handler. */
-static irqreturn_t
-dma_rec_interrupt(int irq, void *dev_id)
+static irqreturn_t dma_rec_interrupt(int irq, void *dev_id)
{
- struct uart_cris_port *up = (struct uart_cris_port *)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;
@@ -1453,10 +1410,9 @@ dma_rec_interrupt(int irq, void *dev_id)
/* "Normal" serial port interrupt handler - both rx and tx. */
-static irqreturn_t
-ser_interrupt(int irq, void *dev_id)
+static irqreturn_t ser_interrupt(int irq, void *dev_id)
{
- struct uart_cris_port *up = (struct uart_cris_port *)dev_id;
+ struct uart_cris_port *up = (struct uart_cris_port *) dev_id;
reg_scope_instances regi_ser;
int handled = 0;
@@ -1470,6 +1426,7 @@ ser_interrupt(int irq, void *dev_id)
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
@@ -1489,7 +1446,7 @@ ser_interrupt(int irq, void *dev_id)
}
spin_unlock(&up->port.lock);
return IRQ_RETVAL(handled);
-} /* ser_interrupt */
+} /* ser_interrupt */
static int start_recv_dma(struct uart_cris_port *up)
{
@@ -1500,8 +1457,8 @@ static int start_recv_dma(struct uart_cris_port *up)
/* 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].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;
@@ -1513,21 +1470,20 @@ static int start_recv_dma(struct uart_cris_port *up)
}
/* Link the last descriptor to the first. */
- descr[i-1].next = (void*)virt_to_phys(&descr[0]);
+ descr[i - 1].next = (void *) virt_to_phys(&descr[0]);
/* And mark it as end of list. */
- descr[i-1].eol = 1;
+ 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]);
+ = (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));
+ DMA_START_CONTEXT(up->regi_dmain, virt_to_phys(&up->rec_context_descr));
/* Input DMA should be running now. */
return 1;
@@ -1543,7 +1499,7 @@ 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;
+ struct uart_cris_port *up = (struct uart_cris_port *) port;
do {
stat = REG_RD(ser, up->regi_ser, rs_stat_din);
@@ -1556,25 +1512,24 @@ static int serial_artpec_get_poll_char(struct uart_port *port)
return stat.data;
}
-static void serial_artpec_put_poll_char(struct uart_port *port,
- unsigned char c)
+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;
+ struct uart_cris_port *up = (struct uart_cris_port *) port;
do {
- stat = REG_RD (ser, up->regi_ser, r_stat_din);
+ stat = REG_RD(ser, up->regi_ser, r_stat_din);
} while (!stat.tr_rdy);
- REG_WR_INT (ser, up->regi_ser, rw_dout, c);
+ 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) {
+
+ if (regi_dmain)
start_recv_dma(up);
- }
}
@@ -1582,16 +1537,17 @@ 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]);
+ 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->tr_descr[i - 1].next = (dma_descr_data *)
+ virt_to_phys(&up->tr_descr[0]);
up->first_tx_descr = &up->tr_descr[0];
/*
@@ -1602,7 +1558,7 @@ static void start_transmitter(struct uart_cris_port *up)
* 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->last_tx_descr = &up->tr_descr[i - 1];
up->tx_started = 0;
up->tx_pending_chars = 0;
}
@@ -1610,12 +1566,12 @@ static void start_transmitter(struct uart_cris_port *up)
static int serial_cris_startup(struct uart_port *port)
{
- struct uart_cris_port *up = (struct uart_cris_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_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
@@ -1629,8 +1585,7 @@ static int serial_cris_startup(struct uart_port *port)
if (port->line == 0) {
if (request_irq(SER0_INTR_VECT, ser_interrupt,
- IRQF_DISABLED, "ser0",
- &serial_cris_ports[0]))
+ 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
@@ -1638,21 +1593,18 @@ static int serial_cris_startup(struct uart_port *port)
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);
+ 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);
+ 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]))
+ IRQF_DISABLED, "ser1", &serial_cris_ports[1]))
panic("irq ser1");
/* Port ser1 can use dma4 for tx and dma5 for rx. */
@@ -1661,21 +1613,18 @@ static int serial_cris_startup(struct uart_port *port)
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);
+ 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);
+ 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]))
+ IRQF_DISABLED, "ser2", &serial_cris_ports[2]))
panic("irq ser2");
/* Port ser2 can use dma2 for tx and dma3 for rx. */
@@ -1684,22 +1633,19 @@ static int serial_cris_startup(struct uart_port *port)
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);
+ 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);
+ 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" );
+ 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
@@ -1707,40 +1653,35 @@ static int serial_cris_startup(struct uart_port *port)
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);
+ 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);
+ 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" );
+ 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",
+ 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);
+ 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",
+ 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);
+ crisv32_request_dma(5, "ser4", DMA_PANIC_ON_ERROR, 0, dma_ser4);
#endif
}
#endif
@@ -1754,6 +1695,7 @@ static int serial_cris_startup(struct uart_port *port)
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);
@@ -1769,6 +1711,7 @@ static int serial_cris_startup(struct uart_port *port)
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);
@@ -1801,7 +1744,7 @@ static int serial_cris_startup(struct uart_port *port)
static void serial_cris_shutdown(struct uart_port *port)
{
- struct uart_cris_port *up = (struct uart_cris_port *)port;
+ struct uart_cris_port *up = (struct uart_cris_port *) port;
unsigned long flags;
spin_lock_irqsave(&up->port.lock, flags);
@@ -1867,7 +1810,7 @@ static void serial_cris_shutdown(struct uart_port *port)
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]);
@@ -1893,7 +1836,7 @@ static void serial_cris_shutdown(struct uart_port *port)
*/
for (rb = up->first_recv_buffer; rb != NULL; rb = rb_next) {
rb_next = rb->next;
- kfree (rb);
+ kfree(rb);
}
up->first_recv_buffer = NULL;
up->last_recv_buffer = NULL;
@@ -1903,11 +1846,10 @@ static void serial_cris_shutdown(struct uart_port *port)
* before we shut down the hardware above.
*/
for (i = 0, descr = up->rec_descr;
- i < SERIAL_RECV_DESCRIPTORS;
- i++)
+ i < SERIAL_RECV_DESCRIPTORS; i++)
if (descr[i].buf) {
rb = phys_to_virt((u32) descr[i].buf)
- - sizeof *rb;
+ - sizeof(*rb);
kfree(rb);
descr[i].buf = NULL;
}
@@ -1919,22 +1861,22 @@ static void serial_cris_shutdown(struct uart_port *port)
static void
serial_cris_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ struct ktermios *old)
{
- struct uart_cris_port *up = (struct uart_cris_port *)port;
+ 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_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;
+ int baud;
if (old &&
- termios->c_cflag == old->c_cflag &&
+ termios->c_cflag == old->c_cflag &&
termios->c_iflag == old->c_iflag)
return;
@@ -1950,16 +1892,15 @@ serial_cris_set_termios(struct uart_port *port, struct ktermios *termios,
tx_ctrl.rts_setup = regk_ser_bits2;
if (termios->c_cflag & CSTOPB) {
- /* 2 stop bits. */
- tx_ctrl.rts_delay = regk_ser_del2;
- }
- else {
+ /* 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.auto_rts = regk_ser_no;
tx_ctrl.txd = 1;
tx_ctrl.auto_cts = 0;
/* Rx: 8 bit, no/even parity. */
@@ -1973,16 +1914,16 @@ serial_cris_set_termios(struct uart_port *port, struct ktermios *termios,
#ifdef CONFIG_ETRAX_RS485
if (up->rs485.enabled && (up->port_type != TYPE_485FD)) {
-# ifdef CONFIG_ETRAX_RS485_DISABLE_RECEIVER
+#ifdef CONFIG_ETRAX_RS485_DISABLE_RECEIVER
rx_ctrl.half_duplex = regk_ser_yes;
-# endif
+#endif
rx_ctrl.rts_n = up->rs485.rts_after_sent ?
- regk_ser_active : regk_ser_inactive;
+ 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;
+ rx_ctrl.rts_n = regk_ser_inactive;
/* Common for tx and rx: 8N1. */
tx_ctrl.data_bits = regk_ser_bits8;
@@ -2008,7 +1949,7 @@ serial_cris_set_termios(struct uart_port *port, struct ktermios *termios,
* For the console port we keep the original baudrate here. Not very
* beautiful.
*/
- if ((port != console_port) || old)
+ if ((port != console_port) || old)
baud = uart_get_baud_rate(port, termios, old, 0,
port->uartclk / 8);
else
@@ -2048,8 +1989,8 @@ serial_cris_set_termios(struct uart_port *port, struct ktermios *termios,
} else {
if (termios->c_cflag & PARODD) {
/* Set odd parity. */
- tx_ctrl.par = regk_ser_odd;
- rx_ctrl.par = regk_ser_odd;
+ tx_ctrl.par = regk_ser_odd;
+ rx_ctrl.par = regk_ser_odd;
}
}
@@ -2094,7 +2035,7 @@ serial_cris_set_termios(struct uart_port *port, struct ktermios *termios,
/* Actually write the control regs (if modified) to the hardware. */
- uart_update_timeout(port, termios->c_cflag, port->uartclk/8);
+ 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);
@@ -2126,8 +2067,7 @@ serial_cris_set_termios(struct uart_port *port, struct ktermios *termios,
spin_unlock_irqrestore(&up->port.lock, flags);
}
-static const char *
-serial_cris_type(struct uart_port *port)
+static const char *serial_cris_type(struct uart_port *port)
{
return "CRISv32";
}
@@ -2143,13 +2083,15 @@ static int serial_cris_request_port(struct uart_port *port)
static void serial_cris_config_port(struct uart_port *port, int flags)
{
- struct uart_cris_port *up = (struct uart_cris_port *)port;
+ 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) {
+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;
@@ -2165,7 +2107,7 @@ static void cris_set_rs485_mode(struct uart_cris_port* up) {
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;
+ regk_ser_active : regk_ser_inactive;
}
/* Set port to RS-232 mode */
else {
@@ -2179,8 +2121,7 @@ static void cris_set_rs485_mode(struct uart_cris_port* up) {
}
/* Enable/disable RS-485 mode on selected port. */
-static int
-cris_enable_rs485(struct uart_cris_port* up, struct rs485_control *r)
+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 */
@@ -2190,9 +2131,9 @@ cris_enable_rs485(struct uart_cris_port* up, struct rs485_control *r)
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:
+out:
return 0;
}
@@ -2201,7 +2142,7 @@ cris_enable_rs485(struct uart_cris_port* up, struct rs485_control *r)
* 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)
+cris_write_rs485(struct uart_cris_port *up, const unsigned char *buf, int count)
{
up->rs485.enabled = 1;
@@ -2209,7 +2150,9 @@ cris_write_rs485(struct uart_cris_port *up, const unsigned char* buf, int count)
cris_set_rs485_mode(up);
/* Send the data */
- count = serial_cris_driver.tty_driver->ops->write(up->port.state->port.tty, buf, count);
+ count =
+ serial_cris_driver.tty_driver->ops->write(up->port.state->port.tty,
+ buf, count);
return count;
}
@@ -2217,73 +2160,82 @@ cris_write_rs485(struct uart_cris_port *up, const unsigned char* buf, int count)
#endif /* CONFIG_ETRAX_RS485 */
static int serial_cris_ioctl(struct uart_port *port, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
#if defined(CONFIG_ETRAX_RS485)
- struct uart_cris_port *up = (struct uart_cris_port *)port;
+ 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 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;
+ case TIOCSERSETRS485:{
+ struct rs485_control rs485ctrl;
- return cris_enable_rs485(up, &rs485ctrl);
- }
+ if (copy_from_user
+ (&rs485ctrl, (struct rs485_control *) arg,
+ sizeof(rs485ctrl)))
+ return -EFAULT;
- case TIOCSERWRRS485: {
- struct rs485_write rs485wr;
- if (copy_from_user(&rs485wr, (struct rs485_write*)arg,
- sizeof(rs485wr)))
- return -EFAULT;
+ return cris_enable_rs485(up, &rs485ctrl);
+ }
- return cris_write_rs485(up, rs485wr.outc, rs485wr.outc_size);
- }
+ case TIOCSERWRRS485:{
+ struct rs485_write rs485wr;
- 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 (copy_from_user(&rs485wr, (struct rs485_write *) arg,
+ sizeof(rs485wr)))
+ return -EFAULT;
- if (arg)
- rec_ctrl.half_duplex = regk_ser_no;
- else
- rec_ctrl.half_duplex = regk_ser_yes;
+ return cris_write_rs485(up, rs485wr.outc,
+ rs485wr.outc_size);
+ }
- REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
- return 0;
- }
+ 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;
- case TIOCSERSETDIVISOR: {
- reg_ser_rw_tr_baud_div tx_baud_div = {0};
- reg_ser_rw_rec_baud_div rx_baud_div = {0};
+ REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
+ return 0;
+ }
- /* divisor must be >= 8 */
- if (arg < 8)
- return -EINVAL;
+ case TIOCSERSETDIVISOR:{
+ reg_ser_rw_tr_baud_div tx_baud_div = { 0 };
+ reg_ser_rw_rec_baud_div rx_baud_div = { 0 };
- tx_baud_div.div = arg;
- rx_baud_div.div = tx_baud_div.div; /* same as tx. */
+ /* divisor must be >= 8 */
+ if (arg < 8)
+ return -EINVAL;
- MODIFY_REG(up->regi_ser, rw_rec_baud_div, rx_baud_div);
- MODIFY_REG(up->regi_ser, rw_tr_baud_div, tx_baud_div);
+ tx_baud_div.div = arg;
+ rx_baud_div.div = tx_baud_div.div; /* same as tx. */
- return 0;
- }
+ 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;
@@ -2296,23 +2248,23 @@ static int serial_cris_ioctl(struct uart_port *port, unsigned int cmd,
}
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,
+ .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,
@@ -2350,8 +2302,9 @@ 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 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);
}
@@ -2360,8 +2313,7 @@ static void serial_cris_start_tx_dummy(struct uart_port *port)
#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 void serial_cris_break_ctl_dummy(struct uart_port *port, int break_state)
{
}
@@ -2389,34 +2341,34 @@ static const struct uart_ops serial_cris_dummy_pops = {
* 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,
+ .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,
+ .type = serial_cris_type,
- .release_port = serial_cris_release_port_dummy,
- .request_port = serial_cris_request_port_dummy,
+ .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,
+ .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;
+ struct uart_cris_port *up = (struct uart_cris_port *) port;
static int first = 1;
if (up->initialized)
@@ -2425,8 +2377,7 @@ static void cris_serial_port_init(struct uart_port *port, int line)
port->line = line;
spin_lock_init(&port->lock);
port->ops =
- up->regi_ser == 0 ? &serial_cris_dummy_pops :
- &serial_cris_pops;
+ 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;
@@ -2475,11 +2426,12 @@ static void cris_serial_port_init(struct uart_port *port, int line)
static int __init serial_cris_init(void)
{
int ret, i;
- printk(KERN_INFO "Serial: CRISv32 driver $Revision: 1.109 $ ");
+
+ pr_info("Serial: CRISv32 driver Revision: 1.109");
ret = uart_register_driver(&serial_cris_driver);
if (ret)
- goto out;
+ return ret;
for (i = 0; i < UART_NR; i++) {
if (serial_cris_ports[i].used) {
@@ -2488,34 +2440,37 @@ static int __init serial_cris_init(void)
reg_ser_rw_rec_ctrl rec_ctrl;
/* Make sure that the RTS pin stays low when allocating
- * pins for a port in 485 mode.
+ * 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 =
+ 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);
+ 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_ser0:
+ break;
case regi_ser1:
if (crisv32_pinmux_alloc_fixed(pinmux_ser1)) {
- printk("Failed to allocate pins for ser1, disable port\n");
+ pr_err("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");
+ pr_err("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");
+ pr_err("Failed to allocate pins for ser3, disable port\n");
serial_cris_ports[i].used = 0;
continue;
}
@@ -2523,14 +2478,15 @@ static int __init serial_cris_init(void)
#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");
+ pr_err("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);
+ pr_err("No such serial port (%d)\n",
+ serial_cris_ports[i].regi_ser);
serial_cris_ports[i].used = 0;
break;
}
@@ -2541,14 +2497,13 @@ static int __init serial_cris_init(void)
uart_add_one_port(&serial_cris_driver, port);
}
}
-
-out:
- return ret;
+ return 0;
}
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) {
@@ -2567,12 +2522,13 @@ static void __exit serial_cris_exit(void)
break;
#endif
default:
- printk("Error: No such serial port (%d) \n", serial_cris_ports[i].regi_ser);
+ pr_err("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);
+ &serial_cris_ports[i].port);
}
uart_unregister_driver(&serial_cris_driver);
}
--
1.9.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 7/8] resource: Add NULL check in next_resource
2014-09-21 16:27 [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5 Guenter Roeck
` (5 preceding siblings ...)
2014-09-21 16:27 ` [RFC PATCH 6/8] tty: crisv32: Coding style cleanup, delete dead code Guenter Roeck
@ 2014-09-21 16:27 ` Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system" Guenter Roeck
7 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 16:27 UTC (permalink / raw)
To: linux-kernel
Cc: Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
Commit 8c86e70acead ("resource: provide new functions to walk through
resources") adds a suble new requirement that iomem_resource.child must
not be NULL when walk_system_ram_range is called. This can cause a crash
if it turns out that there are no children. The crash ('Unable to handle
kernel NULL pointer dereference') is seen when trying to test a crisv32
image on kernels with this commit applied.
Fix by adding a NULL check into next_resource().
Fixes: 8c86e70acead ("resource: provide new functions to walk through resources")
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
kernel/resource.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/resource.c b/kernel/resource.c
index 60c5a38..00c57ad 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -61,6 +61,9 @@ static DEFINE_SPINLOCK(bootmem_resource_lock);
static struct resource *next_resource(struct resource *p, bool sibling_only)
{
+ if (p == NULL)
+ return NULL;
+
/* Caller wants to traverse through siblings only */
if (sibling_only)
return p->sibling;
--
1.9.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system"
2014-09-21 16:27 [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5 Guenter Roeck
` (6 preceding siblings ...)
2014-09-21 16:27 ` [RFC PATCH 7/8] resource: Add NULL check in next_resource Guenter Roeck
@ 2014-09-21 16:27 ` Guenter Roeck
2014-09-21 17:23 ` Mikael Starvik
2014-09-21 21:12 ` Tejun Heo
7 siblings, 2 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 16:27 UTC (permalink / raw)
To: linux-kernel
Cc: Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
This reverts commit 3189eddbcafcc4d827f7f19facbeddec4424eba8.
The commit causes a hang with a crisv32 image. This may be an architecture
problem, but at least for now the revert is necessary to be able to boot a
crisv32 image.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
mm/percpu.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/mm/percpu.c b/mm/percpu.c
index da997f9..2139e30 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1932,8 +1932,6 @@ void __init setup_per_cpu_areas(void)
if (pcpu_setup_first_chunk(ai, fc) < 0)
panic("Failed to initialize percpu areas.");
-
- pcpu_free_alloc_info(ai);
}
#endif /* CONFIG_SMP */
--
1.9.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system"
2014-09-21 16:27 ` [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system" Guenter Roeck
@ 2014-09-21 17:23 ` Mikael Starvik
2014-09-21 18:37 ` Guenter Roeck
2014-09-21 21:12 ` Tejun Heo
1 sibling, 1 reply; 14+ messages in thread
From: Mikael Starvik @ 2014-09-21 17:23 UTC (permalink / raw)
To: Guenter Roeck
Cc: linux-kernel, Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel, Guenter Roeck
Thanks for all your work with CRIS! CRISv10 is alive but is currently used as small helper CPUs close to hardware blocks.
Jesper will review and ack.
> 21 sep 2014 kl. 18:27 skrev "Guenter Roeck" <linux@roeck-us.net>:
>
> This reverts commit 3189eddbcafcc4d827f7f19facbeddec4424eba8.
>
> The commit causes a hang with a crisv32 image. This may be an architecture
> problem, but at least for now the revert is necessary to be able to boot a
> crisv32 image.
>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> ---
> mm/percpu.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/mm/percpu.c b/mm/percpu.c
> index da997f9..2139e30 100644
> --- a/mm/percpu.c
> +++ b/mm/percpu.c
> @@ -1932,8 +1932,6 @@ void __init setup_per_cpu_areas(void)
>
> if (pcpu_setup_first_chunk(ai, fc) < 0)
> panic("Failed to initialize percpu areas.");
> -
> - pcpu_free_alloc_info(ai);
> }
>
> #endif /* CONFIG_SMP */
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system"
2014-09-21 17:23 ` Mikael Starvik
@ 2014-09-21 18:37 ` Guenter Roeck
2014-09-21 19:19 ` Waldemar Brodkorb
0 siblings, 1 reply; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 18:37 UTC (permalink / raw)
To: Mikael Starvik
Cc: linux-kernel, Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel
On 09/21/2014 10:23 AM, Mikael Starvik wrote:
> Thanks for all your work with CRIS! CRISv10 is alive but is currently used as small helper CPUs close to hardware blocks.
>
You are welcome. Now it would be even better if we could get the upstream code to work
with qemu. Which leads to the questions - is CRISv32 alive, and is there a chance
to get there ? Also, if CRISv10 is alive, is there any interest or even benefit to
maintain it in the latest kernel ? Because if not, we might as well drop v10 support
to simplify kernel maintenance.
Thanks,
Guenter
> Jesper will review and ack.
>
>> 21 sep 2014 kl. 18:27 skrev "Guenter Roeck" <linux@roeck-us.net>:
>>
>> This reverts commit 3189eddbcafcc4d827f7f19facbeddec4424eba8.
>>
>> The commit causes a hang with a crisv32 image. This may be an architecture
>> problem, but at least for now the revert is necessary to be able to boot a
>> crisv32 image.
>>
>> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
>> ---
>> mm/percpu.c | 2 --
>> 1 file changed, 2 deletions(-)
>>
>> diff --git a/mm/percpu.c b/mm/percpu.c
>> index da997f9..2139e30 100644
>> --- a/mm/percpu.c
>> +++ b/mm/percpu.c
>> @@ -1932,8 +1932,6 @@ void __init setup_per_cpu_areas(void)
>>
>> if (pcpu_setup_first_chunk(ai, fc) < 0)
>> panic("Failed to initialize percpu areas.");
>> -
>> - pcpu_free_alloc_info(ai);
>> }
>>
>> #endif /* CONFIG_SMP */
>> --
>> 1.9.1
>>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system"
2014-09-21 18:37 ` Guenter Roeck
@ 2014-09-21 19:19 ` Waldemar Brodkorb
2014-09-21 20:08 ` Guenter Roeck
0 siblings, 1 reply; 14+ messages in thread
From: Waldemar Brodkorb @ 2014-09-21 19:19 UTC (permalink / raw)
To: Guenter Roeck
Cc: Mikael Starvik, linux-kernel, Waldemar Brodkorb, Jesper Nilsson,
Mikael Starvik, linux-cris-kernel
Hi Guenter,
Guenter Roeck wrote,
> On 09/21/2014 10:23 AM, Mikael Starvik wrote:
> >Thanks for all your work with CRIS! CRISv10 is alive but is currently used as small helper CPUs close to hardware blocks.
> >
>
> You are welcome. Now it would be even better if we could get the upstream code to work
> with qemu. Which leads to the questions - is CRISv32 alive, and is there a chance
> to get there ? Also, if CRISv10 is alive, is there any interest or even benefit to
> maintain it in the latest kernel ? Because if not, we might as well drop v10 support
> to simplify kernel maintenance.
Please do not drop crisv10 support.
Don't kill my foxboard lx cluster ;)
http://www.openadk.org/cris/cris1.jpg
http://www.openadk.org/cris/cris2.jpg
best regards,
Waldemar
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system"
2014-09-21 19:19 ` Waldemar Brodkorb
@ 2014-09-21 20:08 ` Guenter Roeck
0 siblings, 0 replies; 14+ messages in thread
From: Guenter Roeck @ 2014-09-21 20:08 UTC (permalink / raw)
To: Waldemar Brodkorb
Cc: Mikael Starvik, linux-kernel, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel
On 09/21/2014 12:19 PM, Waldemar Brodkorb wrote:
> Hi Guenter,
> Guenter Roeck wrote,
>
>> On 09/21/2014 10:23 AM, Mikael Starvik wrote:
>>> Thanks for all your work with CRIS! CRISv10 is alive but is currently used as small helper CPUs close to hardware blocks.
>>>
>>
>> You are welcome. Now it would be even better if we could get the upstream code to work
>> with qemu. Which leads to the questions - is CRISv32 alive, and is there a chance
>> to get there ? Also, if CRISv10 is alive, is there any interest or even benefit to
>> maintain it in the latest kernel ? Because if not, we might as well drop v10 support
>> to simplify kernel maintenance.
>
> Please do not drop crisv10 support.
> Don't kill my foxboard lx cluster ;)
>
> http://www.openadk.org/cris/cris1.jpg
> http://www.openadk.org/cris/cris2.jpg
>
No problem as long as it's working and someone keeps it maintained.
Guenter
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system"
2014-09-21 16:27 ` [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system" Guenter Roeck
2014-09-21 17:23 ` Mikael Starvik
@ 2014-09-21 21:12 ` Tejun Heo
1 sibling, 0 replies; 14+ messages in thread
From: Tejun Heo @ 2014-09-21 21:12 UTC (permalink / raw)
To: Guenter Roeck
Cc: linux-kernel, Waldemar Brodkorb, Jesper Nilsson, Mikael Starvik,
linux-cris-kernel
Hello,
On Sun, Sep 21, 2014 at 09:27:18AM -0700, Guenter Roeck wrote:
> This reverts commit 3189eddbcafcc4d827f7f19facbeddec4424eba8.
Please use 12-DIGIT-PREFIX-OF-SHA1 ("PATCH_TITLE") format.
> The commit causes a hang with a crisv32 image. This may be an architecture
> problem, but at least for now the revert is necessary to be able to boot a
> crisv32 image.
>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Please repost with the original patch author and me cc'd.
Thanks!
--
tejun
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2014-09-21 21:12 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-21 16:27 [RFC PATCH 0/8] cris: Patches needed on top of v3.17-rc5 Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 1/8] cris: Add support for early console Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 2/8] cris: Add serial driver for Cris v32 Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 3/8] cris: Add dummy free_initrd_mem Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 4/8] cris: time.c: Add missing include file to fix compile error Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 5/8] cris: Add basic qemu_defconfig Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 6/8] tty: crisv32: Coding style cleanup, delete dead code Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 7/8] resource: Add NULL check in next_resource Guenter Roeck
2014-09-21 16:27 ` [RFC PATCH 8/8] Revert "percpu: free percpu allocation info for uniprocessor system" Guenter Roeck
2014-09-21 17:23 ` Mikael Starvik
2014-09-21 18:37 ` Guenter Roeck
2014-09-21 19:19 ` Waldemar Brodkorb
2014-09-21 20:08 ` Guenter Roeck
2014-09-21 21:12 ` Tejun Heo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).