blob: 3770aa38ee9f9f6b039316ca1714997e431933d3 [file] [log] [blame]
Roy Huang088eec12007-06-21 11:34:16 +08001#include <linux/serial.h>
2#include <asm/dma.h>
Michael Hennerichb99ab542007-10-11 10:57:54 +08003#include <asm/portmux.h>
Roy Huang088eec12007-06-21 11:34:16 +08004
Roy Huang24a07a12007-07-12 22:41:45 +08005#define NR_PORTS 4
Roy Huang088eec12007-06-21 11:34:16 +08006
Roy Huang088eec12007-06-21 11:34:16 +08007#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
Roy Huang088eec12007-06-21 11:34:16 +08008#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
Roy Huang24a07a12007-07-12 22:41:45 +08009#define OFFSET_GCTL 0x08 /* Global Control Register */
Roy Huang088eec12007-06-21 11:34:16 +080010#define OFFSET_LCR 0x0C /* Line Control Register */
11#define OFFSET_MCR 0x10 /* Modem Control Register */
12#define OFFSET_LSR 0x14 /* Line Status Register */
13#define OFFSET_MSR 0x18 /* Modem Status Register */
14#define OFFSET_SCR 0x1C /* SCR Scratch Register */
Roy Huang24a07a12007-07-12 22:41:45 +080015#define OFFSET_IER_SET 0x20 /* Set Interrupt Enable Register */
16#define OFFSET_IER_CLEAR 0x24 /* Clear Interrupt Enable Register */
17#define OFFSET_THR 0x28 /* Transmit Holding register */
18#define OFFSET_RBR 0x2C /* Receive Buffer register */
Roy Huang088eec12007-06-21 11:34:16 +080019
20#define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
21#define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
Roy Huang088eec12007-06-21 11:34:16 +080022#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
Roy Huang24a07a12007-07-12 22:41:45 +080023#define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER_SET))
Roy Huang088eec12007-06-21 11:34:16 +080024#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR))
25#define UART_GET_LSR(uart) bfin_read16(((uart)->port.membase + OFFSET_LSR))
26#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL))
27
28#define UART_PUT_CHAR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_THR),v)
29#define UART_PUT_DLL(uart,v) bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
Roy Huang24a07a12007-07-12 22:41:45 +080030#define UART_SET_IER(uart,v) bfin_write16(((uart)->port.membase + OFFSET_IER_SET),v)
31#define UART_CLEAR_IER(uart,v) bfin_write16(((uart)->port.membase + OFFSET_IER_CLEAR),v)
Roy Huang088eec12007-06-21 11:34:16 +080032#define UART_PUT_DLH(uart,v) bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
Roy Huang24a07a12007-07-12 22:41:45 +080033#define UART_PUT_LSR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_LSR),v)
Roy Huang088eec12007-06-21 11:34:16 +080034#define UART_PUT_LCR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
35#define UART_PUT_GCTL(uart,v) bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
36
37#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
38# define CONFIG_SERIAL_BFIN_CTSRTS
39
40# ifndef CONFIG_UART0_CTS_PIN
41# define CONFIG_UART0_CTS_PIN -1
42# endif
43
44# ifndef CONFIG_UART0_RTS_PIN
45# define CONFIG_UART0_RTS_PIN -1
46# endif
47
48# ifndef CONFIG_UART1_CTS_PIN
49# define CONFIG_UART1_CTS_PIN -1
50# endif
51
52# ifndef CONFIG_UART1_RTS_PIN
53# define CONFIG_UART1_RTS_PIN -1
54# endif
55#endif
56/*
57 * The pin configuration is different from schematic
58 */
59struct bfin_serial_port {
60 struct uart_port port;
61 unsigned int old_status;
62#ifdef CONFIG_SERIAL_BFIN_DMA
63 int tx_done;
64 int tx_count;
65 struct circ_buf rx_dma_buf;
66 struct timer_list rx_dma_timer;
67 int rx_dma_nrows;
68 unsigned int tx_dma_channel;
69 unsigned int rx_dma_channel;
70 struct work_struct tx_dma_workqueue;
71#else
72 struct work_struct cts_workqueue;
73#endif
74#ifdef CONFIG_SERIAL_BFIN_CTSRTS
75 int cts_pin;
76 int rts_pin;
77#endif
78};
79
80struct bfin_serial_port bfin_serial_ports[NR_PORTS];
81struct bfin_serial_res {
82 unsigned long uart_base_addr;
83 int uart_irq;
84#ifdef CONFIG_SERIAL_BFIN_DMA
85 unsigned int uart_tx_dma_channel;
86 unsigned int uart_rx_dma_channel;
87#endif
88#ifdef CONFIG_SERIAL_BFIN_CTSRTS
89 int uart_cts_pin;
90 int uart_rts_pin;
91#endif
92};
93
94struct bfin_serial_res bfin_serial_resource[] = {
95#ifdef CONFIG_SERIAL_BFIN_UART0
96 {
97 0xFFC00400,
98 IRQ_UART0_RX,
99#ifdef CONFIG_SERIAL_BFIN_DMA
100 CH_UART0_TX,
101 CH_UART0_RX,
102#endif
103#ifdef CONFIG_BFIN_UART0_CTSRTS
104 CONFIG_UART0_CTS_PIN,
105 CONFIG_UART0_RTS_PIN,
106#endif
107 },
108#endif
109#ifdef CONFIG_SERIAL_BFIN_UART1
110 {
111 0xFFC02000,
112 IRQ_UART1_RX,
113#ifdef CONFIG_SERIAL_BFIN_DMA
114 CH_UART1_TX,
115 CH_UART1_RX,
116#endif
Roy Huang24a07a12007-07-12 22:41:45 +0800117 },
118#endif
119#ifdef CONFIG_SERIAL_BFIN_UART2
120 {
121 0xFFC02100,
122 IRQ_UART2_RX,
123#ifdef CONFIG_SERIAL_BFIN_DMA
124 CH_UART2_TX,
125 CH_UART2_RX,
126#endif
127#ifdef CONFIG_BFIN_UART2_CTSRTS
128 CONFIG_UART2_CTS_PIN,
129 CONFIG_UART2_RTS_PIN,
130#endif
131 },
132#endif
133#ifdef CONFIG_SERIAL_BFIN_UART3
134 {
135 0xFFC03100,
136 IRQ_UART3_RX,
137#ifdef CONFIG_SERIAL_BFIN_DMA
138 CH_UART3_TX,
139 CH_UART3_RX,
Roy Huang088eec12007-06-21 11:34:16 +0800140#endif
141 },
142#endif
143};
144
145int nr_ports = ARRAY_SIZE(bfin_serial_resource);
146
Michael Hennerichb99ab542007-10-11 10:57:54 +0800147#define DRIVER_NAME "bfin-uart"
148
Roy Huang088eec12007-06-21 11:34:16 +0800149static void bfin_serial_hw_init(struct bfin_serial_port *uart)
150{
Roy Huang24a07a12007-07-12 22:41:45 +0800151#ifdef CONFIG_SERIAL_BFIN_UART0
Michael Hennerichb99ab542007-10-11 10:57:54 +0800152 peripheral_request(P_UART0_TX, DRIVER_NAME);
153 peripheral_request(P_UART0_RX, DRIVER_NAME);
Roy Huang24a07a12007-07-12 22:41:45 +0800154#endif
Roy Huang088eec12007-06-21 11:34:16 +0800155
Roy Huang24a07a12007-07-12 22:41:45 +0800156#ifdef CONFIG_SERIAL_BFIN_UART1
Michael Hennerichb99ab542007-10-11 10:57:54 +0800157 peripheral_request(P_UART1_TX, DRIVER_NAME);
158 peripheral_request(P_UART1_RX, DRIVER_NAME);
159
Roy Huang24a07a12007-07-12 22:41:45 +0800160#ifdef CONFIG_BFIN_UART1_CTSRTS
Michael Hennerichb99ab542007-10-11 10:57:54 +0800161 peripheral_request(P_UART1_RTS, DRIVER_NAME);
162 peripheral_request(P_UART1_CTS DRIVER_NAME);
Roy Huang24a07a12007-07-12 22:41:45 +0800163#endif
164#endif
Roy Huang088eec12007-06-21 11:34:16 +0800165
Roy Huang24a07a12007-07-12 22:41:45 +0800166#ifdef CONFIG_SERIAL_BFIN_UART2
Michael Hennerichb99ab542007-10-11 10:57:54 +0800167 peripheral_request(P_UART2_TX, DRIVER_NAME);
168 peripheral_request(P_UART2_RX, DRIVER_NAME);
Roy Huang24a07a12007-07-12 22:41:45 +0800169#endif
170
171#ifdef CONFIG_SERIAL_BFIN_UART3
Michael Hennerichb99ab542007-10-11 10:57:54 +0800172 peripheral_request(P_UART3_TX, DRIVER_NAME);
173 peripheral_request(P_UART3_RX, DRIVER_NAME);
174
Roy Huang24a07a12007-07-12 22:41:45 +0800175#ifdef CONFIG_BFIN_UART3_CTSRTS
Michael Hennerichb99ab542007-10-11 10:57:54 +0800176 peripheral_request(P_UART3_RTS, DRIVER_NAME);
177 peripheral_request(P_UART3_CTS DRIVER_NAME);
Roy Huang24a07a12007-07-12 22:41:45 +0800178#endif
179#endif
180 SSYNC();
Roy Huang088eec12007-06-21 11:34:16 +0800181#ifdef CONFIG_SERIAL_BFIN_CTSRTS
182 if (uart->cts_pin >= 0) {
Michael Hennerichb99ab542007-10-11 10:57:54 +0800183 gpio_request(uart->cts_pin, DRIVER_NAME);
Roy Huang088eec12007-06-21 11:34:16 +0800184 gpio_direction_input(uart->cts_pin);
185 }
186
187 if (uart->rts_pin >= 0) {
Michael Hennerichb99ab542007-10-11 10:57:54 +0800188 gpio_request(uart->rts_pin, DRIVER_NAME);
Michael Hennerichacbcd262008-01-22 18:36:20 +0800189 gpio_direction_output(uart->rts_pin, 0);
Roy Huang088eec12007-06-21 11:34:16 +0800190 }
191#endif
192}