2 * arch/ppc/boot/simple/mv64x60_tty.c
4 * Bootloader version of the embedded MPSC/UART driver for the Marvell 64x60.
5 * Note: Due to a GT64260A erratum, DMA will be used for UART input (via SDMA).
7 * Author: Mark A. Greer <mgreer@mvista.com>
9 * 2001 (c) MontaVista Software, Inc. This file is licensed under
10 * the terms of the GNU General Public License version 2. This program
11 * is licensed "as is" without any warranty of any kind, whether express
15 /* This code assumes that the data cache has been disabled (L1, L2, L3). */
17 #include <linux/config.h>
18 #include <linux/types.h>
19 #include <linux/serial_reg.h>
20 #include <asm/serial.h>
22 #include <asm/mv64x60_defs.h>
23 #include <mpsc_defs.h>
26 #include <platforms/ev64360.h>
27 u32 mv64x60_console_baud
= EV64360_DEFAULT_BAUD
;
28 u32 mv64x60_mpsc_clk_src
= EV64360_MPSC_CLK_SRC
; /* TCLK */
29 u32 mv64x60_mpsc_clk_freq
= EV64360_MPSC_CLK_FREQ
;
31 u32 mv64x60_console_baud
= 9600;
32 u32 mv64x60_mpsc_clk_src
= 8; /* TCLK */
33 u32 mv64x60_mpsc_clk_freq
= 100000000;
36 extern void udelay(long);
37 static void stop_dma(int chan
);
39 static void __iomem
*mv64x60_base
= (void __iomem
*)CONFIG_MV64X60_NEW_BASE
;
52 static struct sdma_regs sdma_regs
[2];
54 #define SDMA_REGS_INIT(s, reg_base) { \
55 (s)->sdc = (reg_base) + SDMA_SDC; \
56 (s)->sdcm = (reg_base) + SDMA_SDCM; \
57 (s)->rx_desc = (reg_base) + SDMA_RX_DESC; \
58 (s)->rx_buf_ptr = (reg_base) + SDMA_RX_BUF_PTR; \
59 (s)->scrdp = (reg_base) + SDMA_SCRDP; \
60 (s)->tx_desc = (reg_base) + SDMA_TX_DESC; \
61 (s)->sctdp = (reg_base) + SDMA_SCTDP; \
62 (s)->sftdp = (reg_base) + SDMA_SFTDP; \
65 static u32 mpsc_base
[2] = { MV64x60_MPSC_0_OFFSET
, MV64x60_MPSC_1_OFFSET
};
67 struct mv64x60_rx_desc
{
75 struct mv64x60_tx_desc
{
83 #define MAX_RESET_WAIT 10000
84 #define MAX_TX_WAIT 10000
89 #define RX_BUF_SIZE 32
90 #define TX_BUF_SIZE 32
92 static struct mv64x60_rx_desc rd
[2][RX_NUM_DESC
] __attribute__ ((aligned(32)));
93 static struct mv64x60_tx_desc td
[2][TX_NUM_DESC
] __attribute__ ((aligned(32)));
95 static char rx_buf
[2][RX_NUM_DESC
* RX_BUF_SIZE
] __attribute__ ((aligned(32)));
96 static char tx_buf
[2][TX_NUM_DESC
* TX_BUF_SIZE
] __attribute__ ((aligned(32)));
98 static int cur_rd
[2] = { 0, 0 };
99 static int cur_td
[2] = { 0, 0 };
101 static char chan_initialized
[2] = { 0, 0 };
104 #define RX_INIT_RDP(rdp) { \
105 (rdp)->bufsize = 2; \
106 (rdp)->bytecnt = 0; \
107 (rdp)->cmd_stat = SDMA_DESC_CMDSTAT_L | SDMA_DESC_CMDSTAT_F | \
108 SDMA_DESC_CMDSTAT_O; \
111 #ifdef CONFIG_MV64360
112 static u32 cpu2mem_tab
[MV64x60_CPU2MEM_WINDOWS
][2] = {
113 { MV64x60_CPU2MEM_0_BASE
, MV64x60_CPU2MEM_0_SIZE
},
114 { MV64x60_CPU2MEM_1_BASE
, MV64x60_CPU2MEM_1_SIZE
},
115 { MV64x60_CPU2MEM_2_BASE
, MV64x60_CPU2MEM_2_SIZE
},
116 { MV64x60_CPU2MEM_3_BASE
, MV64x60_CPU2MEM_3_SIZE
}
119 static u32 com2mem_tab
[MV64x60_CPU2MEM_WINDOWS
][2] = {
120 { MV64360_MPSC2MEM_0_BASE
, MV64360_MPSC2MEM_0_SIZE
},
121 { MV64360_MPSC2MEM_1_BASE
, MV64360_MPSC2MEM_1_SIZE
},
122 { MV64360_MPSC2MEM_2_BASE
, MV64360_MPSC2MEM_2_SIZE
},
123 { MV64360_MPSC2MEM_3_BASE
, MV64360_MPSC2MEM_3_SIZE
}
126 static u32 dram_selects
[MV64x60_CPU2MEM_WINDOWS
] = { 0xe, 0xd, 0xb, 0x7 };
130 serial_init(int chan
, void *ignored
)
132 u32 mpsc_routing_base
, sdma_base
, brg_bcr
, cdv
;
135 chan
= (chan
== 1); /* default to chan 0 if anything but 1 */
137 if (chan_initialized
[chan
])
140 chan_initialized
[chan
] = 1;
143 sdma_base
= MV64x60_SDMA_0_OFFSET
;
144 brg_bcr
= MV64x60_BRG_0_OFFSET
+ BRG_BCR
;
145 SDMA_REGS_INIT(&sdma_regs
[0], MV64x60_SDMA_0_OFFSET
);
147 sdma_base
= MV64x60_SDMA_1_OFFSET
;
148 brg_bcr
= MV64x60_BRG_1_OFFSET
+ BRG_BCR
;
149 SDMA_REGS_INIT(&sdma_regs
[0], MV64x60_SDMA_1_OFFSET
);
152 mpsc_routing_base
= MV64x60_MPSC_ROUTING_OFFSET
;
156 /* Set up ring buffers */
157 for (i
=0; i
<RX_NUM_DESC
; i
++) {
158 RX_INIT_RDP(&rd
[chan
][i
]);
159 rd
[chan
][i
].buffer
= (u32
)&rx_buf
[chan
][i
* RX_BUF_SIZE
];
160 rd
[chan
][i
].next_desc_ptr
= (u32
)&rd
[chan
][i
+1];
162 rd
[chan
][RX_NUM_DESC
- 1].next_desc_ptr
= (u32
)&rd
[chan
][0];
164 for (i
=0; i
<TX_NUM_DESC
; i
++) {
165 td
[chan
][i
].bytecnt
= 0;
166 td
[chan
][i
].shadow
= 0;
167 td
[chan
][i
].buffer
= (u32
)&tx_buf
[chan
][i
* TX_BUF_SIZE
];
168 td
[chan
][i
].cmd_stat
= SDMA_DESC_CMDSTAT_F
|SDMA_DESC_CMDSTAT_L
;
169 td
[chan
][i
].next_desc_ptr
= (u32
)&td
[chan
][i
+1];
171 td
[chan
][TX_NUM_DESC
- 1].next_desc_ptr
= (u32
)&td
[chan
][0];
173 /* Set MPSC Routing */
174 out_le32(mv64x60_base
+ mpsc_routing_base
+ MPSC_MRR
, 0x3ffffe38);
176 #ifdef CONFIG_GT64260
177 out_le32(mv64x60_base
+ GT64260_MPP_SERIAL_PORTS_MULTIPLEX
, 0x00001102);
178 #else /* Must be MV64360 or MV64460 */
180 u32 enables
, prot_bits
, v
;
182 /* Set up comm unit to memory mapping windows */
183 /* Note: Assumes MV64x60_CPU2MEM_WINDOWS == 4 */
185 enables
= in_le32(mv64x60_base
+ MV64360_CPU_BAR_ENABLE
) & 0xf;
188 for (i
=0; i
<MV64x60_CPU2MEM_WINDOWS
; i
++) {
189 if (!(enables
& (1 << i
))) {
190 v
= in_le32(mv64x60_base
+ cpu2mem_tab
[i
][0]);
191 v
= ((v
& 0xffff) << 16) | (dram_selects
[i
] << 8);
192 out_le32(mv64x60_base
+ com2mem_tab
[i
][0], v
);
194 v
= in_le32(mv64x60_base
+ cpu2mem_tab
[i
][1]);
195 v
= (v
& 0xffff) << 16;
196 out_le32(mv64x60_base
+ com2mem_tab
[i
][1], v
);
198 prot_bits
|= (0x3 << (i
<< 1)); /* r/w access */
202 out_le32(mv64x60_base
+ MV64360_MPSC_0_REMAP
, 0);
203 out_le32(mv64x60_base
+ MV64360_MPSC_1_REMAP
, 0);
204 out_le32(mv64x60_base
+ MV64360_MPSC2MEM_ACC_PROT_0
, prot_bits
);
205 out_le32(mv64x60_base
+ MV64360_MPSC2MEM_ACC_PROT_1
, prot_bits
);
206 out_le32(mv64x60_base
+ MV64360_MPSC2MEM_BAR_ENABLE
, enables
);
210 /* MPSC 0/1 Rx & Tx get clocks BRG0/1 */
211 out_le32(mv64x60_base
+ mpsc_routing_base
+ MPSC_RCRR
, 0x00000100);
212 out_le32(mv64x60_base
+ mpsc_routing_base
+ MPSC_TCRR
, 0x00000100);
214 /* clear pending interrupts */
215 out_le32(mv64x60_base
+ MV64x60_SDMA_INTR_OFFSET
+ SDMA_INTR_MASK
, 0);
217 out_le32(mv64x60_base
+ SDMA_SCRDP
+ sdma_base
, (int)&rd
[chan
][0]);
218 out_le32(mv64x60_base
+ SDMA_SCTDP
+ sdma_base
,
219 (int)&td
[chan
][TX_NUM_DESC
- 1]);
220 out_le32(mv64x60_base
+ SDMA_SFTDP
+ sdma_base
,
221 (int)&td
[chan
][TX_NUM_DESC
- 1]);
223 out_le32(mv64x60_base
+ SDMA_SDC
+ sdma_base
,
224 SDMA_SDC_RFT
| SDMA_SDC_SFM
| SDMA_SDC_BLMR
| SDMA_SDC_BLMT
|
227 cdv
= ((mv64x60_mpsc_clk_freq
/(32*mv64x60_console_baud
))-1);
228 out_le32(mv64x60_base
+ brg_bcr
,
229 ((mv64x60_mpsc_clk_src
<< 18) | (1 << 16) | cdv
));
231 /* Put MPSC into UART mode, no null modem, 16x clock mode */
232 out_le32(mv64x60_base
+ MPSC_MMCRL
+ mpsc_base
[chan
], 0x000004c4);
233 out_le32(mv64x60_base
+ MPSC_MMCRH
+ mpsc_base
[chan
], 0x04400400);
235 out_le32(mv64x60_base
+ MPSC_CHR_1
+ mpsc_base
[chan
], 0);
236 out_le32(mv64x60_base
+ MPSC_CHR_9
+ mpsc_base
[chan
], 0);
237 out_le32(mv64x60_base
+ MPSC_CHR_10
+ mpsc_base
[chan
], 0);
238 out_le32(mv64x60_base
+ MPSC_CHR_3
+ mpsc_base
[chan
], 4);
239 out_le32(mv64x60_base
+ MPSC_CHR_4
+ mpsc_base
[chan
], 0);
240 out_le32(mv64x60_base
+ MPSC_CHR_5
+ mpsc_base
[chan
], 0);
241 out_le32(mv64x60_base
+ MPSC_CHR_6
+ mpsc_base
[chan
], 0);
242 out_le32(mv64x60_base
+ MPSC_CHR_7
+ mpsc_base
[chan
], 0);
243 out_le32(mv64x60_base
+ MPSC_CHR_8
+ mpsc_base
[chan
], 0);
245 /* 8 data bits, 1 stop bit */
246 out_le32(mv64x60_base
+ MPSC_MPCR
+ mpsc_base
[chan
], (3 << 12));
247 out_le32(mv64x60_base
+ SDMA_SDCM
+ sdma_base
, SDMA_SDCM_ERD
);
248 out_le32(mv64x60_base
+ MPSC_CHR_2
+ mpsc_base
[chan
], MPSC_CHR_2_EH
);
260 /* Abort MPSC Rx (aborting Tx messes things up) */
261 out_le32(mv64x60_base
+ MPSC_CHR_2
+ mpsc_base
[chan
], MPSC_CHR_2_RA
);
263 /* Abort SDMA Rx, Tx */
264 out_le32(mv64x60_base
+ sdma_regs
[chan
].sdcm
,
265 SDMA_SDCM_AR
| SDMA_SDCM_STD
);
267 for (i
=0; i
<MAX_RESET_WAIT
; i
++) {
268 if ((in_le32(mv64x60_base
+ sdma_regs
[chan
].sdcm
) &
269 (SDMA_SDCM_AR
| SDMA_SDCM_AT
)) == 0)
277 wait_for_ownership(int chan
)
281 for (i
=0; i
<MAX_TX_WAIT
; i
++) {
282 if ((in_le32(mv64x60_base
+ sdma_regs
[chan
].sdcm
) &
289 return (i
< MAX_TX_WAIT
);
293 serial_putc(unsigned long com_port
, unsigned char c
)
295 struct mv64x60_tx_desc
*tdp
;
297 if (wait_for_ownership(com_port
) == 0)
300 tdp
= &td
[com_port
][cur_td
[com_port
]];
301 if (++cur_td
[com_port
] >= TX_NUM_DESC
)
302 cur_td
[com_port
] = 0;
304 *(unchar
*)(tdp
->buffer
^ 7) = c
;
307 tdp
->cmd_stat
= SDMA_DESC_CMDSTAT_L
| SDMA_DESC_CMDSTAT_F
|
310 out_le32(mv64x60_base
+ sdma_regs
[com_port
].sctdp
, (int)tdp
);
311 out_le32(mv64x60_base
+ sdma_regs
[com_port
].sftdp
, (int)tdp
);
312 out_le32(mv64x60_base
+ sdma_regs
[com_port
].sdcm
,
313 in_le32(mv64x60_base
+ sdma_regs
[com_port
].sdcm
) |
318 serial_getc(unsigned long com_port
)
320 struct mv64x60_rx_desc
*rdp
;
323 rdp
= &rd
[com_port
][cur_rd
[com_port
]];
325 if ((rdp
->cmd_stat
& (SDMA_DESC_CMDSTAT_O
|SDMA_DESC_CMDSTAT_ES
)) == 0) {
326 c
= *(unchar
*)(rdp
->buffer
^ 7);
328 if (++cur_rd
[com_port
] >= RX_NUM_DESC
)
329 cur_rd
[com_port
] = 0;
336 serial_tstc(unsigned long com_port
)
338 struct mv64x60_rx_desc
*rdp
;
342 rdp
= &rd
[com_port
][cur_rd
[com_port
]];
344 /* Go thru rcv desc's until empty looking for one with data (no error)*/
345 while (((rdp
->cmd_stat
& SDMA_DESC_CMDSTAT_O
) == 0) &&
346 (loop_count
++ < RX_NUM_DESC
)) {
348 /* If there was an error, reinit the desc & continue */
349 if ((rdp
->cmd_stat
& SDMA_DESC_CMDSTAT_ES
) != 0) {
351 if (++cur_rd
[com_port
] >= RX_NUM_DESC
)
352 cur_rd
[com_port
] = 0;
353 rdp
= (struct mv64x60_rx_desc
*)rdp
->next_desc_ptr
;
364 serial_close(unsigned long com_port
)