diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-26 09:11:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-26 09:11:09 -0400 |
commit | efb8d21b2c6db3497655cc6a033ae8a9883e4063 (patch) | |
tree | a14a0dbb9fec3a6db5e542ba7ed4a49681706420 /arch/mips/pmc-sierra/msp71xx/msp_serial.c | |
parent | 3cb603284b3d256ae9ae9e65887cee8416bfef15 (diff) | |
parent | d208a3bf77f902283894f546b6b5383202cf7882 (diff) |
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (79 commits)
TTY: serial_core: Fix crash if DCD drop during suspend
tty/serial: atmel_serial: bootconsole removed from auto-enumerates
Revert "TTY: call tty_driver_lookup_tty unconditionally"
tty/serial: atmel_serial: add device tree support
tty/serial: atmel_serial: auto-enumerate ports
tty/serial: atmel_serial: whitespace and braces modifications
tty/serial: atmel_serial: change platform_data variable name
tty/serial: RS485 bindings for device tree
TTY: call tty_driver_lookup_tty unconditionally
TTY: pty, release tty in all ptmx_open fail paths
TTY: make tty_add_file non-failing
TTY: drop driver reference in tty_open fail path
8250_pci: Fix kernel panic when pch_uart is disabled
h8300: drivers/serial/Kconfig was moved
parport_pc: release IO region properly if unsupported ITE887x card is found
tty: Support compat_ioctl get/set termios_locked
hvc_console: display printk messages on console.
TTY: snyclinkmp: forever loop in tx_load_dma_buffer()
tty/n_gsm: avoid fifo overflow in gsm_dlci_data_output
tty/n_gsm: fix a bug in gsm_dlci_data_output (adaption = 2 case)
...
Fix up Conflicts in:
- drivers/tty/serial/8250_pci.c
Trivial conflict with removed duplicate device ID
- drivers/tty/serial/atmel_serial.c
Annoying silly conflict between "specify the port num via
platform_data" and other changes to atmel_console_init
Diffstat (limited to 'arch/mips/pmc-sierra/msp71xx/msp_serial.c')
-rw-r--r-- | arch/mips/pmc-sierra/msp71xx/msp_serial.c | 73 |
1 files changed, 67 insertions, 6 deletions
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_serial.c b/arch/mips/pmc-sierra/msp71xx/msp_serial.c index f7261628d8a6..a1c7c7da2336 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_serial.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_serial.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/serial.h> | 27 | #include <linux/serial.h> |
28 | #include <linux/serial_core.h> | 28 | #include <linux/serial_core.h> |
29 | #include <linux/serial_reg.h> | 29 | #include <linux/serial_reg.h> |
30 | #include <linux/slab.h> | ||
30 | 31 | ||
31 | #include <asm/bootinfo.h> | 32 | #include <asm/bootinfo.h> |
32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
@@ -38,6 +39,55 @@ | |||
38 | #include <msp_int.h> | 39 | #include <msp_int.h> |
39 | #include <msp_regs.h> | 40 | #include <msp_regs.h> |
40 | 41 | ||
42 | struct msp_uart_data { | ||
43 | int last_lcr; | ||
44 | }; | ||
45 | |||
46 | static void msp_serial_out(struct uart_port *p, int offset, int value) | ||
47 | { | ||
48 | struct msp_uart_data *d = p->private_data; | ||
49 | |||
50 | if (offset == UART_LCR) | ||
51 | d->last_lcr = value; | ||
52 | |||
53 | offset <<= p->regshift; | ||
54 | writeb(value, p->membase + offset); | ||
55 | } | ||
56 | |||
57 | static unsigned int msp_serial_in(struct uart_port *p, int offset) | ||
58 | { | ||
59 | offset <<= p->regshift; | ||
60 | |||
61 | return readb(p->membase + offset); | ||
62 | } | ||
63 | |||
64 | static int msp_serial_handle_irq(struct uart_port *p) | ||
65 | { | ||
66 | struct msp_uart_data *d = p->private_data; | ||
67 | unsigned int iir = readb(p->membase + (UART_IIR << p->regshift)); | ||
68 | |||
69 | if (serial8250_handle_irq(p, iir)) { | ||
70 | return 1; | ||
71 | } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | ||
72 | /* | ||
73 | * The DesignWare APB UART has an Busy Detect (0x07) interrupt | ||
74 | * meaning an LCR write attempt occurred while the UART was | ||
75 | * busy. The interrupt must be cleared by reading the UART | ||
76 | * status register (USR) and the LCR re-written. | ||
77 | * | ||
78 | * Note: MSP reserves 0x20 bytes of address space for the UART | ||
79 | * and the USR is mapped in a separate block at an offset of | ||
80 | * 0xc0 from the start of the UART. | ||
81 | */ | ||
82 | (void)readb(p->membase + 0xc0); | ||
83 | writeb(d->last_lcr, p->membase + (UART_LCR << p->regshift)); | ||
84 | |||
85 | return 1; | ||
86 | } | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
41 | void __init msp_serial_setup(void) | 91 | void __init msp_serial_setup(void) |
42 | { | 92 | { |
43 | char *s; | 93 | char *s; |
@@ -59,13 +109,22 @@ void __init msp_serial_setup(void) | |||
59 | up.irq = MSP_INT_UART0; | 109 | up.irq = MSP_INT_UART0; |
60 | up.uartclk = uartclk; | 110 | up.uartclk = uartclk; |
61 | up.regshift = 2; | 111 | up.regshift = 2; |
62 | up.iotype = UPIO_DWAPB; /* UPIO_MEM like */ | 112 | up.iotype = UPIO_MEM; |
63 | up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; | 113 | up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; |
64 | up.type = PORT_16550A; | 114 | up.type = PORT_16550A; |
65 | up.line = 0; | 115 | up.line = 0; |
66 | up.private_data = (void*)UART0_STATUS_REG; | 116 | up.serial_out = msp_serial_out; |
67 | if (early_serial_setup(&up)) | 117 | up.serial_in = msp_serial_in; |
68 | printk(KERN_ERR "Early serial init of port 0 failed\n"); | 118 | up.handle_irq = msp_serial_handle_irq; |
119 | up.private_data = kzalloc(sizeof(struct msp_uart_data), GFP_KERNEL); | ||
120 | if (!up.private_data) { | ||
121 | pr_err("failed to allocate uart private data\n"); | ||
122 | return; | ||
123 | } | ||
124 | if (early_serial_setup(&up)) { | ||
125 | kfree(up.private_data); | ||
126 | pr_err("Early serial init of port 0 failed\n"); | ||
127 | } | ||
69 | 128 | ||
70 | /* Initialize the second serial port, if one exists */ | 129 | /* Initialize the second serial port, if one exists */ |
71 | switch (mips_machtype) { | 130 | switch (mips_machtype) { |
@@ -88,6 +147,8 @@ void __init msp_serial_setup(void) | |||
88 | up.irq = MSP_INT_UART1; | 147 | up.irq = MSP_INT_UART1; |
89 | up.line = 1; | 148 | up.line = 1; |
90 | up.private_data = (void*)UART1_STATUS_REG; | 149 | up.private_data = (void*)UART1_STATUS_REG; |
91 | if (early_serial_setup(&up)) | 150 | if (early_serial_setup(&up)) { |
92 | printk(KERN_ERR "Early serial init of port 1 failed\n"); | 151 | kfree(up.private_data); |
152 | pr_err("Early serial init of port 1 failed\n"); | ||
153 | } | ||
93 | } | 154 | } |