1 /* Minimal serial functions needed to send messages out the serial
4 #include <linux/types.h>
5 #include <asm/mpc8260.h>
6 #include <asm/cpm_8260.h>
11 static u_char cons_hold[128], *sgptr;
12 static int cons_hold_cnt;
14 /* If defined, enables serial console. The value (1 through 4)
15 * should designate which SCC is used, but this isn't complete. Only
16 * SCC1 is known to work at this time.
18 #ifdef CONFIG_SCC_CONSOLE
23 serial_init(int ignored, bd_t *bd)
26 volatile smc_uart_t *up;
29 volatile scc_uart_t *sup;
31 volatile cbd_t *tbdf, *rbdf;
33 volatile iop8260_t *io;
34 volatile cpm8260_t *cp;
37 ip = (immap_t *)IMAP_ADDR;
43 cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
47 while (cp->cp_cpcr & CPM_CR_FLG);
50 /* Enable the RS-232 transceivers.
52 *(volatile uint *)(BCSR_ADDR + 4) &=
53 ~(BCSR1_RS232_EN1 | BCSR1_RS232_EN2);
57 sccp = (scc_t *)&(ip->im_scc[SCC_CONSOLE-1]);
58 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
59 sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
60 sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
62 /* Use Port D for SCC1 instead of other functions.
64 io->iop_ppard |= 0x00000003;
65 io->iop_psord &= ~0x00000001; /* Rx */
66 io->iop_psord |= 0x00000002; /* Tx */
67 io->iop_pdird &= ~0x00000001; /* Rx */
68 io->iop_pdird |= 0x00000002; /* Tx */
71 sp = (smc_t*)&(ip->im_smc[0]);
72 *(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
73 up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1];
75 /* Disable transmitter/receiver.
77 sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
79 /* Use Port D for SMC1 instead of other functions.
81 io->iop_ppard |= 0x00c00000;
82 io->iop_pdird |= 0x00400000;
83 io->iop_pdird &= ~0x00800000;
84 io->iop_psord &= ~0x00c00000;
87 /* Allocate space for two buffer descriptors in the DP ram.
88 * For now, this address seems OK, but it may have to
89 * change with newer versions of the firmware.
93 /* Grab a few bytes from the top of memory.
95 memaddr = (bd->bi_memsize - 256) & ~15;
97 /* Set the physical address of the host memory buffers in
98 * the buffer descriptors.
100 rbdf = (cbd_t *)&ip->im_dprambase[dpaddr];
101 rbdf->cbd_bufaddr = memaddr;
104 tbdf->cbd_bufaddr = memaddr+128;
107 /* Set up the uart parameters in the parameter ram.
110 sup->scc_genscc.scc_rbase = dpaddr;
111 sup->scc_genscc.scc_tbase = dpaddr + sizeof(cbd_t);
113 /* Set up the uart parameters in the
116 sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
117 sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
119 sup->scc_genscc.scc_mrblr = 128;
129 sup->scc_char1 = 0x8000;
130 sup->scc_char2 = 0x8000;
131 sup->scc_char3 = 0x8000;
132 sup->scc_char4 = 0x8000;
133 sup->scc_char5 = 0x8000;
134 sup->scc_char6 = 0x8000;
135 sup->scc_char7 = 0x8000;
136 sup->scc_char8 = 0x8000;
137 sup->scc_rccm = 0xc0ff;
139 /* Send the CPM an initialize command.
141 cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
142 CPM_CR_INIT_TRX) | CPM_CR_FLG;
143 while (cp->cp_cpcr & CPM_CR_FLG);
145 /* Set UART mode, 8 bit, no parity, one stop.
146 * Enable receive and transmit.
150 (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
152 /* Disable all interrupts and clear all pending
156 sccp->scc_scce = 0xffff;
157 sccp->scc_dsr = 0x7e7e;
158 sccp->scc_pmsr = 0x3000;
160 /* Wire BRG1 to SCC1. The console driver will take care of
163 ip->im_cpmux.cmx_scr = 0;
165 up->smc_rbase = dpaddr;
166 up->smc_tbase = dpaddr+sizeof(cbd_t);
167 up->smc_rfcr = CPMFCR_EB;
168 up->smc_tfcr = CPMFCR_EB;
175 /* Set UART mode, 8 bit, no parity, one stop.
176 * Enable receive and transmit.
178 sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
180 /* Mask all interrupts and remove anything pending.
185 /* Set up the baud rate generator.
187 ip->im_cpmux.cmx_smr = 0;
190 /* The baud rate divisor needs to be coordinated with clk_8260().
193 (((bd->bi_brgfreq/16) / bd->bi_baudrate) << 1) |
196 /* Make the first buffer the only buffer.
198 tbdf->cbd_sc |= BD_SC_WRAP;
199 rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
201 /* Initialize Tx/Rx parameters.
204 sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
206 cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
207 while (cp->cp_cpcr & CPM_CR_FLG);
209 /* Enable transmitter/receiver.
211 sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
220 serial_readbuf(u_char *cbuf)
222 volatile cbd_t *rbdf;
224 volatile smc_uart_t *up;
225 volatile scc_uart_t *sup;
226 volatile immap_t *ip;
229 ip = (immap_t *)IMAP_ADDR;
232 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
233 rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
235 up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
236 rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
239 /* Wait for character to show up.
241 buf = (char *)rbdf->cbd_bufaddr;
242 while (rbdf->cbd_sc & BD_SC_EMPTY);
243 nc = rbdf->cbd_datlen;
246 rbdf->cbd_sc |= BD_SC_EMPTY;
252 serial_putc(void *ignored, const char c)
254 volatile cbd_t *tbdf;
256 volatile smc_uart_t *up;
257 volatile scc_uart_t *sup;
258 volatile immap_t *ip;
259 extern bd_t *board_info;
261 ip = (immap_t *)IMAP_ADDR;
263 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
264 tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase];
266 up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
267 tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase];
270 /* Wait for last character to go.
272 buf = (char *)tbdf->cbd_bufaddr;
273 while (tbdf->cbd_sc & BD_SC_READY);
276 tbdf->cbd_datlen = 1;
277 tbdf->cbd_sc |= BD_SC_READY;
281 serial_getc(void *ignored)
285 if (cons_hold_cnt <= 0) {
286 cons_hold_cnt = serial_readbuf(cons_hold);
296 serial_tstc(void *ignored)
298 volatile cbd_t *rbdf;
299 volatile smc_uart_t *up;
300 volatile scc_uart_t *sup;
301 volatile immap_t *ip;
303 ip = (immap_t *)IMAP_ADDR;
305 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
306 rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
308 up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
309 rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
312 return(!(rbdf->cbd_sc & BD_SC_EMPTY));