1 /* Minimal serial functions needed to send messages out the serial
4 #include <linux/types.h>
5 #include <asm/mpc8260.h>
7 #include <asm/immap_cpm2.h>
10 extern char *params[];
12 static u_char cons_hold[128], *sgptr;
13 static int cons_hold_cnt;
15 /* If defined, enables serial console. The value (1 through 4)
16 * should designate which SCC is used, but this isn't complete. Only
17 * SCC1 is known to work at this time.
19 #ifdef CONFIG_SCC_CONSOLE
24 serial_init(int ignored, bd_t *bd)
27 volatile smc_uart_t *up;
30 volatile scc_uart_t *sup;
32 volatile cbd_t *tbdf, *rbdf;
33 volatile cpm2_map_t *ip;
34 volatile iop_cpm2_t *io;
35 volatile cpm_cpm2_t *cp;
38 ip = (cpm2_map_t *)CPM_MAP_ADDR;
44 cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
48 while (cp->cp_cpcr & CPM_CR_FLG);
51 /* Enable the RS-232 transceivers.
53 *(volatile uint *)(BCSR_ADDR + 4) &=
54 ~(BCSR1_RS232_EN1 | BCSR1_RS232_EN2);
58 sccp = (scc_t *)&(ip->im_scc[SCC_CONSOLE-1]);
59 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
60 sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
61 sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
63 /* Use Port D for SCC1 instead of other functions.
65 io->iop_ppard |= 0x00000003;
66 io->iop_psord &= ~0x00000001; /* Rx */
67 io->iop_psord |= 0x00000002; /* Tx */
68 io->iop_pdird &= ~0x00000001; /* Rx */
69 io->iop_pdird |= 0x00000002; /* Tx */
72 sp = (smc_t*)&(ip->im_smc[0]);
73 *(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
74 up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1];
76 /* Disable transmitter/receiver.
78 sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
80 /* Use Port D for SMC1 instead of other functions.
82 io->iop_ppard |= 0x00c00000;
83 io->iop_pdird |= 0x00400000;
84 io->iop_pdird &= ~0x00800000;
85 io->iop_psord &= ~0x00c00000;
88 /* Allocate space for two buffer descriptors in the DP ram.
89 * For now, this address seems OK, but it may have to
90 * change with newer versions of the firmware.
94 /* Grab a few bytes from the top of memory.
96 memaddr = (bd->bi_memsize - 256) & ~15;
98 /* Set the physical address of the host memory buffers in
99 * the buffer descriptors.
101 rbdf = (cbd_t *)&ip->im_dprambase[dpaddr];
102 rbdf->cbd_bufaddr = memaddr;
105 tbdf->cbd_bufaddr = memaddr+128;
108 /* Set up the uart parameters in the parameter ram.
111 sup->scc_genscc.scc_rbase = dpaddr;
112 sup->scc_genscc.scc_tbase = dpaddr + sizeof(cbd_t);
114 /* Set up the uart parameters in the
117 sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
118 sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
120 sup->scc_genscc.scc_mrblr = 128;
130 sup->scc_char1 = 0x8000;
131 sup->scc_char2 = 0x8000;
132 sup->scc_char3 = 0x8000;
133 sup->scc_char4 = 0x8000;
134 sup->scc_char5 = 0x8000;
135 sup->scc_char6 = 0x8000;
136 sup->scc_char7 = 0x8000;
137 sup->scc_char8 = 0x8000;
138 sup->scc_rccm = 0xc0ff;
140 /* Send the CPM an initialize command.
142 cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
143 CPM_CR_INIT_TRX) | CPM_CR_FLG;
144 while (cp->cp_cpcr & CPM_CR_FLG);
146 /* Set UART mode, 8 bit, no parity, one stop.
147 * Enable receive and transmit.
151 (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
153 /* Disable all interrupts and clear all pending
157 sccp->scc_scce = 0xffff;
158 sccp->scc_dsr = 0x7e7e;
159 sccp->scc_pmsr = 0x3000;
161 /* Wire BRG1 to SCC1. The console driver will take care of
164 ip->im_cpmux.cmx_scr = 0;
166 up->smc_rbase = dpaddr;
167 up->smc_tbase = dpaddr+sizeof(cbd_t);
168 up->smc_rfcr = CPMFCR_EB;
169 up->smc_tfcr = CPMFCR_EB;
176 /* Set UART mode, 8 bit, no parity, one stop.
177 * Enable receive and transmit.
179 sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
181 /* Mask all interrupts and remove anything pending.
186 /* Set up the baud rate generator.
188 ip->im_cpmux.cmx_smr = 0;
191 /* The baud rate divisor needs to be coordinated with clk_8260().
194 (((bd->bi_brgfreq/16) / bd->bi_baudrate) << 1) |
197 /* Make the first buffer the only buffer.
199 tbdf->cbd_sc |= BD_SC_WRAP;
200 rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
202 /* Initialize Tx/Rx parameters.
205 sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
207 cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
208 while (cp->cp_cpcr & CPM_CR_FLG);
210 /* Enable transmitter/receiver.
212 sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
221 serial_readbuf(u_char *cbuf)
223 volatile cbd_t *rbdf;
225 volatile smc_uart_t *up;
226 volatile scc_uart_t *sup;
227 volatile cpm2_map_t *ip;
230 ip = (cpm2_map_t *)CPM_MAP_ADDR;
233 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
234 rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
236 up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
237 rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
240 /* Wait for character to show up.
242 buf = (char *)rbdf->cbd_bufaddr;
243 while (rbdf->cbd_sc & BD_SC_EMPTY);
244 nc = rbdf->cbd_datlen;
247 rbdf->cbd_sc |= BD_SC_EMPTY;
253 serial_putc(void *ignored, const char c)
255 volatile cbd_t *tbdf;
257 volatile smc_uart_t *up;
258 volatile scc_uart_t *sup;
259 volatile cpm2_map_t *ip;
260 extern bd_t *board_info;
262 ip = (cpm2_map_t *)CPM_MAP_ADDR;
264 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
265 tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase];
267 up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
268 tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase];
271 /* Wait for last character to go.
273 buf = (char *)tbdf->cbd_bufaddr;
274 while (tbdf->cbd_sc & BD_SC_READY);
277 tbdf->cbd_datlen = 1;
278 tbdf->cbd_sc |= BD_SC_READY;
282 serial_getc(void *ignored)
286 if (cons_hold_cnt <= 0) {
287 cons_hold_cnt = serial_readbuf(cons_hold);
297 serial_tstc(void *ignored)
299 volatile cbd_t *rbdf;
300 volatile smc_uart_t *up;
301 volatile scc_uart_t *sup;
302 volatile cpm2_map_t *ip;
304 ip = (cpm2_map_t *)CPM_MAP_ADDR;
306 sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
307 rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
309 up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
310 rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
313 return(!(rbdf->cbd_sc & BD_SC_EMPTY));