2 * BK Id: %F% %I% %G% %U% %#%
6 /* Minimal serial functions needed to send messages out the serial
9 #include <linux/types.h>
10 #include <asm/mpc8260.h>
11 #include <asm/cpm_8260.h>
14 extern char *params[];
16 static u_char cons_hold[128], *sgptr;
17 static int cons_hold_cnt;
19 /* If defined, enables serial console. The value (1 through 4)
20 * should designate which SCC is used, but this isn't complete. Only
21 * SCC1 is known to work at this time.
23 #ifdef CONFIG_SCC_CONSOLE
28 serial_init(int ignored, bd_t *bd)
31 volatile smc_uart_t *up;
34 volatile scc_uart_t *sup;
36 volatile cbd_t *tbdf, *rbdf;
38 volatile iop8260_t *io;
39 volatile cpm8260_t *cp;
42 ip = (immap_t *)IMAP_ADDR;
48 cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
52 while (cp->cp_cpcr & CPM_CR_FLG);
55 /* Enable the RS-232 transceivers.
57 *(volatile uint *)(BCSR_ADDR + 4) &=
58 ~(BCSR1_RS232_EN1 | BCSR1_RS232_EN2);
62 sccp = (scc_t *)&(ip->im_scc[SCC_CONSOLE-1]);
63 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
64 sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
65 sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
67 /* Use Port D for SCC1 instead of other functions.
69 io->iop_ppard |= 0x00000003;
70 io->iop_psord &= ~0x00000001; /* Rx */
71 io->iop_psord |= 0x00000002; /* Tx */
72 io->iop_pdird &= ~0x00000001; /* Rx */
73 io->iop_pdird |= 0x00000002; /* Tx */
76 sp = (smc_t*)&(ip->im_smc[0]);
77 *(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
78 up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1];
80 /* Disable transmitter/receiver.
82 sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
84 /* Use Port D for SMC1 instead of other functions.
86 io->iop_ppard |= 0x00c00000;
87 io->iop_pdird |= 0x00400000;
88 io->iop_pdird &= ~0x00800000;
89 io->iop_psord &= ~0x00c00000;
92 /* Allocate space for two buffer descriptors in the DP ram.
93 * For now, this address seems OK, but it may have to
94 * change with newer versions of the firmware.
98 /* Grab a few bytes from the top of memory.
100 memaddr = (bd->bi_memsize - 256) & ~15;
102 /* Set the physical address of the host memory buffers in
103 * the buffer descriptors.
105 rbdf = (cbd_t *)&ip->im_dprambase[dpaddr];
106 rbdf->cbd_bufaddr = memaddr;
109 tbdf->cbd_bufaddr = memaddr+128;
112 /* Set up the uart parameters in the parameter ram.
115 sup->scc_genscc.scc_rbase = dpaddr;
116 sup->scc_genscc.scc_tbase = dpaddr + sizeof(cbd_t);
118 /* Set up the uart parameters in the
121 sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
122 sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
124 sup->scc_genscc.scc_mrblr = 128;
134 sup->scc_char1 = 0x8000;
135 sup->scc_char2 = 0x8000;
136 sup->scc_char3 = 0x8000;
137 sup->scc_char4 = 0x8000;
138 sup->scc_char5 = 0x8000;
139 sup->scc_char6 = 0x8000;
140 sup->scc_char7 = 0x8000;
141 sup->scc_char8 = 0x8000;
142 sup->scc_rccm = 0xc0ff;
144 /* Send the CPM an initialize command.
146 cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
147 CPM_CR_INIT_TRX) | CPM_CR_FLG;
148 while (cp->cp_cpcr & CPM_CR_FLG);
150 /* Set UART mode, 8 bit, no parity, one stop.
151 * Enable receive and transmit.
155 (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
157 /* Disable all interrupts and clear all pending
161 sccp->scc_scce = 0xffff;
162 sccp->scc_dsr = 0x7e7e;
163 sccp->scc_pmsr = 0x3000;
165 /* Wire BRG1 to SCC1. The console driver will take care of
168 ip->im_cpmux.cmx_scr = 0;
170 up->smc_rbase = dpaddr;
171 up->smc_tbase = dpaddr+sizeof(cbd_t);
172 up->smc_rfcr = CPMFCR_EB;
173 up->smc_tfcr = CPMFCR_EB;
180 /* Set UART mode, 8 bit, no parity, one stop.
181 * Enable receive and transmit.
183 sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
185 /* Mask all interrupts and remove anything pending.
190 /* Set up the baud rate generator.
192 ip->im_cpmux.cmx_smr = 0;
195 /* The baud rate divisor needs to be coordinated with clk_8260().
198 (((bd->bi_brgfreq/16) / bd->bi_baudrate) << 1) |
201 /* Make the first buffer the only buffer.
203 tbdf->cbd_sc |= BD_SC_WRAP;
204 rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
206 /* Initialize Tx/Rx parameters.
209 sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
211 cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
212 while (cp->cp_cpcr & CPM_CR_FLG);
214 /* Enable transmitter/receiver.
216 sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
225 serial_readbuf(u_char *cbuf)
227 volatile cbd_t *rbdf;
229 volatile smc_uart_t *up;
230 volatile scc_uart_t *sup;
231 volatile immap_t *ip;
234 ip = (immap_t *)IMAP_ADDR;
237 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
238 rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
240 up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
241 rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
244 /* Wait for character to show up.
246 buf = (char *)rbdf->cbd_bufaddr;
247 while (rbdf->cbd_sc & BD_SC_EMPTY);
248 nc = rbdf->cbd_datlen;
251 rbdf->cbd_sc |= BD_SC_EMPTY;
257 serial_putc(void *ignored, const char c)
259 volatile cbd_t *tbdf;
261 volatile smc_uart_t *up;
262 volatile scc_uart_t *sup;
263 volatile immap_t *ip;
264 extern bd_t *board_info;
266 ip = (immap_t *)IMAP_ADDR;
268 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
269 tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase];
271 up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
272 tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase];
275 /* Wait for last character to go.
277 buf = (char *)tbdf->cbd_bufaddr;
278 while (tbdf->cbd_sc & BD_SC_READY);
281 tbdf->cbd_datlen = 1;
282 tbdf->cbd_sc |= BD_SC_READY;
286 serial_getc(void *ignored)
290 if (cons_hold_cnt <= 0) {
291 cons_hold_cnt = serial_readbuf(cons_hold);
301 serial_tstc(void *ignored)
303 volatile cbd_t *rbdf;
304 volatile smc_uart_t *up;
305 volatile scc_uart_t *sup;
306 volatile immap_t *ip;
308 ip = (immap_t *)IMAP_ADDR;
310 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
311 rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
313 up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
314 rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
317 return(!(rbdf->cbd_sc & BD_SC_EMPTY));