* '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
Unified · Split
| @@ -0,0 +1,31 @@ | ||
| 1 | +* RS485 serial communications | |
| 2 | + | |
| 3 | +The RTS signal is capable of automatically controlling line direction for | |
| 4 | +the built-in half-duplex mode. | |
| 5 | +The properties described hereafter shall be given to a half-duplex capable | |
| 6 | +UART node. | |
| 7 | + | |
| 8 | +Required properties: | |
| 9 | +- rs485-rts-delay: prop-encoded-array <a b> where: | |
| 10 | + * a is the delay beteween rts signal and beginning of data sent in milliseconds. | |
| 11 | + it corresponds to the delay before sending data. | |
| 12 | + * b is the delay between end of data sent and rts signal in milliseconds | |
| 13 | + it corresponds to the delay after sending data and actual release of the line. | |
| 14 | + | |
| 15 | +Optional properties: | |
| 16 | +- linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485 | |
| 17 | + feature at boot time. It can be disabled later with proper ioctl. | |
| 18 | +- rs485-rx-during-tx: empty property that enables the receiving of data even | |
| 19 | + whilst sending data. | |
| 20 | + | |
| 21 | +RS485 example for Atmel USART: | |
| 22 | + usart0: serial@fff8c000 { | |
| 23 | + compatible = "atmel,at91sam9260-usart"; | |
| 24 | + reg = <0xfff8c000 0x4000>; | |
| 25 | + interrupts = <7>; | |
| 26 | + atmel,use-dma-rx; | |
| 27 | + atmel,use-dma-tx; | |
| 28 | + linux,rs485-enabled-at-boot-time; | |
| 29 | + rs485-rts-delay = <0 200>; // in milliseconds | |
| 30 | + }; | |
| 31 | + | |
| @@ -0,0 +1,27 @@ | ||
| 1 | +* Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) | |
| 2 | + | |
| 3 | +Required properties: | |
| 4 | +- compatible: Should be "atmel,<chip>-usart" | |
| 5 | + The compatible <chip> indicated will be the first SoC to support an | |
| 6 | + additional mode or an USART new feature. | |
| 7 | +- reg: Should contain registers location and length | |
| 8 | +- interrupts: Should contain interrupt | |
| 9 | + | |
| 10 | +Optional properties: | |
| 11 | +- atmel,use-dma-rx: use of PDC or DMA for receiving data | |
| 12 | +- atmel,use-dma-tx: use of PDC or DMA for transmitting data | |
| 13 | + | |
| 14 | +<chip> compatible description: | |
| 15 | +- at91rm9200: legacy USART support | |
| 16 | +- at91sam9260: generic USART implementation for SAM9 SoCs | |
| 17 | + | |
| 18 | +Example: | |
| 19 | + | |
| 20 | + usart0: serial@fff8c000 { | |
| 21 | + compatible = "atmel,at91sam9260-usart"; | |
| 22 | + reg = <0xfff8c000 0x4000>; | |
| 23 | + interrupts = <7>; | |
| 24 | + atmel,use-dma-rx; | |
| 25 | + atmel,use-dma-tx; | |
| 26 | + }; | |
| 27 | + | |
| @@ -0,0 +1,25 @@ | ||
| 1 | +* Synopsys DesignWare ABP UART | |
| 2 | + | |
| 3 | +Required properties: | |
| 4 | +- compatible : "snps,dw-apb-uart" | |
| 5 | +- reg : offset and length of the register set for the device. | |
| 6 | +- interrupts : should contain uart interrupt. | |
| 7 | +- clock-frequency : the input clock frequency for the UART. | |
| 8 | + | |
| 9 | +Optional properties: | |
| 10 | +- reg-shift : quantity to shift the register offsets by. If this property is | |
| 11 | + not present then the register offsets are not shifted. | |
| 12 | +- reg-io-width : the size (in bytes) of the IO accesses that should be | |
| 13 | + performed on the device. If this property is not present then single byte | |
| 14 | + accesses are used. | |
| 15 | + | |
| 16 | +Example: | |
| 17 | + | |
| 18 | + uart@80230000 { | |
| 19 | + compatible = "snps,dw-apb-uart"; | |
| 20 | + reg = <0x80230000 0x100>; | |
| 21 | + clock-frequency = <3686400>; | |
| 22 | + interrupts = <10>; | |
| 23 | + reg-shift = <2>; | |
| 24 | + reg-io-width = <4>; | |
| 25 | + }; | |
| @@ -28,6 +28,10 @@ · 27 unmodified lines | ||
| 28 | 28 | RS485 communications. This data structure is used to set and configure RS485 |
| 29 | 29 | parameters in the platform data and in ioctls. |
| 30 | 30 | |
| 31 | + The device tree can also provide RS485 boot time parameters (see [2] | |
| 32 | + for bindings). The driver is in charge of filling this data structure from | |
| 33 | + the values given by the device tree. | |
| 34 | + | |
| 31 | 35 | Any driver for devices capable of working both as RS232 and RS485 should |
| 32 | 36 | provide at least the following ioctls: |
| 33 | 37 | |
| @@ -104,6 +108,9 @@ · 70 unmodified lines | ||
| 104 | 108 | rs485conf.flags |= SER_RS485_RTS_AFTER_SEND; |
| 105 | 109 | rs485conf.delay_rts_after_send = ...; |
| 106 | 110 | |
| 111 | + /* Set this flag if you want to receive data even whilst sending data */ | |
| 112 | + rs485conf.flags |= SER_RS485_RX_DURING_TX; | |
| 113 | + | |
| 107 | 114 | if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) { |
| 108 | 115 | /* Error handling. See errno. */ |
| 109 | 116 | } |
| @@ -118,3 +125,4 @@ · 8 unmodified lines | ||
| 118 | 125 | 5. REFERENCES |
| 119 | 126 | |
| 120 | 127 | [1] include/linux/serial.h |
| 128 | + [2] Documentation/devicetree/bindings/serial/rs485.txt | |
| @@ -727,7 +727,6 @@ config ARCH_S3C64XX · 726 unmodified lines | ||
| 727 | 727 | select ARCH_REQUIRE_GPIOLIB |
| 728 | 728 | select SAMSUNG_CLKSRC |
| 729 | 729 | select SAMSUNG_IRQ_VIC_TIMER |
| 730 | − select SAMSUNG_IRQ_UART | |
| 731 | 730 | select S3C_GPIO_TRACK |
| 732 | 731 | select S3C_GPIO_PULL_UPDOWN |
| 733 | 732 | select S3C_GPIO_CFG_S3C24XX |
| @@ -37,21 +37,10 @@ static struct resource s3c64xx_uart0_resource[] = { · 36 unmodified lines | ||
| 37 | 37 | .flags = IORESOURCE_MEM, |
| 38 | 38 | }, |
| 39 | 39 | [1] = { |
| 40 | − .start = IRQ_S3CUART_RX0, | |
| 41 | − .end = IRQ_S3CUART_RX0, | |
| 40 | + .start = IRQ_UART0, | |
| 41 | + .end = IRQ_UART0, | |
| 42 | 42 | .flags = IORESOURCE_IRQ, |
| 43 | 43 | }, |
| 44 | − [2] = { | |
| 45 | − .start = IRQ_S3CUART_TX0, | |
| 46 | − .end = IRQ_S3CUART_TX0, | |
| 47 | − .flags = IORESOURCE_IRQ, | |
| 48 | − | |
| 49 | − }, | |
| 50 | − [3] = { | |
| 51 | − .start = IRQ_S3CUART_ERR0, | |
| 52 | − .end = IRQ_S3CUART_ERR0, | |
| 53 | − .flags = IORESOURCE_IRQ, | |
| 54 | − } | |
| 55 | 44 | }; |
| 56 | 45 | |
| 57 | 46 | static struct resource s3c64xx_uart1_resource[] = { |
| @@ -61,19 +50,8 @@ static struct resource s3c64xx_uart1_resource[] = { · 3 unmodified lines | ||
| 61 | 50 | .flags = IORESOURCE_MEM, |
| 62 | 51 | }, |
| 63 | 52 | [1] = { |
| 64 | − .start = IRQ_S3CUART_RX1, | |
| 65 | − .end = IRQ_S3CUART_RX1, | |
| 66 | − .flags = IORESOURCE_IRQ, | |
| 67 | − }, | |
| 68 | − [2] = { | |
| 69 | − .start = IRQ_S3CUART_TX1, | |
| 70 | − .end = IRQ_S3CUART_TX1, | |
| 71 | − .flags = IORESOURCE_IRQ, | |
| 72 | − | |
| 73 | − }, | |
| 74 | − [3] = { | |
| 75 | − .start = IRQ_S3CUART_ERR1, | |
| 76 | − .end = IRQ_S3CUART_ERR1, | |
| 53 | + .start = IRQ_UART1, | |
| 54 | + .end = IRQ_UART1, | |
| 77 | 55 | .flags = IORESOURCE_IRQ, |
| 78 | 56 | }, |
| 79 | 57 | }; |
| @@ -85,19 +63,8 @@ static struct resource s3c6xx_uart2_resource[] = { · 5 unmodified lines | ||
| 85 | 63 | .flags = IORESOURCE_MEM, |
| 86 | 64 | }, |
| 87 | 65 | [1] = { |
| 88 | − .start = IRQ_S3CUART_RX2, | |
| 89 | − .end = IRQ_S3CUART_RX2, | |
| 90 | − .flags = IORESOURCE_IRQ, | |
| 91 | − }, | |
| 92 | − [2] = { | |
| 93 | − .start = IRQ_S3CUART_TX2, | |
| 94 | − .end = IRQ_S3CUART_TX2, | |
| 95 | − .flags = IORESOURCE_IRQ, | |
| 96 | − | |
| 97 | − }, | |
| 98 | − [3] = { | |
| 99 | − .start = IRQ_S3CUART_ERR2, | |
| 100 | − .end = IRQ_S3CUART_ERR2, | |
| 66 | + .start = IRQ_UART2, | |
| 67 | + .end = IRQ_UART2, | |
| 101 | 68 | .flags = IORESOURCE_IRQ, |
| 102 | 69 | }, |
| 103 | 70 | }; |
| @@ -109,19 +76,8 @@ static struct resource s3c64xx_uart3_resource[] = { · 5 unmodified lines | ||
| 109 | 76 | .flags = IORESOURCE_MEM, |
| 110 | 77 | }, |
| 111 | 78 | [1] = { |
| 112 | − .start = IRQ_S3CUART_RX3, | |
| 113 | − .end = IRQ_S3CUART_RX3, | |
| 114 | − .flags = IORESOURCE_IRQ, | |
| 115 | − }, | |
| 116 | − [2] = { | |
| 117 | − .start = IRQ_S3CUART_TX3, | |
| 118 | − .end = IRQ_S3CUART_TX3, | |
| 119 | − .flags = IORESOURCE_IRQ, | |
| 120 | − | |
| 121 | − }, | |
| 122 | − [3] = { | |
| 123 | − .start = IRQ_S3CUART_ERR3, | |
| 124 | − .end = IRQ_S3CUART_ERR3, | |
| 79 | + .start = IRQ_UART3, | |
| 80 | + .end = IRQ_UART3, | |
| 125 | 81 | .flags = IORESOURCE_IRQ, |
| 126 | 82 | }, |
| 127 | 83 | }; |
| @@ -27,36 +27,6 @@ · 26 unmodified lines | ||
| 27 | 27 | #define IRQ_VIC0_BASE S3C_IRQ(0) |
| 28 | 28 | #define IRQ_VIC1_BASE S3C_IRQ(32) |
| 29 | 29 | |
| 30 | −/* UART interrupts, each UART has 4 intterupts per channel so | |
| 31 | − * use the space between the ISA and S3C main interrupts. Note, these | |
| 32 | − * are not in the same order as the S3C24XX series! */ | |
| 33 | − | |
| 34 | −#define IRQ_S3CUART_BASE0 (16) | |
| 35 | −#define IRQ_S3CUART_BASE1 (20) | |
| 36 | −#define IRQ_S3CUART_BASE2 (24) | |
| 37 | −#define IRQ_S3CUART_BASE3 (28) | |
| 38 | − | |
| 39 | −#define UART_IRQ_RXD (0) | |
| 40 | −#define UART_IRQ_ERR (1) | |
| 41 | −#define UART_IRQ_TXD (2) | |
| 42 | −#define UART_IRQ_MODEM (3) | |
| 43 | − | |
| 44 | −#define IRQ_S3CUART_RX0 (IRQ_S3CUART_BASE0 + UART_IRQ_RXD) | |
| 45 | −#define IRQ_S3CUART_TX0 (IRQ_S3CUART_BASE0 + UART_IRQ_TXD) | |
| 46 | −#define IRQ_S3CUART_ERR0 (IRQ_S3CUART_BASE0 + UART_IRQ_ERR) | |
| 47 | − | |
| 48 | −#define IRQ_S3CUART_RX1 (IRQ_S3CUART_BASE1 + UART_IRQ_RXD) | |
| 49 | −#define IRQ_S3CUART_TX1 (IRQ_S3CUART_BASE1 + UART_IRQ_TXD) | |
| 50 | −#define IRQ_S3CUART_ERR1 (IRQ_S3CUART_BASE1 + UART_IRQ_ERR) | |
| 51 | − | |
| 52 | −#define IRQ_S3CUART_RX2 (IRQ_S3CUART_BASE2 + UART_IRQ_RXD) | |
| 53 | −#define IRQ_S3CUART_TX2 (IRQ_S3CUART_BASE2 + UART_IRQ_TXD) | |
| 54 | −#define IRQ_S3CUART_ERR2 (IRQ_S3CUART_BASE2 + UART_IRQ_ERR) | |
| 55 | − | |
| 56 | −#define IRQ_S3CUART_RX3 (IRQ_S3CUART_BASE3 + UART_IRQ_RXD) | |
| 57 | −#define IRQ_S3CUART_TX3 (IRQ_S3CUART_BASE3 + UART_IRQ_TXD) | |
| 58 | −#define IRQ_S3CUART_ERR3 (IRQ_S3CUART_BASE3 + UART_IRQ_ERR) | |
| 59 | − | |
| 60 | 30 | /* VIC based IRQs */ |
| 61 | 31 | |
| 62 | 32 | #define S3C64XX_IRQ_VIC0(x) (IRQ_VIC0_BASE + (x)) |
| @@ -25,29 +25,6 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <plat/irq-uart.h> |
| 26 | 26 | #include <plat/cpu.h> |
| 27 | 27 | |
| 28 | −static struct s3c_uart_irq uart_irqs[] = { | |
| 29 | − [0] = { | |
| 30 | − .regs = S3C_VA_UART0, | |
| 31 | − .base_irq = IRQ_S3CUART_BASE0, | |
| 32 | − .parent_irq = IRQ_UART0, | |
| 33 | − }, | |
| 34 | − [1] = { | |
| 35 | − .regs = S3C_VA_UART1, | |
| 36 | − .base_irq = IRQ_S3CUART_BASE1, | |
| 37 | − .parent_irq = IRQ_UART1, | |
| 38 | − }, | |
| 39 | − [2] = { | |
| 40 | − .regs = S3C_VA_UART2, | |
| 41 | − .base_irq = IRQ_S3CUART_BASE2, | |
| 42 | − .parent_irq = IRQ_UART2, | |
| 43 | − }, | |
| 44 | − [3] = { | |
| 45 | − .regs = S3C_VA_UART3, | |
| 46 | − .base_irq = IRQ_S3CUART_BASE3, | |
| 47 | − .parent_irq = IRQ_UART3, | |
| 48 | − }, | |
| 49 | −}; | |
| 50 | − | |
| 51 | 28 | /* setup the sources the vic should advertise resume for, even though it |
| 52 | 29 | * is not doing the wake (set_irq_wake needs to be valid) */ |
| 53 | 30 | #define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE)) |
| @@ -67,6 +44,4 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) · 13 unmodified lines | ||
| 67 | 44 | |
| 68 | 45 | /* add the timer sub-irqs */ |
| 69 | 46 | s3c_init_vic_timer_irq(5, IRQ_TIMER0); |
| 70 | − | |
| 71 | − s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs)); | |
| 72 | 47 | } |
| @@ -22,7 +22,6 @@ config PLAT_S5P · 21 unmodified lines | ||
| 22 | 22 | select PLAT_SAMSUNG |
| 23 | 23 | select SAMSUNG_CLKSRC |
| 24 | 24 | select SAMSUNG_IRQ_VIC_TIMER |
| 25 | − select SAMSUNG_IRQ_UART | |
| 26 | 25 | help |
| 27 | 26 | Base platform code for Samsung's S5P series SoC. |
| 28 | 27 | |
| @@ -32,20 +32,10 @@ static struct resource s5p_uart0_resource[] = { · 31 unmodified lines | ||
| 32 | 32 | .flags = IORESOURCE_MEM, |
| 33 | 33 | }, |
| 34 | 34 | [1] = { |
| 35 | − .start = IRQ_S5P_UART_RX0, | |
| 36 | − .end = IRQ_S5P_UART_RX0, | |
| 35 | + .start = IRQ_UART0, | |
| 36 | + .end = IRQ_UART0, | |
| 37 | 37 | .flags = IORESOURCE_IRQ, |
| 38 | 38 | }, |
| 39 | − [2] = { | |
| 40 | − .start = IRQ_S5P_UART_TX0, | |
| 41 | − .end = IRQ_S5P_UART_TX0, | |
| 42 | − .flags = IORESOURCE_IRQ, | |
| 43 | − }, | |
| 44 | − [3] = { | |
| 45 | − .start = IRQ_S5P_UART_ERR0, | |
| 46 | − .end = IRQ_S5P_UART_ERR0, | |
| 47 | − .flags = IORESOURCE_IRQ, | |
| 48 | − } | |
| 49 | 39 | }; |
| 50 | 40 | |
| 51 | 41 | static struct resource s5p_uart1_resource[] = { |
| @@ -55,18 +45,8 @@ static struct resource s5p_uart1_resource[] = { · 3 unmodified lines | ||
| 55 | 45 | .flags = IORESOURCE_MEM, |
| 56 | 46 | }, |
| 57 | 47 | [1] = { |
| 58 | − .start = IRQ_S5P_UART_RX1, | |
| 59 | − .end = IRQ_S5P_UART_RX1, | |
| 60 | − .flags = IORESOURCE_IRQ, | |
| 61 | − }, | |
| 62 | − [2] = { | |
| 63 | − .start = IRQ_S5P_UART_TX1, | |
| 64 | − .end = IRQ_S5P_UART_TX1, | |
| 65 | − .flags = IORESOURCE_IRQ, | |
| 66 | − }, | |
| 67 | − [3] = { | |
| 68 | − .start = IRQ_S5P_UART_ERR1, | |
| 69 | − .end = IRQ_S5P_UART_ERR1, | |
| 48 | + .start = IRQ_UART1, | |
| 49 | + .end = IRQ_UART1, | |
| 70 | 50 | .flags = IORESOURCE_IRQ, |
| 71 | 51 | }, |
| 72 | 52 | }; |
| @@ -78,18 +58,8 @@ static struct resource s5p_uart2_resource[] = { · 5 unmodified lines | ||
| 78 | 58 | .flags = IORESOURCE_MEM, |
| 79 | 59 | }, |
| 80 | 60 | [1] = { |
| 81 | − .start = IRQ_S5P_UART_RX2, | |
| 82 | − .end = IRQ_S5P_UART_RX2, | |
| 83 | − .flags = IORESOURCE_IRQ, | |
| 84 | − }, | |
| 85 | − [2] = { | |
| 86 | − .start = IRQ_S5P_UART_TX2, | |
| 87 | − .end = IRQ_S5P_UART_TX2, | |
| 88 | − .flags = IORESOURCE_IRQ, | |
| 89 | − }, | |
| 90 | − [3] = { | |
| 91 | − .start = IRQ_S5P_UART_ERR2, | |
| 92 | − .end = IRQ_S5P_UART_ERR2, | |
| 61 | + .start = IRQ_UART2, | |
| 62 | + .end = IRQ_UART2, | |
| 93 | 63 | .flags = IORESOURCE_IRQ, |
| 94 | 64 | }, |
| 95 | 65 | }; |
| @@ -102,18 +72,8 @@ static struct resource s5p_uart3_resource[] = { · 6 unmodified lines | ||
| 102 | 72 | .flags = IORESOURCE_MEM, |
| 103 | 73 | }, |
| 104 | 74 | [1] = { |
| 105 | − .start = IRQ_S5P_UART_RX3, | |
| 106 | − .end = IRQ_S5P_UART_RX3, | |
| 107 | − .flags = IORESOURCE_IRQ, | |
| 108 | − }, | |
| 109 | − [2] = { | |
| 110 | − .start = IRQ_S5P_UART_TX3, | |
| 111 | − .end = IRQ_S5P_UART_TX3, | |
| 112 | − .flags = IORESOURCE_IRQ, | |
| 113 | − }, | |
| 114 | − [3] = { | |
| 115 | − .start = IRQ_S5P_UART_ERR3, | |
| 116 | − .end = IRQ_S5P_UART_ERR3, | |
| 75 | + .start = IRQ_UART3, | |
| 76 | + .end = IRQ_UART3, | |
| 117 | 77 | .flags = IORESOURCE_IRQ, |
| 118 | 78 | }, |
| 119 | 79 | #endif |
| @@ -127,18 +87,8 @@ static struct resource s5p_uart4_resource[] = { · 7 unmodified lines | ||
| 127 | 87 | .flags = IORESOURCE_MEM, |
| 128 | 88 | }, |
| 129 | 89 | [1] = { |
| 130 | − .start = IRQ_S5P_UART_RX4, | |
| 131 | − .end = IRQ_S5P_UART_RX4, | |
| 132 | − .flags = IORESOURCE_IRQ, | |
| 133 | − }, | |
| 134 | − [2] = { | |
| 135 | − .start = IRQ_S5P_UART_TX4, | |
| 136 | − .end = IRQ_S5P_UART_TX4, | |
| 137 | − .flags = IORESOURCE_IRQ, | |
| 138 | − }, | |
| 139 | − [3] = { | |
| 140 | − .start = IRQ_S5P_UART_ERR4, | |
| 141 | − .end = IRQ_S5P_UART_ERR4, | |
| 90 | + .start = IRQ_UART4, | |
| 91 | + .end = IRQ_UART4, | |
| 142 | 92 | .flags = IORESOURCE_IRQ, |
| 143 | 93 | }, |
| 144 | 94 | #endif |
| @@ -152,18 +102,8 @@ static struct resource s5p_uart5_resource[] = { · 7 unmodified lines | ||
| 152 | 102 | .flags = IORESOURCE_MEM, |
| 153 | 103 | }, |
| 154 | 104 | [1] = { |
| 155 | − .start = IRQ_S5P_UART_RX5, | |
| 156 | − .end = IRQ_S5P_UART_RX5, | |
| 157 | − .flags = IORESOURCE_IRQ, | |
| 158 | − }, | |
| 159 | − [2] = { | |
| 160 | − .start = IRQ_S5P_UART_TX5, | |
| 161 | − .end = IRQ_S5P_UART_TX5, | |
| 162 | − .flags = IORESOURCE_IRQ, | |
| 163 | − }, | |
| 164 | − [3] = { | |
| 165 | − .start = IRQ_S5P_UART_ERR5, | |
| 166 | − .end = IRQ_S5P_UART_ERR5, | |
| 105 | + .start = IRQ_UART5, | |
| 106 | + .end = IRQ_UART5, | |
| 167 | 107 | .flags = IORESOURCE_IRQ, |
| 168 | 108 | }, |
| 169 | 109 | #endif |
| @@ -37,41 +37,6 @@ · 36 unmodified lines | ||
| 37 | 37 | #define IRQ_VIC1_BASE S5P_VIC1_BASE |
| 38 | 38 | #define IRQ_VIC2_BASE S5P_VIC2_BASE |
| 39 | 39 | |
| 40 | −/* UART interrupts, each UART has 4 intterupts per channel so | |
| 41 | − * use the space between the ISA and S3C main interrupts. Note, these | |
| 42 | − * are not in the same order as the S3C24XX series! */ | |
| 43 | − | |
| 44 | −#define IRQ_S5P_UART_BASE0 (16) | |
| 45 | −#define IRQ_S5P_UART_BASE1 (20) | |
| 46 | −#define IRQ_S5P_UART_BASE2 (24) | |
| 47 | −#define IRQ_S5P_UART_BASE3 (28) | |
| 48 | − | |
| 49 | −#define UART_IRQ_RXD (0) | |
| 50 | −#define UART_IRQ_ERR (1) | |
| 51 | −#define UART_IRQ_TXD (2) | |
| 52 | − | |
| 53 | −#define IRQ_S5P_UART_RX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_RXD) | |
| 54 | −#define IRQ_S5P_UART_TX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_TXD) | |
| 55 | −#define IRQ_S5P_UART_ERR0 (IRQ_S5P_UART_BASE0 + UART_IRQ_ERR) | |
| 56 | − | |
| 57 | −#define IRQ_S5P_UART_RX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_RXD) | |
| 58 | −#define IRQ_S5P_UART_TX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_TXD) | |
| 59 | −#define IRQ_S5P_UART_ERR1 (IRQ_S5P_UART_BASE1 + UART_IRQ_ERR) | |
| 60 | − | |
| 61 | −#define IRQ_S5P_UART_RX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_RXD) | |
| 62 | −#define IRQ_S5P_UART_TX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_TXD) | |
| 63 | −#define IRQ_S5P_UART_ERR2 (IRQ_S5P_UART_BASE2 + UART_IRQ_ERR) | |
| 64 | − | |
| 65 | −#define IRQ_S5P_UART_RX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_RXD) | |
| 66 | −#define IRQ_S5P_UART_TX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_TXD) | |
| 67 | −#define IRQ_S5P_UART_ERR3 (IRQ_S5P_UART_BASE3 + UART_IRQ_ERR) | |
| 68 | − | |
| 69 | −/* S3C compatibilty defines */ | |
| 70 | −#define IRQ_S3CUART_RX0 IRQ_S5P_UART_RX0 | |
| 71 | −#define IRQ_S3CUART_RX1 IRQ_S5P_UART_RX1 | |
| 72 | −#define IRQ_S3CUART_RX2 IRQ_S5P_UART_RX2 | |
| 73 | −#define IRQ_S3CUART_RX3 IRQ_S5P_UART_RX3 | |
| 74 | − | |
| 75 | 40 | /* VIC based IRQs */ |
| 76 | 41 | |
| 77 | 42 | #define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x)) |
| @@ -17,42 +17,10 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | #include <asm/hardware/vic.h> |
| 19 | 19 | |
| 20 | −#include <linux/serial_core.h> | |
| 21 | 20 | #include <mach/map.h> |
| 22 | 21 | #include <plat/regs-timer.h> |
| 23 | −#include <plat/regs-serial.h> | |
| 24 | 22 | #include <plat/cpu.h> |
| 25 | 23 | #include <plat/irq-vic-timer.h> |
| 26 | −#include <plat/irq-uart.h> | |
| 27 | − | |
| 28 | −/* | |
| 29 | − * Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] | |
| 30 | − * are consecutive when looking up the interrupt in the demux routines. | |
| 31 | − */ | |
| 32 | −static struct s3c_uart_irq uart_irqs[] = { | |
| 33 | − [0] = { | |
| 34 | − .regs = S5P_VA_UART0, | |
| 35 | − .base_irq = IRQ_S5P_UART_BASE0, | |
| 36 | − .parent_irq = IRQ_UART0, | |
| 37 | − }, | |
| 38 | − [1] = { | |
| 39 | − .regs = S5P_VA_UART1, | |
| 40 | − .base_irq = IRQ_S5P_UART_BASE1, | |
| 41 | − .parent_irq = IRQ_UART1, | |
| 42 | − }, | |
| 43 | − [2] = { | |
| 44 | − .regs = S5P_VA_UART2, | |
| 45 | − .base_irq = IRQ_S5P_UART_BASE2, | |
| 46 | − .parent_irq = IRQ_UART2, | |
| 47 | − }, | |
| 48 | −#if CONFIG_SERIAL_SAMSUNG_UARTS > 3 | |
| 49 | − [3] = { | |
| 50 | − .regs = S5P_VA_UART3, | |
| 51 | − .base_irq = IRQ_S5P_UART_BASE3, | |
| 52 | − .parent_irq = IRQ_UART3, | |
| 53 | − }, | |
| 54 | −#endif | |
| 55 | −}; | |
| 56 | 24 | |
| 57 | 25 | void __init s5p_init_irq(u32 *vic, u32 num_vic) |
| 58 | 26 | { |
| @@ -65,6 +33,4 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic) · 6 unmodified lines | ||
| 65 | 33 | #endif |
| 66 | 34 | |
| 67 | 35 | s3c_init_vic_timer_irq(5, IRQ_TIMER0); |
| 68 | − | |
| 69 | − s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs)); | |
| 70 | 36 | } |
| @@ -65,11 +65,6 @@ config SAMSUNG_IRQ_VIC_TIMER · 64 unmodified lines | ||
| 65 | 65 | help |
| 66 | 66 | Internal configuration to build the VIC timer interrupt code. |
| 67 | 67 | |
| 68 | −config SAMSUNG_IRQ_UART | |
| 69 | − bool | |
| 70 | − help | |
| 71 | − Internal configuration to build the IRQ UART demux code. | |
| 72 | − | |
| 73 | 68 | # options for gpio configuration support |
| 74 | 69 | |
| 75 | 70 | config SAMSUNG_GPIOLIB_4BIT |
| @@ -21,7 +21,6 @@ obj-y += dev-asocdma.o · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 22 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o |
| 23 | 23 | |
| 24 | −obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o | |
| 25 | 24 | obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o |
| 26 | 25 | |
| 27 | 26 | # ADC |
| @@ -186,6 +186,11 @@ · 185 unmodified lines | ||
| 186 | 186 | #define S3C64XX_UINTSP 0x34 |
| 187 | 187 | #define S3C64XX_UINTM 0x38 |
| 188 | 188 | |
| 189 | +#define S3C64XX_UINTM_RXD (0) | |
| 190 | +#define S3C64XX_UINTM_TXD (2) | |
| 191 | +#define S3C64XX_UINTM_RXD_MSK (1 << S3C64XX_UINTM_RXD) | |
| 192 | +#define S3C64XX_UINTM_TXD_MSK (1 << S3C64XX_UINTM_TXD) | |
| 193 | + | |
| 189 | 194 | /* Following are specific to S5PV210 */ |
| 190 | 195 | #define S5PV210_UCON_CLKMASK (1<<10) |
| 191 | 196 | #define S5PV210_UCON_PCLK (0<<10) |
| @@ -1,96 +0,0 @@ | ||
| 1 | −/* arch/arm/plat-samsung/irq-uart.c | |
| 2 | − * originally part of arch/arm/plat-s3c64xx/irq.c | |
| 3 | − * | |
| 4 | − * Copyright 2008 Openmoko, Inc. | |
| 5 | − * Copyright 2008 Simtec Electronics | |
| 6 | − * Ben Dooks <ben@simtec.co.uk> | |
| 7 | − * http://armlinux.simtec.co.uk/ | |
| 8 | − * | |
| 9 | − * Samsung- UART Interrupt handling | |
| 10 | − * | |
| 11 | − * This program is free software; you can redistribute it and/or modify | |
| 12 | − * it under the terms of the GNU General Public License version 2 as | |
| 13 | − * published by the Free Software Foundation. | |
| 14 | − */ | |
| 15 | − | |
| 16 | −#include <linux/kernel.h> | |
| 17 | −#include <linux/interrupt.h> | |
| 18 | −#include <linux/serial_core.h> | |
| 19 | −#include <linux/irq.h> | |
| 20 | −#include <linux/io.h> | |
| 21 | − | |
| 22 | −#include <asm/mach/irq.h> | |
| 23 | − | |
| 24 | −#include <mach/map.h> | |
| 25 | −#include <plat/irq-uart.h> | |
| 26 | −#include <plat/regs-serial.h> | |
| 27 | −#include <plat/cpu.h> | |
| 28 | − | |
| 29 | −/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] | |
| 30 | − * are consecutive when looking up the interrupt in the demux routines. | |
| 31 | − */ | |
| 32 | −static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) | |
| 33 | −{ | |
| 34 | − struct s3c_uart_irq *uirq = desc->irq_data.handler_data; | |
| 35 | − struct irq_chip *chip = irq_get_chip(irq); | |
| 36 | − u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); | |
| 37 | − int base = uirq->base_irq; | |
| 38 | − | |
| 39 | − chained_irq_enter(chip, desc); | |
| 40 | − | |
| 41 | − if (pend & (1 << 0)) | |
| 42 | − generic_handle_irq(base); | |
| 43 | − if (pend & (1 << 1)) | |
| 44 | − generic_handle_irq(base + 1); | |
| 45 | − if (pend & (1 << 2)) | |
| 46 | − generic_handle_irq(base + 2); | |
| 47 | − if (pend & (1 << 3)) | |
| 48 | − generic_handle_irq(base + 3); | |
| 49 | − | |
| 50 | − chained_irq_exit(chip, desc); | |
| 51 | −} | |
| 52 | − | |
| 53 | −static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) | |
| 54 | −{ | |
| 55 | − void __iomem *reg_base = uirq->regs; | |
| 56 | − struct irq_chip_generic *gc; | |
| 57 | − struct irq_chip_type *ct; | |
| 58 | − | |
| 59 | − /* mask all interrupts at the start. */ | |
| 60 | − __raw_writel(0xf, reg_base + S3C64XX_UINTM); | |
| 61 | − | |
| 62 | − gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base, | |
| 63 | − handle_level_irq); | |
| 64 | − | |
| 65 | − if (!gc) { | |
| 66 | − pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n", | |
| 67 | − __func__, uirq->base_irq); | |
| 68 | − return; | |
| 69 | − } | |
| 70 | − | |
| 71 | − ct = gc->chip_types; | |
| 72 | − ct->chip.irq_ack = irq_gc_ack_set_bit; | |
| 73 | − ct->chip.irq_mask = irq_gc_mask_set_bit; | |
| 74 | − ct->chip.irq_unmask = irq_gc_mask_clr_bit; | |
| 75 | − ct->regs.ack = S3C64XX_UINTP; | |
| 76 | − ct->regs.mask = S3C64XX_UINTM; | |
| 77 | − irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE, | |
| 78 | − IRQ_NOREQUEST | IRQ_NOPROBE, 0); | |
| 79 | − | |
| 80 | − irq_set_handler_data(uirq->parent_irq, uirq); | |
| 81 | − irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); | |
| 82 | −} | |
| 83 | − | |
| 84 | −/** | |
| 85 | − * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing | |
| 86 | − * @irq: The interrupt data for registering | |
| 87 | − * @nr_irqs: The number of interrupt descriptions in @irq. | |
| 88 | − * | |
| 89 | − * Register the UART interrupts specified by @irq including the demuxing | |
| 90 | − * routines. This supports the S3C6400 and newer style of devices. | |
| 91 | − */ | |
| 92 | −void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs) | |
| 93 | −{ | |
| 94 | − for (; nr_irqs > 0; nr_irqs--, irq++) | |
| 95 | − s3c_init_uart_irq(irq); | |
| 96 | −} | |
| @@ -195,7 +195,7 @@ config UNIX98_PTYS · 194 unmodified lines | ||
| 195 | 195 | |
| 196 | 196 | source "drivers/char/pcmcia/Kconfig" |
| 197 | 197 | |
| 198 | −source "drivers/serial/Kconfig" | |
| 198 | +source "drivers/tty/serial/Kconfig" | |
| 199 | 199 | |
| 200 | 200 | source "drivers/i2c/Kconfig" |
| 201 | 201 | |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/serial.h> |
| 28 | 28 | #include <linux/serial_core.h> |
| 29 | 29 | #include <linux/serial_reg.h> |
| 30 | +#include <linux/slab.h> | |
| 30 | 31 | |
| 31 | 32 | #include <asm/bootinfo.h> |
| 32 | 33 | #include <asm/io.h> |
| @@ -38,6 +39,55 @@ · 5 unmodified lines | ||
| 38 | 39 | #include <msp_int.h> |
| 39 | 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 | 91 | void __init msp_serial_setup(void) |
| 42 | 92 | { |
| 43 | 93 | char *s; |
| @@ -59,13 +109,22 @@ void __init msp_serial_setup(void) · 15 unmodified lines | ||
| 59 | 109 | up.irq = MSP_INT_UART0; |
| 60 | 110 | up.uartclk = uartclk; |
| 61 | 111 | up.regshift = 2; |
| 62 | − up.iotype = UPIO_DWAPB; /* UPIO_MEM like */ | |
| 112 | + up.iotype = UPIO_MEM; | |
| 63 | 113 | up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; |
| 64 | 114 | up.type = PORT_16550A; |
| 65 | 115 | up.line = 0; |
| 66 | − up.private_data = (void*)UART0_STATUS_REG; | |
| 67 | − if (early_serial_setup(&up)) | |
| 68 | − printk(KERN_ERR "Early serial init of port 0 failed\n"); | |
| 116 | + up.serial_out = msp_serial_out; | |
| 117 | + up.serial_in = msp_serial_in; | |
| 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 | 129 | /* Initialize the second serial port, if one exists */ |
| 71 | 130 | switch (mips_machtype) { |
| @@ -88,6 +147,8 @@ void __init msp_serial_setup(void) · 16 unmodified lines | ||
| 88 | 147 | up.irq = MSP_INT_UART1; |
| 89 | 148 | up.line = 1; |
| 90 | 149 | up.private_data = (void*)UART1_STATUS_REG; |
| 91 | − if (early_serial_setup(&up)) | |
| 92 | − printk(KERN_ERR "Early serial init of port 1 failed\n"); | |
| 150 | + if (early_serial_setup(&up)) { | |
| 151 | + kfree(up.private_data); | |
| 152 | + pr_err("Early serial init of port 1 failed\n"); | |
| 153 | + } | |
| 93 | 154 | } |
| @@ -54,6 +54,7 @@ extern void __init udbg_init_40x_realmode(void); · 53 unmodified lines | ||
| 54 | 54 | extern void __init udbg_init_cpm(void); |
| 55 | 55 | extern void __init udbg_init_usbgecko(void); |
| 56 | 56 | extern void __init udbg_init_wsp(void); |
| 57 | +extern void __init udbg_init_ehv_bc(void); | |
| 57 | 58 | |
| 58 | 59 | #endif /* __KERNEL__ */ |
| 59 | 60 | #endif /* _ASM_POWERPC_UDBG_H */ |
| @@ -67,6 +67,8 @@ void __init udbg_early_init(void) · 66 unmodified lines | ||
| 67 | 67 | udbg_init_usbgecko(); |
| 68 | 68 | #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP) |
| 69 | 69 | udbg_init_wsp(); |
| 70 | +#elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC) | |
| 71 | + udbg_init_ehv_bc(); | |
| 70 | 72 | #endif |
| 71 | 73 | |
| 72 | 74 | #ifdef CONFIG_PPC_EARLY_DEBUG |
| @@ -14,6 +14,8 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #include <linux/init.h> |
| 16 | 16 | #include <linux/kernel.h> |
| 17 | +#include <linux/interrupt.h> | |
| 18 | +#include <linux/scatterlist.h> | |
| 17 | 19 | #include <linux/sfi.h> |
| 18 | 20 | #include <linux/intel_pmic_gpio.h> |
| 19 | 21 | #include <linux/spi/spi.h> |
| @@ -392,6 +394,7 @@ static void __init *max3111_platform_data(void *info) · 372 unmodified lines | ||
| 392 | 394 | struct spi_board_info *spi_info = info; |
| 393 | 395 | int intr = get_gpio_by_name("max3111_int"); |
| 394 | 396 | |
| 397 | + spi_info->mode = SPI_MODE_0; | |
| 395 | 398 | if (intr == -1) |
| 396 | 399 | return NULL; |
| 397 | 400 | spi_info->irq = intr + MRST_IRQ_OFFSET; |
| @@ -1693,7 +1693,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) · 1692 unmodified lines | ||
| 1693 | 1693 | * line status register. |
| 1694 | 1694 | */ |
| 1695 | 1695 | if (info->flags & ISDN_ASYNC_INITIALIZED) { |
| 1696 | − tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ | |
| 1696 | + tty_wait_until_sent_from_close(tty, 3000); /* 30 seconds timeout */ | |
| 1697 | 1697 | /* |
| 1698 | 1698 | * Before we drop DTR, make sure the UART transmitter |
| 1699 | 1699 | * has completely drained; this is especially |
| @@ -2595,14 +2595,17 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, · 2594 unmodified lines | ||
| 2595 | 2595 | break; |
| 2596 | 2596 | case 0x6: |
| 2597 | 2597 | printk(KERN_INFO "parport_pc: ITE8873 found (1S)\n"); |
| 2598 | + release_region(inta_addr[i], 32); | |
| 2598 | 2599 | return 0; |
| 2599 | 2600 | case 0x8: |
| 2600 | 2601 | printk(KERN_INFO "parport_pc: ITE8874 found (2S)\n"); |
| 2602 | + release_region(inta_addr[i], 32); | |
| 2601 | 2603 | return 0; |
| 2602 | 2604 | default: |
| 2603 | 2605 | printk(KERN_INFO "parport_pc: unknown ITE887x\n"); |
| 2604 | 2606 | printk(KERN_INFO "parport_pc: please mail 'lspci -nvv' " |
| 2605 | 2607 | "output to Rich.Liu@ite.com.tw\n"); |
| 2608 | + release_region(inta_addr[i], 32); | |
| 2606 | 2609 | return 0; |
| 2607 | 2610 | } |
| 2608 | 2611 | |
| @@ -24,6 +24,8 @@ menuconfig STAGING · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | if STAGING |
| 26 | 26 | |
| 27 | +source "drivers/staging/serial/Kconfig" | |
| 28 | + | |
| 27 | 29 | source "drivers/staging/et131x/Kconfig" |
| 28 | 30 | |
| 29 | 31 | source "drivers/staging/slicoss/Kconfig" |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | # fix for build system bug... |
| 4 | 4 | obj-$(CONFIG_STAGING) += staging.o |
| 5 | 5 | |
| 6 | +obj-y += serial/ | |
| 6 | 7 | obj-$(CONFIG_ET131X) += et131x/ |
| 7 | 8 | obj-$(CONFIG_SLICOSS) += slicoss/ |
| 8 | 9 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ |
File renamed without changes.
| @@ -0,0 +1,16 @@ | ||
| 1 | +config SERIAL_68360_SMC | |
| 2 | + bool "68360 SMC uart support" | |
| 3 | + depends on M68360 | |
| 4 | + help | |
| 5 | + This driver supports the SMC serial ports of the Motorola 68360 CPU. | |
| 6 | + | |
| 7 | +config SERIAL_68360_SCC | |
| 8 | + bool "68360 SCC uart support" | |
| 9 | + depends on M68360 | |
| 10 | + help | |
| 11 | + This driver supports the SCC serial ports of the Motorola 68360 CPU. | |
| 12 | + | |
| 13 | +config SERIAL_68360 | |
| 14 | + bool | |
| 15 | + depends on SERIAL_68360_SMC || SERIAL_68360_SCC | |
| 16 | + default y | |
| @@ -0,0 +1 @@ | ||
| 1 | +obj-$(CONFIG_SERIAL_68360) += 68360serial.o | |
| @@ -0,0 +1,6 @@ | ||
| 1 | +These are a few serial drivers that either do not build, or do not work if they | |
| 2 | +do build, or if they seem to work, are for obsolete hardware, or are full of | |
| 3 | +unfixable races and no one uses them anymore. | |
| 4 | + | |
| 5 | +If no one steps up to adopt any of these drivers, they will be removed | |
| 6 | +in the 3.4 release. | |
| @@ -354,3 +354,37 @@ config TRACE_SINK · 353 unmodified lines | ||
| 354 | 354 | |
| 355 | 355 | If you select this option, you need to select |
| 356 | 356 | "Trace data router for MIPI P1149.7 cJTAG standard". |
| 357 | + | |
| 358 | +config PPC_EPAPR_HV_BYTECHAN | |
| 359 | + tristate "ePAPR hypervisor byte channel driver" | |
| 360 | + depends on PPC | |
| 361 | + help | |
| 362 | + This driver creates /dev entries for each ePAPR hypervisor byte | |
| 363 | + channel, thereby allowing applications to communicate with byte | |
| 364 | + channels as if they were serial ports. | |
| 365 | + | |
| 366 | +config PPC_EARLY_DEBUG_EHV_BC | |
| 367 | + bool "Early console (udbg) support for ePAPR hypervisors" | |
| 368 | + depends on PPC_EPAPR_HV_BYTECHAN | |
| 369 | + help | |
| 370 | + Select this option to enable early console (a.k.a. "udbg") support | |
| 371 | + via an ePAPR byte channel. You also need to choose the byte channel | |
| 372 | + handle below. | |
| 373 | + | |
| 374 | +config PPC_EARLY_DEBUG_EHV_BC_HANDLE | |
| 375 | + int "Byte channel handle for early console (udbg)" | |
| 376 | + depends on PPC_EARLY_DEBUG_EHV_BC | |
| 377 | + default 0 | |
| 378 | + help | |
| 379 | + If you want early console (udbg) output through a byte channel, | |
| 380 | + specify the handle of the byte channel to use. | |
| 381 | + | |
| 382 | + For this to work, the byte channel driver must be compiled | |
| 383 | + in-kernel, not as a module. | |
| 384 | + | |
| 385 | + Note that only one early console driver can be enabled, so don't | |
| 386 | + enable any others if you enable this one. | |
| 387 | + | |
| 388 | + If the number you specify is not a valid byte channel handle, then | |
| 389 | + there simply will be no early console output. This is true also | |
| 390 | + if you don't boot under a hypervisor at all. | |
| @@ -26,5 +26,6 @@ obj-$(CONFIG_ROCKETPORT) += rocket.o · 25 unmodified lines | ||
| 26 | 26 | obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o |
| 27 | 27 | obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o |
| 28 | 28 | obj-$(CONFIG_SYNCLINK) += synclink.o |
| 29 | +obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o | |
| 29 | 30 | |
| 30 | 31 | obj-y += ipwireless/ |
| @@ -1529,7 +1529,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) · 1528 unmodified lines | ||
| 1529 | 1529 | { |
| 1530 | 1530 | struct async_struct * info = tty->driver_data; |
| 1531 | 1531 | unsigned long orig_jiffies, char_time; |
| 1532 | − int tty_was_locked = tty_locked(); | |
| 1533 | 1532 | int lsr; |
| 1534 | 1533 | |
| 1535 | 1534 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) |
| @@ -1540,12 +1539,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) · 4 unmodified lines | ||
| 1540 | 1539 | |
| 1541 | 1540 | orig_jiffies = jiffies; |
| 1542 | 1541 | |
| 1543 | − /* | |
| 1544 | − * tty_wait_until_sent is called from lots of places, | |
| 1545 | − * with or without the BTM. | |
| 1546 | − */ | |
| 1547 | − if (!tty_was_locked) | |
| 1548 | − tty_lock(); | |
| 1549 | 1542 | /* |
| 1550 | 1543 | * Set the check interval to be 1/5 of the estimated time to |
| 1551 | 1544 | * send a single character, and make it at least 1. The check |
| @@ -1586,8 +1579,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) · 34 unmodified lines | ||
| 1586 | 1579 | break; |
| 1587 | 1580 | } |
| 1588 | 1581 | __set_current_state(TASK_RUNNING); |
| 1589 | − if (!tty_was_locked) | |
| 1590 | − tty_unlock(); | |
| 1582 | + | |
| 1591 | 1583 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
| 1592 | 1584 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
| 1593 | 1585 | #endif |
| @@ -2025,7 +2017,7 @@ static int __init amiga_serial_probe(struct platform_device *pdev) · 431 unmodified lines | ||
| 2025 | 2017 | if (error) |
| 2026 | 2018 | goto fail_unregister; |
| 2027 | 2019 | |
| 2028 | − error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED, | |
| 2020 | + error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, 0, | |
| 2029 | 2021 | "serial RX", state); |
| 2030 | 2022 | if (error) |
| 2031 | 2023 | goto fail_free_irq; |
| @@ -45,7 +45,6 @@ · 44 unmodified lines | ||
| 45 | 45 | #undef CY_DEBUG_IO |
| 46 | 46 | #undef CY_DEBUG_COUNT |
| 47 | 47 | #undef CY_DEBUG_DTR |
| 48 | −#undef CY_DEBUG_WAIT_UNTIL_SENT | |
| 49 | 48 | #undef CY_DEBUG_INTERRUPTS |
| 50 | 49 | #undef CY_16Y_HACK |
| 51 | 50 | #undef CY_ENABLE_MONITORING |
| @@ -1678,16 +1677,10 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) · 1626 unmodified lines | ||
| 1678 | 1677 | */ |
| 1679 | 1678 | if (!timeout || timeout > 2 * info->timeout) |
| 1680 | 1679 | timeout = 2 * info->timeout; |
| 1681 | −#ifdef CY_DEBUG_WAIT_UNTIL_SENT | |
| 1682 | − printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...", | |
| 1683 | − timeout, char_time, jiffies); | |
| 1684 | −#endif | |
| 1680 | + | |
| 1685 | 1681 | card = info->card; |
| 1686 | 1682 | if (!cy_is_Z(card)) { |
| 1687 | 1683 | while (cyy_readb(info, CySRER) & CyTxRdy) { |
| 1688 | −#ifdef CY_DEBUG_WAIT_UNTIL_SENT | |
| 1689 | − printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies); | |
| 1690 | −#endif | |
| 1691 | 1684 | if (msleep_interruptible(jiffies_to_msecs(char_time))) |
| 1692 | 1685 | break; |
| 1693 | 1686 | if (timeout && time_after(jiffies, orig_jiffies + |
| @@ -1697,9 +1690,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) · 3 unmodified lines | ||
| 1697 | 1690 | } |
| 1698 | 1691 | /* Run one more char cycle */ |
| 1699 | 1692 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); |
| 1700 | −#ifdef CY_DEBUG_WAIT_UNTIL_SENT | |
| 1701 | − printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); | |
| 1702 | −#endif | |
| 1703 | 1693 | } |
| 1704 | 1694 | |
| 1705 | 1695 | static void cy_flush_buffer(struct tty_struct *tty) |
| @@ -3377,7 +3367,7 @@ static int __init cy_detect_isa(void) · 1671 unmodified lines | ||
| 3377 | 3367 | |
| 3378 | 3368 | /* allocate IRQ */ |
| 3379 | 3369 | if (request_irq(cy_isa_irq, cyy_interrupt, |
| 3380 | − IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { | |
| 3370 | + 0, "Cyclom-Y", &cy_card[j])) { | |
| 3381 | 3371 | printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " |
| 3382 | 3372 | "could not allocate IRQ#%d.\n", |
| 3383 | 3373 | (unsigned long)cy_isa_address, cy_isa_irq); |
| @@ -0,0 +1,881 @@ | ||
| 1 | +/* ePAPR hypervisor byte channel device driver | |
| 2 | + * | |
| 3 | + * Copyright 2009-2011 Freescale Semiconductor, Inc. | |
| 4 | + * | |
| 5 | + * Author: Timur Tabi <timur@freescale.com> | |
| 6 | + * | |
| 7 | + * This file is licensed under the terms of the GNU General Public License | |
| 8 | + * version 2. This program is licensed "as is" without any warranty of any | |
| 9 | + * kind, whether express or implied. | |
| 10 | + * | |
| 11 | + * This driver support three distinct interfaces, all of which are related to | |
| 12 | + * ePAPR hypervisor byte channels. | |
| 13 | + * | |
| 14 | + * 1) An early-console (udbg) driver. This provides early console output | |
| 15 | + * through a byte channel. The byte channel handle must be specified in a | |
| 16 | + * Kconfig option. | |
| 17 | + * | |
| 18 | + * 2) A normal console driver. Output is sent to the byte channel designated | |
| 19 | + * for stdout in the device tree. The console driver is for handling kernel | |
| 20 | + * printk calls. | |
| 21 | + * | |
| 22 | + * 3) A tty driver, which is used to handle user-space input and output. The | |
| 23 | + * byte channel used for the console is designated as the default tty. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +#include <linux/module.h> | |
| 27 | +#include <linux/init.h> | |
| 28 | +#include <linux/slab.h> | |
| 29 | +#include <linux/err.h> | |
| 30 | +#include <linux/interrupt.h> | |
| 31 | +#include <linux/fs.h> | |
| 32 | +#include <linux/poll.h> | |
| 33 | +#include <asm/epapr_hcalls.h> | |
| 34 | +#include <linux/of.h> | |
| 35 | +#include <linux/platform_device.h> | |
| 36 | +#include <linux/cdev.h> | |
| 37 | +#include <linux/console.h> | |
| 38 | +#include <linux/tty.h> | |
| 39 | +#include <linux/tty_flip.h> | |
| 40 | +#include <linux/circ_buf.h> | |
| 41 | +#include <asm/udbg.h> | |
| 42 | + | |
| 43 | +/* The size of the transmit circular buffer. This must be a power of two. */ | |
| 44 | +#define BUF_SIZE 2048 | |
| 45 | + | |
| 46 | +/* Per-byte channel private data */ | |
| 47 | +struct ehv_bc_data { | |
| 48 | + struct device *dev; | |
| 49 | + struct tty_port port; | |
| 50 | + uint32_t handle; | |
| 51 | + unsigned int rx_irq; | |
| 52 | + unsigned int tx_irq; | |
| 53 | + | |
| 54 | + spinlock_t lock; /* lock for transmit buffer */ | |
| 55 | + unsigned char buf[BUF_SIZE]; /* transmit circular buffer */ | |
| 56 | + unsigned int head; /* circular buffer head */ | |
| 57 | + unsigned int tail; /* circular buffer tail */ | |
| 58 | + | |
| 59 | + int tx_irq_enabled; /* true == TX interrupt is enabled */ | |
| 60 | +}; | |
| 61 | + | |
| 62 | +/* Array of byte channel objects */ | |
| 63 | +static struct ehv_bc_data *bcs; | |
| 64 | + | |
| 65 | +/* Byte channel handle for stdout (and stdin), taken from device tree */ | |
| 66 | +static unsigned int stdout_bc; | |
| 67 | + | |
| 68 | +/* Virtual IRQ for the byte channel handle for stdin, taken from device tree */ | |
| 69 | +static unsigned int stdout_irq; | |
| 70 | + | |
| 71 | +/**************************** SUPPORT FUNCTIONS ****************************/ | |
| 72 | + | |
| 73 | +/* | |
| 74 | + * Enable the transmit interrupt | |
| 75 | + * | |
| 76 | + * Unlike a serial device, byte channels have no mechanism for disabling their | |
| 77 | + * own receive or transmit interrupts. To emulate that feature, we toggle | |
| 78 | + * the IRQ in the kernel. | |
| 79 | + * | |
| 80 | + * We cannot just blindly call enable_irq() or disable_irq(), because these | |
| 81 | + * calls are reference counted. This means that we cannot call enable_irq() | |
| 82 | + * if interrupts are already enabled. This can happen in two situations: | |
| 83 | + * | |
| 84 | + * 1. The tty layer makes two back-to-back calls to ehv_bc_tty_write() | |
| 85 | + * 2. A transmit interrupt occurs while executing ehv_bc_tx_dequeue() | |
| 86 | + * | |
| 87 | + * To work around this, we keep a flag to tell us if the IRQ is enabled or not. | |
| 88 | + */ | |
| 89 | +static void enable_tx_interrupt(struct ehv_bc_data *bc) | |
| 90 | +{ | |
| 91 | + if (!bc->tx_irq_enabled) { | |
| 92 | + enable_irq(bc->tx_irq); | |
| 93 | + bc->tx_irq_enabled = 1; | |
| 94 | + } | |
| 95 | +} | |
| 96 | + | |
| 97 | +static void disable_tx_interrupt(struct ehv_bc_data *bc) | |
| 98 | +{ | |
| 99 | + if (bc->tx_irq_enabled) { | |
| 100 | + disable_irq_nosync(bc->tx_irq); | |
| 101 | + bc->tx_irq_enabled = 0; | |
| 102 | + } | |
| 103 | +} | |
| 104 | + | |
| 105 | +/* | |
| 106 | + * find the byte channel handle to use for the console | |
| 107 | + * | |
| 108 | + * The byte channel to be used for the console is specified via a "stdout" | |
| 109 | + * property in the /chosen node. | |
| 110 | + * | |
| 111 | + * For compatible with legacy device trees, we also look for a "stdout" alias. | |
| 112 | + */ | |
| 113 | +static int find_console_handle(void) | |
| 114 | +{ | |
| 115 | + struct device_node *np, *np2; | |
| 116 | + const char *sprop = NULL; | |
| 117 | + const uint32_t *iprop; | |
| 118 | + | |
| 119 | + np = of_find_node_by_path("/chosen"); | |
| 120 | + if (np) | |
| 121 | + sprop = of_get_property(np, "stdout-path", NULL); | |
| 122 | + | |
| 123 | + if (!np || !sprop) { | |
| 124 | + of_node_put(np); | |
| 125 | + np = of_find_node_by_name(NULL, "aliases"); | |
| 126 | + if (np) | |
| 127 | + sprop = of_get_property(np, "stdout", NULL); | |
| 128 | + } | |
| 129 | + | |
| 130 | + if (!sprop) { | |
| 131 | + of_node_put(np); | |
| 132 | + return 0; | |
| 133 | + } | |
| 134 | + | |
| 135 | + /* We don't care what the aliased node is actually called. We only | |
| 136 | + * care if it's compatible with "epapr,hv-byte-channel", because that | |
| 137 | + * indicates that it's a byte channel node. We use a temporary | |
| 138 | + * variable, 'np2', because we can't release 'np' until we're done with | |
| 139 | + * 'sprop'. | |
| 140 | + */ | |
| 141 | + np2 = of_find_node_by_path(sprop); | |
| 142 | + of_node_put(np); | |
| 143 | + np = np2; | |
| 144 | + if (!np) { | |
| 145 | + pr_warning("ehv-bc: stdout node '%s' does not exist\n", sprop); | |
| 146 | + return 0; | |
| 147 | + } | |
| 148 | + | |
| 149 | + /* Is it a byte channel? */ | |
| 150 | + if (!of_device_is_compatible(np, "epapr,hv-byte-channel")) { | |
| 151 | + of_node_put(np); | |
| 152 | + return 0; | |
| 153 | + } | |
| 154 | + | |
| 155 | + stdout_irq = irq_of_parse_and_map(np, 0); | |
| 156 | + if (stdout_irq == NO_IRQ) { | |
| 157 | + pr_err("ehv-bc: no 'interrupts' property in %s node\n", sprop); | |
| 158 | + of_node_put(np); | |
| 159 | + return 0; | |
| 160 | + } | |
| 161 | + | |
| 162 | + /* | |
| 163 | + * The 'hv-handle' property contains the handle for this byte channel. | |
| 164 | + */ | |
| 165 | + iprop = of_get_property(np, "hv-handle", NULL); | |
| 166 | + if (!iprop) { | |
| 167 | + pr_err("ehv-bc: no 'hv-handle' property in %s node\n", | |
| 168 | + np->name); | |
| 169 | + of_node_put(np); | |
| 170 | + return 0; | |
| 171 | + } | |
| 172 | + stdout_bc = be32_to_cpu(*iprop); | |
| 173 | + | |
| 174 | + of_node_put(np); | |
| 175 | + return 1; | |
| 176 | +} | |
| 177 | + | |
| 178 | +/*************************** EARLY CONSOLE DRIVER ***************************/ | |
| 179 | + | |
| 180 | +#ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC | |
| 181 | + | |
| 182 | +/* | |
| 183 | + * send a byte to a byte channel, wait if necessary | |
| 184 | + * | |
| 185 | + * This function sends a byte to a byte channel, and it waits and | |
| 186 | + * retries if the byte channel is full. It returns if the character | |
| 187 | + * has been sent, or if some error has occurred. | |
| 188 | + * | |
| 189 | + */ | |
| 190 | +static void byte_channel_spin_send(const char data) | |
| 191 | +{ | |
| 192 | + int ret, count; | |
| 193 | + | |
| 194 | + do { | |
| 195 | + count = 1; | |
| 196 | + ret = ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE, | |
| 197 | + &count, &data); | |
| 198 | + } while (ret == EV_EAGAIN); | |
| 199 | +} | |
| 200 | + | |
| 201 | +/* | |
| 202 | + * The udbg subsystem calls this function to display a single character. | |
| 203 | + * We convert CR to a CR/LF. | |
| 204 | + */ | |
| 205 | +static void ehv_bc_udbg_putc(char c) | |
| 206 | +{ | |
| 207 | + if (c == '\n') | |
| 208 | + byte_channel_spin_send('\r'); | |
| 209 | + | |
| 210 | + byte_channel_spin_send(c); | |
| 211 | +} | |
| 212 | + | |
| 213 | +/* | |
| 214 | + * early console initialization | |
| 215 | + * | |
| 216 | + * PowerPC kernels support an early printk console, also known as udbg. | |
| 217 | + * This function must be called via the ppc_md.init_early function pointer. | |
| 218 | + * At this point, the device tree has been unflattened, so we can obtain the | |
| 219 | + * byte channel handle for stdout. | |
| 220 | + * | |
| 221 | + * We only support displaying of characters (putc). We do not support | |
| 222 | + * keyboard input. | |
| 223 | + */ | |
| 224 | +void __init udbg_init_ehv_bc(void) | |
| 225 | +{ | |
| 226 | + unsigned int rx_count, tx_count; | |
| 227 | + unsigned int ret; | |
| 228 | + | |
| 229 | + /* Verify the byte channel handle */ | |
| 230 | + ret = ev_byte_channel_poll(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE, | |
| 231 | + &rx_count, &tx_count); | |
| 232 | + if (ret) | |
| 233 | + return; | |
| 234 | + | |
| 235 | + udbg_putc = ehv_bc_udbg_putc; | |
| 236 | + register_early_udbg_console(); | |
| 237 | + | |
| 238 | + udbg_printf("ehv-bc: early console using byte channel handle %u\n", | |
| 239 | + CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE); | |
| 240 | +} | |
| 241 | + | |
| 242 | +#endif | |
| 243 | + | |
| 244 | +/****************************** CONSOLE DRIVER ******************************/ | |
| 245 | + | |
| 246 | +static struct tty_driver *ehv_bc_driver; | |
| 247 | + | |
| 248 | +/* | |
| 249 | + * Byte channel console sending worker function. | |
| 250 | + * | |
| 251 | + * For consoles, if the output buffer is full, we should just spin until it | |
| 252 | + * clears. | |
| 253 | + */ | |
| 254 | +static int ehv_bc_console_byte_channel_send(unsigned int handle, const char *s, | |
| 255 | + unsigned int count) | |
| 256 | +{ | |
| 257 | + unsigned int len; | |
| 258 | + int ret = 0; | |
| 259 | + | |
| 260 | + while (count) { | |
| 261 | + len = min_t(unsigned int, count, EV_BYTE_CHANNEL_MAX_BYTES); | |
| 262 | + do { | |
| 263 | + ret = ev_byte_channel_send(handle, &len, s); | |
| 264 | + } while (ret == EV_EAGAIN); | |
| 265 | + count -= len; | |
| 266 | + s += len; | |
| 267 | + } | |
| 268 | + | |
| 269 | + return ret; | |
| 270 | +} | |
| 271 | + | |
| 272 | +/* | |
| 273 | + * write a string to the console | |
| 274 | + * | |
| 275 | + * This function gets called to write a string from the kernel, typically from | |
| 276 | + * a printk(). This function spins until all data is written. | |
| 277 | + * | |
| 278 | + * We copy the data to a temporary buffer because we need to insert a \r in | |
| 279 | + * front of every \n. It's more efficient to copy the data to the buffer than | |
| 280 | + * it is to make multiple hcalls for each character or each newline. | |
| 281 | + */ | |
| 282 | +static void ehv_bc_console_write(struct console *co, const char *s, | |
| 283 | + unsigned int count) | |
| 284 | +{ | |
| 285 | + char s2[EV_BYTE_CHANNEL_MAX_BYTES]; | |
| 286 | + unsigned int i, j = 0; | |
| 287 | + char c; | |
| 288 | + | |
| 289 | + for (i = 0; i < count; i++) { | |
| 290 | + c = *s++; | |
| 291 | + | |
| 292 | + if (c == '\n') | |
| 293 | + s2[j++] = '\r'; | |
| 294 | + | |
| 295 | + s2[j++] = c; | |
| 296 | + if (j >= (EV_BYTE_CHANNEL_MAX_BYTES - 1)) { | |
| 297 | + if (ehv_bc_console_byte_channel_send(stdout_bc, s2, j)) | |
| 298 | + return; | |
| 299 | + j = 0; | |
| 300 | + } | |
| 301 | + } | |
| 302 | + | |
| 303 | + if (j) | |
| 304 | + ehv_bc_console_byte_channel_send(stdout_bc, s2, j); | |
| 305 | +} | |
| 306 | + | |
| 307 | +/* | |
| 308 | + * When /dev/console is opened, the kernel iterates the console list looking | |
| 309 | + * for one with ->device and then calls that method. On success, it expects | |
| 310 | + * the passed-in int* to contain the minor number to use. | |
| 311 | + */ | |
| 312 | +static struct tty_driver *ehv_bc_console_device(struct console *co, int *index) | |
| 313 | +{ | |
| 314 | + *index = co->index; | |
| 315 | + | |
| 316 | + return ehv_bc_driver; | |
| 317 | +} | |
| 318 | + | |
| 319 | +static struct console ehv_bc_console = { | |
| 320 | + .name = "ttyEHV", | |
| 321 | + .write = ehv_bc_console_write, | |
| 322 | + .device = ehv_bc_console_device, | |
| 323 | + .flags = CON_PRINTBUFFER | CON_ENABLED, | |
| 324 | +}; | |
| 325 | + | |
| 326 | +/* | |
| 327 | + * Console initialization | |
| 328 | + * | |
| 329 | + * This is the first function that is called after the device tree is | |
| 330 | + * available, so here is where we determine the byte channel handle and IRQ for | |
| 331 | + * stdout/stdin, even though that information is used by the tty and character | |
| 332 | + * drivers. | |
| 333 | + */ | |
| 334 | +static int __init ehv_bc_console_init(void) | |
| 335 | +{ | |
| 336 | + if (!find_console_handle()) { | |
| 337 | + pr_debug("ehv-bc: stdout is not a byte channel\n"); | |
| 338 | + return -ENODEV; | |
| 339 | + } | |
| 340 | + | |
| 341 | +#ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC | |
| 342 | + /* Print a friendly warning if the user chose the wrong byte channel | |
| 343 | + * handle for udbg. | |
| 344 | + */ | |
| 345 | + if (stdout_bc != CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE) | |
| 346 | + pr_warning("ehv-bc: udbg handle %u is not the stdout handle\n", | |
| 347 | + CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE); | |
| 348 | +#endif | |
| 349 | + | |
| 350 | + /* add_preferred_console() must be called before register_console(), | |
| 351 | + otherwise it won't work. However, we don't want to enumerate all the | |
| 352 | + byte channels here, either, since we only care about one. */ | |
| 353 | + | |
| 354 | + add_preferred_console(ehv_bc_console.name, ehv_bc_console.index, NULL); | |
| 355 | + register_console(&ehv_bc_console); | |
| 356 | + | |
| 357 | + pr_info("ehv-bc: registered console driver for byte channel %u\n", | |
| 358 | + stdout_bc); | |
| 359 | + | |
| 360 | + return 0; | |
| 361 | +} | |
| 362 | +console_initcall(ehv_bc_console_init); | |
| 363 | + | |
| 364 | +/******************************** TTY DRIVER ********************************/ | |
| 365 | + | |
| 366 | +/* | |
| 367 | + * byte channel receive interupt handler | |
| 368 | + * | |
| 369 | + * This ISR is called whenever data is available on a byte channel. | |
| 370 | + */ | |
| 371 | +static irqreturn_t ehv_bc_tty_rx_isr(int irq, void *data) | |
| 372 | +{ | |
| 373 | + struct ehv_bc_data *bc = data; | |
| 374 | + struct tty_struct *ttys = tty_port_tty_get(&bc->port); | |
| 375 | + unsigned int rx_count, tx_count, len; | |
| 376 | + int count; | |
| 377 | + char buffer[EV_BYTE_CHANNEL_MAX_BYTES]; | |
| 378 | + int ret; | |
| 379 | + | |
| 380 | + /* ttys could be NULL during a hangup */ | |
| 381 | + if (!ttys) | |
| 382 | + return IRQ_HANDLED; | |
| 383 | + | |
| 384 | + /* Find out how much data needs to be read, and then ask the TTY layer | |
| 385 | + * if it can handle that much. We want to ensure that every byte we | |
| 386 | + * read from the byte channel will be accepted by the TTY layer. | |
| 387 | + */ | |
| 388 | + ev_byte_channel_poll(bc->handle, &rx_count, &tx_count); | |
| 389 | + count = tty_buffer_request_room(ttys, rx_count); | |
| 390 | + | |
| 391 | + /* 'count' is the maximum amount of data the TTY layer can accept at | |
| 392 | + * this time. However, during testing, I was never able to get 'count' | |
| 393 | + * to be less than 'rx_count'. I'm not sure whether I'm calling it | |
| 394 | + * correctly. | |
| 395 | + */ | |
| 396 | + | |
| 397 | + while (count > 0) { | |
| 398 | + len = min_t(unsigned int, count, sizeof(buffer)); | |
| 399 | + | |
| 400 | + /* Read some data from the byte channel. This function will | |
| 401 | + * never return more than EV_BYTE_CHANNEL_MAX_BYTES bytes. | |
| 402 | + */ | |
| 403 | + ev_byte_channel_receive(bc->handle, &len, buffer); | |
| 404 | + | |
| 405 | + /* 'len' is now the amount of data that's been received. 'len' | |
| 406 | + * can't be zero, and most likely it's equal to one. | |
| 407 | + */ | |
| 408 | + | |
| 409 | + /* Pass the received data to the tty layer. */ | |
| 410 | + ret = tty_insert_flip_string(ttys, buffer, len); | |
| 411 | + | |
| 412 | + /* 'ret' is the number of bytes that the TTY layer accepted. | |
| 413 | + * If it's not equal to 'len', then it means the buffer is | |
| 414 | + * full, which should never happen. If it does happen, we can | |
| 415 | + * exit gracefully, but we drop the last 'len - ret' characters | |
| 416 | + * that we read from the byte channel. | |
| 417 | + */ | |
| 418 | + if (ret != len) | |
| 419 | + break; | |
| 420 | + | |
| 421 | + count -= len; | |
| 422 | + } | |
| 423 | + | |
| 424 | + /* Tell the tty layer that we're done. */ | |
| 425 | + tty_flip_buffer_push(ttys); | |
| 426 | + | |
| 427 | + tty_kref_put(ttys); | |
| 428 | + | |
| 429 | + return IRQ_HANDLED; | |
| 430 | +} | |
| 431 | + | |
| 432 | +/* | |
| 433 | + * dequeue the transmit buffer to the hypervisor | |
| 434 | + * | |
| 435 | + * This function, which can be called in interrupt context, dequeues as much | |
| 436 | + * data as possible from the transmit buffer to the byte channel. | |
| 437 | + */ | |
| 438 | +static void ehv_bc_tx_dequeue(struct ehv_bc_data *bc) | |
| 439 | +{ | |
| 440 | + unsigned int count; | |
| 441 | + unsigned int len, ret; | |
| 442 | + unsigned long flags; | |
| 443 | + | |
| 444 | + do { | |
| 445 | + spin_lock_irqsave(&bc->lock, flags); | |
| 446 | + len = min_t(unsigned int, | |
| 447 | + CIRC_CNT_TO_END(bc->head, bc->tail, BUF_SIZE), | |
| 448 | + EV_BYTE_CHANNEL_MAX_BYTES); | |
| 449 | + | |
| 450 | + ret = ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail); | |
| 451 | + | |
| 452 | + /* 'len' is valid only if the return code is 0 or EV_EAGAIN */ | |
| 453 | + if (!ret || (ret == EV_EAGAIN)) | |
| 454 | + bc->tail = (bc->tail + len) & (BUF_SIZE - 1); | |
| 455 | + | |
| 456 | + count = CIRC_CNT(bc->head, bc->tail, BUF_SIZE); | |
| 457 | + spin_unlock_irqrestore(&bc->lock, flags); | |
| 458 | + } while (count && !ret); | |
| 459 | + | |
| 460 | + spin_lock_irqsave(&bc->lock, flags); | |
| 461 | + if (CIRC_CNT(bc->head, bc->tail, BUF_SIZE)) | |
| 462 | + /* | |
| 463 | + * If we haven't emptied the buffer, then enable the TX IRQ. | |
| 464 | + * We'll get an interrupt when there's more room in the | |
| 465 | + * hypervisor's output buffer. | |
| 466 | + */ | |
| 467 | + enable_tx_interrupt(bc); | |
| 468 | + else | |
| 469 | + disable_tx_interrupt(bc); | |
| 470 | + spin_unlock_irqrestore(&bc->lock, flags); | |
| 471 | +} | |
| 472 | + | |
| 473 | +/* | |
| 474 | + * byte channel transmit interupt handler | |
| 475 | + * | |
| 476 | + * This ISR is called whenever space becomes available for transmitting | |
| 477 | + * characters on a byte channel. | |
| 478 | + */ | |
| 479 | +static irqreturn_t ehv_bc_tty_tx_isr(int irq, void *data) | |
| 480 | +{ | |
| 481 | + struct ehv_bc_data *bc = data; | |
| 482 | + struct tty_struct *ttys = tty_port_tty_get(&bc->port); | |
| 483 | + | |
| 484 | + ehv_bc_tx_dequeue(bc); | |
| 485 | + if (ttys) { | |
| 486 | + tty_wakeup(ttys); | |
| 487 | + tty_kref_put(ttys); | |
| 488 | + } | |
| 489 | + | |
| 490 | + return IRQ_HANDLED; | |
| 491 | +} | |
| 492 | + | |
| 493 | +/* | |
| 494 | + * This function is called when the tty layer has data for us send. We store | |
| 495 | + * the data first in a circular buffer, and then dequeue as much of that data | |
| 496 | + * as possible. | |
| 497 | + * | |
| 498 | + * We don't need to worry about whether there is enough room in the buffer for | |
| 499 | + * all the data. The purpose of ehv_bc_tty_write_room() is to tell the tty | |
| 500 | + * layer how much data it can safely send to us. We guarantee that | |
| 501 | + * ehv_bc_tty_write_room() will never lie, so the tty layer will never send us | |
| 502 | + * too much data. | |
| 503 | + */ | |
| 504 | +static int ehv_bc_tty_write(struct tty_struct *ttys, const unsigned char *s, | |
| 505 | + int count) | |
| 506 | +{ | |
| 507 | + struct ehv_bc_data *bc = ttys->driver_data; | |
| 508 | + unsigned long flags; | |
| 509 | + unsigned int len; | |
| 510 | + unsigned int written = 0; | |
| 511 | + | |
| 512 | + while (1) { | |
| 513 | + spin_lock_irqsave(&bc->lock, flags); | |
| 514 | + len = CIRC_SPACE_TO_END(bc->head, bc->tail, BUF_SIZE); | |
| 515 | + if (count < len) | |
| 516 | + len = count; | |
| 517 | + if (len) { | |
| 518 | + memcpy(bc->buf + bc->head, s, len); | |
| 519 | + bc->head = (bc->head + len) & (BUF_SIZE - 1); | |
| 520 | + } | |
| 521 | + spin_unlock_irqrestore(&bc->lock, flags); | |
| 522 | + if (!len) | |
| 523 | + break; | |
| 524 | + | |
| 525 | + s += len; | |
| 526 | + count -= len; | |
| 527 | + written += len; | |
| 528 | + } | |
| 529 | + | |
| 530 | + ehv_bc_tx_dequeue(bc); | |
| 531 | + | |
| 532 | + return written; | |
| 533 | +} | |
| 534 | + | |
| 535 | +/* | |
| 536 | + * This function can be called multiple times for a given tty_struct, which is | |
| 537 | + * why we initialize bc->ttys in ehv_bc_tty_port_activate() instead. | |
| 538 | + * | |
| 539 | + * The tty layer will still call this function even if the device was not | |
| 540 | + * registered (i.e. tty_register_device() was not called). This happens | |
| 541 | + * because tty_register_device() is optional and some legacy drivers don't | |
| 542 | + * use it. So we need to check for that. | |
| 543 | + */ | |
| 544 | +static int ehv_bc_tty_open(struct tty_struct *ttys, struct file *filp) | |
| 545 | +{ | |
| 546 | + struct ehv_bc_data *bc = &bcs[ttys->index]; | |
| 547 | + | |
| 548 | + if (!bc->dev) | |
| 549 | + return -ENODEV; | |
| 550 | + | |
| 551 | + return tty_port_open(&bc->port, ttys, filp); | |
| 552 | +} | |
| 553 | + | |
| 554 | +/* | |
| 555 | + * Amazingly, if ehv_bc_tty_open() returns an error code, the tty layer will | |
| 556 | + * still call this function to close the tty device. So we can't assume that | |
| 557 | + * the tty port has been initialized. | |
| 558 | + */ | |
| 559 | +static void ehv_bc_tty_close(struct tty_struct *ttys, struct file *filp) | |
| 560 | +{ | |
| 561 | + struct ehv_bc_data *bc = &bcs[ttys->index]; | |
| 562 | + | |
| 563 | + if (bc->dev) | |
| 564 | + tty_port_close(&bc->port, ttys, filp); | |
| 565 | +} | |
| 566 | + | |
| 567 | +/* | |
| 568 | + * Return the amount of space in the output buffer | |
| 569 | + * | |
| 570 | + * This is actually a contract between the driver and the tty layer outlining | |
| 571 | + * how much write room the driver can guarantee will be sent OR BUFFERED. This | |
| 572 | + * driver MUST honor the return value. | |
| 573 | + */ | |
| 574 | +static int ehv_bc_tty_write_room(struct tty_struct *ttys) | |
| 575 | +{ | |
| 576 | + struct ehv_bc_data *bc = ttys->driver_data; | |
| 577 | + unsigned long flags; | |
| 578 | + int count; | |
| 579 | + | |
| 580 | + spin_lock_irqsave(&bc->lock, flags); | |
| 581 | + count = CIRC_SPACE(bc->head, bc->tail, BUF_SIZE); | |
| 582 | + spin_unlock_irqrestore(&bc->lock, flags); | |
| 583 | + | |
| 584 | + return count; | |
| 585 | +} | |
| 586 | + | |
| 587 | +/* | |
| 588 | + * Stop sending data to the tty layer | |
| 589 | + * | |
| 590 | + * This function is called when the tty layer's input buffers are getting full, | |
| 591 | + * so the driver should stop sending it data. The easiest way to do this is to | |
| 592 | + * disable the RX IRQ, which will prevent ehv_bc_tty_rx_isr() from being | |
| 593 | + * called. | |
| 594 | + * | |
| 595 | + * The hypervisor will continue to queue up any incoming data. If there is any | |
| 596 | + * data in the queue when the RX interrupt is enabled, we'll immediately get an | |
| 597 | + * RX interrupt. | |
| 598 | + */ | |
| 599 | +static void ehv_bc_tty_throttle(struct tty_struct *ttys) | |
| 600 | +{ | |
| 601 | + struct ehv_bc_data *bc = ttys->driver_data; | |
| 602 | + | |
| 603 | + disable_irq(bc->rx_irq); | |
| 604 | +} | |
| 605 | + | |
| 606 | +/* | |
| 607 | + * Resume sending data to the tty layer | |
| 608 | + * | |
| 609 | + * This function is called after previously calling ehv_bc_tty_throttle(). The | |
| 610 | + * tty layer's input buffers now have more room, so the driver can resume | |
| 611 | + * sending it data. | |
| 612 | + */ | |
| 613 | +static void ehv_bc_tty_unthrottle(struct tty_struct *ttys) | |
| 614 | +{ | |
| 615 | + struct ehv_bc_data *bc = ttys->driver_data; | |
| 616 | + | |
| 617 | + /* If there is any data in the queue when the RX interrupt is enabled, | |
| 618 | + * we'll immediately get an RX interrupt. | |
| 619 | + */ | |
| 620 | + enable_irq(bc->rx_irq); | |
| 621 | +} | |
| 622 | + | |
| 623 | +static void ehv_bc_tty_hangup(struct tty_struct *ttys) | |
| 624 | +{ | |
| 625 | + struct ehv_bc_data *bc = ttys->driver_data; | |
| 626 | + | |
| 627 | + ehv_bc_tx_dequeue(bc); | |
| 628 | + tty_port_hangup(&bc->port); | |
| 629 | +} | |
| 630 | + | |
| 631 | +/* | |
| 632 | + * TTY driver operations | |
| 633 | + * | |
| 634 | + * If we could ask the hypervisor how much data is still in the TX buffer, or | |
| 635 | + * at least how big the TX buffers are, then we could implement the | |
| 636 | + * .wait_until_sent and .chars_in_buffer functions. | |
| 637 | + */ | |
| 638 | +static const struct tty_operations ehv_bc_ops = { | |
| 639 | + .open = ehv_bc_tty_open, | |
| 640 | + .close = ehv_bc_tty_close, | |
| 641 | + .write = ehv_bc_tty_write, | |
| 642 | + .write_room = ehv_bc_tty_write_room, | |
| 643 | + .throttle = ehv_bc_tty_throttle, | |
| 644 | + .unthrottle = ehv_bc_tty_unthrottle, | |
| 645 | + .hangup = ehv_bc_tty_hangup, | |
| 646 | +}; | |
| 647 | + | |
| 648 | +/* | |
| 649 | + * initialize the TTY port | |
| 650 | + * | |
| 651 | + * This function will only be called once, no matter how many times | |
| 652 | + * ehv_bc_tty_open() is called. That's why we register the ISR here, and also | |
| 653 | + * why we initialize tty_struct-related variables here. | |
| 654 | + */ | |
| 655 | +static int ehv_bc_tty_port_activate(struct tty_port *port, | |
| 656 | + struct tty_struct *ttys) | |
| 657 | +{ | |
| 658 | + struct ehv_bc_data *bc = container_of(port, struct ehv_bc_data, port); | |
| 659 | + int ret; | |
| 660 | + | |
| 661 | + ttys->driver_data = bc; | |
| 662 | + | |
| 663 | + ret = request_irq(bc->rx_irq, ehv_bc_tty_rx_isr, 0, "ehv-bc", bc); | |
| 664 | + if (ret < 0) { | |
| 665 | + dev_err(bc->dev, "could not request rx irq %u (ret=%i)\n", | |
| 666 | + bc->rx_irq, ret); | |
| 667 | + return ret; | |
| 668 | + } | |
| 669 | + | |
| 670 | + /* request_irq also enables the IRQ */ | |
| 671 | + bc->tx_irq_enabled = 1; | |
| 672 | + | |
| 673 | + ret = request_irq(bc->tx_irq, ehv_bc_tty_tx_isr, 0, "ehv-bc", bc); | |
| 674 | + if (ret < 0) { | |
| 675 | + dev_err(bc->dev, "could not request tx irq %u (ret=%i)\n", | |
| 676 | + bc->tx_irq, ret); | |
| 677 | + free_irq(bc->rx_irq, bc); | |
| 678 | + return ret; | |
| 679 | + } | |
| 680 | + | |
| 681 | + /* The TX IRQ is enabled only when we can't write all the data to the | |
| 682 | + * byte channel at once, so by default it's disabled. | |
| 683 | + */ | |
| 684 | + disable_tx_interrupt(bc); | |
| 685 | + | |
| 686 | + return 0; | |
| 687 | +} | |
| 688 | + | |
| 689 | +static void ehv_bc_tty_port_shutdown(struct tty_port *port) | |
| 690 | +{ | |
| 691 | + struct ehv_bc_data *bc = container_of(port, struct ehv_bc_data, port); | |
| 692 | + | |
| 693 | + free_irq(bc->tx_irq, bc); | |
| 694 | + free_irq(bc->rx_irq, bc); | |
| 695 | +} | |
| 696 | + | |
| 697 | +static const struct tty_port_operations ehv_bc_tty_port_ops = { | |
| 698 | + .activate = ehv_bc_tty_port_activate, | |
| 699 | + .shutdown = ehv_bc_tty_port_shutdown, | |
| 700 | +}; | |
| 701 | + | |
| 702 | +static int __devinit ehv_bc_tty_probe(struct platform_device *pdev) | |
| 703 | +{ | |
| 704 | + struct device_node *np = pdev->dev.of_node; | |
| 705 | + struct ehv_bc_data *bc; | |
| 706 | + const uint32_t *iprop; | |
| 707 | + unsigned int handle; | |
| 708 | + int ret; | |
| 709 | + static unsigned int index = 1; | |
| 710 | + unsigned int i; | |
| 711 | + | |
| 712 | + iprop = of_get_property(np, "hv-handle", NULL); | |
| 713 | + if (!iprop) { | |
| 714 | + dev_err(&pdev->dev, "no 'hv-handle' property in %s node\n", | |
| 715 | + np->name); | |
| 716 | + return -ENODEV; | |
| 717 | + } | |
| 718 | + | |
| 719 | + /* We already told the console layer that the index for the console | |
| 720 | + * device is zero, so we need to make sure that we use that index when | |
| 721 | + * we probe the console byte channel node. | |
| 722 | + */ | |
| 723 | + handle = be32_to_cpu(*iprop); | |
| 724 | + i = (handle == stdout_bc) ? 0 : index++; | |
| 725 | + bc = &bcs[i]; | |
| 726 | + | |
| 727 | + bc->handle = handle; | |
| 728 | + bc->head = 0; | |
| 729 | + bc->tail = 0; | |
| 730 | + spin_lock_init(&bc->lock); | |
| 731 | + | |
| 732 | + bc->rx_irq = irq_of_parse_and_map(np, 0); | |
| 733 | + bc->tx_irq = irq_of_parse_and_map(np, 1); | |
| 734 | + if ((bc->rx_irq == NO_IRQ) || (bc->tx_irq == NO_IRQ)) { | |
| 735 | + dev_err(&pdev->dev, "no 'interrupts' property in %s node\n", | |
| 736 | + np->name); | |
| 737 | + ret = -ENODEV; | |
| 738 | + goto error; | |
| 739 | + } | |
| 740 | + | |
| 741 | + bc->dev = tty_register_device(ehv_bc_driver, i, &pdev->dev); | |
| 742 | + if (IS_ERR(bc->dev)) { | |
| 743 | + ret = PTR_ERR(bc->dev); | |
| 744 | + dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret); | |
| 745 | + goto error; | |
| 746 | + } | |
| 747 | + | |
| 748 | + tty_port_init(&bc->port); | |
| 749 | + bc->port.ops = &ehv_bc_tty_port_ops; | |
| 750 | + | |
| 751 | + dev_set_drvdata(&pdev->dev, bc); | |
| 752 | + | |
| 753 | + dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n", | |
| 754 | + ehv_bc_driver->name, i, bc->handle); | |
| 755 | + | |
| 756 | + return 0; | |
| 757 | + | |
| 758 | +error: | |
| 759 | + irq_dispose_mapping(bc->tx_irq); | |
| 760 | + irq_dispose_mapping(bc->rx_irq); | |
| 761 | + | |
| 762 | + memset(bc, 0, sizeof(struct ehv_bc_data)); | |
| 763 | + return ret; | |
| 764 | +} | |
| 765 | + | |
| 766 | +static int ehv_bc_tty_remove(struct platform_device *pdev) | |
| 767 | +{ | |
| 768 | + struct ehv_bc_data *bc = dev_get_drvdata(&pdev->dev); | |
| 769 | + | |
| 770 | + tty_unregister_device(ehv_bc_driver, bc - bcs); | |
| 771 | + | |
| 772 | + irq_dispose_mapping(bc->tx_irq); | |
| 773 | + irq_dispose_mapping(bc->rx_irq); | |
| 774 | + | |
| 775 | + return 0; | |
| 776 | +} | |
| 777 | + | |
| 778 | +static const struct of_device_id ehv_bc_tty_of_ids[] = { | |
| 779 | + { .compatible = "epapr,hv-byte-channel" }, | |
| 780 | + {} | |
| 781 | +}; | |
| 782 | + | |
| 783 | +static struct platform_driver ehv_bc_tty_driver = { | |
| 784 | + .driver = { | |
| 785 | + .owner = THIS_MODULE, | |
| 786 | + .name = "ehv-bc", | |
| 787 | + .of_match_table = ehv_bc_tty_of_ids, | |
| 788 | + }, | |
| 789 | + .probe = ehv_bc_tty_probe, | |
| 790 | + .remove = ehv_bc_tty_remove, | |
| 791 | +}; | |
| 792 | + | |
| 793 | +/** | |
| 794 | + * ehv_bc_init - ePAPR hypervisor byte channel driver initialization | |
| 795 | + * | |
| 796 | + * This function is called when this module is loaded. | |
| 797 | + */ | |
| 798 | +static int __init ehv_bc_init(void) | |
| 799 | +{ | |
| 800 | + struct device_node *np; | |
| 801 | + unsigned int count = 0; /* Number of elements in bcs[] */ | |
| 802 | + int ret; | |
| 803 | + | |
| 804 | + pr_info("ePAPR hypervisor byte channel driver\n"); | |
| 805 | + | |
| 806 | + /* Count the number of byte channels */ | |
| 807 | + for_each_compatible_node(np, NULL, "epapr,hv-byte-channel") | |
| 808 | + count++; | |
| 809 | + | |
| 810 | + if (!count) | |
| 811 | + return -ENODEV; | |
| 812 | + | |
| 813 | + /* The array index of an element in bcs[] is the same as the tty index | |
| 814 | + * for that element. If you know the address of an element in the | |
| 815 | + * array, then you can use pointer math (e.g. "bc - bcs") to get its | |
| 816 | + * tty index. | |
| 817 | + */ | |
| 818 | + bcs = kzalloc(count * sizeof(struct ehv_bc_data), GFP_KERNEL); | |
| 819 | + if (!bcs) | |
| 820 | + return -ENOMEM; | |
| 821 | + | |
| 822 | + ehv_bc_driver = alloc_tty_driver(count); | |
| 823 | + if (!ehv_bc_driver) { | |
| 824 | + ret = -ENOMEM; | |
| 825 | + goto error; | |
| 826 | + } | |
| 827 | + | |
| 828 | + ehv_bc_driver->owner = THIS_MODULE; | |
| 829 | + ehv_bc_driver->driver_name = "ehv-bc"; | |
| 830 | + ehv_bc_driver->name = ehv_bc_console.name; | |
| 831 | + ehv_bc_driver->type = TTY_DRIVER_TYPE_CONSOLE; | |
| 832 | + ehv_bc_driver->subtype = SYSTEM_TYPE_CONSOLE; | |
| 833 | + ehv_bc_driver->init_termios = tty_std_termios; | |
| 834 | + ehv_bc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | |
| 835 | + tty_set_operations(ehv_bc_driver, &ehv_bc_ops); | |
| 836 | + | |
| 837 | + ret = tty_register_driver(ehv_bc_driver); | |
| 838 | + if (ret) { | |
| 839 | + pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret); | |
| 840 | + goto error; | |
| 841 | + } | |
| 842 | + | |
| 843 | + ret = platform_driver_register(&ehv_bc_tty_driver); | |
| 844 | + if (ret) { | |
| 845 | + pr_err("ehv-bc: could not register platform driver (ret=%i)\n", | |
| 846 | + ret); | |
| 847 | + goto error; | |
| 848 | + } | |
| 849 | + | |
| 850 | + return 0; | |
| 851 | + | |
| 852 | +error: | |
| 853 | + if (ehv_bc_driver) { | |
| 854 | + tty_unregister_driver(ehv_bc_driver); | |
| 855 | + put_tty_driver(ehv_bc_driver); | |
| 856 | + } | |
| 857 | + | |
| 858 | + kfree(bcs); | |
| 859 | + | |
| 860 | + return ret; | |
| 861 | +} | |
| 862 | + | |
| 863 | + | |
| 864 | +/** | |
| 865 | + * ehv_bc_exit - ePAPR hypervisor byte channel driver termination | |
| 866 | + * | |
| 867 | + * This function is called when this driver is unloaded. | |
| 868 | + */ | |
| 869 | +static void __exit ehv_bc_exit(void) | |
| 870 | +{ | |
| 871 | + tty_unregister_driver(ehv_bc_driver); | |
| 872 | + put_tty_driver(ehv_bc_driver); | |
| 873 | + kfree(bcs); | |
| 874 | +} | |
| 875 | + | |
| 876 | +module_init(ehv_bc_init); | |
| 877 | +module_exit(ehv_bc_exit); | |
| 878 | + | |
| 879 | +MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | |
| 880 | +MODULE_DESCRIPTION("ePAPR hypervisor byte channel driver"); | |
| 881 | +MODULE_LICENSE("GPL v2"); | |
| @@ -388,7 +388,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) · 387 unmodified lines | ||
| 388 | 388 | * there is no buffered data otherwise sleeps on a wait queue |
| 389 | 389 | * waking periodically to check chars_in_buffer(). |
| 390 | 390 | */ |
| 391 | − tty_wait_until_sent(tty, HVC_CLOSE_WAIT); | |
| 391 | + tty_wait_until_sent_from_close(tty, HVC_CLOSE_WAIT); | |
| 392 | 392 | } else { |
| 393 | 393 | if (hp->count < 0) |
| 394 | 394 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", |
| @@ -852,7 +852,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, · 457 unmodified lines | ||
| 852 | 852 | * find index to use: |
| 853 | 853 | * see if this vterm id matches one registered for console. |
| 854 | 854 | */ |
| 855 | − for (i=0; i < MAX_NR_HVC_CONSOLES; i++) | |
| 855 | + for (i = 0; i < MAX_NR_HVC_CONSOLES; i++) | |
| 856 | 856 | if (vtermnos[i] == hp->vtermno && |
| 857 | 857 | cons_ops[i] == hp->ops) |
| 858 | 858 | break; |
| @@ -862,9 +862,13 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, · 3 unmodified lines | ||
| 862 | 862 | i = ++last_hvc; |
| 863 | 863 | |
| 864 | 864 | hp->index = i; |
| 865 | + hvc_console.index = i; | |
| 866 | + vtermnos[i] = vtermno; | |
| 867 | + cons_ops[i] = ops; | |
| 865 | 868 | |
| 866 | 869 | list_add_tail(&(hp->next), &hvc_structs); |
| 867 | 870 | spin_unlock(&hvc_structs_lock); |
| 871 | + register_console(&hvc_console); | |
| 868 | 872 | |
| 869 | 873 | return hp; |
| 870 | 874 | } |
| @@ -875,6 +879,7 @@ int hvc_remove(struct hvc_struct *hp) · 4 unmodified lines | ||
| 875 | 879 | unsigned long flags; |
| 876 | 880 | struct tty_struct *tty; |
| 877 | 881 | |
| 882 | + unregister_console(&hvc_console); | |
| 878 | 883 | spin_lock_irqsave(&hp->lock, flags); |
| 879 | 884 | tty = tty_kref_get(hp->tty); |
| 880 | 885 | |
| @@ -28,7 +28,7 @@ int notifier_add_irq(struct hvc_struct *hp, int irq) · 27 unmodified lines | ||
| 28 | 28 | hp->irq_requested = 0; |
| 29 | 29 | return 0; |
| 30 | 30 | } |
| 31 | − rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, | |
| 31 | + rc = request_irq(irq, hvc_handle_interrupt, 0, | |
| 32 | 32 | "hvc_console", hp); |
| 33 | 33 | if (!rc) |
| 34 | 34 | hp->irq_requested = 1; |
| @@ -1057,7 +1057,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, · 1056 unmodified lines | ||
| 1057 | 1057 | * the conn was registered and now. |
| 1058 | 1058 | */ |
| 1059 | 1059 | if (!(rc = request_irq(irq, &hvcs_handle_interrupt, |
| 1060 | − IRQF_DISABLED, "ibmhvcs", hvcsd))) { | |
| 1060 | + 0, "ibmhvcs", hvcsd))) { | |
| 1061 | 1061 | /* |
| 1062 | 1062 | * It is possible the vty-server was removed after the irq was |
| 1063 | 1063 | * requested but before we have time to enable interrupts. |
| @@ -1237,7 +1237,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) · 173 unmodified lines | ||
| 1237 | 1237 | irq = hvcsd->vdev->irq; |
| 1238 | 1238 | spin_unlock_irqrestore(&hvcsd->lock, flags); |
| 1239 | 1239 | |
| 1240 | − tty_wait_until_sent(tty, HVCS_CLOSE_WAIT); | |
| 1240 | + tty_wait_until_sent_from_close(tty, HVCS_CLOSE_WAIT); | |
| 1241 | 1241 | |
| 1242 | 1242 | /* |
| 1243 | 1243 | * This line is important because it tells hvcs_open that this |
| @@ -1105,7 +1105,7 @@ static int __init hvsi_init(void) · 1104 unmodified lines | ||
| 1105 | 1105 | struct hvsi_struct *hp = &hvsi_ports[i]; |
| 1106 | 1106 | int ret = 1; |
| 1107 | 1107 | |
| 1108 | − ret = request_irq(hp->virq, hvsi_interrupt, IRQF_DISABLED, "hvsi", hp); | |
| 1108 | + ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp); | |
| 1109 | 1109 | if (ret) |
| 1110 | 1110 | printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n", |
| 1111 | 1111 | hp->virq, ret); |
| @@ -1598,7 +1598,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, · 1597 unmodified lines | ||
| 1598 | 1598 | } |
| 1599 | 1599 | |
| 1600 | 1600 | retval = request_irq(board->irq, isicom_interrupt, |
| 1601 | − IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board); | |
| 1601 | + IRQF_SHARED, ISICOM_NAME, board); | |
| 1602 | 1602 | if (retval < 0) { |
| 1603 | 1603 | dev_err(&pdev->dev, "Could not install handler at Irq %d. " |
| 1604 | 1604 | "Card%d will be disabled.\n", board->irq, index + 1); |
| @@ -2005,16 +2005,9 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) · 2004 unmodified lines | ||
| 2005 | 2005 | */ |
| 2006 | 2006 | if (!timeout || timeout > 2 * info->timeout) |
| 2007 | 2007 | timeout = 2 * info->timeout; |
| 2008 | −#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | |
| 2009 | − printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", | |
| 2010 | − timeout, char_time); | |
| 2011 | − printk("jiff=%lu...", jiffies); | |
| 2012 | −#endif | |
| 2008 | + | |
| 2013 | 2009 | spin_lock_irqsave(&info->slock, flags); |
| 2014 | 2010 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { |
| 2015 | −#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | |
| 2016 | − printk("lsr = %d (jiff=%lu)...", lsr, jiffies); | |
| 2017 | −#endif | |
| 2018 | 2011 | spin_unlock_irqrestore(&info->slock, flags); |
| 2019 | 2012 | schedule_timeout_interruptible(char_time); |
| 2020 | 2013 | spin_lock_irqsave(&info->slock, flags); |
| @@ -2025,10 +2018,6 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) · 4 unmodified lines | ||
| 2025 | 2018 | } |
| 2026 | 2019 | spin_unlock_irqrestore(&info->slock, flags); |
| 2027 | 2020 | set_current_state(TASK_RUNNING); |
| 2028 | − | |
| 2029 | −#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | |
| 2030 | − printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | |
| 2031 | −#endif | |
| 2032 | 2021 | } |
| 2033 | 2022 | |
| 2034 | 2023 | /* |
| @@ -21,7 +21,6 @@ · 20 unmodified lines | ||
| 21 | 21 | * Mostly done: ioctls for setting modes/timing |
| 22 | 22 | * Partly done: hooks so you can pull off frames to non tty devs |
| 23 | 23 | * Restart DLCI 0 when it closes ? |
| 24 | − * Test basic encoding | |
| 25 | 24 | * Improve the tx engine |
| 26 | 25 | * Resolve tx side locking by adding a queue_head and routing |
| 27 | 26 | * all control traffic via it |
| @@ -810,38 +809,41 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) · 782 unmodified lines | ||
| 810 | 809 | { |
| 811 | 810 | struct gsm_msg *msg; |
| 812 | 811 | u8 *dp; |
| 813 | − int len, size; | |
| 812 | + int len, total_size, size; | |
| 814 | 813 | int h = dlci->adaption - 1; |
| 815 | 814 | |
| 816 | − len = kfifo_len(dlci->fifo); | |
| 817 | − if (len == 0) | |
| 818 | − return 0; | |
| 819 | − | |
| 820 | − /* MTU/MRU count only the data bits */ | |
| 821 | − if (len > gsm->mtu) | |
| 822 | − len = gsm->mtu; | |
| 823 | − | |
| 824 | − size = len + h; | |
| 825 | − | |
| 826 | − msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); | |
| 827 | − /* FIXME: need a timer or something to kick this so it can't | |
| 828 | − get stuck with no work outstanding and no buffer free */ | |
| 829 | − if (msg == NULL) | |
| 830 | − return -ENOMEM; | |
| 831 | − dp = msg->data; | |
| 832 | − switch (dlci->adaption) { | |
| 833 | − case 1: /* Unstructured */ | |
| 834 | − break; | |
| 835 | − case 2: /* Unstructed with modem bits. Always one byte as we never | |
| 836 | − send inline break data */ | |
| 837 | − *dp += gsm_encode_modem(dlci); | |
| 838 | − len--; | |
| 839 | − break; | |
| 815 | + total_size = 0; | |
| 816 | + while(1) { | |
| 817 | + len = kfifo_len(dlci->fifo); | |
| 818 | + if (len == 0) | |
| 819 | + return total_size; | |
| 820 | + | |
| 821 | + /* MTU/MRU count only the data bits */ | |
| 822 | + if (len > gsm->mtu) | |
| 823 | + len = gsm->mtu; | |
| 824 | + | |
| 825 | + size = len + h; | |
| 826 | + | |
| 827 | + msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); | |
| 828 | + /* FIXME: need a timer or something to kick this so it can't | |
| 829 | + get stuck with no work outstanding and no buffer free */ | |
| 830 | + if (msg == NULL) | |
| 831 | + return -ENOMEM; | |
| 832 | + dp = msg->data; | |
| 833 | + switch (dlci->adaption) { | |
| 834 | + case 1: /* Unstructured */ | |
| 835 | + break; | |
| 836 | + case 2: /* Unstructed with modem bits. Always one byte as we never | |
| 837 | + send inline break data */ | |
| 838 | + *dp++ = gsm_encode_modem(dlci); | |
| 839 | + break; | |
| 840 | + } | |
| 841 | + WARN_ON(kfifo_out_locked(dlci->fifo, dp , len, &dlci->lock) != len); | |
| 842 | + __gsm_data_queue(dlci, msg); | |
| 843 | + total_size += size; | |
| 840 | 844 | } |
| 841 | − WARN_ON(kfifo_out_locked(dlci->fifo, dp , len, &dlci->lock) != len); | |
| 842 | − __gsm_data_queue(dlci, msg); | |
| 843 | 845 | /* Bytes of data we used up */ |
| 844 | − return size; | |
| 846 | + return total_size; | |
| 845 | 847 | } |
| 846 | 848 | |
| 847 | 849 | /** |
| @@ -2004,6 +2006,7 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) · 1156 unmodified lines | ||
| 2004 | 2006 | int i; |
| 2005 | 2007 | struct gsm_dlci *dlci = gsm->dlci[0]; |
| 2006 | 2008 | struct gsm_msg *txq; |
| 2009 | + struct gsm_control *gc; | |
| 2007 | 2010 | |
| 2008 | 2011 | gsm->dead = 1; |
| 2009 | 2012 | |
| @@ -2017,6 +2020,13 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) · 7 unmodified lines | ||
| 2017 | 2020 | spin_unlock(&gsm_mux_lock); |
| 2018 | 2021 | WARN_ON(i == MAX_MUX); |
| 2019 | 2022 | |
| 2023 | + /* In theory disconnecting DLCI 0 is sufficient but for some | |
| 2024 | + modems this is apparently not the case. */ | |
| 2025 | + if (dlci) { | |
| 2026 | + gc = gsm_control_send(gsm, CMD_CLD, NULL, 0); | |
| 2027 | + if (gc) | |
| 2028 | + gsm_control_wait(gsm, gc); | |
| 2029 | + } | |
| 2020 | 2030 | del_timer_sync(&gsm->t2_timer); |
| 2021 | 2031 | /* Now we are sure T2 has stopped */ |
| 2022 | 2032 | if (dlci) { |
| @@ -2982,7 +2992,7 @@ static int gsmtty_tiocmset(struct tty_struct *tty, · 959 unmodified lines | ||
| 2982 | 2992 | struct gsm_dlci *dlci = tty->driver_data; |
| 2983 | 2993 | unsigned int modem_tx = dlci->modem_tx; |
| 2984 | 2994 | |
| 2985 | − modem_tx &= clear; | |
| 2995 | + modem_tx &= ~clear; | |
| 2986 | 2996 | modem_tx |= set; |
| 2987 | 2997 | |
| 2988 | 2998 | if (modem_tx != dlci->modem_tx) { |
| @@ -670,12 +670,18 @@ static int ptmx_open(struct inode *inode, struct file *filp) · 669 unmodified lines | ||
| 670 | 670 | |
| 671 | 671 | nonseekable_open(inode, filp); |
| 672 | 672 | |
| 673 | + retval = tty_alloc_file(filp); | |
| 674 | + if (retval) | |
| 675 | + return retval; | |
| 676 | + | |
| 673 | 677 | /* find a device that is not in use. */ |
| 674 | 678 | tty_lock(); |
| 675 | 679 | index = devpts_new_index(inode); |
| 676 | 680 | tty_unlock(); |
| 677 | − if (index < 0) | |
| 678 | − return index; | |
| 681 | + if (index < 0) { | |
| 682 | + retval = index; | |
| 683 | + goto err_file; | |
| 684 | + } | |
| 679 | 685 | |
| 680 | 686 | mutex_lock(&tty_mutex); |
| 681 | 687 | tty_lock(); |
| @@ -689,27 +695,27 @@ static int ptmx_open(struct inode *inode, struct file *filp) · 7 unmodified lines | ||
| 689 | 695 | |
| 690 | 696 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
| 691 | 697 | |
| 692 | − retval = tty_add_file(tty, filp); | |
| 693 | − if (retval) | |
| 694 | − goto out; | |
| 698 | + tty_add_file(tty, filp); | |
| 695 | 699 | |
| 696 | 700 | retval = devpts_pty_new(inode, tty->link); |
| 697 | 701 | if (retval) |
| 698 | − goto out1; | |
| 702 | + goto err_release; | |
| 699 | 703 | |
| 700 | 704 | retval = ptm_driver->ops->open(tty, filp); |
| 701 | 705 | if (retval) |
| 702 | − goto out2; | |
| 703 | −out1: | |
| 706 | + goto err_release; | |
| 707 | + | |
| 704 | 708 | tty_unlock(); |
| 705 | − return retval; | |
| 706 | −out2: | |
| 709 | + return 0; | |
| 710 | +err_release: | |
| 707 | 711 | tty_unlock(); |
| 708 | 712 | tty_release(inode, filp); |
| 709 | 713 | return retval; |
| 710 | 714 | out: |
| 711 | 715 | devpts_kill_index(inode, index); |
| 712 | 716 | tty_unlock(); |
| 717 | +err_file: | |
| 718 | + tty_free_file(filp); | |
| 713 | 719 | return retval; |
| 714 | 720 | } |
| 715 | 721 | |
| @@ -235,22 +235,6 @@ static void batten_down_hatches(void) · 234 unmodified lines | ||
| 235 | 235 | |
| 236 | 236 | static void status_handle(struct m68k_serial *info, unsigned short status) |
| 237 | 237 | { |
| 238 | −#if 0 | |
| 239 | − if(status & DCD) { | |
| 240 | − if((info->port.tty->termios->c_cflag & CRTSCTS) && | |
| 241 | − ((info->curregs[3] & AUTO_ENAB)==0)) { | |
| 242 | − info->curregs[3] |= AUTO_ENAB; | |
| 243 | − info->pendregs[3] |= AUTO_ENAB; | |
| 244 | − write_zsreg(info->m68k_channel, 3, info->curregs[3]); | |
| 245 | − } | |
| 246 | − } else { | |
| 247 | − if((info->curregs[3] & AUTO_ENAB)) { | |
| 248 | − info->curregs[3] &= ~AUTO_ENAB; | |
| 249 | − info->pendregs[3] &= ~AUTO_ENAB; | |
| 250 | − write_zsreg(info->m68k_channel, 3, info->curregs[3]); | |
| 251 | − } | |
| 252 | − } | |
| 253 | −#endif | |
| 254 | 238 | /* If this is console input and this is a |
| 255 | 239 | * 'break asserted' status change interrupt |
| 256 | 240 | * see if we can drop into the debugger |
| @@ -340,9 +324,6 @@ static void transmit_chars(struct m68k_serial *info) · 83 unmodified lines | ||
| 340 | 324 | info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); |
| 341 | 325 | info->xmit_cnt--; |
| 342 | 326 | |
| 343 | − if (info->xmit_cnt < WAKEUP_CHARS) | |
| 344 | − schedule_work(&info->tqueue); | |
| 345 | − | |
| 346 | 327 | if(info->xmit_cnt <= 0) { |
| 347 | 328 | /* All done for now... TX ints off */ |
| 348 | 329 | uart->ustcnt &= ~USTCNT_TX_INTR_MASK; |
| @@ -378,21 +359,6 @@ irqreturn_t rs_interrupt(int irq, void *dev_id) · 29 unmodified lines | ||
| 378 | 359 | return IRQ_HANDLED; |
| 379 | 360 | } |
| 380 | 361 | |
| 381 | −static void do_softint(struct work_struct *work) | |
| 382 | −{ | |
| 383 | − struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue); | |
| 384 | − struct tty_struct *tty; | |
| 385 | − | |
| 386 | − tty = info->tty; | |
| 387 | − if (!tty) | |
| 388 | − return; | |
| 389 | −#if 0 | |
| 390 | − if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { | |
| 391 | − tty_wakeup(tty); | |
| 392 | − } | |
| 393 | −#endif | |
| 394 | −} | |
| 395 | − | |
| 396 | 362 | static int startup(struct m68k_serial * info) |
| 397 | 363 | { |
| 398 | 364 | m68328_uart *uart = &uart_addr[info->line]; |
| @@ -1324,7 +1290,6 @@ rs68328_init(void) · 925 unmodified lines | ||
| 1324 | 1290 | info->event = 0; |
| 1325 | 1291 | info->count = 0; |
| 1326 | 1292 | info->blocked_open = 0; |
| 1327 | − INIT_WORK(&info->tqueue, do_softint); | |
| 1328 | 1293 | init_waitqueue_head(&info->open_wait); |
| 1329 | 1294 | init_waitqueue_head(&info->close_wait); |
| 1330 | 1295 | info->line = i; |
| @@ -1341,7 +1306,7 @@ rs68328_init(void) · 10 unmodified lines | ||
| 1341 | 1306 | |
| 1342 | 1307 | if (request_irq(uart_irqs[i], |
| 1343 | 1308 | rs_interrupt, |
| 1344 | − IRQF_DISABLED, | |
| 1309 | + 0, | |
| 1345 | 1310 | "M68328_UART", info)) |
| 1346 | 1311 | panic("Unable to attach 68328 serial interrupt\n"); |
| 1347 | 1312 | } |
| @@ -158,7 +158,6 @@ struct m68k_serial { · 157 unmodified lines | ||
| 158 | 158 | int xmit_head; |
| 159 | 159 | int xmit_tail; |
| 160 | 160 | int xmit_cnt; |
| 161 | − struct work_struct tqueue; | |
| 162 | 161 | wait_queue_head_t open_wait; |
| 163 | 162 | wait_queue_head_t close_wait; |
| 164 | 163 | }; |
| @@ -309,6 +309,13 @@ static const struct serial8250_config uart_config[] = { · 308 unmodified lines | ||
| 309 | 309 | UART_FCR_T_TRIG_01, |
| 310 | 310 | .flags = UART_CAP_FIFO | UART_CAP_RTOIE, |
| 311 | 311 | }, |
| 312 | + [PORT_XR17D15X] = { | |
| 313 | + .name = "XR17D15X", | |
| 314 | + .fifo_size = 64, | |
| 315 | + .tx_loadsz = 64, | |
| 316 | + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | |
| 317 | + .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, | |
| 318 | + }, | |
| 312 | 319 | }; |
| 313 | 320 | |
| 314 | 321 | #if defined(CONFIG_MIPS_ALCHEMY) |
| @@ -461,42 +468,6 @@ static void tsi_serial_out(struct uart_port *p, int offset, int value) · 146 unmodified lines | ||
| 461 | 468 | writeb(value, p->membase + offset); |
| 462 | 469 | } |
| 463 | 470 | |
| 464 | −/* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */ | |
| 465 | −static inline void dwapb_save_out_value(struct uart_port *p, int offset, | |
| 466 | − int value) | |
| 467 | −{ | |
| 468 | − struct uart_8250_port *up = | |
| 469 | − container_of(p, struct uart_8250_port, port); | |
| 470 | − | |
| 471 | − if (offset == UART_LCR) | |
| 472 | − up->lcr = value; | |
| 473 | −} | |
| 474 | − | |
| 475 | −/* Read the IER to ensure any interrupt is cleared before returning from ISR. */ | |
| 476 | −static inline void dwapb_check_clear_ier(struct uart_port *p, int offset) | |
| 477 | −{ | |
| 478 | − if (offset == UART_TX || offset == UART_IER) | |
| 479 | − p->serial_in(p, UART_IER); | |
| 480 | −} | |
| 481 | − | |
| 482 | −static void dwapb_serial_out(struct uart_port *p, int offset, int value) | |
| 483 | −{ | |
| 484 | − int save_offset = offset; | |
| 485 | − offset = map_8250_out_reg(p, offset) << p->regshift; | |
| 486 | − dwapb_save_out_value(p, save_offset, value); | |
| 487 | − writeb(value, p->membase + offset); | |
| 488 | − dwapb_check_clear_ier(p, save_offset); | |
| 489 | −} | |
| 490 | − | |
| 491 | −static void dwapb32_serial_out(struct uart_port *p, int offset, int value) | |
| 492 | −{ | |
| 493 | − int save_offset = offset; | |
| 494 | − offset = map_8250_out_reg(p, offset) << p->regshift; | |
| 495 | − dwapb_save_out_value(p, save_offset, value); | |
| 496 | − writel(value, p->membase + offset); | |
| 497 | − dwapb_check_clear_ier(p, save_offset); | |
| 498 | −} | |
| 499 | − | |
| 500 | 471 | static unsigned int io_serial_in(struct uart_port *p, int offset) |
| 501 | 472 | { |
| 502 | 473 | offset = map_8250_in_reg(p, offset) << p->regshift; |
| @@ -509,6 +480,8 @@ static void io_serial_out(struct uart_port *p, int offset, int value) · 6 unmodified lines | ||
| 509 | 480 | outb(value, p->iobase + offset); |
| 510 | 481 | } |
| 511 | 482 | |
| 483 | +static int serial8250_default_handle_irq(struct uart_port *port); | |
| 484 | + | |
| 512 | 485 | static void set_io_from_upio(struct uart_port *p) |
| 513 | 486 | { |
| 514 | 487 | struct uart_8250_port *up = |
| @@ -540,16 +513,6 @@ static void set_io_from_upio(struct uart_port *p) · 25 unmodified lines | ||
| 540 | 513 | p->serial_out = tsi_serial_out; |
| 541 | 514 | break; |
| 542 | 515 | |
| 543 | − case UPIO_DWAPB: | |
| 544 | − p->serial_in = mem_serial_in; | |
| 545 | − p->serial_out = dwapb_serial_out; | |
| 546 | − break; | |
| 547 | − | |
| 548 | − case UPIO_DWAPB32: | |
| 549 | − p->serial_in = mem32_serial_in; | |
| 550 | − p->serial_out = dwapb32_serial_out; | |
| 551 | − break; | |
| 552 | − | |
| 553 | 516 | default: |
| 554 | 517 | p->serial_in = io_serial_in; |
| 555 | 518 | p->serial_out = io_serial_out; |
| @@ -557,6 +520,7 @@ static void set_io_from_upio(struct uart_port *p) · 1 unmodified line | ||
| 557 | 520 | } |
| 558 | 521 | /* Remember loaded iotype */ |
| 559 | 522 | up->cur_iotype = p->iotype; |
| 523 | + p->handle_irq = serial8250_default_handle_irq; | |
| 560 | 524 | } |
| 561 | 525 | |
| 562 | 526 | static void |
| @@ -567,8 +531,6 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value) · 4 unmodified lines | ||
| 567 | 531 | case UPIO_MEM: |
| 568 | 532 | case UPIO_MEM32: |
| 569 | 533 | case UPIO_AU: |
| 570 | − case UPIO_DWAPB: | |
| 571 | − case UPIO_DWAPB32: | |
| 572 | 534 | p->serial_out(p, offset, value); |
| 573 | 535 | p->serial_in(p, UART_LCR); /* safe, no side-effects */ |
| 574 | 536 | break; |
| @@ -1119,6 +1081,14 @@ static void autoconfig_16550a(struct uart_8250_port *up) · 544 unmodified lines | ||
| 1119 | 1081 | } |
| 1120 | 1082 | serial_outp(up, UART_IER, iersave); |
| 1121 | 1083 | |
| 1084 | + /* | |
| 1085 | + * Exar uarts have EFR in a weird location | |
| 1086 | + */ | |
| 1087 | + if (up->port.flags & UPF_EXAR_EFR) { | |
| 1088 | + up->port.type = PORT_XR17D15X; | |
| 1089 | + up->capabilities |= UART_CAP_AFE | UART_CAP_EFR; | |
| 1090 | + } | |
| 1091 | + | |
| 1122 | 1092 | /* |
| 1123 | 1093 | * We distinguish between 16550A and U6 16550A by counting |
| 1124 | 1094 | * how many bytes are in the FIFO. |
| @@ -1621,6 +1591,29 @@ static void serial8250_handle_port(struct uart_8250_port *up) · 496 unmodified lines | ||
| 1621 | 1591 | spin_unlock_irqrestore(&up->port.lock, flags); |
| 1622 | 1592 | } |
| 1623 | 1593 | |
| 1594 | +int serial8250_handle_irq(struct uart_port *port, unsigned int iir) | |
| 1595 | +{ | |
| 1596 | + struct uart_8250_port *up = | |
| 1597 | + container_of(port, struct uart_8250_port, port); | |
| 1598 | + | |
| 1599 | + if (!(iir & UART_IIR_NO_INT)) { | |
| 1600 | + serial8250_handle_port(up); | |
| 1601 | + return 1; | |
| 1602 | + } | |
| 1603 | + | |
| 1604 | + return 0; | |
| 1605 | +} | |
| 1606 | +EXPORT_SYMBOL_GPL(serial8250_handle_irq); | |
| 1607 | + | |
| 1608 | +static int serial8250_default_handle_irq(struct uart_port *port) | |
| 1609 | +{ | |
| 1610 | + struct uart_8250_port *up = | |
| 1611 | + container_of(port, struct uart_8250_port, port); | |
| 1612 | + unsigned int iir = serial_in(up, UART_IIR); | |
| 1613 | + | |
| 1614 | + return serial8250_handle_irq(port, iir); | |
| 1615 | +} | |
| 1616 | + | |
| 1624 | 1617 | /* |
| 1625 | 1618 | * This is the serial driver's interrupt routine. |
| 1626 | 1619 | * |
| @@ -1648,30 +1641,13 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) · 21 unmodified lines | ||
| 1648 | 1641 | l = i->head; |
| 1649 | 1642 | do { |
| 1650 | 1643 | struct uart_8250_port *up; |
| 1651 | − unsigned int iir; | |
| 1644 | + struct uart_port *port; | |
| 1652 | 1645 | |
| 1653 | 1646 | up = list_entry(l, struct uart_8250_port, list); |
| 1647 | + port = &up->port; | |
| 1654 | 1648 | |
| 1655 | − iir = serial_in(up, UART_IIR); | |
| 1656 | − if (!(iir & UART_IIR_NO_INT)) { | |
| 1657 | − serial8250_handle_port(up); | |
| 1658 | − | |
| 1649 | + if (port->handle_irq(port)) { | |
| 1659 | 1650 | handled = 1; |
| 1660 | − | |
| 1661 | − end = NULL; | |
| 1662 | − } else if ((up->port.iotype == UPIO_DWAPB || | |
| 1663 | − up->port.iotype == UPIO_DWAPB32) && | |
| 1664 | − (iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | |
| 1665 | − /* The DesignWare APB UART has an Busy Detect (0x07) | |
| 1666 | − * interrupt meaning an LCR write attempt occurred while the | |
| 1667 | − * UART was busy. The interrupt must be cleared by reading | |
| 1668 | − * the UART status register (USR) and the LCR re-written. */ | |
| 1669 | − unsigned int status; | |
| 1670 | − status = *(volatile u32 *)up->port.private_data; | |
| 1671 | − serial_out(up, UART_LCR, up->lcr); | |
| 1672 | − | |
| 1673 | − handled = 1; | |
| 1674 | − | |
| 1675 | 1651 | end = NULL; |
| 1676 | 1652 | } else if (end == NULL) |
| 1677 | 1653 | end = l; |
| @@ -2081,8 +2057,8 @@ static int serial8250_startup(struct uart_port *port) · 403 unmodified lines | ||
| 2081 | 2057 | */ |
| 2082 | 2058 | if (!(up->port.flags & UPF_BUGGY_UART) && |
| 2083 | 2059 | (serial_inp(up, UART_LSR) == 0xff)) { |
| 2084 | − printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n", | |
| 2085 | − serial_index(&up->port)); | |
| 2060 | + printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n", | |
| 2061 | + serial_index(&up->port)); | |
| 2086 | 2062 | return -ENODEV; |
| 2087 | 2063 | } |
| 2088 | 2064 | |
| @@ -2458,7 +2434,10 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, · 369 unmodified lines | ||
| 2458 | 2434 | efr |= UART_EFR_CTS; |
| 2459 | 2435 | |
| 2460 | 2436 | serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| 2461 | − serial_outp(up, UART_EFR, efr); | |
| 2437 | + if (up->port.flags & UPF_EXAR_EFR) | |
| 2438 | + serial_outp(up, UART_XR_EFR, efr); | |
| 2439 | + else | |
| 2440 | + serial_outp(up, UART_EFR, efr); | |
| 2462 | 2441 | } |
| 2463 | 2442 | |
| 2464 | 2443 | #ifdef CONFIG_ARCH_OMAP |
| @@ -2570,8 +2549,6 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) · 105 unmodified lines | ||
| 2570 | 2549 | case UPIO_TSI: |
| 2571 | 2550 | case UPIO_MEM32: |
| 2572 | 2551 | case UPIO_MEM: |
| 2573 | − case UPIO_DWAPB: | |
| 2574 | − case UPIO_DWAPB32: | |
| 2575 | 2552 | if (!up->port.mapbase) |
| 2576 | 2553 | break; |
| 2577 | 2554 | |
| @@ -2608,8 +2585,6 @@ static void serial8250_release_std_resource(struct uart_8250_port *up) · 30 unmodified lines | ||
| 2608 | 2585 | case UPIO_TSI: |
| 2609 | 2586 | case UPIO_MEM32: |
| 2610 | 2587 | case UPIO_MEM: |
| 2611 | − case UPIO_DWAPB: | |
| 2612 | − case UPIO_DWAPB32: | |
| 2613 | 2588 | if (!up->port.mapbase) |
| 2614 | 2589 | break; |
| 2615 | 2590 | |
| @@ -3050,6 +3025,10 @@ int __init early_serial_setup(struct uart_port *port) · 434 unmodified lines | ||
| 3050 | 3025 | p->serial_in = port->serial_in; |
| 3051 | 3026 | if (port->serial_out) |
| 3052 | 3027 | p->serial_out = port->serial_out; |
| 3028 | + if (port->handle_irq) | |
| 3029 | + p->handle_irq = port->handle_irq; | |
| 3030 | + else | |
| 3031 | + p->handle_irq = serial8250_default_handle_irq; | |
| 3053 | 3032 | |
| 3054 | 3033 | return 0; |
| 3055 | 3034 | } |
| @@ -3118,6 +3097,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) · 62 unmodified lines | ||
| 3118 | 3097 | port.type = p->type; |
| 3119 | 3098 | port.serial_in = p->serial_in; |
| 3120 | 3099 | port.serial_out = p->serial_out; |
| 3100 | + port.handle_irq = p->handle_irq; | |
| 3121 | 3101 | port.set_termios = p->set_termios; |
| 3122 | 3102 | port.pm = p->pm; |
| 3123 | 3103 | port.dev = &dev->dev; |
| @@ -3283,6 +3263,8 @@ int serial8250_register_port(struct uart_port *port) · 159 unmodified lines | ||
| 3283 | 3263 | uart->port.serial_in = port->serial_in; |
| 3284 | 3264 | if (port->serial_out) |
| 3285 | 3265 | uart->port.serial_out = port->serial_out; |
| 3266 | + if (port->handle_irq) | |
| 3267 | + uart->port.handle_irq = port->handle_irq; | |
| 3286 | 3268 | /* Possibly override set_termios call */ |
| 3287 | 3269 | if (port->set_termios) |
| 3288 | 3270 | uart->port.set_termios = port->set_termios; |
| @@ -0,0 +1,194 @@ | ||
| 1 | +/* | |
| 2 | + * Synopsys DesignWare 8250 driver. | |
| 3 | + * | |
| 4 | + * Copyright 2011 Picochip, Jamie Iles. | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the | |
| 12 | + * LCR is written whilst busy. If it is, then a busy detect interrupt is | |
| 13 | + * raised, the LCR needs to be rewritten and the uart status register read. | |
| 14 | + */ | |
| 15 | +#include <linux/device.h> | |
| 16 | +#include <linux/init.h> | |
| 17 | +#include <linux/io.h> | |
| 18 | +#include <linux/module.h> | |
| 19 | +#include <linux/serial_8250.h> | |
| 20 | +#include <linux/serial_core.h> | |
| 21 | +#include <linux/serial_reg.h> | |
| 22 | +#include <linux/of.h> | |
| 23 | +#include <linux/of_irq.h> | |
| 24 | +#include <linux/of_platform.h> | |
| 25 | +#include <linux/platform_device.h> | |
| 26 | +#include <linux/slab.h> | |
| 27 | + | |
| 28 | +struct dw8250_data { | |
| 29 | + int last_lcr; | |
| 30 | + int line; | |
| 31 | +}; | |
| 32 | + | |
| 33 | +static void dw8250_serial_out(struct uart_port *p, int offset, int value) | |
| 34 | +{ | |
| 35 | + struct dw8250_data *d = p->private_data; | |
| 36 | + | |
| 37 | + if (offset == UART_LCR) | |
| 38 | + d->last_lcr = value; | |
| 39 | + | |
| 40 | + offset <<= p->regshift; | |
| 41 | + writeb(value, p->membase + offset); | |
| 42 | +} | |
| 43 | + | |
| 44 | +static unsigned int dw8250_serial_in(struct uart_port *p, int offset) | |
| 45 | +{ | |
| 46 | + offset <<= p->regshift; | |
| 47 | + | |
| 48 | + return readb(p->membase + offset); | |
| 49 | +} | |
| 50 | + | |
| 51 | +static void dw8250_serial_out32(struct uart_port *p, int offset, int value) | |
| 52 | +{ | |
| 53 | + struct dw8250_data *d = p->private_data; | |
| 54 | + | |
| 55 | + if (offset == UART_LCR) | |
| 56 | + d->last_lcr = value; | |
| 57 | + | |
| 58 | + offset <<= p->regshift; | |
| 59 | + writel(value, p->membase + offset); | |
| 60 | +} | |
| 61 | + | |
| 62 | +static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) | |
| 63 | +{ | |
| 64 | + offset <<= p->regshift; | |
| 65 | + | |
| 66 | + return readl(p->membase + offset); | |
| 67 | +} | |
| 68 | + | |
| 69 | +/* Offset for the DesignWare's UART Status Register. */ | |
| 70 | +#define UART_USR 0x1f | |
| 71 | + | |
| 72 | +static int dw8250_handle_irq(struct uart_port *p) | |
| 73 | +{ | |
| 74 | + struct dw8250_data *d = p->private_data; | |
| 75 | + unsigned int iir = p->serial_in(p, UART_IIR); | |
| 76 | + | |
| 77 | + if (serial8250_handle_irq(p, iir)) { | |
| 78 | + return 1; | |
| 79 | + } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | |
| 80 | + /* Clear the USR and write the LCR again. */ | |
| 81 | + (void)p->serial_in(p, UART_USR); | |
| 82 | + p->serial_out(p, d->last_lcr, UART_LCR); | |
| 83 | + | |
| 84 | + return 1; | |
| 85 | + } | |
| 86 | + | |
| 87 | + return 0; | |
| 88 | +} | |
| 89 | + | |
| 90 | +static int __devinit dw8250_probe(struct platform_device *pdev) | |
| 91 | +{ | |
| 92 | + struct uart_port port = {}; | |
| 93 | + struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 94 | + struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
| 95 | + struct device_node *np = pdev->dev.of_node; | |
| 96 | + u32 val; | |
| 97 | + struct dw8250_data *data; | |
| 98 | + | |
| 99 | + if (!regs || !irq) { | |
| 100 | + dev_err(&pdev->dev, "no registers/irq defined\n"); | |
| 101 | + return -EINVAL; | |
| 102 | + } | |
| 103 | + | |
| 104 | + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | |
| 105 | + if (!data) | |
| 106 | + return -ENOMEM; | |
| 107 | + port.private_data = data; | |
| 108 | + | |
| 109 | + spin_lock_init(&port.lock); | |
| 110 | + port.mapbase = regs->start; | |
| 111 | + port.irq = irq->start; | |
| 112 | + port.handle_irq = dw8250_handle_irq; | |
| 113 | + port.type = PORT_8250; | |
| 114 | + port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | | |
| 115 | + UPF_FIXED_PORT | UPF_FIXED_TYPE; | |
| 116 | + port.dev = &pdev->dev; | |
| 117 | + | |
| 118 | + port.iotype = UPIO_MEM; | |
| 119 | + port.serial_in = dw8250_serial_in; | |
| 120 | + port.serial_out = dw8250_serial_out; | |
| 121 | + if (!of_property_read_u32(np, "reg-io-width", &val)) { | |
| 122 | + switch (val) { | |
| 123 | + case 1: | |
| 124 | + break; | |
| 125 | + case 4: | |
| 126 | + port.iotype = UPIO_MEM32; | |
| 127 | + port.serial_in = dw8250_serial_in32; | |
| 128 | + port.serial_out = dw8250_serial_out32; | |
| 129 | + break; | |
| 130 | + default: | |
| 131 | + dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n", | |
| 132 | + val); | |
| 133 | + return -EINVAL; | |
| 134 | + } | |
| 135 | + } | |
| 136 | + | |
| 137 | + if (!of_property_read_u32(np, "reg-shift", &val)) | |
| 138 | + port.regshift = val; | |
| 139 | + | |
| 140 | + if (of_property_read_u32(np, "clock-frequency", &val)) { | |
| 141 | + dev_err(&pdev->dev, "no clock-frequency property set\n"); | |
| 142 | + return -EINVAL; | |
| 143 | + } | |
| 144 | + port.uartclk = val; | |
| 145 | + | |
| 146 | + data->line = serial8250_register_port(&port); | |
| 147 | + if (data->line < 0) | |
| 148 | + return data->line; | |
| 149 | + | |
| 150 | + platform_set_drvdata(pdev, data); | |
| 151 | + | |
| 152 | + return 0; | |
| 153 | +} | |
| 154 | + | |
| 155 | +static int __devexit dw8250_remove(struct platform_device *pdev) | |
| 156 | +{ | |
| 157 | + struct dw8250_data *data = platform_get_drvdata(pdev); | |
| 158 | + | |
| 159 | + serial8250_unregister_port(data->line); | |
| 160 | + | |
| 161 | + return 0; | |
| 162 | +} | |
| 163 | + | |
| 164 | +static const struct of_device_id dw8250_match[] = { | |
| 165 | + { .compatible = "snps,dw-apb-uart" }, | |
| 166 | + { /* Sentinel */ } | |
| 167 | +}; | |
| 168 | +MODULE_DEVICE_TABLE(of, dw8250_match); | |
| 169 | + | |
| 170 | +static struct platform_driver dw8250_platform_driver = { | |
| 171 | + .driver = { | |
| 172 | + .name = "dw-apb-uart", | |
| 173 | + .owner = THIS_MODULE, | |
| 174 | + .of_match_table = dw8250_match, | |
| 175 | + }, | |
| 176 | + .probe = dw8250_probe, | |
| 177 | + .remove = __devexit_p(dw8250_remove), | |
| 178 | +}; | |
| 179 | + | |
| 180 | +static int __init dw8250_init(void) | |
| 181 | +{ | |
| 182 | + return platform_driver_register(&dw8250_platform_driver); | |
| 183 | +} | |
| 184 | +module_init(dw8250_init); | |
| 185 | + | |
| 186 | +static void __exit dw8250_exit(void) | |
| 187 | +{ | |
| 188 | + platform_driver_unregister(&dw8250_platform_driver); | |
| 189 | +} | |
| 190 | +module_exit(dw8250_exit); | |
| 191 | + | |
| 192 | +MODULE_AUTHOR("Jamie Iles"); | |
| 193 | +MODULE_LICENSE("GPL"); | |
| 194 | +MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver"); | |
| @@ -1101,6 +1101,15 @@ static int pci_eg20t_init(struct pci_dev *dev) · 1100 unmodified lines | ||
| 1101 | 1101 | #endif |
| 1102 | 1102 | } |
| 1103 | 1103 | |
| 1104 | +static int | |
| 1105 | +pci_xr17c154_setup(struct serial_private *priv, | |
| 1106 | + const struct pciserial_board *board, | |
| 1107 | + struct uart_port *port, int idx) | |
| 1108 | +{ | |
| 1109 | + port->flags |= UPF_EXAR_EFR; | |
| 1110 | + return pci_default_setup(priv, board, port, idx); | |
| 1111 | +} | |
| 1112 | + | |
| 1104 | 1113 | /* This should be in linux/pci_ids.h */ |
| 1105 | 1114 | #define PCI_VENDOR_ID_SBSMODULARIO 0x124B |
| 1106 | 1115 | #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B |
| @@ -1505,6 +1514,30 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { · 398 unmodified lines | ||
| 1505 | 1514 | .subdevice = PCI_ANY_ID, |
| 1506 | 1515 | .setup = pci_timedia_setup, |
| 1507 | 1516 | }, |
| 1517 | + /* | |
| 1518 | + * Exar cards | |
| 1519 | + */ | |
| 1520 | + { | |
| 1521 | + .vendor = PCI_VENDOR_ID_EXAR, | |
| 1522 | + .device = PCI_DEVICE_ID_EXAR_XR17C152, | |
| 1523 | + .subvendor = PCI_ANY_ID, | |
| 1524 | + .subdevice = PCI_ANY_ID, | |
| 1525 | + .setup = pci_xr17c154_setup, | |
| 1526 | + }, | |
| 1527 | + { | |
| 1528 | + .vendor = PCI_VENDOR_ID_EXAR, | |
| 1529 | + .device = PCI_DEVICE_ID_EXAR_XR17C154, | |
| 1530 | + .subvendor = PCI_ANY_ID, | |
| 1531 | + .subdevice = PCI_ANY_ID, | |
| 1532 | + .setup = pci_xr17c154_setup, | |
| 1533 | + }, | |
| 1534 | + { | |
| 1535 | + .vendor = PCI_VENDOR_ID_EXAR, | |
| 1536 | + .device = PCI_DEVICE_ID_EXAR_XR17C158, | |
| 1537 | + .subvendor = PCI_ANY_ID, | |
| 1538 | + .subdevice = PCI_ANY_ID, | |
| 1539 | + .setup = pci_xr17c154_setup, | |
| 1540 | + }, | |
| 1508 | 1541 | /* |
| 1509 | 1542 | * Xircom cards |
| 1510 | 1543 | */ |
| @@ -1558,46 +1591,55 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { · 47 unmodified lines | ||
| 1558 | 1591 | .vendor = PCI_VENDOR_ID_INTEL, |
| 1559 | 1592 | .device = 0x8811, |
| 1560 | 1593 | .init = pci_eg20t_init, |
| 1594 | + .setup = pci_default_setup, | |
| 1561 | 1595 | }, |
| 1562 | 1596 | { |
| 1563 | 1597 | .vendor = PCI_VENDOR_ID_INTEL, |
| 1564 | 1598 | .device = 0x8812, |
| 1565 | 1599 | .init = pci_eg20t_init, |
| 1600 | + .setup = pci_default_setup, | |
| 1566 | 1601 | }, |
| 1567 | 1602 | { |
| 1568 | 1603 | .vendor = PCI_VENDOR_ID_INTEL, |
| 1569 | 1604 | .device = 0x8813, |
| 1570 | 1605 | .init = pci_eg20t_init, |
| 1606 | + .setup = pci_default_setup, | |
| 1571 | 1607 | }, |
| 1572 | 1608 | { |
| 1573 | 1609 | .vendor = PCI_VENDOR_ID_INTEL, |
| 1574 | 1610 | .device = 0x8814, |
| 1575 | 1611 | .init = pci_eg20t_init, |
| 1612 | + .setup = pci_default_setup, | |
| 1576 | 1613 | }, |
| 1577 | 1614 | { |
| 1578 | 1615 | .vendor = 0x10DB, |
| 1579 | 1616 | .device = 0x8027, |
| 1580 | 1617 | .init = pci_eg20t_init, |
| 1618 | + .setup = pci_default_setup, | |
| 1581 | 1619 | }, |
| 1582 | 1620 | { |
| 1583 | 1621 | .vendor = 0x10DB, |
| 1584 | 1622 | .device = 0x8028, |
| 1585 | 1623 | .init = pci_eg20t_init, |
| 1624 | + .setup = pci_default_setup, | |
| 1586 | 1625 | }, |
| 1587 | 1626 | { |
| 1588 | 1627 | .vendor = 0x10DB, |
| 1589 | 1628 | .device = 0x8029, |
| 1590 | 1629 | .init = pci_eg20t_init, |
| 1630 | + .setup = pci_default_setup, | |
| 1591 | 1631 | }, |
| 1592 | 1632 | { |
| 1593 | 1633 | .vendor = 0x10DB, |
| 1594 | 1634 | .device = 0x800C, |
| 1595 | 1635 | .init = pci_eg20t_init, |
| 1636 | + .setup = pci_default_setup, | |
| 1596 | 1637 | }, |
| 1597 | 1638 | { |
| 1598 | 1639 | .vendor = 0x10DB, |
| 1599 | 1640 | .device = 0x800D, |
| 1600 | 1641 | .init = pci_eg20t_init, |
| 1642 | + .setup = pci_default_setup, | |
| 1601 | 1643 | }, |
| 1602 | 1644 | /* |
| 1603 | 1645 | * Cronyx Omega PCI (PLX-chip based) |
| @@ -267,6 +267,13 @@ config SERIAL_8250_RM9K · 266 unmodified lines | ||
| 267 | 267 | port hardware found on MIPS RM9122 and similar processors. |
| 268 | 268 | If unsure, say N. |
| 269 | 269 | |
| 270 | +config SERIAL_8250_DW | |
| 271 | + tristate "Support for Synopsys DesignWare 8250 quirks" | |
| 272 | + depends on SERIAL_8250 && OF | |
| 273 | + help | |
| 274 | + Selecting this option will enable handling of the extra features | |
| 275 | + present in the Synopsys DesignWare APB UART. | |
| 276 | + | |
| 270 | 277 | comment "Non-8250 serial port support" |
| 271 | 278 | |
| 272 | 279 | config SERIAL_AMBA_PL010 |
| @@ -522,8 +529,8 @@ config SERIAL_S3C6400 · 249 unmodified lines | ||
| 522 | 529 | |
| 523 | 530 | config SERIAL_S5PV210 |
| 524 | 531 | tristate "Samsung S5PV210 Serial port support" |
| 525 | − depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210) | |
| 526 | − select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210) | |
| 532 | + depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212) | |
| 533 | + select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212) | |
| 527 | 534 | default y |
| 528 | 535 | help |
| 529 | 536 | Serial port support for Samsung's S5P Family of SoC's |
| @@ -722,7 +729,7 @@ config SERIAL_BFIN · 192 unmodified lines | ||
| 722 | 729 | Add support for the built-in UARTs on the Blackfin. |
| 723 | 730 | |
| 724 | 731 | To compile this driver as a module, choose M here: the |
| 725 | − module will be called bfin_5xx. | |
| 732 | + module is named bfin_uart.ko. | |
| 726 | 733 | |
| 727 | 734 | config SERIAL_BFIN_CONSOLE |
| 728 | 735 | bool "Console on Blackfin serial port" |
| @@ -1035,23 +1042,6 @@ config SERIAL_MCF_CONSOLE · 306 unmodified lines | ||
| 1035 | 1042 | help |
| 1036 | 1043 | Enable a ColdFire internal serial port to be the system console. |
| 1037 | 1044 | |
| 1038 | −config SERIAL_68360_SMC | |
| 1039 | − bool "68360 SMC uart support" | |
| 1040 | − depends on M68360 | |
| 1041 | − help | |
| 1042 | − This driver supports the SMC serial ports of the Motorola 68360 CPU. | |
| 1043 | − | |
| 1044 | −config SERIAL_68360_SCC | |
| 1045 | − bool "68360 SCC uart support" | |
| 1046 | − depends on M68360 | |
| 1047 | − help | |
| 1048 | − This driver supports the SCC serial ports of the Motorola 68360 CPU. | |
| 1049 | − | |
| 1050 | −config SERIAL_68360 | |
| 1051 | − bool | |
| 1052 | − depends on SERIAL_68360_SMC || SERIAL_68360_SCC | |
| 1053 | − default y | |
| 1054 | − | |
| 1055 | 1045 | config SERIAL_PMACZILOG |
| 1056 | 1046 | tristate "Mac or PowerMac z85c30 ESCC support" |
| 1057 | 1047 | depends on (M68K && MAC) || (PPC_OF && PPC_PMAC) |
| @@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o · 27 unmodified lines | ||
| 28 | 28 | obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o |
| 29 | 29 | obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o |
| 30 | 30 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o |
| 31 | +obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o | |
| 31 | 32 | obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o |
| 32 | 33 | obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o |
| 33 | 34 | obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o |
| @@ -35,7 +36,7 @@ obj-$(CONFIG_SERIAL_PXA) += pxa.o · 1 unmodified line | ||
| 35 | 36 | obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o |
| 36 | 37 | obj-$(CONFIG_SERIAL_SA1100) += sa1100.o |
| 37 | 38 | obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o |
| 38 | −obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o | |
| 39 | +obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o | |
| 39 | 40 | obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o |
| 40 | 41 | obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o |
| 41 | 42 | obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o |
| @@ -49,7 +50,6 @@ obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o · 7 unmodified lines | ||
| 49 | 50 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o |
| 50 | 51 | obj-$(CONFIG_SERIAL_MUX) += mux.o |
| 51 | 52 | obj-$(CONFIG_SERIAL_68328) += 68328serial.o |
| 52 | −obj-$(CONFIG_SERIAL_68360) += 68360serial.o | |
| 53 | 53 | obj-$(CONFIG_SERIAL_MCF) += mcf.o |
| 54 | 54 | obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o |
| 55 | 55 | obj-$(CONFIG_SERIAL_DZ) += dz.o |
| @@ -218,7 +218,7 @@ static int altera_jtaguart_startup(struct uart_port *port) · 217 unmodified lines | ||
| 218 | 218 | unsigned long flags; |
| 219 | 219 | int ret; |
| 220 | 220 | |
| 221 | − ret = request_irq(port->irq, altera_jtaguart_interrupt, IRQF_DISABLED, | |
| 221 | + ret = request_irq(port->irq, altera_jtaguart_interrupt, 0, | |
| 222 | 222 | DRV_NAME, port); |
| 223 | 223 | if (ret) { |
| 224 | 224 | pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d " |
| @@ -315,7 +315,7 @@ static int altera_uart_startup(struct uart_port *port) · 314 unmodified lines | ||
| 315 | 315 | return 0; |
| 316 | 316 | } |
| 317 | 317 | |
| 318 | − ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED, | |
| 318 | + ret = request_irq(port->irq, altera_uart_interrupt, 0, | |
| 319 | 319 | DRV_NAME, port); |
| 320 | 320 | if (ret) { |
| 321 | 321 | pr_err(DRV_NAME ": unable to attach Altera UART %d " |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | #include <linux/module.h> |
| 18 | 18 | #include <linux/tty.h> |
| 19 | +#include <linux/tty_flip.h> | |
| 19 | 20 | #include <linux/ioport.h> |
| 20 | 21 | #include <linux/init.h> |
| 21 | 22 | #include <linux/serial.h> |
| @@ -33,6 +33,8 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <linux/sysrq.h> |
| 34 | 34 | #include <linux/tty_flip.h> |
| 35 | 35 | #include <linux/platform_device.h> |
| 36 | +#include <linux/of.h> | |
| 37 | +#include <linux/of_device.h> | |
| 36 | 38 | #include <linux/dma-mapping.h> |
| 37 | 39 | #include <linux/atmel_pdc.h> |
| 38 | 40 | #include <linux/atmel_serial.h> |
| @@ -157,11 +159,22 @@ struct atmel_uart_port { · 118 unmodified lines | ||
| 157 | 159 | }; |
| 158 | 160 | |
| 159 | 161 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; |
| 162 | +static unsigned long atmel_ports_in_use; | |
| 160 | 163 | |
| 161 | 164 | #ifdef SUPPORT_SYSRQ |
| 162 | 165 | static struct console atmel_console; |
| 163 | 166 | #endif |
| 164 | 167 | |
| 168 | +#if defined(CONFIG_OF) | |
| 169 | +static const struct of_device_id atmel_serial_dt_ids[] = { | |
| 170 | + { .compatible = "atmel,at91rm9200-usart" }, | |
| 171 | + { .compatible = "atmel,at91sam9260-usart" }, | |
| 172 | + { /* sentinel */ } | |
| 173 | +}; | |
| 174 | + | |
| 175 | +MODULE_DEVICE_TABLE(of, atmel_serial_dt_ids); | |
| 176 | +#endif | |
| 177 | + | |
| 165 | 178 | static inline struct atmel_uart_port * |
| 166 | 179 | to_atmel_uart_port(struct uart_port *uart) |
| 167 | 180 | { |
| @@ -339,7 +352,8 @@ static void atmel_stop_tx(struct uart_port *port) · 171 unmodified lines | ||
| 339 | 352 | /* Disable interrupts */ |
| 340 | 353 | UART_PUT_IDR(port, atmel_port->tx_done_mask); |
| 341 | 354 | |
| 342 | − if (atmel_port->rs485.flags & SER_RS485_ENABLED) | |
| 355 | + if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && | |
| 356 | + !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) | |
| 343 | 357 | atmel_start_rx(port); |
| 344 | 358 | } |
| 345 | 359 | |
| @@ -356,7 +370,8 @@ static void atmel_start_tx(struct uart_port *port) · 10 unmodified lines | ||
| 356 | 370 | really need this.*/ |
| 357 | 371 | return; |
| 358 | 372 | |
| 359 | − if (atmel_port->rs485.flags & SER_RS485_ENABLED) | |
| 373 | + if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && | |
| 374 | + !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) | |
| 360 | 375 | atmel_stop_rx(port); |
| 361 | 376 | |
| 362 | 377 | /* re-enable PDC transmit */ |
| @@ -680,7 +695,8 @@ static void atmel_tx_dma(struct uart_port *port) · 317 unmodified lines | ||
| 680 | 695 | /* Enable interrupts */ |
| 681 | 696 | UART_PUT_IER(port, atmel_port->tx_done_mask); |
| 682 | 697 | } else { |
| 683 | − if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | |
| 698 | + if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && | |
| 699 | + !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) { | |
| 684 | 700 | /* DMA done, stop TX, start RX for RS485 */ |
| 685 | 701 | atmel_start_rx(port); |
| 686 | 702 | } |
| @@ -1407,6 +1423,48 @@ static struct uart_ops atmel_pops = { · 720 unmodified lines | ||
| 1407 | 1423 | #endif |
| 1408 | 1424 | }; |
| 1409 | 1425 | |
| 1426 | +static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port, | |
| 1427 | + struct device_node *np) | |
| 1428 | +{ | |
| 1429 | + u32 rs485_delay[2]; | |
| 1430 | + | |
| 1431 | + /* DMA/PDC usage specification */ | |
| 1432 | + if (of_get_property(np, "atmel,use-dma-rx", NULL)) | |
| 1433 | + atmel_port->use_dma_rx = 1; | |
| 1434 | + else | |
| 1435 | + atmel_port->use_dma_rx = 0; | |
| 1436 | + if (of_get_property(np, "atmel,use-dma-tx", NULL)) | |
| 1437 | + atmel_port->use_dma_tx = 1; | |
| 1438 | + else | |
| 1439 | + atmel_port->use_dma_tx = 0; | |
| 1440 | + | |
| 1441 | + /* rs485 properties */ | |
| 1442 | + if (of_property_read_u32_array(np, "rs485-rts-delay", | |
| 1443 | + rs485_delay, 2) == 0) { | |
| 1444 | + struct serial_rs485 *rs485conf = &atmel_port->rs485; | |
| 1445 | + | |
| 1446 | + rs485conf->delay_rts_before_send = rs485_delay[0]; | |
| 1447 | + rs485conf->delay_rts_after_send = rs485_delay[1]; | |
| 1448 | + rs485conf->flags = 0; | |
| 1449 | + | |
| 1450 | + if (rs485conf->delay_rts_before_send == 0 && | |
| 1451 | + rs485conf->delay_rts_after_send == 0) { | |
| 1452 | + rs485conf->flags |= SER_RS485_RTS_ON_SEND; | |
| 1453 | + } else { | |
| 1454 | + if (rs485conf->delay_rts_before_send) | |
| 1455 | + rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND; | |
| 1456 | + if (rs485conf->delay_rts_after_send) | |
| 1457 | + rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; | |
| 1458 | + } | |
| 1459 | + | |
| 1460 | + if (of_get_property(np, "rs485-rx-during-tx", NULL)) | |
| 1461 | + rs485conf->flags |= SER_RS485_RX_DURING_TX; | |
| 1462 | + | |
| 1463 | + if (of_get_property(np, "linux,rs485-enabled-at-boot-time", NULL)) | |
| 1464 | + rs485conf->flags |= SER_RS485_ENABLED; | |
| 1465 | + } | |
| 1466 | +} | |
| 1467 | + | |
| 1410 | 1468 | /* |
| 1411 | 1469 | * Configure the port from the platform device resource info. |
| 1412 | 1470 | */ |
| @@ -1414,13 +1472,20 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, · 1 unmodified line | ||
| 1414 | 1472 | struct platform_device *pdev) |
| 1415 | 1473 | { |
| 1416 | 1474 | struct uart_port *port = &atmel_port->uart; |
| 1417 | − struct atmel_uart_data *data = pdev->dev.platform_data; | |
| 1475 | + struct atmel_uart_data *pdata = pdev->dev.platform_data; | |
| 1476 | + | |
| 1477 | + if (pdev->dev.of_node) { | |
| 1478 | + atmel_of_init_port(atmel_port, pdev->dev.of_node); | |
| 1479 | + } else { | |
| 1480 | + atmel_port->use_dma_rx = pdata->use_dma_rx; | |
| 1481 | + atmel_port->use_dma_tx = pdata->use_dma_tx; | |
| 1482 | + atmel_port->rs485 = pdata->rs485; | |
| 1483 | + } | |
| 1418 | 1484 | |
| 1419 | 1485 | port->iotype = UPIO_MEM; |
| 1420 | 1486 | port->flags = UPF_BOOT_AUTOCONF; |
| 1421 | 1487 | port->ops = &atmel_pops; |
| 1422 | 1488 | port->fifosize = 1; |
| 1423 | − port->line = data->num; | |
| 1424 | 1489 | port->dev = &pdev->dev; |
| 1425 | 1490 | port->mapbase = pdev->resource[0].start; |
| 1426 | 1491 | port->irq = pdev->resource[1].start; |
| @@ -1430,10 +1495,10 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, · 3 unmodified lines | ||
| 1430 | 1495 | |
| 1431 | 1496 | memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); |
| 1432 | 1497 | |
| 1433 | − if (data->regs) | |
| 1498 | + if (pdata && pdata->regs) { | |
| 1434 | 1499 | /* Already mapped by setup code */ |
| 1435 | − port->membase = data->regs; | |
| 1436 | − else { | |
| 1500 | + port->membase = pdata->regs; | |
| 1501 | + } else { | |
| 1437 | 1502 | port->flags |= UPF_IOREMAP; |
| 1438 | 1503 | port->membase = NULL; |
| 1439 | 1504 | } |
| @@ -1447,9 +1512,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, · 7 unmodified lines | ||
| 1447 | 1512 | /* only enable clock when USART is in use */ |
| 1448 | 1513 | } |
| 1449 | 1514 | |
| 1450 | − atmel_port->use_dma_rx = data->use_dma_rx; | |
| 1451 | − atmel_port->use_dma_tx = data->use_dma_tx; | |
| 1452 | − atmel_port->rs485 = data->rs485; | |
| 1453 | 1515 | /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ |
| 1454 | 1516 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) |
| 1455 | 1517 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; |
| @@ -1611,10 +1673,14 @@ static int __init atmel_console_init(void) · 155 unmodified lines | ||
| 1611 | 1673 | if (atmel_default_console_device) { |
| 1612 | 1674 | struct atmel_uart_data *pdata = |
| 1613 | 1675 | atmel_default_console_device->dev.platform_data; |
| 1676 | + int id = pdata->num; | |
| 1677 | + struct atmel_uart_port *port = &atmel_ports[id]; | |
| 1678 | + | |
| 1679 | + port->backup_imr = 0; | |
| 1680 | + port->uart.line = id; | |
| 1614 | 1681 | |
| 1615 | − add_preferred_console(ATMEL_DEVICENAME, pdata->num, NULL); | |
| 1616 | − atmel_init_port(&atmel_ports[pdata->num], | |
| 1617 | − atmel_default_console_device); | |
| 1682 | + add_preferred_console(ATMEL_DEVICENAME, id, NULL); | |
| 1683 | + atmel_init_port(port, atmel_default_console_device); | |
| 1618 | 1684 | register_console(&atmel_console); |
| 1619 | 1685 | } |
| 1620 | 1686 | |
| @@ -1711,14 +1777,39 @@ static int atmel_serial_resume(struct platform_device *pdev) · 90 unmodified lines | ||
| 1711 | 1777 | static int __devinit atmel_serial_probe(struct platform_device *pdev) |
| 1712 | 1778 | { |
| 1713 | 1779 | struct atmel_uart_port *port; |
| 1780 | + struct device_node *np = pdev->dev.of_node; | |
| 1714 | 1781 | struct atmel_uart_data *pdata = pdev->dev.platform_data; |
| 1715 | 1782 | void *data; |
| 1716 | − int ret; | |
| 1783 | + int ret = -ENODEV; | |
| 1717 | 1784 | |
| 1718 | 1785 | BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); |
| 1719 | 1786 | |
| 1720 | − port = &atmel_ports[pdata->num]; | |
| 1787 | + if (np) | |
| 1788 | + ret = of_alias_get_id(np, "serial"); | |
| 1789 | + else | |
| 1790 | + if (pdata) | |
| 1791 | + ret = pdata->num; | |
| 1792 | + | |
| 1793 | + if (ret < 0) | |
| 1794 | + /* port id not found in platform data nor device-tree aliases: | |
| 1795 | + * auto-enumerate it */ | |
| 1796 | + ret = find_first_zero_bit(&atmel_ports_in_use, | |
| 1797 | + sizeof(atmel_ports_in_use)); | |
| 1798 | + | |
| 1799 | + if (ret > ATMEL_MAX_UART) { | |
| 1800 | + ret = -ENODEV; | |
| 1801 | + goto err; | |
| 1802 | + } | |
| 1803 | + | |
| 1804 | + if (test_and_set_bit(ret, &atmel_ports_in_use)) { | |
| 1805 | + /* port already in use */ | |
| 1806 | + ret = -EBUSY; | |
| 1807 | + goto err; | |
| 1808 | + } | |
| 1809 | + | |
| 1810 | + port = &atmel_ports[ret]; | |
| 1721 | 1811 | port->backup_imr = 0; |
| 1812 | + port->uart.line = ret; | |
| 1722 | 1813 | |
| 1723 | 1814 | atmel_init_port(port, pdev); |
| 1724 | 1815 | |
| @@ -1764,7 +1855,7 @@ err_alloc_ring: · 39 unmodified lines | ||
| 1764 | 1855 | clk_put(port->clk); |
| 1765 | 1856 | port->clk = NULL; |
| 1766 | 1857 | } |
| 1767 | − | |
| 1858 | +err: | |
| 1768 | 1859 | return ret; |
| 1769 | 1860 | } |
| 1770 | 1861 | |
| @@ -1784,6 +1875,8 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) · 13 unmodified lines | ||
| 1784 | 1875 | |
| 1785 | 1876 | /* "port" is allocated statically, so we shouldn't free it */ |
| 1786 | 1877 | |
| 1878 | + clear_bit(port->line, &atmel_ports_in_use); | |
| 1879 | + | |
| 1787 | 1880 | clk_put(atmel_port->clk); |
| 1788 | 1881 | |
| 1789 | 1882 | return ret; |
| @@ -1797,6 +1890,7 @@ static struct platform_driver atmel_serial_driver = { · 7 unmodified lines | ||
| 1797 | 1890 | .driver = { |
| 1798 | 1891 | .name = "atmel_usart", |
| 1799 | 1892 | .owner = THIS_MODULE, |
| 1893 | + .of_match_table = of_match_ptr(atmel_serial_dt_ids), | |
| 1800 | 1894 | }, |
| 1801 | 1895 | }; |
| 1802 | 1896 | |
| @@ -294,7 +294,7 @@ static int sport_startup(struct uart_port *port) · 293 unmodified lines | ||
| 294 | 294 | if (request_irq(gpio_to_irq(up->cts_pin), |
| 295 | 295 | sport_mctrl_cts_int, |
| 296 | 296 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | |
| 297 | − IRQF_DISABLED, "BFIN_SPORT_UART_CTS", up)) { | |
| 297 | + 0, "BFIN_SPORT_UART_CTS", up)) { | |
| 298 | 298 | up->cts_pin = -1; |
| 299 | 299 | dev_info(port->dev, "Unable to attach BlackFin UART over SPORT CTS interrupt. So, disable it.\n"); |
| 300 | 300 | } |
| @@ -234,8 +234,8 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) · 233 unmodified lines | ||
| 234 | 234 | status = UART_GET_LSR(uart); |
| 235 | 235 | UART_CLEAR_LSR(uart); |
| 236 | 236 | |
| 237 | − ch = UART_GET_CHAR(uart); | |
| 238 | − uart->port.icount.rx++; | |
| 237 | + ch = UART_GET_CHAR(uart); | |
| 238 | + uart->port.icount.rx++; | |
| 239 | 239 | |
| 240 | 240 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ |
| 241 | 241 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) |
| @@ -667,17 +667,17 @@ static int bfin_serial_startup(struct uart_port *port) · 425 unmodified lines | ||
| 667 | 667 | kgdboc_break_enabled = 0; |
| 668 | 668 | else { |
| 669 | 669 | # endif |
| 670 | − if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, | |
| 670 | + if (request_irq(uart->rx_irq, bfin_serial_rx_int, 0, | |
| 671 | 671 | "BFIN_UART_RX", uart)) { |
| 672 | 672 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); |
| 673 | 673 | return -EBUSY; |
| 674 | 674 | } |
| 675 | 675 | |
| 676 | 676 | if (request_irq |
| 677 | − (uart->port.irq+1, bfin_serial_tx_int, IRQF_DISABLED, | |
| 677 | + (uart->tx_irq, bfin_serial_tx_int, 0, | |
| 678 | 678 | "BFIN_UART_TX", uart)) { |
| 679 | 679 | printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n"); |
| 680 | − free_irq(uart->port.irq, uart); | |
| 680 | + free_irq(uart->rx_irq, uart); | |
| 681 | 681 | return -EBUSY; |
| 682 | 682 | } |
| 683 | 683 | |
| @@ -692,7 +692,7 @@ static int bfin_serial_startup(struct uart_port *port) · 8 unmodified lines | ||
| 692 | 692 | */ |
| 693 | 693 | unsigned uart_dma_ch_rx, uart_dma_ch_tx; |
| 694 | 694 | |
| 695 | − switch (uart->port.irq) { | |
| 695 | + switch (uart->rx_irq) { | |
| 696 | 696 | case IRQ_UART3_RX: |
| 697 | 697 | uart_dma_ch_rx = CH_UART3_RX; |
| 698 | 698 | uart_dma_ch_tx = CH_UART3_TX; |
| @@ -709,16 +709,16 @@ static int bfin_serial_startup(struct uart_port *port) · 10 unmodified lines | ||
| 709 | 709 | if (uart_dma_ch_rx && |
| 710 | 710 | request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) { |
| 711 | 711 | printk(KERN_NOTICE"Fail to attach UART interrupt\n"); |
| 712 | − free_irq(uart->port.irq, uart); | |
| 713 | − free_irq(uart->port.irq + 1, uart); | |
| 712 | + free_irq(uart->rx_irq, uart); | |
| 713 | + free_irq(uart->tx_irq, uart); | |
| 714 | 714 | return -EBUSY; |
| 715 | 715 | } |
| 716 | 716 | if (uart_dma_ch_tx && |
| 717 | 717 | request_dma(uart_dma_ch_tx, "BFIN_UART_TX") < 0) { |
| 718 | 718 | printk(KERN_NOTICE "Fail to attach UART interrupt\n"); |
| 719 | 719 | free_dma(uart_dma_ch_rx); |
| 720 | − free_irq(uart->port.irq, uart); | |
| 721 | − free_irq(uart->port.irq + 1, uart); | |
| 720 | + free_irq(uart->rx_irq, uart); | |
| 721 | + free_irq(uart->tx_irq, uart); | |
| 722 | 722 | return -EBUSY; |
| 723 | 723 | } |
| 724 | 724 | } |
| @@ -734,19 +734,18 @@ static int bfin_serial_startup(struct uart_port *port) · 9 unmodified lines | ||
| 734 | 734 | if (request_irq(gpio_to_irq(uart->cts_pin), |
| 735 | 735 | bfin_serial_mctrl_cts_int, |
| 736 | 736 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | |
| 737 | − IRQF_DISABLED, "BFIN_UART_CTS", uart)) { | |
| 737 | + 0, "BFIN_UART_CTS", uart)) { | |
| 738 | 738 | uart->cts_pin = -1; |
| 739 | 739 | pr_info("Unable to attach BlackFin UART CTS interrupt. So, disable it.\n"); |
| 740 | 740 | } |
| 741 | 741 | } |
| 742 | − if (uart->rts_pin >= 0) { | |
| 742 | + if (uart->rts_pin >= 0) | |
| 743 | 743 | gpio_direction_output(uart->rts_pin, 0); |
| 744 | − } | |
| 745 | 744 | #endif |
| 746 | 745 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS |
| 747 | 746 | if (uart->cts_pin >= 0 && request_irq(uart->status_irq, |
| 748 | 747 | bfin_serial_mctrl_cts_int, |
| 749 | − IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) { | |
| 748 | + 0, "BFIN_UART_MODEM_STATUS", uart)) { | |
| 750 | 749 | uart->cts_pin = -1; |
| 751 | 750 | pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n"); |
| 752 | 751 | } |
| @@ -786,8 +785,8 @@ static void bfin_serial_shutdown(struct uart_port *port) · 33 unmodified lines | ||
| 786 | 785 | break; |
| 787 | 786 | }; |
| 788 | 787 | #endif |
| 789 | − free_irq(uart->port.irq, uart); | |
| 790 | − free_irq(uart->port.irq+1, uart); | |
| 788 | + free_irq(uart->rx_irq, uart); | |
| 789 | + free_irq(uart->tx_irq, uart); | |
| 791 | 790 | #endif |
| 792 | 791 | |
| 793 | 792 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS |
| @@ -1091,10 +1090,18 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud, · 297 unmodified lines | ||
| 1091 | 1090 | *parity = 'o'; |
| 1092 | 1091 | } |
| 1093 | 1092 | switch (lcr & 0x03) { |
| 1094 | − case 0: *bits = 5; break; | |
| 1095 | − case 1: *bits = 6; break; | |
| 1096 | − case 2: *bits = 7; break; | |
| 1097 | − case 3: *bits = 8; break; | |
| 1093 | + case 0: | |
| 1094 | + *bits = 5; | |
| 1095 | + break; | |
| 1096 | + case 1: | |
| 1097 | + *bits = 6; | |
| 1098 | + break; | |
| 1099 | + case 2: | |
| 1100 | + *bits = 7; | |
| 1101 | + break; | |
| 1102 | + case 3: | |
| 1103 | + *bits = 8; | |
| 1104 | + break; | |
| 1098 | 1105 | } |
| 1099 | 1106 | /* Set DLAB in LCR to Access DLL and DLH */ |
| 1100 | 1107 | UART_SET_DLAB(uart); |
| @@ -1183,7 +1190,7 @@ static struct console bfin_serial_console = { · 82 unmodified lines | ||
| 1183 | 1190 | .index = -1, |
| 1184 | 1191 | .data = &bfin_serial_reg, |
| 1185 | 1192 | }; |
| 1186 | −#define BFIN_SERIAL_CONSOLE &bfin_serial_console | |
| 1193 | +#define BFIN_SERIAL_CONSOLE (&bfin_serial_console) | |
| 1187 | 1194 | #else |
| 1188 | 1195 | #define BFIN_SERIAL_CONSOLE NULL |
| 1189 | 1196 | #endif /* CONFIG_SERIAL_BFIN_CONSOLE */ |
| @@ -1312,14 +1319,22 @@ static int bfin_serial_probe(struct platform_device *pdev) · 122 unmodified lines | ||
| 1312 | 1319 | } |
| 1313 | 1320 | uart->port.mapbase = res->start; |
| 1314 | 1321 | |
| 1315 | − uart->port.irq = platform_get_irq(pdev, 0); | |
| 1316 | − if (uart->port.irq < 0) { | |
| 1317 | − dev_err(&pdev->dev, "No uart RX/TX IRQ specified\n"); | |
| 1322 | + uart->tx_irq = platform_get_irq(pdev, 0); | |
| 1323 | + if (uart->tx_irq < 0) { | |
| 1324 | + dev_err(&pdev->dev, "No uart TX IRQ specified\n"); | |
| 1325 | + ret = -ENOENT; | |
| 1326 | + goto out_error_unmap; | |
| 1327 | + } | |
| 1328 | + | |
| 1329 | + uart->rx_irq = platform_get_irq(pdev, 1); | |
| 1330 | + if (uart->rx_irq < 0) { | |
| 1331 | + dev_err(&pdev->dev, "No uart RX IRQ specified\n"); | |
| 1318 | 1332 | ret = -ENOENT; |
| 1319 | 1333 | goto out_error_unmap; |
| 1320 | 1334 | } |
| 1335 | + uart->port.irq = uart->rx_irq; | |
| 1321 | 1336 | |
| 1322 | − uart->status_irq = platform_get_irq(pdev, 1); | |
| 1337 | + uart->status_irq = platform_get_irq(pdev, 2); | |
| 1323 | 1338 | if (uart->status_irq < 0) { |
| 1324 | 1339 | dev_err(&pdev->dev, "No uart status IRQ specified\n"); |
| 1325 | 1340 | ret = -ENOENT; |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | #include <linux/module.h> |
| 33 | 33 | #include <linux/tty.h> |
| 34 | +#include <linux/tty_flip.h> | |
| 34 | 35 | #include <linux/ioport.h> |
| 35 | 36 | #include <linux/init.h> |
| 36 | 37 | #include <linux/serial.h> |
| @@ -258,7 +258,7 @@ static struct e100_serial rs_table[] = { · 257 unmodified lines | ||
| 258 | 258 | .dma_out_enabled = 1, |
| 259 | 259 | .dma_out_nbr = SER0_TX_DMA_NBR, |
| 260 | 260 | .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR, |
| 261 | − .dma_out_irq_flags = IRQF_DISABLED, | |
| 261 | + .dma_out_irq_flags = 0, | |
| 262 | 262 | .dma_out_irq_description = "serial 0 dma tr", |
| 263 | 263 | #else |
| 264 | 264 | .dma_out_enabled = 0, |
| @@ -271,7 +271,7 @@ static struct e100_serial rs_table[] = { · 6 unmodified lines | ||
| 271 | 271 | .dma_in_enabled = 1, |
| 272 | 272 | .dma_in_nbr = SER0_RX_DMA_NBR, |
| 273 | 273 | .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR, |
| 274 | − .dma_in_irq_flags = IRQF_DISABLED, | |
| 274 | + .dma_in_irq_flags = 0, | |
| 275 | 275 | .dma_in_irq_description = "serial 0 dma rec", |
| 276 | 276 | #else |
| 277 | 277 | .dma_in_enabled = 0, |
| @@ -313,7 +313,7 @@ static struct e100_serial rs_table[] = { · 35 unmodified lines | ||
| 313 | 313 | .dma_out_enabled = 1, |
| 314 | 314 | .dma_out_nbr = SER1_TX_DMA_NBR, |
| 315 | 315 | .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR, |
| 316 | − .dma_out_irq_flags = IRQF_DISABLED, | |
| 316 | + .dma_out_irq_flags = 0, | |
| 317 | 317 | .dma_out_irq_description = "serial 1 dma tr", |
| 318 | 318 | #else |
| 319 | 319 | .dma_out_enabled = 0, |
| @@ -326,7 +326,7 @@ static struct e100_serial rs_table[] = { · 6 unmodified lines | ||
| 326 | 326 | .dma_in_enabled = 1, |
| 327 | 327 | .dma_in_nbr = SER1_RX_DMA_NBR, |
| 328 | 328 | .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR, |
| 329 | − .dma_in_irq_flags = IRQF_DISABLED, | |
| 329 | + .dma_in_irq_flags = 0, | |
| 330 | 330 | .dma_in_irq_description = "serial 1 dma rec", |
| 331 | 331 | #else |
| 332 | 332 | .dma_in_enabled = 0, |
| @@ -369,7 +369,7 @@ static struct e100_serial rs_table[] = { · 36 unmodified lines | ||
| 369 | 369 | .dma_out_enabled = 1, |
| 370 | 370 | .dma_out_nbr = SER2_TX_DMA_NBR, |
| 371 | 371 | .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR, |
| 372 | − .dma_out_irq_flags = IRQF_DISABLED, | |
| 372 | + .dma_out_irq_flags = 0, | |
| 373 | 373 | .dma_out_irq_description = "serial 2 dma tr", |
| 374 | 374 | #else |
| 375 | 375 | .dma_out_enabled = 0, |
| @@ -382,7 +382,7 @@ static struct e100_serial rs_table[] = { · 6 unmodified lines | ||
| 382 | 382 | .dma_in_enabled = 1, |
| 383 | 383 | .dma_in_nbr = SER2_RX_DMA_NBR, |
| 384 | 384 | .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR, |
| 385 | − .dma_in_irq_flags = IRQF_DISABLED, | |
| 385 | + .dma_in_irq_flags = 0, | |
| 386 | 386 | .dma_in_irq_description = "serial 2 dma rec", |
| 387 | 387 | #else |
| 388 | 388 | .dma_in_enabled = 0, |
| @@ -423,7 +423,7 @@ static struct e100_serial rs_table[] = { · 34 unmodified lines | ||
| 423 | 423 | .dma_out_enabled = 1, |
| 424 | 424 | .dma_out_nbr = SER3_TX_DMA_NBR, |
| 425 | 425 | .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR, |
| 426 | − .dma_out_irq_flags = IRQF_DISABLED, | |
| 426 | + .dma_out_irq_flags = 0, | |
| 427 | 427 | .dma_out_irq_description = "serial 3 dma tr", |
| 428 | 428 | #else |
| 429 | 429 | .dma_out_enabled = 0, |
| @@ -436,7 +436,7 @@ static struct e100_serial rs_table[] = { · 6 unmodified lines | ||
| 436 | 436 | .dma_in_enabled = 1, |
| 437 | 437 | .dma_in_nbr = SER3_RX_DMA_NBR, |
| 438 | 438 | .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR, |
| 439 | − .dma_in_irq_flags = IRQF_DISABLED, | |
| 439 | + .dma_in_irq_flags = 0, | |
| 440 | 440 | .dma_in_irq_description = "serial 3 dma rec", |
| 441 | 441 | #else |
| 442 | 442 | .dma_in_enabled = 0, |
| @@ -1788,7 +1788,7 @@ static unsigned int handle_descr_data(struct e100_serial *info, · 1345 unmodified lines | ||
| 1788 | 1788 | struct etrax_recv_buffer *buffer = phys_to_virt(descr->buf) - sizeof *buffer; |
| 1789 | 1789 | |
| 1790 | 1790 | if (info->recv_cnt + recvl > 65536) { |
| 1791 | − printk(KERN_CRIT | |
| 1791 | + printk(KERN_WARNING | |
| 1792 | 1792 | "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __func__, recvl); |
| 1793 | 1793 | return 0; |
| 1794 | 1794 | } |
| @@ -3813,13 +3813,13 @@ rs_close(struct tty_struct *tty, struct file * filp) · 2018 unmodified lines | ||
| 3813 | 3813 | * one, we've got real problems, since it means the |
| 3814 | 3814 | * serial port won't be shutdown. |
| 3815 | 3815 | */ |
| 3816 | − printk(KERN_CRIT | |
| 3816 | + printk(KERN_ERR | |
| 3817 | 3817 | "rs_close: bad serial port count; tty->count is 1, " |
| 3818 | 3818 | "info->count is %d\n", info->count); |
| 3819 | 3819 | info->count = 1; |
| 3820 | 3820 | } |
| 3821 | 3821 | if (--info->count < 0) { |
| 3822 | − printk(KERN_CRIT "rs_close: bad serial port count for ttyS%d: %d\n", | |
| 3822 | + printk(KERN_ERR "rs_close: bad serial port count for ttyS%d: %d\n", | |
| 3823 | 3823 | info->line, info->count); |
| 3824 | 3824 | info->count = 0; |
| 3825 | 3825 | } |
| @@ -4452,7 +4452,7 @@ static int __init rs_init(void) · 626 unmodified lines | ||
| 4452 | 4452 | #if defined(CONFIG_ETRAX_RS485_ON_PA) |
| 4453 | 4453 | if (cris_io_interface_allocate_pins(if_serial_0, 'a', rs485_pa_bit, |
| 4454 | 4454 | rs485_pa_bit)) { |
| 4455 | − printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " | |
| 4455 | + printk(KERN_ERR "ETRAX100LX serial: Could not allocate " | |
| 4456 | 4456 | "RS485 pin\n"); |
| 4457 | 4457 | put_tty_driver(driver); |
| 4458 | 4458 | return -EBUSY; |
| @@ -4461,7 +4461,7 @@ static int __init rs_init(void) · 2 unmodified lines | ||
| 4461 | 4461 | #if defined(CONFIG_ETRAX_RS485_ON_PORT_G) |
| 4462 | 4462 | if (cris_io_interface_allocate_pins(if_serial_0, 'g', rs485_pa_bit, |
| 4463 | 4463 | rs485_port_g_bit)) { |
| 4464 | − printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " | |
| 4464 | + printk(KERN_ERR "ETRAX100LX serial: Could not allocate " | |
| 4465 | 4465 | "RS485 pin\n"); |
| 4466 | 4466 | put_tty_driver(driver); |
| 4467 | 4467 | return -EBUSY; |
| @@ -4494,7 +4494,7 @@ static int __init rs_init(void) · 26 unmodified lines | ||
| 4494 | 4494 | if (info->enabled) { |
| 4495 | 4495 | if (cris_request_io_interface(info->io_if, |
| 4496 | 4496 | info->io_if_description)) { |
| 4497 | − printk(KERN_CRIT "ETRAX100LX async serial: " | |
| 4497 | + printk(KERN_ERR "ETRAX100LX async serial: " | |
| 4498 | 4498 | "Could not allocate IO pins for " |
| 4499 | 4499 | "%s, port %d\n", |
| 4500 | 4500 | info->io_if_description, i); |
| @@ -4558,7 +4558,7 @@ static int __init rs_init(void) · 57 unmodified lines | ||
| 4558 | 4558 | /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ |
| 4559 | 4559 | |
| 4560 | 4560 | if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, |
| 4561 | − IRQF_SHARED | IRQF_DISABLED, "serial ", driver)) | |
| 4561 | + IRQF_SHARED, "serial ", driver)) | |
| 4562 | 4562 | panic("%s: Failed to request irq8", __func__); |
| 4563 | 4563 | |
| 4564 | 4564 | #endif |
| @@ -47,6 +47,7 @@ · 46 unmodified lines | ||
| 47 | 47 | #include <linux/serial_core.h> |
| 48 | 48 | #include <linux/sysrq.h> |
| 49 | 49 | #include <linux/tty.h> |
| 50 | +#include <linux/tty_flip.h> | |
| 50 | 51 | |
| 51 | 52 | #include <linux/atomic.h> |
| 52 | 53 | #include <asm/bootinfo.h> |
| @@ -1554,7 +1554,7 @@ static int __devinit icom_probe(struct pci_dev *dev, · 1553 unmodified lines | ||
| 1554 | 1554 | |
| 1555 | 1555 | /* save off irq and request irq line */ |
| 1556 | 1556 | if ( (retval = request_irq(dev->irq, icom_interrupt, |
| 1557 | − IRQF_DISABLED | IRQF_SHARED, ICOM_DRIVER_NAME, | |
| 1557 | + IRQF_SHARED, ICOM_DRIVER_NAME, | |
| 1558 | 1558 | (void *) icom_adapter))) { |
| 1559 | 1559 | goto probe_exit2; |
| 1560 | 1560 | } |
| @@ -508,8 +508,10 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) · 507 unmodified lines | ||
| 508 | 508 | if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx)) |
| 509 | 509 | continue; |
| 510 | 510 | |
| 511 | − if (rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) ) { | |
| 512 | − if (rx & URXD_PRERR) | |
| 511 | + if (unlikely(rx & URXD_ERR)) { | |
| 512 | + if (rx & URXD_BRK) | |
| 513 | + sport->port.icount.brk++; | |
| 514 | + else if (rx & URXD_PRERR) | |
| 513 | 515 | sport->port.icount.parity++; |
| 514 | 516 | else if (rx & URXD_FRMERR) |
| 515 | 517 | sport->port.icount.frame++; |
| @@ -524,7 +526,9 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) · 8 unmodified lines | ||
| 524 | 526 | |
| 525 | 527 | rx &= sport->port.read_status_mask; |
| 526 | 528 | |
| 527 | − if (rx & URXD_PRERR) | |
| 529 | + if (rx & URXD_BRK) | |
| 530 | + flg = TTY_BREAK; | |
| 531 | + else if (rx & URXD_PRERR) | |
| 528 | 532 | flg = TTY_PARITY; |
| 529 | 533 | else if (rx & URXD_FRMERR) |
| 530 | 534 | flg = TTY_FRAME; |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | */ |
| 14 | 14 | #include <linux/errno.h> |
| 15 | 15 | #include <linux/tty.h> |
| 16 | +#include <linux/tty_flip.h> | |
| 16 | 17 | #include <linux/serial.h> |
| 17 | 18 | #include <linux/circ_buf.h> |
| 18 | 19 | #include <linux/serial_reg.h> |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | */ |
| 15 | 15 | #include <linux/errno.h> |
| 16 | 16 | #include <linux/tty.h> |
| 17 | +#include <linux/tty_flip.h> | |
| 17 | 18 | #include <linux/serial.h> |
| 18 | 19 | #include <linux/serialP.h> |
| 19 | 20 | #include <linux/circ_buf.h> |
| @@ -88,7 +88,6 @@ enum { · 87 unmodified lines | ||
| 88 | 88 | |
| 89 | 89 | /* 4 extra for alignment play space */ |
| 90 | 90 | #define WRITEBUFLEN ((4096) + 4) |
| 91 | −#define MYFLIPLEN N_TTY_BUF_SIZE | |
| 92 | 91 | |
| 93 | 92 | #define JSM_VERSION "jsm: 1.2-1-INKERNEL" |
| 94 | 93 | #define JSM_PARTNUM "40002438_A-INKERNEL" |
| @@ -150,7 +149,6 @@ struct jsm_board · 55 unmodified lines | ||
| 150 | 149 | u32 bd_uart_offset; /* Space between each UART */ |
| 151 | 150 | |
| 152 | 151 | struct jsm_channel *channels[MAXPORTS]; /* array of pointers to our channels. */ |
| 153 | − char *flipbuf; /* Our flip buffer, alloced if board is found */ | |
| 154 | 152 | |
| 155 | 153 | u32 bd_dividend; /* Board/UARTs specific dividend */ |
| 156 | 154 | |
| @@ -177,16 +175,13 @@ struct jsm_board · 20 unmodified lines | ||
| 177 | 175 | #define CH_TX_FIFO_LWM 0x0800 /* TX Fifo is below Low Water */ |
| 178 | 176 | #define CH_BREAK_SENDING 0x1000 /* Break is being sent */ |
| 179 | 177 | #define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */ |
| 180 | −#define CH_FLIPBUF_IN_USE 0x4000 /* Channel's flipbuf is in use */ | |
| 181 | 178 | #define CH_BAUD0 0x08000 /* Used for checking B0 transitions */ |
| 182 | 179 | |
| 183 | 180 | /* Our Read/Error/Write queue sizes */ |
| 184 | 181 | #define RQUEUEMASK 0x1FFF /* 8 K - 1 */ |
| 185 | 182 | #define EQUEUEMASK 0x1FFF /* 8 K - 1 */ |
| 186 | −#define WQUEUEMASK 0x0FFF /* 4 K - 1 */ | |
| 187 | 183 | #define RQUEUESIZE (RQUEUEMASK + 1) |
| 188 | 184 | #define EQUEUESIZE RQUEUESIZE |
| 189 | −#define WQUEUESIZE (WQUEUEMASK + 1) | |
| 190 | 185 | |
| 191 | 186 | |
| 192 | 187 | /************************************************************************ |
| @@ -226,10 +221,6 @@ struct jsm_channel { · 33 unmodified lines | ||
| 226 | 221 | u16 ch_e_head; /* Head location of the error queue */ |
| 227 | 222 | u16 ch_e_tail; /* Tail location of the error queue */ |
| 228 | 223 | |
| 229 | − u8 *ch_wqueue; /* Our write queue buffer - malloc'ed */ | |
| 230 | − u16 ch_w_head; /* Head location of the write queue */ | |
| 231 | − u16 ch_w_tail; /* Tail location of the write queue */ | |
| 232 | − | |
| 233 | 224 | u64 ch_rxcount; /* total of data received so far */ |
| 234 | 225 | u64 ch_txcount; /* total of data transmitted so far */ |
| 235 | 226 | |
| @@ -378,7 +369,6 @@ extern int jsm_debug; · 142 unmodified lines | ||
| 378 | 369 | * Prototypes for non-static functions used in more than one module |
| 379 | 370 | * |
| 380 | 371 | *************************************************************************/ |
| 381 | −int jsm_tty_write(struct uart_port *port); | |
| 382 | 372 | int jsm_tty_init(struct jsm_board *); |
| 383 | 373 | int jsm_uart_port_init(struct jsm_board *); |
| 384 | 374 | int jsm_remove_uart_port(struct jsm_board *); |
| @@ -160,27 +160,10 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device · 159 unmodified lines | ||
| 160 | 160 | dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n", |
| 161 | 161 | adapter_count, brd->rev, brd->irq); |
| 162 | 162 | |
| 163 | − /* | |
| 164 | − * allocate flip buffer for board. | |
| 165 | − * | |
| 166 | − * Okay to malloc with GFP_KERNEL, we are not at interrupt | |
| 167 | − * context, and there are no locks held. | |
| 168 | − */ | |
| 169 | − brd->flipbuf = kzalloc(MYFLIPLEN, GFP_KERNEL); | |
| 170 | − if (!brd->flipbuf) { | |
| 171 | − /* XXX: leaking all resources from jsm_tty_init and | |
| 172 | − jsm_uart_port_init here! */ | |
| 173 | − dev_err(&pdev->dev, "memory allocation for flipbuf failed\n"); | |
| 174 | − rc = -ENOMEM; | |
| 175 | − goto out_free_uart; | |
| 176 | − } | |
| 177 | − | |
| 178 | 163 | pci_set_drvdata(pdev, brd); |
| 179 | 164 | pci_save_state(pdev); |
| 180 | 165 | |
| 181 | 166 | return 0; |
| 182 | − out_free_uart: | |
| 183 | − jsm_remove_uart_port(brd); | |
| 184 | 167 | out_free_irq: |
| 185 | 168 | jsm_remove_uart_port(brd); |
| 186 | 169 | free_irq(brd->irq, brd); |
| @@ -211,14 +194,12 @@ static void __devexit jsm_remove_one(struct pci_dev *pdev) · 24 unmodified lines | ||
| 211 | 194 | if (brd->channels[i]) { |
| 212 | 195 | kfree(brd->channels[i]->ch_rqueue); |
| 213 | 196 | kfree(brd->channels[i]->ch_equeue); |
| 214 | − kfree(brd->channels[i]->ch_wqueue); | |
| 215 | 197 | kfree(brd->channels[i]); |
| 216 | 198 | } |
| 217 | 199 | } |
| 218 | 200 | |
| 219 | 201 | pci_release_regions(pdev); |
| 220 | 202 | pci_disable_device(pdev); |
| 221 | − kfree(brd->flipbuf); | |
| 222 | 203 | kfree(brd); |
| 223 | 204 | } |
| 224 | 205 | |
| @@ -496,12 +496,15 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch) · 495 unmodified lines | ||
| 496 | 496 | int s; |
| 497 | 497 | int qlen; |
| 498 | 498 | u32 len_written = 0; |
| 499 | + struct circ_buf *circ; | |
| 499 | 500 | |
| 500 | 501 | if (!ch) |
| 501 | 502 | return; |
| 502 | 503 | |
| 504 | + circ = &ch->uart_port.state->xmit; | |
| 505 | + | |
| 503 | 506 | /* No data to write to the UART */ |
| 504 | − if (ch->ch_w_tail == ch->ch_w_head) | |
| 507 | + if (uart_circ_empty(circ)) | |
| 505 | 508 | return; |
| 506 | 509 | |
| 507 | 510 | /* If port is "stopped", don't send any data to the UART */ |
| @@ -517,11 +520,10 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch) · 9 unmodified lines | ||
| 517 | 520 | if (ch->ch_cached_lsr & UART_LSR_THRE) { |
| 518 | 521 | ch->ch_cached_lsr &= ~(UART_LSR_THRE); |
| 519 | 522 | |
| 520 | − writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx); | |
| 523 | + writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx); | |
| 521 | 524 | jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev, |
| 522 | − "Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]); | |
| 523 | − ch->ch_w_tail++; | |
| 524 | − ch->ch_w_tail &= WQUEUEMASK; | |
| 525 | + "Tx data: %x\n", circ->buf[circ->tail]); | |
| 526 | + circ->tail = (circ->tail + 1) & (UART_XMIT_SIZE - 1); | |
| 525 | 527 | ch->ch_txcount++; |
| 526 | 528 | } |
| 527 | 529 | return; |
| @@ -536,36 +538,36 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch) · 8 unmodified lines | ||
| 536 | 538 | n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel; |
| 537 | 539 | |
| 538 | 540 | /* cache head and tail of queue */ |
| 539 | − head = ch->ch_w_head & WQUEUEMASK; | |
| 540 | − tail = ch->ch_w_tail & WQUEUEMASK; | |
| 541 | − qlen = (head - tail) & WQUEUEMASK; | |
| 541 | + head = circ->head & (UART_XMIT_SIZE - 1); | |
| 542 | + tail = circ->tail & (UART_XMIT_SIZE - 1); | |
| 543 | + qlen = uart_circ_chars_pending(circ); | |
| 542 | 544 | |
| 543 | 545 | /* Find minimum of the FIFO space, versus queue length */ |
| 544 | 546 | n = min(n, qlen); |
| 545 | 547 | |
| 546 | 548 | while (n > 0) { |
| 547 | 549 | |
| 548 | − s = ((head >= tail) ? head : WQUEUESIZE) - tail; | |
| 550 | + s = ((head >= tail) ? head : UART_XMIT_SIZE) - tail; | |
| 549 | 551 | s = min(s, n); |
| 550 | 552 | |
| 551 | 553 | if (s <= 0) |
| 552 | 554 | break; |
| 553 | 555 | |
| 554 | − memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s); | |
| 556 | + memcpy_toio(&ch->ch_neo_uart->txrxburst, circ->buf + tail, s); | |
| 555 | 557 | /* Add and flip queue if needed */ |
| 556 | − tail = (tail + s) & WQUEUEMASK; | |
| 558 | + tail = (tail + s) & (UART_XMIT_SIZE - 1); | |
| 557 | 559 | n -= s; |
| 558 | 560 | ch->ch_txcount += s; |
| 559 | 561 | len_written += s; |
| 560 | 562 | } |
| 561 | 563 | |
| 562 | 564 | /* Update the final tail */ |
| 563 | − ch->ch_w_tail = tail & WQUEUEMASK; | |
| 565 | + circ->tail = tail & (UART_XMIT_SIZE - 1); | |
| 564 | 566 | |
| 565 | 567 | if (len_written >= ch->ch_t_tlevel) |
| 566 | 568 | ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); |
| 567 | 569 | |
| 568 | − if (!jsm_tty_write(&ch->uart_port)) | |
| 570 | + if (uart_circ_empty(circ)) | |
| 569 | 571 | uart_write_wakeup(&ch->uart_port); |
| 570 | 572 | } |
| 571 | 573 | |
| @@ -946,7 +948,6 @@ static void neo_param(struct jsm_channel *ch) · 374 unmodified lines | ||
| 946 | 948 | if ((ch->ch_c_cflag & (CBAUD)) == 0) { |
| 947 | 949 | ch->ch_r_head = ch->ch_r_tail = 0; |
| 948 | 950 | ch->ch_e_head = ch->ch_e_tail = 0; |
| 949 | − ch->ch_w_head = ch->ch_w_tail = 0; | |
| 950 | 951 | |
| 951 | 952 | neo_flush_uart_write(ch); |
| 952 | 953 | neo_flush_uart_read(ch); |
| @@ -118,6 +118,19 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl) · 117 unmodified lines | ||
| 118 | 118 | udelay(10); |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | +/* | |
| 122 | + * jsm_tty_write() | |
| 123 | + * | |
| 124 | + * Take data from the user or kernel and send it out to the FEP. | |
| 125 | + * In here exists all the Transparent Print magic as well. | |
| 126 | + */ | |
| 127 | +static void jsm_tty_write(struct uart_port *port) | |
| 128 | +{ | |
| 129 | + struct jsm_channel *channel; | |
| 130 | + channel = container_of(port, struct jsm_channel, uart_port); | |
| 131 | + channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel); | |
| 132 | +} | |
| 133 | + | |
| 121 | 134 | static void jsm_tty_start_tx(struct uart_port *port) |
| 122 | 135 | { |
| 123 | 136 | struct jsm_channel *channel = (struct jsm_channel *)port; |
| @@ -216,14 +229,6 @@ static int jsm_tty_open(struct uart_port *port) · 92 unmodified lines | ||
| 216 | 229 | return -ENOMEM; |
| 217 | 230 | } |
| 218 | 231 | } |
| 219 | − if (!channel->ch_wqueue) { | |
| 220 | − channel->ch_wqueue = kzalloc(WQUEUESIZE, GFP_KERNEL); | |
| 221 | − if (!channel->ch_wqueue) { | |
| 222 | − jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev, | |
| 223 | − "unable to allocate write queue buf"); | |
| 224 | − return -ENOMEM; | |
| 225 | − } | |
| 226 | − } | |
| 227 | 232 | |
| 228 | 233 | channel->ch_flags &= ~(CH_OPENING); |
| 229 | 234 | /* |
| @@ -237,7 +242,6 @@ static int jsm_tty_open(struct uart_port *port) · 7 unmodified lines | ||
| 237 | 242 | */ |
| 238 | 243 | channel->ch_r_head = channel->ch_r_tail = 0; |
| 239 | 244 | channel->ch_e_head = channel->ch_e_tail = 0; |
| 240 | − channel->ch_w_head = channel->ch_w_tail = 0; | |
| 241 | 245 | |
| 242 | 246 | brd->bd_ops->flush_uart_write(channel); |
| 243 | 247 | brd->bd_ops->flush_uart_read(channel); |
| @@ -836,75 +840,3 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch) · 592 unmodified lines | ||
| 836 | 840 | } |
| 837 | 841 | } |
| 838 | 842 | } |
| 839 | − | |
| 840 | −/* | |
| 841 | − * jsm_tty_write() | |
| 842 | − * | |
| 843 | − * Take data from the user or kernel and send it out to the FEP. | |
| 844 | − * In here exists all the Transparent Print magic as well. | |
| 845 | − */ | |
| 846 | −int jsm_tty_write(struct uart_port *port) | |
| 847 | −{ | |
| 848 | − int bufcount; | |
| 849 | − int data_count = 0,data_count1 =0; | |
| 850 | − u16 head; | |
| 851 | − u16 tail; | |
| 852 | − u16 tmask; | |
| 853 | − u32 remain; | |
| 854 | − int temp_tail = port->state->xmit.tail; | |
| 855 | − struct jsm_channel *channel = (struct jsm_channel *)port; | |
| 856 | − | |
| 857 | − tmask = WQUEUEMASK; | |
| 858 | − head = (channel->ch_w_head) & tmask; | |
| 859 | − tail = (channel->ch_w_tail) & tmask; | |
| 860 | − | |
| 861 | − if ((bufcount = tail - head - 1) < 0) | |
| 862 | − bufcount += WQUEUESIZE; | |
| 863 | − | |
| 864 | − bufcount = min(bufcount, 56); | |
| 865 | − remain = WQUEUESIZE - head; | |
| 866 | − | |
| 867 | − data_count = 0; | |
| 868 | − if (bufcount >= remain) { | |
| 869 | − bufcount -= remain; | |
| 870 | − while ((port->state->xmit.head != temp_tail) && | |
| 871 | − (data_count < remain)) { | |
| 872 | − channel->ch_wqueue[head++] = | |
| 873 | − port->state->xmit.buf[temp_tail]; | |
| 874 | − | |
| 875 | − temp_tail++; | |
| 876 | − temp_tail &= (UART_XMIT_SIZE - 1); | |
| 877 | − data_count++; | |
| 878 | − } | |
| 879 | − if (data_count == remain) head = 0; | |
| 880 | − } | |
| 881 | − | |
| 882 | − data_count1 = 0; | |
| 883 | − if (bufcount > 0) { | |
| 884 | − remain = bufcount; | |
| 885 | − while ((port->state->xmit.head != temp_tail) && | |
| 886 | − (data_count1 < remain)) { | |
| 887 | − channel->ch_wqueue[head++] = | |
| 888 | − port->state->xmit.buf[temp_tail]; | |
| 889 | − | |
| 890 | − temp_tail++; | |
| 891 | − temp_tail &= (UART_XMIT_SIZE - 1); | |
| 892 | − data_count1++; | |
| 893 | − | |
| 894 | − } | |
| 895 | − } | |
| 896 | − | |
| 897 | − port->state->xmit.tail = temp_tail; | |
| 898 | − | |
| 899 | − data_count += data_count1; | |
| 900 | − if (data_count) { | |
| 901 | − head &= tmask; | |
| 902 | − channel->ch_w_head = head; | |
| 903 | − } | |
| 904 | − | |
| 905 | − if (data_count) { | |
| 906 | − channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel); | |
| 907 | − } | |
| 908 | − | |
| 909 | − return data_count; | |
| 910 | −} | |
| @@ -338,21 +338,21 @@ lqasc_startup(struct uart_port *port) · 337 unmodified lines | ||
| 338 | 338 | ASCCON_ROEN, port->membase + LTQ_ASC_CON); |
| 339 | 339 | |
| 340 | 340 | retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, |
| 341 | − IRQF_DISABLED, "asc_tx", port); | |
| 341 | + 0, "asc_tx", port); | |
| 342 | 342 | if (retval) { |
| 343 | 343 | pr_err("failed to request lqasc_tx_int\n"); |
| 344 | 344 | return retval; |
| 345 | 345 | } |
| 346 | 346 | |
| 347 | 347 | retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, |
| 348 | − IRQF_DISABLED, "asc_rx", port); | |
| 348 | + 0, "asc_rx", port); | |
| 349 | 349 | if (retval) { |
| 350 | 350 | pr_err("failed to request lqasc_rx_int\n"); |
| 351 | 351 | goto err1; |
| 352 | 352 | } |
| 353 | 353 | |
| 354 | 354 | retval = request_irq(ltq_port->err_irq, lqasc_err_int, |
| 355 | − IRQF_DISABLED, "asc_err", port); | |
| 355 | + 0, "asc_err", port); | |
| 356 | 356 | if (retval) { |
| 357 | 357 | pr_err("failed to request lqasc_err_int\n"); |
| 358 | 358 | goto err2; |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | ||
| 32 | 32 | |
| 33 | 33 | #include <linux/module.h> |
| 34 | 34 | #include <linux/tty.h> |
| 35 | +#include <linux/tty_flip.h> | |
| 35 | 36 | #include <linux/ioport.h> |
| 36 | 37 | #include <linux/init.h> |
| 37 | 38 | #include <linux/console.h> |
| @@ -47,6 +47,8 @@ · 46 unmodified lines | ||
| 47 | 47 | #include <linux/serial.h> |
| 48 | 48 | #include <linux/spi/spi.h> |
| 49 | 49 | #include <linux/freezer.h> |
| 50 | +#include <linux/tty.h> | |
| 51 | +#include <linux/tty_flip.h> | |
| 50 | 52 | |
| 51 | 53 | #include <linux/serial_max3100.h> |
| 52 | 54 | |
| @@ -31,6 +31,8 @@ · 30 unmodified lines | ||
| 31 | 31 | #include <linux/device.h> |
| 32 | 32 | #include <linux/serial_core.h> |
| 33 | 33 | #include <linux/serial.h> |
| 34 | +#include <linux/tty.h> | |
| 35 | +#include <linux/tty_flip.h> | |
| 34 | 36 | #include <linux/gpio.h> |
| 35 | 37 | #include <linux/spi/spi.h> |
| 36 | 38 | #include <linux/freezer.h> |
| @@ -380,7 +380,7 @@ static void mcf_config_port(struct uart_port *port, int flags) · 379 unmodified lines | ||
| 380 | 380 | /* Clear mask, so no surprise interrupts. */ |
| 381 | 381 | writeb(0, port->membase + MCFUART_UIMR); |
| 382 | 382 | |
| 383 | − if (request_irq(port->irq, mcf_interrupt, IRQF_DISABLED, "UART", port)) | |
| 383 | + if (request_irq(port->irq, mcf_interrupt, 0, "UART", port)) | |
| 384 | 384 | printk(KERN_ERR "MCF: unable to attach ColdFire UART %d " |
| 385 | 385 | "interrupt vector=%d\n", port->line, port->irq); |
| 386 | 386 | } |
| @@ -38,6 +38,7 @@ · 37 unmodified lines | ||
| 38 | 38 | #include <linux/pci.h> |
| 39 | 39 | #include <linux/io.h> |
| 40 | 40 | #include <linux/debugfs.h> |
| 41 | +#include <linux/pm_runtime.h> | |
| 41 | 42 | |
| 42 | 43 | #define HSU_DMA_BUF_SIZE 2048 |
| 43 | 44 | |
| @@ -764,6 +765,8 @@ static int serial_hsu_startup(struct uart_port *port) · 720 unmodified lines | ||
| 764 | 765 | container_of(port, struct uart_hsu_port, port); |
| 765 | 766 | unsigned long flags; |
| 766 | 767 | |
| 768 | + pm_runtime_get_sync(up->dev); | |
| 769 | + | |
| 767 | 770 | /* |
| 768 | 771 | * Clear the FIFO buffers and disable them. |
| 769 | 772 | * (they will be reenabled in set_termios()) |
| @@ -871,6 +874,8 @@ static void serial_hsu_shutdown(struct uart_port *port) · 101 unmodified lines | ||
| 871 | 874 | UART_FCR_CLEAR_RCVR | |
| 872 | 875 | UART_FCR_CLEAR_XMIT); |
| 873 | 876 | serial_out(up, UART_FCR, 0); |
| 877 | + | |
| 878 | + pm_runtime_put(up->dev); | |
| 874 | 879 | } |
| 875 | 880 | |
| 876 | 881 | static void |
| @@ -1249,6 +1254,39 @@ static int serial_hsu_resume(struct pci_dev *pdev) · 372 unmodified lines | ||
| 1249 | 1254 | #define serial_hsu_resume NULL |
| 1250 | 1255 | #endif |
| 1251 | 1256 | |
| 1257 | +#ifdef CONFIG_PM_RUNTIME | |
| 1258 | +static int serial_hsu_runtime_idle(struct device *dev) | |
| 1259 | +{ | |
| 1260 | + int err; | |
| 1261 | + | |
| 1262 | + err = pm_schedule_suspend(dev, 500); | |
| 1263 | + if (err) | |
| 1264 | + return -EBUSY; | |
| 1265 | + | |
| 1266 | + return 0; | |
| 1267 | +} | |
| 1268 | + | |
| 1269 | +static int serial_hsu_runtime_suspend(struct device *dev) | |
| 1270 | +{ | |
| 1271 | + return 0; | |
| 1272 | +} | |
| 1273 | + | |
| 1274 | +static int serial_hsu_runtime_resume(struct device *dev) | |
| 1275 | +{ | |
| 1276 | + return 0; | |
| 1277 | +} | |
| 1278 | +#else | |
| 1279 | +#define serial_hsu_runtime_idle NULL | |
| 1280 | +#define serial_hsu_runtime_suspend NULL | |
| 1281 | +#define serial_hsu_runtime_resume NULL | |
| 1282 | +#endif | |
| 1283 | + | |
| 1284 | +static const struct dev_pm_ops serial_hsu_pm_ops = { | |
| 1285 | + .runtime_suspend = serial_hsu_runtime_suspend, | |
| 1286 | + .runtime_resume = serial_hsu_runtime_resume, | |
| 1287 | + .runtime_idle = serial_hsu_runtime_idle, | |
| 1288 | +}; | |
| 1289 | + | |
| 1252 | 1290 | /* temp global pointer before we settle down on using one or four PCI dev */ |
| 1253 | 1291 | static struct hsu_port *phsu; |
| 1254 | 1292 | |
| @@ -1315,6 +1353,9 @@ static int serial_hsu_probe(struct pci_dev *pdev, · 60 unmodified lines | ||
| 1315 | 1353 | pci_set_drvdata(pdev, uport); |
| 1316 | 1354 | } |
| 1317 | 1355 | |
| 1356 | + pm_runtime_put_noidle(&pdev->dev); | |
| 1357 | + pm_runtime_allow(&pdev->dev); | |
| 1358 | + | |
| 1318 | 1359 | return 0; |
| 1319 | 1360 | |
| 1320 | 1361 | err_disable: |
| @@ -1411,6 +1452,9 @@ static void serial_hsu_remove(struct pci_dev *pdev) · 90 unmodified lines | ||
| 1411 | 1452 | if (!priv) |
| 1412 | 1453 | return; |
| 1413 | 1454 | |
| 1455 | + pm_runtime_forbid(&pdev->dev); | |
| 1456 | + pm_runtime_get_noresume(&pdev->dev); | |
| 1457 | + | |
| 1414 | 1458 | /* For port 0/1/2, priv is the address of uart_hsu_port */ |
| 1415 | 1459 | if (pdev->device != 0x081E) { |
| 1416 | 1460 | up = priv; |
| @@ -1423,7 +1467,7 @@ static void serial_hsu_remove(struct pci_dev *pdev) · 6 unmodified lines | ||
| 1423 | 1467 | } |
| 1424 | 1468 | |
| 1425 | 1469 | /* First 3 are UART ports, and the 4th is the DMA */ |
| 1426 | −static const struct pci_device_id pci_ids[] __devinitdata = { | |
| 1470 | +static const struct pci_device_id pci_ids[] __devinitconst = { | |
| 1427 | 1471 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) }, |
| 1428 | 1472 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) }, |
| 1429 | 1473 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) }, |
| @@ -1438,6 +1482,9 @@ static struct pci_driver hsu_pci_driver = { · 8 unmodified lines | ||
| 1438 | 1482 | .remove = __devexit_p(serial_hsu_remove), |
| 1439 | 1483 | .suspend = serial_hsu_suspend, |
| 1440 | 1484 | .resume = serial_hsu_resume, |
| 1485 | + .driver = { | |
| 1486 | + .pm = &serial_hsu_pm_ops, | |
| 1487 | + }, | |
| 1441 | 1488 | }; |
| 1442 | 1489 | |
| 1443 | 1490 | static int __init hsu_pci_init(void) |
| @@ -34,6 +34,7 @@ · 33 unmodified lines | ||
| 34 | 34 | #include <linux/device.h> |
| 35 | 35 | #include <linux/module.h> |
| 36 | 36 | #include <linux/tty.h> |
| 37 | +#include <linux/tty_flip.h> | |
| 37 | 38 | #include <linux/serial.h> |
| 38 | 39 | #include <linux/sysrq.h> |
| 39 | 40 | #include <linux/console.h> |
| @@ -273,7 +274,7 @@ static unsigned int mpc5200b_psc_set_baudrate(struct uart_port *port, · 233 unmodified lines | ||
| 273 | 274 | |
| 274 | 275 | static void mpc52xx_psc_get_irq(struct uart_port *port, struct device_node *np) |
| 275 | 276 | { |
| 276 | − port->irqflags = IRQF_DISABLED; | |
| 277 | + port->irqflags = 0; | |
| 277 | 278 | port->irq = irq_of_parse_and_map(np, 0); |
| 278 | 279 | } |
| 279 | 280 | |
| @@ -27,6 +27,10 @@ · 26 unmodified lines | ||
| 27 | 27 | * interrupt for a low speed UART device |
| 28 | 28 | */ |
| 29 | 29 | |
| 30 | +#ifdef CONFIG_MAGIC_SYSRQ | |
| 31 | +#define SUPPORT_SYSRQ | |
| 32 | +#endif | |
| 33 | + | |
| 30 | 34 | #include <linux/module.h> |
| 31 | 35 | #include <linux/ioport.h> |
| 32 | 36 | #include <linux/irq.h> |
| @@ -73,9 +77,9 @@ struct uart_max3110 { · 40 unmodified lines | ||
| 73 | 77 | /* global data structure, may need be removed */ |
| 74 | 78 | static struct uart_max3110 *pmax; |
| 75 | 79 | |
| 76 | −static void receive_chars(struct uart_max3110 *max, | |
| 77 | − unsigned char *str, int len); | |
| 78 | −static int max3110_read_multi(struct uart_max3110 *max, u8 *buf); | |
| 80 | +static int receive_chars(struct uart_max3110 *max, | |
| 81 | + unsigned short *str, int len); | |
| 82 | +static int max3110_read_multi(struct uart_max3110 *max); | |
| 79 | 83 | static void max3110_con_receive(struct uart_max3110 *max); |
| 80 | 84 | |
| 81 | 85 | static int max3110_write_then_read(struct uart_max3110 *max, |
| @@ -108,7 +112,6 @@ static int max3110_out(struct uart_max3110 *max, const u16 out) · 26 unmodified lines | ||
| 108 | 112 | { |
| 109 | 113 | void *buf; |
| 110 | 114 | u16 *obuf, *ibuf; |
| 111 | − u8 ch; | |
| 112 | 115 | int ret; |
| 113 | 116 | |
| 114 | 117 | buf = kzalloc(8, GFP_KERNEL | GFP_DMA); |
| @@ -125,11 +128,7 @@ static int max3110_out(struct uart_max3110 *max, const u16 out) · 10 unmodified lines | ||
| 125 | 128 | goto exit; |
| 126 | 129 | } |
| 127 | 130 | |
| 128 | − /* If some valid data is read back */ | |
| 129 | − if (*ibuf & MAX3110_READ_DATA_AVAILABLE) { | |
| 130 | − ch = *ibuf & 0xff; | |
| 131 | − receive_chars(max, &ch, 1); | |
| 132 | − } | |
| 131 | + receive_chars(max, ibuf, 1); | |
| 133 | 132 | |
| 134 | 133 | exit: |
| 135 | 134 | kfree(buf); |
| @@ -142,12 +141,11 @@ exit: · 6 unmodified lines | ||
| 142 | 141 | * |
| 143 | 142 | * Return how many valide bytes are read back |
| 144 | 143 | */ |
| 145 | −static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf) | |
| 144 | +static int max3110_read_multi(struct uart_max3110 *max) | |
| 146 | 145 | { |
| 147 | 146 | void *buf; |
| 148 | 147 | u16 *obuf, *ibuf; |
| 149 | − u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH]; | |
| 150 | − int i, j, blen; | |
| 148 | + int ret, blen; | |
| 151 | 149 | |
| 152 | 150 | blen = M3110_RX_FIFO_DEPTH * sizeof(u16); |
| 153 | 151 | buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA); |
| @@ -165,19 +163,10 @@ static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf) · 11 unmodified lines | ||
| 165 | 163 | return 0; |
| 166 | 164 | } |
| 167 | 165 | |
| 168 | − /* If caller doesn't provide a buffer, then handle received char */ | |
| 169 | − pbuf = rxbuf ? rxbuf : valid_str; | |
| 170 | − | |
| 171 | − for (i = 0, j = 0; i < M3110_RX_FIFO_DEPTH; i++) { | |
| 172 | − if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) | |
| 173 | − pbuf[j++] = ibuf[i] & 0xff; | |
| 174 | − } | |
| 175 | − | |
| 176 | − if (j && (pbuf == valid_str)) | |
| 177 | − receive_chars(max, valid_str, j); | |
| 166 | + ret = receive_chars(max, ibuf, M3110_RX_FIFO_DEPTH); | |
| 178 | 167 | |
| 179 | 168 | kfree(buf); |
| 180 | − return j; | |
| 169 | + return ret; | |
| 181 | 170 | } |
| 182 | 171 | |
| 183 | 172 | static void serial_m3110_con_putchar(struct uart_port *port, int ch) |
| @@ -207,7 +196,7 @@ static void serial_m3110_con_write(struct console *co, · 23 unmodified lines | ||
| 207 | 196 | uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar); |
| 208 | 197 | |
| 209 | 198 | if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags)) |
| 210 | − wake_up_process(pmax->main_thread); | |
| 199 | + wake_up(&pmax->wq); | |
| 211 | 200 | } |
| 212 | 201 | |
| 213 | 202 | static int __init |
| @@ -276,8 +265,7 @@ static void send_circ_buf(struct uart_max3110 *max, · 62 unmodified lines | ||
| 276 | 265 | { |
| 277 | 266 | void *buf; |
| 278 | 267 | u16 *obuf, *ibuf; |
| 279 | − u8 valid_str[WORDS_PER_XFER]; | |
| 280 | − int i, j, len, blen, dma_size, left, ret = 0; | |
| 268 | + int i, len, blen, dma_size, left, ret = 0; | |
| 281 | 269 | |
| 282 | 270 | |
| 283 | 271 | dma_size = WORDS_PER_XFER * sizeof(u16) * 2; |
| @@ -301,18 +289,13 @@ static void send_circ_buf(struct uart_max3110 *max, · 17 unmodified lines | ||
| 301 | 289 | } |
| 302 | 290 | |
| 303 | 291 | /* Fail to send msg to console is not very critical */ |
| 292 | + | |
| 304 | 293 | ret = max3110_write_then_read(max, obuf, ibuf, blen, 0); |
| 305 | 294 | if (ret) |
| 306 | 295 | pr_warning(PR_FMT "%s(): get err msg %d\n", |
| 307 | 296 | __func__, ret); |
| 308 | 297 | |
| 309 | − for (i = 0, j = 0; i < len; i++) { | |
| 310 | − if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) | |
| 311 | − valid_str[j++] = ibuf[i] & 0xff; | |
| 312 | − } | |
| 313 | − | |
| 314 | − if (j) | |
| 315 | − receive_chars(max, valid_str, j); | |
| 298 | + receive_chars(max, ibuf, len); | |
| 316 | 299 | |
| 317 | 300 | max->port.icount.tx += len; |
| 318 | 301 | left -= len; |
| @@ -349,33 +332,54 @@ static void serial_m3110_start_tx(struct uart_port *port) · 30 unmodified lines | ||
| 349 | 332 | container_of(port, struct uart_max3110, port); |
| 350 | 333 | |
| 351 | 334 | if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags)) |
| 352 | − wake_up_process(max->main_thread); | |
| 335 | + wake_up(&max->wq); | |
| 353 | 336 | } |
| 354 | 337 | |
| 355 | −static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) | |
| 338 | +static int | |
| 339 | +receive_chars(struct uart_max3110 *max, unsigned short *str, int len) | |
| 356 | 340 | { |
| 357 | 341 | struct uart_port *port = &max->port; |
| 358 | 342 | struct tty_struct *tty; |
| 359 | − int usable; | |
| 343 | + char buf[M3110_RX_FIFO_DEPTH]; | |
| 344 | + int r, w, usable; | |
| 360 | 345 | |
| 361 | 346 | /* If uart is not opened, just return */ |
| 362 | 347 | if (!port->state) |
| 363 | − return; | |
| 348 | + return 0; | |
| 364 | 349 | |
| 365 | − tty = port->state->port.tty; | |
| 350 | + tty = tty_port_tty_get(&port->state->port); | |
| 366 | 351 | if (!tty) |
| 367 | − return; | |
| 352 | + return 0; | |
| 353 | + | |
| 354 | + for (r = 0, w = 0; r < len; r++) { | |
| 355 | + if (str[r] & MAX3110_BREAK && | |
| 356 | + uart_handle_break(port)) | |
| 357 | + continue; | |
| 358 | + | |
| 359 | + if (str[r] & MAX3110_READ_DATA_AVAILABLE) { | |
| 360 | + if (uart_handle_sysrq_char(port, str[r] & 0xff)) | |
| 361 | + continue; | |
| 362 | + | |
| 363 | + buf[w++] = str[r] & 0xff; | |
| 364 | + } | |
| 365 | + } | |
| 366 | + | |
| 367 | + if (!w) { | |
| 368 | + tty_kref_put(tty); | |
| 369 | + return 0; | |
| 370 | + } | |
| 368 | 371 | |
| 369 | − while (len) { | |
| 370 | − usable = tty_buffer_request_room(tty, len); | |
| 372 | + for (r = 0; w; r += usable, w -= usable) { | |
| 373 | + usable = tty_buffer_request_room(tty, w); | |
| 371 | 374 | if (usable) { |
| 372 | − tty_insert_flip_string(tty, str, usable); | |
| 373 | − str += usable; | |
| 375 | + tty_insert_flip_string(tty, buf + r, usable); | |
| 374 | 376 | port->icount.rx += usable; |
| 375 | 377 | } |
| 376 | − len -= usable; | |
| 377 | 378 | } |
| 378 | 379 | tty_flip_buffer_push(tty); |
| 380 | + tty_kref_put(tty); | |
| 381 | + | |
| 382 | + return r; | |
| 379 | 383 | } |
| 380 | 384 | |
| 381 | 385 | /* |
| @@ -390,28 +394,15 @@ static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) · 8 unmodified lines | ||
| 390 | 394 | */ |
| 391 | 395 | static void max3110_con_receive(struct uart_max3110 *max) |
| 392 | 396 | { |
| 393 | − int loop = 1, num, total = 0; | |
| 394 | − u8 recv_buf[512], *pbuf; | |
| 397 | + int loop = 1, num; | |
| 395 | 398 | |
| 396 | − pbuf = recv_buf; | |
| 397 | 399 | do { |
| 398 | − num = max3110_read_multi(max, pbuf); | |
| 400 | + num = max3110_read_multi(max); | |
| 399 | 401 | |
| 400 | 402 | if (num) { |
| 401 | 403 | loop = 5; |
| 402 | − pbuf += num; | |
| 403 | − total += num; | |
| 404 | − | |
| 405 | − if (total >= 504) { | |
| 406 | − receive_chars(max, recv_buf, total); | |
| 407 | − pbuf = recv_buf; | |
| 408 | − total = 0; | |
| 409 | − } | |
| 410 | 404 | } |
| 411 | 405 | } while (--loop); |
| 412 | − | |
| 413 | − if (total) | |
| 414 | − receive_chars(max, recv_buf, total); | |
| 415 | 406 | } |
| 416 | 407 | |
| 417 | 408 | static int max3110_main_thread(void *_max) |
| @@ -424,7 +415,8 @@ static int max3110_main_thread(void *_max) · 6 unmodified lines | ||
| 424 | 415 | pr_info(PR_FMT "start main thread\n"); |
| 425 | 416 | |
| 426 | 417 | do { |
| 427 | − wait_event_interruptible(*wq, max->uart_flags || kthread_should_stop()); | |
| 418 | + wait_event_interruptible(*wq, | |
| 419 | + max->uart_flags || kthread_should_stop()); | |
| 428 | 420 | |
| 429 | 421 | mutex_lock(&max->thread_mutex); |
| 430 | 422 | |
| @@ -452,8 +444,9 @@ static irqreturn_t serial_m3110_irq(int irq, void *dev_id) · 21 unmodified lines | ||
| 452 | 444 | |
| 453 | 445 | /* max3110's irq is a falling edge, not level triggered, |
| 454 | 446 | * so no need to disable the irq */ |
| 447 | + | |
| 455 | 448 | if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags)) |
| 456 | − wake_up_process(max->main_thread); | |
| 449 | + wake_up(&max->wq); | |
| 457 | 450 | |
| 458 | 451 | return IRQ_HANDLED; |
| 459 | 452 | } |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | /* status bits for all 4 MAX3110 operate modes */ |
| 8 | 8 | #define MAX3110_READ_DATA_AVAILABLE (1 << 15) |
| 9 | 9 | #define MAX3110_WRITE_BUF_EMPTY (1 << 14) |
| 10 | +#define MAX3110_BREAK (1 << 10) | |
| 10 | 11 | |
| 11 | 12 | #define WC_TAG (3 << 14) |
| 12 | 13 | #define RC_TAG (1 << 14) |
| @@ -804,8 +804,6 @@ static int __init msm_console_setup(struct console *co, char *options) · 803 unmodified lines | ||
| 804 | 804 | if (unlikely(!port->membase)) |
| 805 | 805 | return -ENXIO; |
| 806 | 806 | |
| 807 | − port->cons = co; | |
| 808 | − | |
| 809 | 807 | msm_init_clock(port); |
| 810 | 808 | |
| 811 | 809 | if (options) |
| @@ -30,6 +30,8 @@ · 29 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | #include <linux/serial.h> |
| 32 | 32 | #include <linux/serial_core.h> |
| 33 | +#include <linux/tty.h> | |
| 34 | +#include <linux/tty_flip.h> | |
| 33 | 35 | #include <linux/slab.h> |
| 34 | 36 | #include <linux/init.h> |
| 35 | 37 | #include <linux/interrupt.h> |
| @@ -21,6 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/ioport.h> |
| 22 | 22 | #include <linux/init.h> |
| 23 | 23 | #include <linux/serial.h> |
| 24 | +#include <linux/tty.h> | |
| 25 | +#include <linux/tty_flip.h> | |
| 24 | 26 | #include <linux/console.h> |
| 25 | 27 | #include <linux/delay.h> /* for udelay */ |
| 26 | 28 | #include <linux/device.h> |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/serial_reg.h> |
| 16 | 16 | #include <linux/serial_core.h> |
| 17 | 17 | #include <linux/tty.h> |
| 18 | +#include <linux/tty_flip.h> | |
| 18 | 19 | #include <linux/irqreturn.h> |
| 19 | 20 | #include <linux/mutex.h> |
| 20 | 21 | #include <linux/of_platform.h> |
| @@ -20,6 +20,8 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/module.h> |
| 21 | 21 | #include <linux/pci.h> |
| 22 | 22 | #include <linux/serial_core.h> |
| 23 | +#include <linux/tty.h> | |
| 24 | +#include <linux/tty_flip.h> | |
| 23 | 25 | #include <linux/interrupt.h> |
| 24 | 26 | #include <linux/io.h> |
| 25 | 27 | #include <linux/dmi.h> |
| @@ -100,6 +100,16 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status) · 99 unmodified lines | ||
| 100 | 100 | int max_count = 256; |
| 101 | 101 | |
| 102 | 102 | do { |
| 103 | + /* work around Errata #20 according to | |
| 104 | + * Intel(R) PXA27x Processor Family | |
| 105 | + * Specification Update (May 2005) | |
| 106 | + * | |
| 107 | + * Step 2 | |
| 108 | + * Disable the Reciever Time Out Interrupt via IER[RTOEI] | |
| 109 | + */ | |
| 110 | + up->ier &= ~UART_IER_RTOIE; | |
| 111 | + serial_out(up, UART_IER, up->ier); | |
| 112 | + | |
| 103 | 113 | ch = serial_in(up, UART_RX); |
| 104 | 114 | flag = TTY_NORMAL; |
| 105 | 115 | up->port.icount.rx++; |
| @@ -156,6 +166,16 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status) · 50 unmodified lines | ||
| 156 | 166 | *status = serial_in(up, UART_LSR); |
| 157 | 167 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); |
| 158 | 168 | tty_flip_buffer_push(tty); |
| 169 | + | |
| 170 | + /* work around Errata #20 according to | |
| 171 | + * Intel(R) PXA27x Processor Family | |
| 172 | + * Specification Update (May 2005) | |
| 173 | + * | |
| 174 | + * Step 6: | |
| 175 | + * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE] | |
| 176 | + */ | |
| 177 | + up->ier |= UART_IER_RTOIE; | |
| 178 | + serial_out(up, UART_IER, up->ier); | |
| 159 | 179 | } |
| 160 | 180 | |
| 161 | 181 | static void transmit_chars(struct uart_pxa_port *up) |
| @@ -83,6 +83,16 @@ static int s3c24xx_serial_txempty_nofifo(struct uart_port *port) · 82 unmodified lines | ||
| 83 | 83 | return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE); |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | +/* | |
| 87 | + * s3c64xx and later SoC's include the interrupt mask and status registers in | |
| 88 | + * the controller itself, unlike the s3c24xx SoC's which have these registers | |
| 89 | + * in the interrupt controller. Check if the port type is s3c64xx or higher. | |
| 90 | + */ | |
| 91 | +static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port) | |
| 92 | +{ | |
| 93 | + return to_ourport(port)->info->type == PORT_S3C6400; | |
| 94 | +} | |
| 95 | + | |
| 86 | 96 | static void s3c24xx_serial_rx_enable(struct uart_port *port) |
| 87 | 97 | { |
| 88 | 98 | unsigned long flags; |
| @@ -126,7 +136,11 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) · 37 unmodified lines | ||
| 126 | 136 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 127 | 137 | |
| 128 | 138 | if (tx_enabled(port)) { |
| 129 | − disable_irq_nosync(ourport->tx_irq); | |
| 139 | + if (s3c24xx_serial_has_interrupt_mask(port)) | |
| 140 | + __set_bit(S3C64XX_UINTM_TXD, | |
| 141 | + portaddrl(port, S3C64XX_UINTM)); | |
| 142 | + else | |
| 143 | + disable_irq_nosync(ourport->tx_irq); | |
| 130 | 144 | tx_enabled(port) = 0; |
| 131 | 145 | if (port->flags & UPF_CONS_FLOW) |
| 132 | 146 | s3c24xx_serial_rx_enable(port); |
| @@ -141,19 +155,26 @@ static void s3c24xx_serial_start_tx(struct uart_port *port) · 8 unmodified lines | ||
| 141 | 155 | if (port->flags & UPF_CONS_FLOW) |
| 142 | 156 | s3c24xx_serial_rx_disable(port); |
| 143 | 157 | |
| 144 | − enable_irq(ourport->tx_irq); | |
| 158 | + if (s3c24xx_serial_has_interrupt_mask(port)) | |
| 159 | + __clear_bit(S3C64XX_UINTM_TXD, | |
| 160 | + portaddrl(port, S3C64XX_UINTM)); | |
| 161 | + else | |
| 162 | + enable_irq(ourport->tx_irq); | |
| 145 | 163 | tx_enabled(port) = 1; |
| 146 | 164 | } |
| 147 | 165 | } |
| 148 | 166 | |
| 149 | − | |
| 150 | 167 | static void s3c24xx_serial_stop_rx(struct uart_port *port) |
| 151 | 168 | { |
| 152 | 169 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 153 | 170 | |
| 154 | 171 | if (rx_enabled(port)) { |
| 155 | 172 | dbg("s3c24xx_serial_stop_rx: port=%p\n", port); |
| 156 | − disable_irq_nosync(ourport->rx_irq); | |
| 173 | + if (s3c24xx_serial_has_interrupt_mask(port)) | |
| 174 | + __set_bit(S3C64XX_UINTM_RXD, | |
| 175 | + portaddrl(port, S3C64XX_UINTM)); | |
| 176 | + else | |
| 177 | + disable_irq_nosync(ourport->rx_irq); | |
| 157 | 178 | rx_enabled(port) = 0; |
| 158 | 179 | } |
| 159 | 180 | } |
| @@ -320,6 +341,28 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) · 160 unmodified lines | ||
| 320 | 341 | return IRQ_HANDLED; |
| 321 | 342 | } |
| 322 | 343 | |
| 344 | +/* interrupt handler for s3c64xx and later SoC's.*/ | |
| 345 | +static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) | |
| 346 | +{ | |
| 347 | + struct s3c24xx_uart_port *ourport = id; | |
| 348 | + struct uart_port *port = &ourport->port; | |
| 349 | + unsigned int pend = rd_regl(port, S3C64XX_UINTP); | |
| 350 | + unsigned long flags; | |
| 351 | + irqreturn_t ret = IRQ_HANDLED; | |
| 352 | + | |
| 353 | + spin_lock_irqsave(&port->lock, flags); | |
| 354 | + if (pend & S3C64XX_UINTM_RXD_MSK) { | |
| 355 | + ret = s3c24xx_serial_rx_chars(irq, id); | |
| 356 | + wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK); | |
| 357 | + } | |
| 358 | + if (pend & S3C64XX_UINTM_TXD_MSK) { | |
| 359 | + ret = s3c24xx_serial_tx_chars(irq, id); | |
| 360 | + wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK); | |
| 361 | + } | |
| 362 | + spin_unlock_irqrestore(&port->lock, flags); | |
| 363 | + return ret; | |
| 364 | +} | |
| 365 | + | |
| 323 | 366 | static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) |
| 324 | 367 | { |
| 325 | 368 | struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
| @@ -377,18 +420,25 @@ static void s3c24xx_serial_shutdown(struct uart_port *port) · 51 unmodified lines | ||
| 377 | 420 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
| 378 | 421 | |
| 379 | 422 | if (ourport->tx_claimed) { |
| 380 | − free_irq(ourport->tx_irq, ourport); | |
| 423 | + if (!s3c24xx_serial_has_interrupt_mask(port)) | |
| 424 | + free_irq(ourport->tx_irq, ourport); | |
| 381 | 425 | tx_enabled(port) = 0; |
| 382 | 426 | ourport->tx_claimed = 0; |
| 383 | 427 | } |
| 384 | 428 | |
| 385 | 429 | if (ourport->rx_claimed) { |
| 386 | − free_irq(ourport->rx_irq, ourport); | |
| 430 | + if (!s3c24xx_serial_has_interrupt_mask(port)) | |
| 431 | + free_irq(ourport->rx_irq, ourport); | |
| 387 | 432 | ourport->rx_claimed = 0; |
| 388 | 433 | rx_enabled(port) = 0; |
| 389 | 434 | } |
| 390 | −} | |
| 391 | 435 | |
| 436 | + /* Clear pending interrupts and mask all interrupts */ | |
| 437 | + if (s3c24xx_serial_has_interrupt_mask(port)) { | |
| 438 | + wr_regl(port, S3C64XX_UINTP, 0xf); | |
| 439 | + wr_regl(port, S3C64XX_UINTM, 0xf); | |
| 440 | + } | |
| 441 | +} | |
| 392 | 442 | |
| 393 | 443 | static int s3c24xx_serial_startup(struct uart_port *port) |
| 394 | 444 | { |
| @@ -436,6 +486,33 @@ static int s3c24xx_serial_startup(struct uart_port *port) · 41 unmodified lines | ||
| 436 | 486 | return ret; |
| 437 | 487 | } |
| 438 | 488 | |
| 489 | +static int s3c64xx_serial_startup(struct uart_port *port) | |
| 490 | +{ | |
| 491 | + struct s3c24xx_uart_port *ourport = to_ourport(port); | |
| 492 | + int ret; | |
| 493 | + | |
| 494 | + dbg("s3c64xx_serial_startup: port=%p (%08lx,%p)\n", | |
| 495 | + port->mapbase, port->membase); | |
| 496 | + | |
| 497 | + ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED, | |
| 498 | + s3c24xx_serial_portname(port), ourport); | |
| 499 | + if (ret) { | |
| 500 | + printk(KERN_ERR "cannot get irq %d\n", port->irq); | |
| 501 | + return ret; | |
| 502 | + } | |
| 503 | + | |
| 504 | + /* For compatibility with s3c24xx Soc's */ | |
| 505 | + rx_enabled(port) = 1; | |
| 506 | + ourport->rx_claimed = 1; | |
| 507 | + tx_enabled(port) = 0; | |
| 508 | + ourport->tx_claimed = 1; | |
| 509 | + | |
| 510 | + /* Enable Rx Interrupt */ | |
| 511 | + __clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM)); | |
| 512 | + dbg("s3c64xx_serial_startup ok\n"); | |
| 513 | + return ret; | |
| 514 | +} | |
| 515 | + | |
| 439 | 516 | /* power power management control */ |
| 440 | 517 | |
| 441 | 518 | static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, |
| @@ -879,7 +956,6 @@ static struct uart_ops s3c24xx_serial_ops = { · 437 unmodified lines | ||
| 879 | 956 | .verify_port = s3c24xx_serial_verify_port, |
| 880 | 957 | }; |
| 881 | 958 | |
| 882 | − | |
| 883 | 959 | static struct uart_driver s3c24xx_uart_drv = { |
| 884 | 960 | .owner = THIS_MODULE, |
| 885 | 961 | .driver_name = "s3c2410_serial", |
| @@ -895,7 +971,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS · 9 unmodified lines | ||
| 895 | 971 | .port = { |
| 896 | 972 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock), |
| 897 | 973 | .iotype = UPIO_MEM, |
| 898 | − .irq = IRQ_S3CUART_RX0, | |
| 899 | 974 | .uartclk = 0, |
| 900 | 975 | .fifosize = 16, |
| 901 | 976 | .ops = &s3c24xx_serial_ops, |
| @@ -907,7 +982,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS · 5 unmodified lines | ||
| 907 | 982 | .port = { |
| 908 | 983 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock), |
| 909 | 984 | .iotype = UPIO_MEM, |
| 910 | − .irq = IRQ_S3CUART_RX1, | |
| 911 | 985 | .uartclk = 0, |
| 912 | 986 | .fifosize = 16, |
| 913 | 987 | .ops = &s3c24xx_serial_ops, |
| @@ -921,7 +995,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS · 7 unmodified lines | ||
| 921 | 995 | .port = { |
| 922 | 996 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock), |
| 923 | 997 | .iotype = UPIO_MEM, |
| 924 | − .irq = IRQ_S3CUART_RX2, | |
| 925 | 998 | .uartclk = 0, |
| 926 | 999 | .fifosize = 16, |
| 927 | 1000 | .ops = &s3c24xx_serial_ops, |
| @@ -935,7 +1008,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS · 7 unmodified lines | ||
| 935 | 1008 | .port = { |
| 936 | 1009 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock), |
| 937 | 1010 | .iotype = UPIO_MEM, |
| 938 | − .irq = IRQ_S3CUART_RX3, | |
| 939 | 1011 | .uartclk = 0, |
| 940 | 1012 | .fifosize = 16, |
| 941 | 1013 | .ops = &s3c24xx_serial_ops, |
| @@ -1077,6 +1149,10 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, · 135 unmodified lines | ||
| 1077 | 1149 | port->dev = &platdev->dev; |
| 1078 | 1150 | ourport->info = info; |
| 1079 | 1151 | |
| 1152 | + /* Startup sequence is different for s3c64xx and higher SoC's */ | |
| 1153 | + if (s3c24xx_serial_has_interrupt_mask(port)) | |
| 1154 | + s3c24xx_serial_ops.startup = s3c64xx_serial_startup; | |
| 1155 | + | |
| 1080 | 1156 | /* copy the info in from provided structure */ |
| 1081 | 1157 | ourport->port.fifosize = info->fifosize; |
| 1082 | 1158 | |
| @@ -1116,6 +1192,13 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, · 33 unmodified lines | ||
| 1116 | 1192 | |
| 1117 | 1193 | ourport->clk = clk_get(&platdev->dev, "uart"); |
| 1118 | 1194 | |
| 1195 | + /* Keep all interrupts masked and cleared */ | |
| 1196 | + if (s3c24xx_serial_has_interrupt_mask(port)) { | |
| 1197 | + wr_regl(port, S3C64XX_UINTM, 0xf); | |
| 1198 | + wr_regl(port, S3C64XX_UINTP, 0xf); | |
| 1199 | + wr_regl(port, S3C64XX_UINTSP, 0xf); | |
| 1200 | + } | |
| 1201 | + | |
| 1119 | 1202 | dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n", |
| 1120 | 1203 | port->mapbase, port->membase, port->irq, |
| 1121 | 1204 | ourport->rx_irq, ourport->tx_irq, port->uartclk); |
| @@ -61,6 +61,7 @@ struct s3c24xx_uart_port { · 60 unmodified lines | ||
| 61 | 61 | /* register access controls */ |
| 62 | 62 | |
| 63 | 63 | #define portaddr(port, reg) ((port)->membase + (reg)) |
| 64 | +#define portaddrl(port, reg) ((unsigned long *)((port)->membase + (reg))) | |
| 64 | 65 | |
| 65 | 66 | #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) |
| 66 | 67 | #define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) |
| @@ -37,6 +37,7 @@ · 36 unmodified lines | ||
| 37 | 37 | #include <linux/spinlock.h> |
| 38 | 38 | #include <linux/sysrq.h> |
| 39 | 39 | #include <linux/tty.h> |
| 40 | +#include <linux/tty_flip.h> | |
| 40 | 41 | #include <linux/types.h> |
| 41 | 42 | |
| 42 | 43 | #include <linux/atomic.h> |
| @@ -57,7 +57,7 @@ static struct lock_class_key port_lock_key; · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
| 59 | 59 | struct ktermios *old_termios); |
| 60 | −static void __uart_wait_until_sent(struct uart_port *port, int timeout); | |
| 60 | +static void uart_wait_until_sent(struct tty_struct *tty, int timeout); | |
| 61 | 61 | static void uart_change_pm(struct uart_state *state, int pm_state); |
| 62 | 62 | |
| 63 | 63 | /* |
| @@ -72,7 +72,7 @@ void uart_write_wakeup(struct uart_port *port) · 8 unmodified lines | ||
| 72 | 72 | * closed. No cookie for you. |
| 73 | 73 | */ |
| 74 | 74 | BUG_ON(!state); |
| 75 | − tasklet_schedule(&state->tlet); | |
| 75 | + tty_wakeup(state->port.tty); | |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | static void uart_stop(struct tty_struct *tty) |
| @@ -107,12 +107,6 @@ static void uart_start(struct tty_struct *tty) · 28 unmodified lines | ||
| 107 | 107 | spin_unlock_irqrestore(&port->lock, flags); |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | −static void uart_tasklet_action(unsigned long data) | |
| 111 | −{ | |
| 112 | − struct uart_state *state = (struct uart_state *)data; | |
| 113 | − tty_wakeup(state->port.tty); | |
| 114 | −} | |
| 115 | − | |
| 116 | 110 | static inline void |
| 117 | 111 | uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) |
| 118 | 112 | { |
| @@ -255,9 +249,11 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) · 136 unmodified lines | ||
| 255 | 249 | } |
| 256 | 250 | |
| 257 | 251 | /* |
| 258 | − * kill off our tasklet | |
| 252 | + * It's possible for shutdown to be called after suspend if we get | |
| 253 | + * a DCD drop (hangup) at just the right time. Clear suspended bit so | |
| 254 | + * we don't try to resume a port that has been shutdown. | |
| 259 | 255 | */ |
| 260 | − tasklet_kill(&state->tlet); | |
| 256 | + clear_bit(ASYNCB_SUSPENDED, &port->flags); | |
| 261 | 257 | |
| 262 | 258 | /* |
| 263 | 259 | * Free the transmit buffer page. |
| @@ -1261,8 +1257,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp) · 997 unmodified lines | ||
| 1261 | 1257 | struct uart_port *uport; |
| 1262 | 1258 | unsigned long flags; |
| 1263 | 1259 | |
| 1264 | − BUG_ON(!tty_locked()); | |
| 1265 | − | |
| 1266 | 1260 | if (!state) |
| 1267 | 1261 | return; |
| 1268 | 1262 | |
| @@ -1271,12 +1265,11 @@ static void uart_close(struct tty_struct *tty, struct file *filp) · 2 unmodified lines | ||
| 1271 | 1265 | |
| 1272 | 1266 | pr_debug("uart_close(%d) called\n", uport->line); |
| 1273 | 1267 | |
| 1274 | − mutex_lock(&port->mutex); | |
| 1275 | 1268 | spin_lock_irqsave(&port->lock, flags); |
| 1276 | 1269 | |
| 1277 | 1270 | if (tty_hung_up_p(filp)) { |
| 1278 | 1271 | spin_unlock_irqrestore(&port->lock, flags); |
| 1279 | − goto done; | |
| 1272 | + return; | |
| 1280 | 1273 | } |
| 1281 | 1274 | |
| 1282 | 1275 | if ((tty->count == 1) && (port->count != 1)) { |
| @@ -1298,7 +1291,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) · 15 unmodified lines | ||
| 1298 | 1291 | } |
| 1299 | 1292 | if (port->count) { |
| 1300 | 1293 | spin_unlock_irqrestore(&port->lock, flags); |
| 1301 | − goto done; | |
| 1294 | + return; | |
| 1302 | 1295 | } |
| 1303 | 1296 | |
| 1304 | 1297 | /* |
| @@ -1306,19 +1299,13 @@ static void uart_close(struct tty_struct *tty, struct file *filp) · 1 unmodified line | ||
| 1306 | 1299 | * the line discipline to only process XON/XOFF characters by |
| 1307 | 1300 | * setting tty->closing. |
| 1308 | 1301 | */ |
| 1302 | + set_bit(ASYNCB_CLOSING, &port->flags); | |
| 1309 | 1303 | tty->closing = 1; |
| 1310 | 1304 | spin_unlock_irqrestore(&port->lock, flags); |
| 1311 | 1305 | |
| 1312 | − if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) { | |
| 1313 | − /* | |
| 1314 | − * hack: open-coded tty_wait_until_sent to avoid | |
| 1315 | − * recursive tty_lock | |
| 1316 | − */ | |
| 1317 | − long timeout = msecs_to_jiffies(port->closing_wait); | |
| 1318 | − if (wait_event_interruptible_timeout(tty->write_wait, | |
| 1319 | − !tty_chars_in_buffer(tty), timeout) >= 0) | |
| 1320 | − __uart_wait_until_sent(uport, timeout); | |
| 1321 | − } | |
| 1306 | + if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | |
| 1307 | + tty_wait_until_sent_from_close(tty, | |
| 1308 | + msecs_to_jiffies(port->closing_wait)); | |
| 1322 | 1309 | |
| 1323 | 1310 | /* |
| 1324 | 1311 | * At this point, we stop accepting input. To do this, we |
| @@ -1334,9 +1321,10 @@ static void uart_close(struct tty_struct *tty, struct file *filp) · 9 unmodified lines | ||
| 1334 | 1321 | * has completely drained; this is especially |
| 1335 | 1322 | * important if there is a transmit FIFO! |
| 1336 | 1323 | */ |
| 1337 | − __uart_wait_until_sent(uport, uport->timeout); | |
| 1324 | + uart_wait_until_sent(tty, uport->timeout); | |
| 1338 | 1325 | } |
| 1339 | 1326 | |
| 1327 | + mutex_lock(&port->mutex); | |
| 1340 | 1328 | uart_shutdown(tty, state); |
| 1341 | 1329 | uart_flush_buffer(tty); |
| 1342 | 1330 | |
| @@ -1361,15 +1349,18 @@ static void uart_close(struct tty_struct *tty, struct file *filp) · 18 unmodified lines | ||
| 1361 | 1349 | * Wake up anyone trying to open this port. |
| 1362 | 1350 | */ |
| 1363 | 1351 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
| 1352 | + clear_bit(ASYNCB_CLOSING, &port->flags); | |
| 1364 | 1353 | spin_unlock_irqrestore(&port->lock, flags); |
| 1365 | 1354 | wake_up_interruptible(&port->open_wait); |
| 1355 | + wake_up_interruptible(&port->close_wait); | |
| 1366 | 1356 | |
| 1367 | −done: | |
| 1368 | 1357 | mutex_unlock(&port->mutex); |
| 1369 | 1358 | } |
| 1370 | 1359 | |
| 1371 | −static void __uart_wait_until_sent(struct uart_port *port, int timeout) | |
| 1360 | +static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | |
| 1372 | 1361 | { |
| 1362 | + struct uart_state *state = tty->driver_data; | |
| 1363 | + struct uart_port *port = state->uart_port; | |
| 1373 | 1364 | unsigned long char_time, expire; |
| 1374 | 1365 | |
| 1375 | 1366 | if (port->type == PORT_UNKNOWN || port->fifosize == 0) |
| @@ -1421,16 +1412,6 @@ static void __uart_wait_until_sent(struct uart_port *port, int timeout) · 45 unmodified lines | ||
| 1421 | 1412 | } |
| 1422 | 1413 | } |
| 1423 | 1414 | |
| 1424 | −static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | |
| 1425 | −{ | |
| 1426 | − struct uart_state *state = tty->driver_data; | |
| 1427 | − struct uart_port *port = state->uart_port; | |
| 1428 | − | |
| 1429 | − tty_lock(); | |
| 1430 | − __uart_wait_until_sent(port, timeout); | |
| 1431 | − tty_unlock(); | |
| 1432 | −} | |
| 1433 | − | |
| 1434 | 1415 | /* |
| 1435 | 1416 | * This is called with the BKL held in |
| 1436 | 1417 | * linux/drivers/char/tty_io.c:do_tty_hangup() |
| @@ -1443,7 +1424,6 @@ static void uart_hangup(struct tty_struct *tty) · 6 unmodified lines | ||
| 1443 | 1424 | struct tty_port *port = &state->port; |
| 1444 | 1425 | unsigned long flags; |
| 1445 | 1426 | |
| 1446 | − BUG_ON(!tty_locked()); | |
| 1447 | 1427 | pr_debug("uart_hangup(%d)\n", state->uart_port->line); |
| 1448 | 1428 | |
| 1449 | 1429 | mutex_lock(&port->mutex); |
| @@ -1530,7 +1510,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp) · 80 unmodified lines | ||
| 1530 | 1510 | struct tty_port *port; |
| 1531 | 1511 | int retval, line = tty->index; |
| 1532 | 1512 | |
| 1533 | − BUG_ON(!tty_locked()); | |
| 1534 | 1513 | pr_debug("uart_open(%d) called\n", line); |
| 1535 | 1514 | |
| 1536 | 1515 | /* |
| @@ -2008,6 +1987,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) · 471 unmodified lines | ||
| 2008 | 1987 | if (port->tty && port->tty->termios && termios.c_cflag == 0) |
| 2009 | 1988 | termios = *(port->tty->termios); |
| 2010 | 1989 | |
| 1990 | + if (console_suspend_enabled) | |
| 1991 | + uart_change_pm(state, 0); | |
| 2011 | 1992 | uport->ops->set_termios(uport, &termios, NULL); |
| 2012 | 1993 | if (console_suspend_enabled) |
| 2013 | 1994 | console_start(uport->cons); |
| @@ -2068,8 +2049,6 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) · 54 unmodified lines | ||
| 2068 | 2049 | case UPIO_MEM32: |
| 2069 | 2050 | case UPIO_AU: |
| 2070 | 2051 | case UPIO_TSI: |
| 2071 | − case UPIO_DWAPB: | |
| 2072 | − case UPIO_DWAPB32: | |
| 2073 | 2052 | snprintf(address, sizeof(address), |
| 2074 | 2053 | "MMIO 0x%llx", (unsigned long long)port->mapbase); |
| 2075 | 2054 | break; |
| @@ -2298,8 +2277,6 @@ int uart_register_driver(struct uart_driver *drv) · 222 unmodified lines | ||
| 2298 | 2277 | port->ops = &uart_port_ops; |
| 2299 | 2278 | port->close_delay = 500; /* .5 seconds */ |
| 2300 | 2279 | port->closing_wait = 30000; /* 30 seconds */ |
| 2301 | − tasklet_init(&state->tlet, uart_tasklet_action, | |
| 2302 | − (unsigned long)state); | |
| 2303 | 2280 | } |
| 2304 | 2281 | |
| 2305 | 2282 | retval = tty_register_driver(normal); |
| @@ -2460,11 +2437,6 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) · 154 unmodified lines | ||
| 2460 | 2437 | */ |
| 2461 | 2438 | uport->type = PORT_UNKNOWN; |
| 2462 | 2439 | |
| 2463 | − /* | |
| 2464 | − * Kill the tasklet, and free resources. | |
| 2465 | − */ | |
| 2466 | − tasklet_kill(&state->tlet); | |
| 2467 | − | |
| 2468 | 2440 | state->uart_port = NULL; |
| 2469 | 2441 | mutex_unlock(&port_mutex); |
| 2470 | 2442 | |
| @@ -2489,8 +2461,6 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2) · 18 unmodified lines | ||
| 2489 | 2461 | case UPIO_MEM32: |
| 2490 | 2462 | case UPIO_AU: |
| 2491 | 2463 | case UPIO_TSI: |
| 2492 | − case UPIO_DWAPB: | |
| 2493 | − case UPIO_DWAPB32: | |
| 2494 | 2464 | return (port1->mapbase == port2->mapbase); |
| 2495 | 2465 | } |
| 2496 | 2466 | return 0; |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | */ |
| 14 | 14 | #include <linux/module.h> |
| 15 | 15 | #include <linux/tty.h> |
| 16 | +#include <linux/tty_flip.h> | |
| 16 | 17 | #include <linux/ioport.h> |
| 17 | 18 | #include <linux/init.h> |
| 18 | 19 | #include <linux/serial.h> |
| @@ -336,19 +337,19 @@ static int ks8695uart_startup(struct uart_port *port) · 317 unmodified lines | ||
| 336 | 337 | /* |
| 337 | 338 | * Allocate the IRQ |
| 338 | 339 | */ |
| 339 | − retval = request_irq(KS8695_IRQ_UART_TX, ks8695uart_tx_chars, IRQF_DISABLED, "UART TX", port); | |
| 340 | + retval = request_irq(KS8695_IRQ_UART_TX, ks8695uart_tx_chars, 0, "UART TX", port); | |
| 340 | 341 | if (retval) |
| 341 | 342 | goto err_tx; |
| 342 | 343 | |
| 343 | − retval = request_irq(KS8695_IRQ_UART_RX, ks8695uart_rx_chars, IRQF_DISABLED, "UART RX", port); | |
| 344 | + retval = request_irq(KS8695_IRQ_UART_RX, ks8695uart_rx_chars, 0, "UART RX", port); | |
| 344 | 345 | if (retval) |
| 345 | 346 | goto err_rx; |
| 346 | 347 | |
| 347 | − retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, IRQF_DISABLED, "UART LineStatus", port); | |
| 348 | + retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, 0, "UART LineStatus", port); | |
| 348 | 349 | if (retval) |
| 349 | 350 | goto err_ls; |
| 350 | 351 | |
| 351 | − retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, IRQF_DISABLED, "UART ModemStatus", port); | |
| 352 | + retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, 0, "UART ModemStatus", port); | |
| 352 | 353 | if (retval) |
| 353 | 354 | goto err_ms; |
| 354 | 355 | |
| @@ -28,6 +28,8 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <linux/pci.h> |
| 29 | 29 | #include <linux/serial_core.h> |
| 30 | 30 | #include <linux/serial.h> |
| 31 | +#include <linux/tty.h> | |
| 32 | +#include <linux/tty_flip.h> | |
| 31 | 33 | |
| 32 | 34 | #include <asm/io.h> |
| 33 | 35 | |
| @@ -1976,7 +1976,7 @@ static int __devinit sci_init_single(struct platform_device *dev, · 1975 unmodified lines | ||
| 1976 | 1976 | * For the muxed case there's nothing more to do. |
| 1977 | 1977 | */ |
| 1978 | 1978 | port->irq = p->irqs[SCIx_RXI_IRQ]; |
| 1979 | − port->irqflags = IRQF_DISABLED; | |
| 1979 | + port->irqflags = 0; | |
| 1980 | 1980 | |
| 1981 | 1981 | port->serial_in = sci_serial_in; |
| 1982 | 1982 | port->serial_out = sci_serial_out; |
| @@ -39,6 +39,7 @@ · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | #include <linux/interrupt.h> |
| 41 | 41 | #include <linux/tty.h> |
| 42 | +#include <linux/tty_flip.h> | |
| 42 | 43 | #include <linux/serial.h> |
| 43 | 44 | #include <linux/console.h> |
| 44 | 45 | #include <linux/module.h> |
| @@ -737,7 +738,7 @@ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) · 692 unmodified lines | ||
| 737 | 738 | DPRINTF("sn_console: switching to interrupt driven console\n"); |
| 738 | 739 | |
| 739 | 740 | if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, |
| 740 | − IRQF_DISABLED | IRQF_SHARED, | |
| 741 | + IRQF_SHARED, | |
| 741 | 742 | "SAL console driver", port) >= 0) { |
| 742 | 743 | spin_lock_irqsave(&port->sc_port.lock, flags); |
| 743 | 744 | port->sc_port.irq = SGI_UART_VECTOR; |
| @@ -23,6 +23,8 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <linux/pci.h> |
| 24 | 24 | #include <linux/interrupt.h> |
| 25 | 25 | #include <linux/serial_core.h> |
| 26 | +#include <linux/tty.h> | |
| 27 | +#include <linux/tty_flip.h> | |
| 26 | 28 | #include <linux/kernel.h> |
| 27 | 29 | #include <linux/platform_device.h> |
| 28 | 30 | #include <linux/ioport.h> |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/serial.h> |
| 16 | 16 | #include <linux/serial_core.h> |
| 17 | 17 | #include <linux/tty.h> |
| 18 | +#include <linux/tty_flip.h> | |
| 18 | 19 | #include <linux/delay.h> |
| 19 | 20 | #include <linux/interrupt.h> |
| 20 | 21 | #include <linux/init.h> |
| @@ -20,8 +20,10 @@ · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | #include <linux/module.h> |
| 22 | 22 | #include <linux/serial.h> |
| 23 | −#include <linux/slab.h> | |
| 24 | 23 | #include <linux/serial_core.h> |
| 24 | +#include <linux/slab.h> | |
| 25 | +#include <linux/tty.h> | |
| 26 | +#include <linux/tty_flip.h> | |
| 25 | 27 | #include <linux/io.h> |
| 26 | 28 | #include <linux/of_platform.h> |
| 27 | 29 | #include <linux/dma-mapping.h> |
| @@ -12,9 +12,11 @@ · 11 unmodified lines | ||
| 12 | 12 | */ |
| 13 | 13 | |
| 14 | 14 | #include <linux/platform_device.h> |
| 15 | +#include <linux/serial.h> | |
| 15 | 16 | #include <linux/serial_core.h> |
| 17 | +#include <linux/tty.h> | |
| 18 | +#include <linux/tty_flip.h> | |
| 16 | 19 | #include <linux/console.h> |
| 17 | −#include <linux/serial.h> | |
| 18 | 20 | #include <linux/irq.h> |
| 19 | 21 | #include <linux/io.h> |
| 20 | 22 | #include <linux/of.h> |
| @@ -63,6 +63,7 @@ · 62 unmodified lines | ||
| 63 | 63 | #include <linux/spinlock.h> |
| 64 | 64 | #include <linux/sysrq.h> |
| 65 | 65 | #include <linux/tty.h> |
| 66 | +#include <linux/tty_flip.h> | |
| 66 | 67 | #include <linux/types.h> |
| 67 | 68 | |
| 68 | 69 | #include <linux/atomic.h> |
| @@ -2124,7 +2124,6 @@ static int mgsl_write(struct tty_struct * tty, · 2123 unmodified lines | ||
| 2124 | 2124 | if ( info->params.mode == MGSL_MODE_HDLC || |
| 2125 | 2125 | info->params.mode == MGSL_MODE_RAW ) { |
| 2126 | 2126 | /* operating in synchronous (frame oriented) mode */ |
| 2127 | − /* operating in synchronous (frame oriented) mode */ | |
| 2128 | 2127 | if (info->tx_active) { |
| 2129 | 2128 | |
| 2130 | 2129 | if ( info->params.mode == MGSL_MODE_HDLC ) { |
| @@ -4950,7 +4950,7 @@ CheckAgain: · 4949 unmodified lines | ||
| 4950 | 4950 | |
| 4951 | 4951 | if ( debug_level >= DEBUG_LEVEL_DATA ) |
| 4952 | 4952 | trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr, |
| 4953 | − min_t(int, framesize,SCABUFSIZE),0); | |
| 4953 | + min_t(unsigned int, framesize, SCABUFSIZE), 0); | |
| 4954 | 4954 | |
| 4955 | 4955 | if (framesize) { |
| 4956 | 4956 | if (framesize > info->max_frame_size) |
| @@ -5015,14 +5015,14 @@ static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int co · 58 unmodified lines | ||
| 5015 | 5015 | SCADESC_EX *desc_ex; |
| 5016 | 5016 | |
| 5017 | 5017 | if ( debug_level >= DEBUG_LEVEL_DATA ) |
| 5018 | − trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1); | |
| 5018 | + trace_block(info, buf, min_t(unsigned int, count, SCABUFSIZE), 1); | |
| 5019 | 5019 | |
| 5020 | 5020 | /* Copy source buffer to one or more DMA buffers, starting with |
| 5021 | 5021 | * the first transmit dma buffer. |
| 5022 | 5022 | */ |
| 5023 | 5023 | for(i=0;;) |
| 5024 | 5024 | { |
| 5025 | − copy_count = min_t(unsigned short,count,SCABUFSIZE); | |
| 5025 | + copy_count = min_t(unsigned int, count, SCABUFSIZE); | |
| 5026 | 5026 | |
| 5027 | 5027 | desc = &info->tx_buf_list[i]; |
| 5028 | 5028 | desc_ex = &info->tx_buf_list_ex[i]; |
| @@ -194,8 +194,7 @@ static inline struct tty_struct *file_tty(struct file *file) · 193 unmodified lines | ||
| 194 | 194 | return ((struct tty_file_private *)file->private_data)->tty; |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | −/* Associate a new file with the tty structure */ | |
| 198 | −int tty_add_file(struct tty_struct *tty, struct file *file) | |
| 197 | +int tty_alloc_file(struct file *file) | |
| 199 | 198 | { |
| 200 | 199 | struct tty_file_private *priv; |
| 201 | 200 | |
| @@ -203,15 +202,36 @@ int tty_add_file(struct tty_struct *tty, struct file *file) · 1 unmodified line | ||
| 203 | 202 | if (!priv) |
| 204 | 203 | return -ENOMEM; |
| 205 | 204 | |
| 205 | + file->private_data = priv; | |
| 206 | + | |
| 207 | + return 0; | |
| 208 | +} | |
| 209 | + | |
| 210 | +/* Associate a new file with the tty structure */ | |
| 211 | +void tty_add_file(struct tty_struct *tty, struct file *file) | |
| 212 | +{ | |
| 213 | + struct tty_file_private *priv = file->private_data; | |
| 214 | + | |
| 206 | 215 | priv->tty = tty; |
| 207 | 216 | priv->file = file; |
| 208 | − file->private_data = priv; | |
| 209 | 217 | |
| 210 | 218 | spin_lock(&tty_files_lock); |
| 211 | 219 | list_add(&priv->list, &tty->tty_files); |
| 212 | 220 | spin_unlock(&tty_files_lock); |
| 221 | +} | |
| 213 | 222 | |
| 214 | − return 0; | |
| 223 | +/** | |
| 224 | + * tty_free_file - free file->private_data | |
| 225 | + * | |
| 226 | + * This shall be used only for fail path handling when tty_add_file was not | |
| 227 | + * called yet. | |
| 228 | + */ | |
| 229 | +void tty_free_file(struct file *file) | |
| 230 | +{ | |
| 231 | + struct tty_file_private *priv = file->private_data; | |
| 232 | + | |
| 233 | + file->private_data = NULL; | |
| 234 | + kfree(priv); | |
| 215 | 235 | } |
| 216 | 236 | |
| 217 | 237 | /* Delete file from its tty */ |
| @@ -222,8 +242,7 @@ void tty_del_file(struct file *file) · 4 unmodified lines | ||
| 222 | 242 | spin_lock(&tty_files_lock); |
| 223 | 243 | list_del(&priv->list); |
| 224 | 244 | spin_unlock(&tty_files_lock); |
| 225 | − file->private_data = NULL; | |
| 226 | − kfree(priv); | |
| 245 | + tty_free_file(file); | |
| 227 | 246 | } |
| 228 | 247 | |
| 229 | 248 | |
| @@ -1811,6 +1830,10 @@ static int tty_open(struct inode *inode, struct file *filp) · 1581 unmodified lines | ||
| 1811 | 1830 | nonseekable_open(inode, filp); |
| 1812 | 1831 | |
| 1813 | 1832 | retry_open: |
| 1833 | + retval = tty_alloc_file(filp); | |
| 1834 | + if (retval) | |
| 1835 | + return -ENOMEM; | |
| 1836 | + | |
| 1814 | 1837 | noctty = filp->f_flags & O_NOCTTY; |
| 1815 | 1838 | index = -1; |
| 1816 | 1839 | retval = 0; |
| @@ -1823,6 +1846,7 @@ retry_open: · 6 unmodified lines | ||
| 1823 | 1846 | if (!tty) { |
| 1824 | 1847 | tty_unlock(); |
| 1825 | 1848 | mutex_unlock(&tty_mutex); |
| 1849 | + tty_free_file(filp); | |
| 1826 | 1850 | return -ENXIO; |
| 1827 | 1851 | } |
| 1828 | 1852 | driver = tty_driver_kref_get(tty->driver); |
| @@ -1855,6 +1879,7 @@ retry_open: · 26 unmodified lines | ||
| 1855 | 1879 | } |
| 1856 | 1880 | tty_unlock(); |
| 1857 | 1881 | mutex_unlock(&tty_mutex); |
| 1882 | + tty_free_file(filp); | |
| 1858 | 1883 | return -ENODEV; |
| 1859 | 1884 | } |
| 1860 | 1885 | |
| @@ -1862,6 +1887,7 @@ retry_open: · 1 unmodified line | ||
| 1862 | 1887 | if (!driver) { |
| 1863 | 1888 | tty_unlock(); |
| 1864 | 1889 | mutex_unlock(&tty_mutex); |
| 1890 | + tty_free_file(filp); | |
| 1865 | 1891 | return -ENODEV; |
| 1866 | 1892 | } |
| 1867 | 1893 | got_driver: |
| @@ -1872,6 +1898,8 @@ got_driver: · 4 unmodified lines | ||
| 1872 | 1898 | if (IS_ERR(tty)) { |
| 1873 | 1899 | tty_unlock(); |
| 1874 | 1900 | mutex_unlock(&tty_mutex); |
| 1901 | + tty_driver_kref_put(driver); | |
| 1902 | + tty_free_file(filp); | |
| 1875 | 1903 | return PTR_ERR(tty); |
| 1876 | 1904 | } |
| 1877 | 1905 | } |
| @@ -1887,15 +1915,11 @@ got_driver: · 9 unmodified lines | ||
| 1887 | 1915 | tty_driver_kref_put(driver); |
| 1888 | 1916 | if (IS_ERR(tty)) { |
| 1889 | 1917 | tty_unlock(); |
| 1918 | + tty_free_file(filp); | |
| 1890 | 1919 | return PTR_ERR(tty); |
| 1891 | 1920 | } |
| 1892 | 1921 | |
| 1893 | − retval = tty_add_file(tty, filp); | |
| 1894 | − if (retval) { | |
| 1895 | − tty_unlock(); | |
| 1896 | − tty_release(inode, filp); | |
| 1897 | − return retval; | |
| 1898 | − } | |
| 1922 | + tty_add_file(tty, filp); | |
| 1899 | 1923 | |
| 1900 | 1924 | check_tty_count(tty, "tty_open"); |
| 1901 | 1925 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
| @@ -2716,6 +2740,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, · 814 unmodified lines | ||
| 2716 | 2740 | ld = tty_ldisc_ref_wait(tty); |
| 2717 | 2741 | if (ld->ops->compat_ioctl) |
| 2718 | 2742 | retval = ld->ops->compat_ioctl(tty, file, cmd, arg); |
| 2743 | + else | |
| 2744 | + retval = n_tty_compat_ioctl_helper(tty, file, cmd, arg); | |
| 2719 | 2745 | tty_ldisc_deref(ld); |
| 2720 | 2746 | |
| 2721 | 2747 | return retval; |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/module.h> |
| 20 | 20 | #include <linux/bitops.h> |
| 21 | 21 | #include <linux/mutex.h> |
| 22 | +#include <linux/compat.h> | |
| 22 | 23 | |
| 23 | 24 | #include <asm/io.h> |
| 24 | 25 | #include <asm/uaccess.h> |
| @@ -1179,3 +1180,19 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, · 1154 unmodified lines | ||
| 1179 | 1180 | } |
| 1180 | 1181 | } |
| 1181 | 1182 | EXPORT_SYMBOL(n_tty_ioctl_helper); |
| 1183 | + | |
| 1184 | +#ifdef CONFIG_COMPAT | |
| 1185 | +long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file, | |
| 1186 | + unsigned int cmd, unsigned long arg) | |
| 1187 | +{ | |
| 1188 | + switch (cmd) { | |
| 1189 | + case TIOCGLCKTRMIOS: | |
| 1190 | + case TIOCSLCKTRMIOS: | |
| 1191 | + return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg)); | |
| 1192 | + default: | |
| 1193 | + return -ENOIOCTLCMD; | |
| 1194 | + } | |
| 1195 | +} | |
| 1196 | +EXPORT_SYMBOL(n_tty_compat_ioctl_helper); | |
| 1197 | +#endif | |
| 1198 | + | |
| @@ -450,7 +450,6 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) · 449 unmodified lines | ||
| 450 | 450 | if (ld->ops->open) { |
| 451 | 451 | int ret; |
| 452 | 452 | /* BTM here locks versus a hangup event */ |
| 453 | − WARN_ON(!tty_locked()); | |
| 454 | 453 | ret = ld->ops->open(tty); |
| 455 | 454 | if (ret) |
| 456 | 455 | clear_bit(TTY_LDISC_OPEN, &tty->flags); |
| @@ -15,30 +15,18 @@ · 14 unmodified lines | ||
| 15 | 15 | * Don't use in new code. |
| 16 | 16 | */ |
| 17 | 17 | static DEFINE_MUTEX(big_tty_mutex); |
| 18 | −struct task_struct *__big_tty_mutex_owner; | |
| 19 | −EXPORT_SYMBOL_GPL(__big_tty_mutex_owner); | |
| 20 | 18 | |
| 21 | 19 | /* |
| 22 | 20 | * Getting the big tty mutex. |
| 23 | 21 | */ |
| 24 | 22 | void __lockfunc tty_lock(void) |
| 25 | 23 | { |
| 26 | − struct task_struct *task = current; | |
| 27 | − | |
| 28 | − WARN_ON(__big_tty_mutex_owner == task); | |
| 29 | − | |
| 30 | 24 | mutex_lock(&big_tty_mutex); |
| 31 | − __big_tty_mutex_owner = task; | |
| 32 | 25 | } |
| 33 | 26 | EXPORT_SYMBOL(tty_lock); |
| 34 | 27 | |
| 35 | 28 | void __lockfunc tty_unlock(void) |
| 36 | 29 | { |
| 37 | − struct task_struct *task = current; | |
| 38 | − | |
| 39 | − WARN_ON(__big_tty_mutex_owner != task); | |
| 40 | − __big_tty_mutex_owner = NULL; | |
| 41 | − | |
| 42 | 30 | mutex_unlock(&big_tty_mutex); |
| 43 | 31 | } |
| 44 | 32 | EXPORT_SYMBOL(tty_unlock); |
| @@ -350,7 +350,7 @@ int tty_port_close_start(struct tty_port *port, · 349 unmodified lines | ||
| 350 | 350 | tty_driver_flush_buffer(tty); |
| 351 | 351 | if (test_bit(ASYNCB_INITIALIZED, &port->flags) && |
| 352 | 352 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
| 353 | − tty_wait_until_sent(tty, port->closing_wait); | |
| 353 | + tty_wait_until_sent_from_close(tty, port->closing_wait); | |
| 354 | 354 | if (port->drain_delay) { |
| 355 | 355 | unsigned int bps = tty_get_baud_rate(tty); |
| 356 | 356 | long timeout; |
| @@ -33,7 +33,6 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <linux/string.h> |
| 34 | 34 | #include <linux/init.h> |
| 35 | 35 | #include <linux/slab.h> |
| 36 | −#include <linux/irq.h> | |
| 37 | 36 | |
| 38 | 37 | #include <linux/kbd_kern.h> |
| 39 | 38 | #include <linux/kbd_diacr.h> |
| @@ -43,6 +42,8 @@ · 3 unmodified lines | ||
| 43 | 42 | #include <linux/notifier.h> |
| 44 | 43 | #include <linux/jiffies.h> |
| 45 | 44 | |
| 45 | +#include <asm/irq_regs.h> | |
| 46 | + | |
| 46 | 47 | extern void ctrl_alt_del(void); |
| 47 | 48 | |
| 48 | 49 | /* |
| @@ -301,6 +301,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t · 300 unmodified lines | ||
| 301 | 301 | /* Insert the contents of the selection buffer into the |
| 302 | 302 | * queue of the tty associated with the current console. |
| 303 | 303 | * Invoked by ioctl(). |
| 304 | + * | |
| 305 | + * Locking: always called with BTM from vt_ioctl | |
| 304 | 306 | */ |
| 305 | 307 | int paste_selection(struct tty_struct *tty) |
| 306 | 308 | { |
| @@ -310,8 +312,6 @@ int paste_selection(struct tty_struct *tty) · 3 unmodified lines | ||
| 310 | 312 | struct tty_ldisc *ld; |
| 311 | 313 | DECLARE_WAITQUEUE(wait, current); |
| 312 | 314 | |
| 313 | − /* always called with BTM from vt_ioctl */ | |
| 314 | − WARN_ON(!tty_locked()); | |
| 315 | 315 | |
| 316 | 316 | console_lock(); |
| 317 | 317 | poke_blanked_console(); |
| @@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(unregister_vt_notifier); · 258 unmodified lines | ||
| 259 | 259 | |
| 260 | 260 | static void notify_write(struct vc_data *vc, unsigned int unicode) |
| 261 | 261 | { |
| 262 | − struct vt_notifier_param param = { .vc = vc, unicode = unicode }; | |
| 262 | + struct vt_notifier_param param = { .vc = vc, .c = unicode }; | |
| 263 | 263 | atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, ¶m); |
| 264 | 264 | } |
| 265 | 265 | |
| @@ -211,6 +211,7 @@ struct serial_rs485 { · 210 unmodified lines | ||
| 211 | 211 | #define SER_RS485_RTS_ON_SEND (1 << 1) |
| 212 | 212 | #define SER_RS485_RTS_AFTER_SEND (1 << 2) |
| 213 | 213 | #define SER_RS485_RTS_BEFORE_SEND (1 << 3) |
| 214 | +#define SER_RS485_RX_DURING_TX (1 << 4) | |
| 214 | 215 | __u32 delay_rts_before_send; /* Milliseconds */ |
| 215 | 216 | __u32 delay_rts_after_send; /* Milliseconds */ |
| 216 | 217 | __u32 padding[5]; /* Memory is cheap, new structs |
| @@ -35,6 +35,7 @@ struct plat_serial8250_port { · 34 unmodified lines | ||
| 35 | 35 | void (*set_termios)(struct uart_port *, |
| 36 | 36 | struct ktermios *new, |
| 37 | 37 | struct ktermios *old); |
| 38 | + int (*handle_irq)(struct uart_port *); | |
| 38 | 39 | void (*pm)(struct uart_port *, unsigned int state, |
| 39 | 40 | unsigned old); |
| 40 | 41 | }; |
| @@ -80,6 +81,7 @@ extern void serial8250_do_set_termios(struct uart_port *port, · 39 unmodified lines | ||
| 80 | 81 | struct ktermios *termios, struct ktermios *old); |
| 81 | 82 | extern void serial8250_do_pm(struct uart_port *port, unsigned int state, |
| 82 | 83 | unsigned int oldstate); |
| 84 | +int serial8250_handle_irq(struct uart_port *port, unsigned int iir); | |
| 83 | 85 | |
| 84 | 86 | extern void serial8250_set_isa_configurator(void (*v) |
| 85 | 87 | (int port, struct uart_port *up, |
| @@ -46,7 +46,8 @@ · 45 unmodified lines | ||
| 46 | 46 | #define PORT_AR7 18 /* Texas Instruments AR7 internal UART */ |
| 47 | 47 | #define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */ |
| 48 | 48 | #define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */ |
| 49 | −#define PORT_MAX_8250 20 /* max port ID */ | |
| 49 | +#define PORT_XR17D15X 21 /* Exar XR17D15x UART */ | |
| 50 | +#define PORT_MAX_8250 21 /* max port ID */ | |
| 50 | 51 | |
| 51 | 52 | /* |
| 52 | 53 | * ARM specific type numbers. These are not currently guaranteed |
| @@ -300,6 +301,7 @@ struct uart_port { · 247 unmodified lines | ||
| 300 | 301 | void (*set_termios)(struct uart_port *, |
| 301 | 302 | struct ktermios *new, |
| 302 | 303 | struct ktermios *old); |
| 304 | + int (*handle_irq)(struct uart_port *); | |
| 303 | 305 | void (*pm)(struct uart_port *, unsigned int state, |
| 304 | 306 | unsigned int old); |
| 305 | 307 | unsigned int irq; /* irq number */ |
| @@ -317,9 +319,7 @@ struct uart_port { · 11 unmodified lines | ||
| 317 | 319 | #define UPIO_MEM32 (3) |
| 318 | 320 | #define UPIO_AU (4) /* Au1x00 type IO */ |
| 319 | 321 | #define UPIO_TSI (5) /* Tsi108/109 type IO */ |
| 320 | −#define UPIO_DWAPB (6) /* DesignWare APB UART */ | |
| 321 | −#define UPIO_RM9000 (7) /* RM9000 type IO */ | |
| 322 | −#define UPIO_DWAPB32 (8) /* DesignWare APB UART (32 bit accesses) */ | |
| 322 | +#define UPIO_RM9000 (6) /* RM9000 type IO */ | |
| 323 | 323 | |
| 324 | 324 | unsigned int read_status_mask; /* driver specific */ |
| 325 | 325 | unsigned int ignore_status_mask; /* driver specific */ |
| @@ -350,6 +350,7 @@ struct uart_port { · 24 unmodified lines | ||
| 350 | 350 | #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16)) |
| 351 | 351 | #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) |
| 352 | 352 | #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) |
| 353 | +#define UPF_EXAR_EFR ((__force upf_t) (1 << 25)) | |
| 353 | 354 | /* The exact UART type is known and should not be probed. */ |
| 354 | 355 | #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27)) |
| 355 | 356 | #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) |
| @@ -384,7 +385,6 @@ struct uart_state { · 28 unmodified lines | ||
| 384 | 385 | int pm_state; |
| 385 | 386 | struct circ_buf xmit; |
| 386 | 387 | |
| 387 | − struct tasklet_struct tlet; | |
| 388 | 388 | struct uart_port *uart_port; |
| 389 | 389 | }; |
| 390 | 390 | |
| @@ -152,6 +152,7 @@ · 151 unmodified lines | ||
| 152 | 152 | * LCR=0xBF (or DLAB=1 for 16C660) |
| 153 | 153 | */ |
| 154 | 154 | #define UART_EFR 2 /* I/O: Extended Features Register */ |
| 155 | +#define UART_XR_EFR 9 /* I/O: Extended Features Register (XR17D15x) */ | |
| 155 | 156 | #define UART_EFR_CTS 0x80 /* CTS flow control */ |
| 156 | 157 | #define UART_EFR_RTS 0x40 /* RTS flow control */ |
| 157 | 158 | #define UART_EFR_SCD 0x20 /* Special character detect */ |
| @@ -473,7 +473,9 @@ extern void proc_clear_tty(struct task_struct *p); · 472 unmodified lines | ||
| 473 | 473 | extern struct tty_struct *get_current_tty(void); |
| 474 | 474 | extern void tty_default_fops(struct file_operations *fops); |
| 475 | 475 | extern struct tty_struct *alloc_tty_struct(void); |
| 476 | −extern int tty_add_file(struct tty_struct *tty, struct file *file); | |
| 476 | +extern int tty_alloc_file(struct file *file); | |
| 477 | +extern void tty_add_file(struct tty_struct *tty, struct file *file); | |
| 478 | +extern void tty_free_file(struct file *file); | |
| 477 | 479 | extern void free_tty_struct(struct tty_struct *tty); |
| 478 | 480 | extern void initialize_tty_struct(struct tty_struct *tty, |
| 479 | 481 | struct tty_driver *driver, int idx); |
| @@ -581,6 +583,8 @@ extern int __init tty_init(void); · 101 unmodified lines | ||
| 581 | 583 | /* tty_ioctl.c */ |
| 582 | 584 | extern int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, |
| 583 | 585 | unsigned int cmd, unsigned long arg); |
| 586 | +extern long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file, | |
| 587 | + unsigned int cmd, unsigned long arg); | |
| 584 | 588 | |
| 585 | 589 | /* serial.c */ |
| 586 | 590 | |
| @@ -602,8 +606,24 @@ extern long vt_compat_ioctl(struct tty_struct *tty, · 15 unmodified lines | ||
| 602 | 606 | /* functions for preparation of BKL removal */ |
| 603 | 607 | extern void __lockfunc tty_lock(void) __acquires(tty_lock); |
| 604 | 608 | extern void __lockfunc tty_unlock(void) __releases(tty_lock); |
| 605 | −extern struct task_struct *__big_tty_mutex_owner; | |
| 606 | −#define tty_locked() (current == __big_tty_mutex_owner) | |
| 609 | + | |
| 610 | +/* | |
| 611 | + * this shall be called only from where BTM is held (like close) | |
| 612 | + * | |
| 613 | + * We need this to ensure nobody waits for us to finish while we are waiting. | |
| 614 | + * Without this we were encountering system stalls. | |
| 615 | + * | |
| 616 | + * This should be indeed removed with BTM removal later. | |
| 617 | + * | |
| 618 | + * Locking: BTM required. Nobody is allowed to hold port->mutex. | |
| 619 | + */ | |
| 620 | +static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, | |
| 621 | + long timeout) | |
| 622 | +{ | |
| 623 | + tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */ | |
| 624 | + tty_wait_until_sent(tty, timeout); | |
| 625 | + tty_lock(); | |
| 626 | +} | |
| 607 | 627 | |
| 608 | 628 | /* |
| 609 | 629 | * wait_event_interruptible_tty -- wait for a condition with the tty lock held |
| @@ -551,7 +551,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) · 550 unmodified lines | ||
| 551 | 551 | */ |
| 552 | 552 | tty->closing = 1; |
| 553 | 553 | if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
| 554 | − tty_wait_until_sent(tty, self->closing_wait); | |
| 554 | + tty_wait_until_sent_from_close(tty, self->closing_wait); | |
| 555 | 555 | |
| 556 | 556 | ircomm_tty_shutdown(self); |
| 557 | 557 | |