[PATCH] ocfs2: fix oops in mmap_truncate testing
[pandora-kernel.git] / arch / ppc / boot / simple / mv64x60_tty.c
1 /*
2  * Bootloader version of the embedded MPSC/UART driver for the Marvell 64x60.
3  * Note: Due to a GT64260A erratum, DMA will be used for UART input (via SDMA).
4  *
5  * Author: Mark A. Greer <mgreer@mvista.com>
6  *
7  * 2001 (c) MontaVista Software, Inc. This file is licensed under
8  * the terms of the GNU General Public License version 2. This program
9  * is licensed "as is" without any warranty of any kind, whether express
10  * or implied.
11  */
12
13 /* This code assumes that the data cache has been disabled (L1, L2, L3). */
14
15 #include <linux/types.h>
16 #include <linux/serial_reg.h>
17 #include <asm/serial.h>
18 #include <asm/io.h>
19 #include <asm/mv64x60_defs.h>
20 #include <mpsc_defs.h>
21
22 #ifdef CONFIG_EV64360
23 #include <platforms/ev64360.h>
24 u32     mv64x60_console_baud = EV64360_DEFAULT_BAUD;
25 u32     mv64x60_mpsc_clk_src = EV64360_MPSC_CLK_SRC; /* TCLK */
26 u32     mv64x60_mpsc_clk_freq = EV64360_MPSC_CLK_FREQ;
27 #else
28 u32     mv64x60_console_baud = 9600;
29 u32     mv64x60_mpsc_clk_src = 8; /* TCLK */
30 u32     mv64x60_mpsc_clk_freq = 100000000;
31 #endif
32
33 extern void udelay(long);
34 static void stop_dma(int chan);
35
36 static void __iomem *mv64x60_base = (void __iomem *)CONFIG_MV64X60_NEW_BASE;
37
38 struct sdma_regs {
39         u32     sdc;
40         u32     sdcm;
41         u32     rx_desc;
42         u32     rx_buf_ptr;
43         u32     scrdp;
44         u32     tx_desc;
45         u32     sctdp;
46         u32     sftdp;
47 };
48
49 static struct sdma_regs sdma_regs[2];
50
51 #define SDMA_REGS_INIT(s, reg_base) {                   \
52         (s)->sdc        = (reg_base) + SDMA_SDC;        \
53         (s)->sdcm       = (reg_base) + SDMA_SDCM;       \
54         (s)->rx_desc    = (reg_base) + SDMA_RX_DESC;    \
55         (s)->rx_buf_ptr = (reg_base) + SDMA_RX_BUF_PTR; \
56         (s)->scrdp      = (reg_base) + SDMA_SCRDP;      \
57         (s)->tx_desc    = (reg_base) + SDMA_TX_DESC;    \
58         (s)->sctdp      = (reg_base) + SDMA_SCTDP;      \
59         (s)->sftdp      = (reg_base) + SDMA_SFTDP;      \
60 }
61
62 static u32      mpsc_base[2] = { MV64x60_MPSC_0_OFFSET, MV64x60_MPSC_1_OFFSET };
63
64 struct mv64x60_rx_desc {
65         u16     bufsize;
66         u16     bytecnt;
67         u32     cmd_stat;
68         u32     next_desc_ptr;
69         u32     buffer;
70 };
71
72 struct mv64x60_tx_desc {
73         u16     bytecnt;
74         u16     shadow;
75         u32     cmd_stat;
76         u32     next_desc_ptr;
77         u32     buffer;
78 };
79
80 #define MAX_RESET_WAIT  10000
81 #define MAX_TX_WAIT     10000
82
83 #define RX_NUM_DESC     2
84 #define TX_NUM_DESC     2
85
86 #define RX_BUF_SIZE     32
87 #define TX_BUF_SIZE     32
88
89 static struct mv64x60_rx_desc rd[2][RX_NUM_DESC] __attribute__ ((aligned(32)));
90 static struct mv64x60_tx_desc td[2][TX_NUM_DESC] __attribute__ ((aligned(32)));
91
92 static char rx_buf[2][RX_NUM_DESC * RX_BUF_SIZE] __attribute__ ((aligned(32)));
93 static char tx_buf[2][TX_NUM_DESC * TX_BUF_SIZE] __attribute__ ((aligned(32)));
94
95 static int cur_rd[2] = { 0, 0 };
96 static int cur_td[2] = { 0, 0 };
97
98 static char chan_initialized[2] = { 0, 0 };
99
100
101 #define RX_INIT_RDP(rdp) {                      \
102         (rdp)->bufsize = 2;                     \
103         (rdp)->bytecnt = 0;                     \
104         (rdp)->cmd_stat = SDMA_DESC_CMDSTAT_L | SDMA_DESC_CMDSTAT_F |   \
105                 SDMA_DESC_CMDSTAT_O;    \
106 }
107
108 #ifdef CONFIG_MV64360
109 static u32 cpu2mem_tab[MV64x60_CPU2MEM_WINDOWS][2] = {
110                 { MV64x60_CPU2MEM_0_BASE, MV64x60_CPU2MEM_0_SIZE },
111                 { MV64x60_CPU2MEM_1_BASE, MV64x60_CPU2MEM_1_SIZE },
112                 { MV64x60_CPU2MEM_2_BASE, MV64x60_CPU2MEM_2_SIZE },
113                 { MV64x60_CPU2MEM_3_BASE, MV64x60_CPU2MEM_3_SIZE }
114 };
115
116 static u32 com2mem_tab[MV64x60_CPU2MEM_WINDOWS][2] = {
117                 { MV64360_MPSC2MEM_0_BASE, MV64360_MPSC2MEM_0_SIZE },
118                 { MV64360_MPSC2MEM_1_BASE, MV64360_MPSC2MEM_1_SIZE },
119                 { MV64360_MPSC2MEM_2_BASE, MV64360_MPSC2MEM_2_SIZE },
120                 { MV64360_MPSC2MEM_3_BASE, MV64360_MPSC2MEM_3_SIZE }
121 };
122
123 static u32 dram_selects[MV64x60_CPU2MEM_WINDOWS] = { 0xe, 0xd, 0xb, 0x7 };
124 #endif
125
126 unsigned long
127 serial_init(int chan, void *ignored)
128 {
129         u32             mpsc_routing_base, sdma_base, brg_bcr, cdv;
130         int             i;
131
132         chan = (chan == 1); /* default to chan 0 if anything but 1 */
133
134         if (chan_initialized[chan])
135                 return chan;
136
137         chan_initialized[chan] = 1;
138
139         if (chan == 0) {
140                 sdma_base = MV64x60_SDMA_0_OFFSET;
141                 brg_bcr = MV64x60_BRG_0_OFFSET + BRG_BCR;
142                 SDMA_REGS_INIT(&sdma_regs[0], MV64x60_SDMA_0_OFFSET);
143         } else {
144                 sdma_base = MV64x60_SDMA_1_OFFSET;
145                 brg_bcr = MV64x60_BRG_1_OFFSET + BRG_BCR;
146                 SDMA_REGS_INIT(&sdma_regs[0], MV64x60_SDMA_1_OFFSET);
147         }
148
149         mpsc_routing_base = MV64x60_MPSC_ROUTING_OFFSET;
150
151         stop_dma(chan);
152
153         /* Set up ring buffers */
154         for (i=0; i<RX_NUM_DESC; i++) {
155                 RX_INIT_RDP(&rd[chan][i]);
156                 rd[chan][i].buffer = (u32)&rx_buf[chan][i * RX_BUF_SIZE];
157                 rd[chan][i].next_desc_ptr = (u32)&rd[chan][i+1];
158         }
159         rd[chan][RX_NUM_DESC - 1].next_desc_ptr = (u32)&rd[chan][0];
160
161         for (i=0; i<TX_NUM_DESC; i++) {
162                 td[chan][i].bytecnt = 0;
163                 td[chan][i].shadow = 0;
164                 td[chan][i].buffer = (u32)&tx_buf[chan][i * TX_BUF_SIZE];
165                 td[chan][i].cmd_stat = SDMA_DESC_CMDSTAT_F|SDMA_DESC_CMDSTAT_L;
166                 td[chan][i].next_desc_ptr = (u32)&td[chan][i+1];
167         }
168         td[chan][TX_NUM_DESC - 1].next_desc_ptr = (u32)&td[chan][0];
169
170         /* Set MPSC Routing */
171         out_le32(mv64x60_base + mpsc_routing_base + MPSC_MRR, 0x3ffffe38);
172
173 #ifdef CONFIG_GT64260
174         out_le32(mv64x60_base + GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102);
175 #else /* Must be MV64360 or MV64460 */
176         {
177         u32     enables, prot_bits, v;
178
179         /* Set up comm unit to memory mapping windows */
180         /* Note: Assumes MV64x60_CPU2MEM_WINDOWS == 4 */
181
182         enables = in_le32(mv64x60_base + MV64360_CPU_BAR_ENABLE) & 0xf;
183         prot_bits = 0;
184
185         for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
186                 if (!(enables & (1 << i))) {
187                         v = in_le32(mv64x60_base + cpu2mem_tab[i][0]);
188                         v = ((v & 0xffff) << 16) | (dram_selects[i] << 8);
189                         out_le32(mv64x60_base + com2mem_tab[i][0], v);
190
191                         v = in_le32(mv64x60_base + cpu2mem_tab[i][1]);
192                         v = (v & 0xffff) << 16;
193                         out_le32(mv64x60_base + com2mem_tab[i][1], v);
194
195                         prot_bits |= (0x3 << (i << 1)); /* r/w access */
196                 }
197         }
198
199         out_le32(mv64x60_base + MV64360_MPSC_0_REMAP, 0);
200         out_le32(mv64x60_base + MV64360_MPSC_1_REMAP, 0);
201         out_le32(mv64x60_base + MV64360_MPSC2MEM_ACC_PROT_0, prot_bits);
202         out_le32(mv64x60_base + MV64360_MPSC2MEM_ACC_PROT_1, prot_bits);
203         out_le32(mv64x60_base + MV64360_MPSC2MEM_BAR_ENABLE, enables);
204         }
205 #endif
206
207         /* MPSC 0/1 Rx & Tx get clocks BRG0/1 */
208         out_le32(mv64x60_base + mpsc_routing_base + MPSC_RCRR, 0x00000100);
209         out_le32(mv64x60_base + mpsc_routing_base + MPSC_TCRR, 0x00000100);
210
211         /* clear pending interrupts */
212         out_le32(mv64x60_base + MV64x60_SDMA_INTR_OFFSET + SDMA_INTR_MASK, 0);
213
214         out_le32(mv64x60_base + SDMA_SCRDP + sdma_base, (int)&rd[chan][0]);
215         out_le32(mv64x60_base + SDMA_SCTDP + sdma_base,
216                 (int)&td[chan][TX_NUM_DESC - 1]);
217         out_le32(mv64x60_base + SDMA_SFTDP + sdma_base,
218                 (int)&td[chan][TX_NUM_DESC - 1]);
219
220         out_le32(mv64x60_base + SDMA_SDC + sdma_base,
221                 SDMA_SDC_RFT | SDMA_SDC_SFM | SDMA_SDC_BLMR | SDMA_SDC_BLMT |
222                 (3 << 12));
223
224         cdv = ((mv64x60_mpsc_clk_freq/(32*mv64x60_console_baud))-1);
225         out_le32(mv64x60_base + brg_bcr,
226                 ((mv64x60_mpsc_clk_src << 18) | (1 << 16) | cdv));
227
228         /* Put MPSC into UART mode, no null modem, 16x clock mode */
229         out_le32(mv64x60_base + MPSC_MMCRL + mpsc_base[chan], 0x000004c4);
230         out_le32(mv64x60_base + MPSC_MMCRH + mpsc_base[chan], 0x04400400);
231
232         out_le32(mv64x60_base + MPSC_CHR_1 + mpsc_base[chan], 0);
233         out_le32(mv64x60_base + MPSC_CHR_9 + mpsc_base[chan], 0);
234         out_le32(mv64x60_base + MPSC_CHR_10 + mpsc_base[chan], 0);
235         out_le32(mv64x60_base + MPSC_CHR_3 + mpsc_base[chan], 4);
236         out_le32(mv64x60_base + MPSC_CHR_4 + mpsc_base[chan], 0);
237         out_le32(mv64x60_base + MPSC_CHR_5 + mpsc_base[chan], 0);
238         out_le32(mv64x60_base + MPSC_CHR_6 + mpsc_base[chan], 0);
239         out_le32(mv64x60_base + MPSC_CHR_7 + mpsc_base[chan], 0);
240         out_le32(mv64x60_base + MPSC_CHR_8 + mpsc_base[chan], 0);
241
242         /* 8 data bits, 1 stop bit */
243         out_le32(mv64x60_base + MPSC_MPCR + mpsc_base[chan], (3 << 12));
244         out_le32(mv64x60_base + SDMA_SDCM + sdma_base, SDMA_SDCM_ERD);
245         out_le32(mv64x60_base + MPSC_CHR_2 + mpsc_base[chan], MPSC_CHR_2_EH);
246
247         udelay(100);
248
249         return chan;
250 }
251
252 static void
253 stop_dma(int chan)
254 {
255         int     i;
256
257         /* Abort MPSC Rx (aborting Tx messes things up) */
258         out_le32(mv64x60_base + MPSC_CHR_2 + mpsc_base[chan], MPSC_CHR_2_RA);
259
260         /* Abort SDMA Rx, Tx */
261         out_le32(mv64x60_base + sdma_regs[chan].sdcm,
262                 SDMA_SDCM_AR | SDMA_SDCM_STD);
263
264         for (i=0; i<MAX_RESET_WAIT; i++) {
265                 if ((in_le32(mv64x60_base + sdma_regs[chan].sdcm) &
266                                 (SDMA_SDCM_AR | SDMA_SDCM_AT)) == 0)
267                         break;
268
269                 udelay(100);
270         }
271 }
272
273 static int
274 wait_for_ownership(int chan)
275 {
276         int     i;
277
278         for (i=0; i<MAX_TX_WAIT; i++) {
279                 if ((in_le32(mv64x60_base + sdma_regs[chan].sdcm) &
280                                 SDMA_SDCM_TXD) == 0)
281                         break;
282
283                 udelay(1000);
284         }
285
286         return (i < MAX_TX_WAIT);
287 }
288
289 void
290 serial_putc(unsigned long com_port, unsigned char c)
291 {
292         struct mv64x60_tx_desc  *tdp;
293
294         if (wait_for_ownership(com_port) == 0)
295                 return;
296
297         tdp = &td[com_port][cur_td[com_port]];
298         if (++cur_td[com_port] >= TX_NUM_DESC)
299                 cur_td[com_port] = 0;
300
301         *(unchar *)(tdp->buffer ^ 7) = c;
302         tdp->bytecnt = 1;
303         tdp->shadow = 1;
304         tdp->cmd_stat = SDMA_DESC_CMDSTAT_L | SDMA_DESC_CMDSTAT_F |
305                 SDMA_DESC_CMDSTAT_O;
306
307         out_le32(mv64x60_base + sdma_regs[com_port].sctdp, (int)tdp);
308         out_le32(mv64x60_base + sdma_regs[com_port].sftdp, (int)tdp);
309         out_le32(mv64x60_base + sdma_regs[com_port].sdcm,
310                 in_le32(mv64x60_base + sdma_regs[com_port].sdcm) |
311                         SDMA_SDCM_TXD);
312 }
313
314 unsigned char
315 serial_getc(unsigned long com_port)
316 {
317         struct mv64x60_rx_desc  *rdp;
318         unchar                  c = '\0';
319
320         rdp = &rd[com_port][cur_rd[com_port]];
321
322         if ((rdp->cmd_stat & (SDMA_DESC_CMDSTAT_O|SDMA_DESC_CMDSTAT_ES)) == 0) {
323                 c = *(unchar *)(rdp->buffer ^ 7);
324                 RX_INIT_RDP(rdp);
325                 if (++cur_rd[com_port] >= RX_NUM_DESC)
326                         cur_rd[com_port] = 0;
327         }
328
329         return c;
330 }
331
332 int
333 serial_tstc(unsigned long com_port)
334 {
335         struct mv64x60_rx_desc  *rdp;
336         int                     loop_count = 0;
337         int                     rc = 0;
338
339         rdp = &rd[com_port][cur_rd[com_port]];
340
341         /* Go through rcv descs until empty looking for one with data (no error)*/
342         while (((rdp->cmd_stat & SDMA_DESC_CMDSTAT_O) == 0) &&
343                 (loop_count++ < RX_NUM_DESC)) {
344
345                 /* If there was an error, reinit the desc & continue */
346                 if ((rdp->cmd_stat & SDMA_DESC_CMDSTAT_ES) != 0) {
347                         RX_INIT_RDP(rdp);
348                         if (++cur_rd[com_port] >= RX_NUM_DESC)
349                                 cur_rd[com_port] = 0;
350                         rdp = (struct mv64x60_rx_desc *)rdp->next_desc_ptr;
351                 } else {
352                         rc = 1;
353                         break;
354                 }
355         }
356
357         return rc;
358 }
359
360 void
361 serial_close(unsigned long com_port)
362 {
363         stop_dma(com_port);
364 }