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 * Copyright 2001 MontaVista Software Inc.
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
17 /* This code assumes that the data cache has been disabled (L1, L2, L3). */
19 #include <linux/config.h>
20 #include <linux/types.h>
21 #include <linux/serial_reg.h>
22 #include <asm/serial.h>
23 #include <asm/mv64x60_defs.h>
24 #include "../../../../drivers/serial/mpsc/mpsc_defs.h"
26 extern void udelay(long);
27 static void stop_dma(int chan);
29 static u32 mv64x60_base = CONFIG_MV64X60_NEW_BASE;
32 mv64x60_in_le32(volatile unsigned *addr)
36 __asm__ __volatile__("lwbrx %0,0,%1; eieio" : "=r" (ret) :
37 "r" (addr), "m" (*addr));
42 mv64x60_out_le32(volatile unsigned *addr, int val)
44 __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) :
45 "r" (val), "r" (addr));
48 #define MV64x60_REG_READ(offs) \
49 (mv64x60_in_le32((volatile uint *)(mv64x60_base + (offs))))
50 #define MV64x60_REG_WRITE(offs, d) \
51 (mv64x60_out_le32((volatile uint *)(mv64x60_base + (offs)), (int)(d)))
65 static sdma_regs_t sdma_regs[2];
67 #define SDMA_REGS_INIT(s, reg_base) { \
68 (s)->sdc = (reg_base) + SDMA_SDC; \
69 (s)->sdcm = (reg_base) + SDMA_SDCM; \
70 (s)->rx_desc = (reg_base) + SDMA_RX_DESC; \
71 (s)->rx_buf_ptr = (reg_base) + SDMA_RX_BUF_PTR; \
72 (s)->scrdp = (reg_base) + SDMA_SCRDP; \
73 (s)->tx_desc = (reg_base) + SDMA_TX_DESC; \
74 (s)->sctdp = (reg_base) + SDMA_SCTDP; \
75 (s)->sftdp = (reg_base) + SDMA_SFTDP; \
81 volatile u32 cmd_stat;
82 volatile u32 next_desc_ptr;
89 volatile u32 cmd_stat;
90 volatile u32 next_desc_ptr;
94 #define MAX_RESET_WAIT 10000
95 #define MAX_TX_WAIT 10000
100 #define RX_BUF_SIZE 16
101 #define TX_BUF_SIZE 16
103 static mv64x60_rx_desc_t rd[2][RX_NUM_DESC] __attribute__ ((aligned(32)));
104 static mv64x60_tx_desc_t td[2][TX_NUM_DESC] __attribute__ ((aligned(32)));
106 static char rx_buf[2][RX_NUM_DESC * RX_BUF_SIZE] __attribute__ ((aligned(32)));
107 static char tx_buf[2][TX_NUM_DESC * TX_BUF_SIZE] __attribute__ ((aligned(32)));
109 static int cur_rd[2] = { 0, 0 };
110 static int cur_td[2] = { 0, 0 };
112 static char chan_initialized[2] = { 0, 0 };
115 #define RX_INIT_RDP(rdp) { \
116 (rdp)->bufsize = 2; \
117 (rdp)->bytecnt = 0; \
118 (rdp)->cmd_stat = SDMA_DESC_CMDSTAT_L | \
119 SDMA_DESC_CMDSTAT_F | \
120 SDMA_DESC_CMDSTAT_O; \
124 serial_init(int chan, void *ignored)
126 u32 mpsc_base, mpsc_routing_base, sdma_base, brg_bcr, cdv;
128 extern long mv64x60_console_baud;
129 extern long mv64x60_mpsc_clk_src;
130 extern long mv64x60_mpsc_clk_freq;
132 chan = (chan == 1); /* default to chan 0 if anything but 1 */
134 if (chan_initialized[chan]) return chan;
136 chan_initialized[chan] = 1;
139 mpsc_base = MV64x60_MPSC_0_OFFSET;
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);
145 mpsc_base = MV64x60_MPSC_1_OFFSET;
146 sdma_base = MV64x60_SDMA_1_OFFSET;
147 brg_bcr = MV64x60_BRG_1_OFFSET + BRG_BCR;
148 SDMA_REGS_INIT(&sdma_regs[0], MV64x60_SDMA_1_OFFSET);
151 mpsc_routing_base = MV64x60_MPSC_ROUTING_OFFSET;
155 /* Set up ring buffers */
156 for (i=0; i<RX_NUM_DESC; i++) {
157 RX_INIT_RDP(&rd[chan][i]);
158 rd[chan][i].buffer = (u32)&rx_buf[chan][i * RX_BUF_SIZE];
159 rd[chan][i].next_desc_ptr = (u32)&rd[chan][i+1];
161 rd[chan][RX_NUM_DESC - 1].next_desc_ptr = (u32)&rd[chan][0];
163 for (i=0; i<TX_NUM_DESC; i++) {
164 td[chan][i].bytecnt = 0;
165 td[chan][i].shadow = 0;
166 td[chan][i].buffer = (u32)&tx_buf[chan][i * TX_BUF_SIZE];
167 td[chan][i].cmd_stat = SDMA_DESC_CMDSTAT_F|SDMA_DESC_CMDSTAT_L;
168 td[chan][i].next_desc_ptr = (u32)&td[chan][i+1];
170 td[chan][TX_NUM_DESC - 1].next_desc_ptr = (u32)&td[chan][0];
172 /* Set MPSC Routing */
173 MV64x60_REG_WRITE(mpsc_routing_base + MPSC_MRR, 0x3ffffe38);
175 /* XXXX Not for 64360 XXXX*/
176 MV64x60_REG_WRITE(GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102);
178 /* MPSC 0/1 Rx & Tx get clocks BRG0/1 */
179 MV64x60_REG_WRITE(mpsc_routing_base + MPSC_RCRR, 0x00000100);
180 MV64x60_REG_WRITE(mpsc_routing_base + MPSC_TCRR, 0x00000100);
182 /* clear pending interrupts */
183 MV64x60_REG_WRITE(MV64x60_SDMA_INTR_OFFSET + SDMA_INTR_MASK, 0);
185 MV64x60_REG_WRITE(SDMA_SCRDP + sdma_base, &rd[chan][0]);
186 MV64x60_REG_WRITE(SDMA_SCTDP + sdma_base, &td[chan][TX_NUM_DESC - 1]);
187 MV64x60_REG_WRITE(SDMA_SFTDP + sdma_base, &td[chan][TX_NUM_DESC - 1]);
189 MV64x60_REG_WRITE(SDMA_SDC + sdma_base,
190 SDMA_SDC_RFT | SDMA_SDC_SFM | SDMA_SDC_BLMR | SDMA_SDC_BLMT |
193 cdv = ((mv64x60_mpsc_clk_freq/(32*mv64x60_console_baud))-1);
194 MV64x60_REG_WRITE(brg_bcr,
195 ((mv64x60_mpsc_clk_src << 18) | (1 << 16) | cdv));
197 /* Put MPSC into UART mode, no null modem, 16x clock mode */
198 MV64x60_REG_WRITE(MPSC_MMCRL + mpsc_base, 0x000004c4);
199 MV64x60_REG_WRITE(MPSC_MMCRH + mpsc_base, 0x04400400);
201 MV64x60_REG_WRITE(MPSC_CHR_1 + mpsc_base, 0);
202 MV64x60_REG_WRITE(MPSC_CHR_9 + mpsc_base, 0);
203 MV64x60_REG_WRITE(MPSC_CHR_10 + mpsc_base, 0);
204 MV64x60_REG_WRITE(MPSC_CHR_3 + mpsc_base, 4);
205 MV64x60_REG_WRITE(MPSC_CHR_4 + mpsc_base, 0);
206 MV64x60_REG_WRITE(MPSC_CHR_5 + mpsc_base, 0);
207 MV64x60_REG_WRITE(MPSC_CHR_6 + mpsc_base, 0);
208 MV64x60_REG_WRITE(MPSC_CHR_7 + mpsc_base, 0);
209 MV64x60_REG_WRITE(MPSC_CHR_8 + mpsc_base, 0);
211 /* 8 data bits, 1 stop bit */
212 MV64x60_REG_WRITE(MPSC_MPCR + mpsc_base, (3 << 12));
213 MV64x60_REG_WRITE(SDMA_SDCM + sdma_base, SDMA_SDCM_ERD);
214 MV64x60_REG_WRITE(MPSC_CHR_2 + mpsc_base, MPSC_CHR_2_EH);
226 /* Abort SDMA Rx, Tx */
227 MV64x60_REG_WRITE(sdma_regs[chan].sdcm, SDMA_SDCM_AR | SDMA_SDCM_STD);
229 for (i=0; i<MAX_RESET_WAIT; i++) {
230 if ((MV64x60_REG_READ(sdma_regs[chan].sdcm) &
231 (SDMA_SDCM_AR | SDMA_SDCM_AT)) == 0) {
241 wait_for_ownership(int chan)
245 for (i=0; i<MAX_TX_WAIT; i++) {
246 if ((MV64x60_REG_READ(sdma_regs[chan].sdcm) &
252 return (i < MAX_TX_WAIT);
256 serial_putc(unsigned long com_port, unsigned char c)
258 mv64x60_tx_desc_t *tdp;
260 if (wait_for_ownership(com_port) == 0) return;
262 tdp = &td[com_port][cur_td[com_port]];
263 if (++cur_td[com_port] >= TX_NUM_DESC) cur_td[com_port] = 0;
265 *(unchar *)(tdp->buffer ^ 7) = c;
268 tdp->cmd_stat = SDMA_DESC_CMDSTAT_L | SDMA_DESC_CMDSTAT_F |
271 MV64x60_REG_WRITE(sdma_regs[com_port].sctdp, tdp);
272 MV64x60_REG_WRITE(sdma_regs[com_port].sftdp, tdp);
273 MV64x60_REG_WRITE(sdma_regs[com_port].sdcm,
274 MV64x60_REG_READ(sdma_regs[com_port].sdcm) | SDMA_SDCM_TXD);
280 serial_getc(unsigned long com_port)
282 mv64x60_rx_desc_t *rdp;
285 rdp = &rd[com_port][cur_rd[com_port]];
287 if ((rdp->cmd_stat & (SDMA_DESC_CMDSTAT_O|SDMA_DESC_CMDSTAT_ES)) == 0) {
288 c = *(unchar *)(rdp->buffer ^ 7);
290 if (++cur_rd[com_port] >= RX_NUM_DESC) cur_rd[com_port] = 0;
297 serial_tstc(unsigned long com_port)
299 mv64x60_rx_desc_t *rdp;
303 rdp = &rd[com_port][cur_rd[com_port]];
305 /* Go thru rcv desc's until empty looking for one with data (no error)*/
306 while (((rdp->cmd_stat & SDMA_DESC_CMDSTAT_O) == 0) &&
307 (loop_count++ < RX_NUM_DESC)) {
309 /* If there was an error, reinit the desc & continue */
310 if ((rdp->cmd_stat & SDMA_DESC_CMDSTAT_ES) != 0) {
312 if (++cur_rd[com_port] >= RX_NUM_DESC) {
313 cur_rd[com_port] = 0;
315 rdp = (mv64x60_rx_desc_t *)rdp->next_desc_ptr;
327 serial_close(unsigned long com_port)