1 /* Minimal serial functions needed to send messages out the serial
2 * port on the MBX console.
4 * The MBX uses SMC1 for the serial port. We reset the port and use
5 * only the first BD that EPPC-Bug set up as a character FIFO.
7 * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug
8 * use COM1 instead of SMC1 as the console port. This kinda sucks
9 * for the rest of the kernel, so here we force the use of SMC1 again.
11 #include <linux/types.h>
12 #include <asm/uaccess.h>
13 #include <asm/mpc8xx.h>
14 #include <asm/commproc.h>
17 #define MBX_CSR1 ((volatile u_char *)0xfa100000)
18 #define CSR1_COMEN (u_char)0x02
21 #ifdef TQM_SMC2_CONSOLE
22 #define PROFF_CONS PROFF_SMC2
23 #define CPM_CR_CH_CONS CPM_CR_CH_SMC2
25 static volatile iop8xx_t
*iopp
= (iop8xx_t
*)&(((immap_t
*)IMAP_ADDR
)->im_ioport
);
27 #define PROFF_CONS PROFF_SMC1
28 #define CPM_CR_CH_CONS CPM_CR_CH_SMC1
32 static cpm8xx_t
*cpmp
= (cpm8xx_t
*)&(((immap_t
*)IMAP_ADDR
)->im_cpm
);
35 serial_init(int ignored
, bd_t
*bd
)
38 volatile smc_uart_t
*up
;
39 volatile cbd_t
*tbdf
, *rbdf
;
40 volatile cpm8xx_t
*cp
;
47 sp
= (smc_t
*)&(cp
->cp_smc
[SMC_INDEX
]);
48 up
= (smc_uart_t
*)&cp
->cp_dparam
[PROFF_CONS
];
50 /* Disable transmitter/receiver.
52 sp
->smc_smcmr
&= ~(SMCMR_REN
| SMCMR_TEN
);
55 /* Enable SMC1/2 transceivers.
57 *((volatile uint
*)BCSR1
) &= ~(BCSR1_RS232EN_1
|BCSR1_RS232EN_2
);
62 /* Initialize SMCx and use it for the console port.
67 ((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_sdcr
= 1;
69 #ifdef TQM_SMC2_CONSOLE
70 /* Use Port A for SMC2 instead of other functions.
72 iopp
->iop_papar
|= 0x00c0;
73 iopp
->iop_padir
&= ~0x00c0;
74 iopp
->iop_paodr
&= ~0x00c0;
76 /* Use Port B for SMCs instead of other functions.
78 cp
->cp_pbpar
|= 0x00000cc0;
79 cp
->cp_pbdir
&= ~0x00000cc0;
80 cp
->cp_pbodr
&= ~0x00000cc0;
83 /* Allocate space for two buffer descriptors in the DP ram.
84 * For now, this address seems OK, but it may have to
85 * change with newer versions of the firmware.
89 /* Grab a few bytes from the top of memory for SMC FIFOs.
91 memaddr
= (bd
->bi_memsize
- 32) & ~15;
93 /* Set the physical address of the host memory buffers in
94 * the buffer descriptors.
96 rbdf
= (cbd_t
*)&cp
->cp_dpmem
[dpaddr
];
97 rbdf
->cbd_bufaddr
= memaddr
;
100 tbdf
->cbd_bufaddr
= memaddr
+4;
103 /* Set up the uart parameters in the parameter ram.
105 up
->smc_rbase
= dpaddr
;
106 up
->smc_tbase
= dpaddr
+sizeof(cbd_t
);
107 up
->smc_rfcr
= SMC_EB
;
108 up
->smc_tfcr
= SMC_EB
;
110 /* Set UART mode, 8 bit, no parity, one stop.
111 * Enable receive and transmit.
113 sp
->smc_smcmr
= smcr_mk_clen(9) | SMCMR_SM_UART
;
115 /* Mask all interrupts and remove anything pending.
120 /* Set up the baud rate generator.
121 * See 8xx_io/commproc.c for details.
122 * This wires BRG1 to SMC1 and BRG2 to SMC2;
124 cp
->cp_simode
= 0x10000000;
125 ui
= bd
->bi_intfreq
/ 16 / bd
->bi_baudrate
;
126 #ifdef TQM_SMC2_CONSOLE
132 ? (((ui
- 1) << 1) | CPM_BRG_EN
)
133 : ((((ui
/ 16) - 1) << 1) | CPM_BRG_EN
| CPM_BRG_DIV16
);
135 #else /* CONFIG_MBX */
136 if (*MBX_CSR1
& CSR1_COMEN
) {
137 /* COM1 is enabled. Initialize SMC1 and use it for
143 ((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_sdcr
= 1;
145 /* Use Port B for SMCs instead of other functions.
147 cp
->cp_pbpar
|= 0x00000cc0;
148 cp
->cp_pbdir
&= ~0x00000cc0;
149 cp
->cp_pbodr
&= ~0x00000cc0;
151 /* Allocate space for two buffer descriptors in the DP ram.
152 * For now, this address seems OK, but it may have to
153 * change with newer versions of the firmware.
157 /* Grab a few bytes from the top of memory. EPPC-Bug isn't
158 * running any more, so we can do this.
160 memaddr
= (bd
->bi_memsize
- 32) & ~15;
162 /* Set the physical address of the host memory buffers in
163 * the buffer descriptors.
165 rbdf
= (cbd_t
*)&cp
->cp_dpmem
[dpaddr
];
166 rbdf
->cbd_bufaddr
= memaddr
;
169 tbdf
->cbd_bufaddr
= memaddr
+4;
172 /* Set up the uart parameters in the parameter ram.
174 up
->smc_rbase
= dpaddr
;
175 up
->smc_tbase
= dpaddr
+sizeof(cbd_t
);
176 up
->smc_rfcr
= SMC_EB
;
177 up
->smc_tfcr
= SMC_EB
;
179 /* Set UART mode, 8 bit, no parity, one stop.
180 * Enable receive and transmit.
182 sp
->smc_smcmr
= smcr_mk_clen(9) | SMCMR_SM_UART
;
184 /* Mask all interrupts and remove anything pending.
189 /* Set up the baud rate generator.
190 * See 8xx_io/commproc.c for details.
192 cp
->cp_simode
= 0x10000000;
194 (((bd
->bi_intfreq
/16) / 9600) << 1) | CPM_BRG_EN
;
196 /* Enable SMC1 for console output.
198 *MBX_CSR1
&= ~CSR1_COMEN
;
201 #endif /* ndef CONFIG_MBX */
202 /* SMCx is used as console port.
204 tbdf
= (cbd_t
*)&cp
->cp_dpmem
[up
->smc_tbase
];
205 rbdf
= (cbd_t
*)&cp
->cp_dpmem
[up
->smc_rbase
];
207 /* Issue a stop transmit, and wait for it.
209 cp
->cp_cpcr
= mk_cr_cmd(CPM_CR_CH_CONS
,
210 CPM_CR_STOP_TX
) | CPM_CR_FLG
;
211 while (cp
->cp_cpcr
& CPM_CR_FLG
);
214 /* Make the first buffer the only buffer.
216 tbdf
->cbd_sc
|= BD_SC_WRAP
;
217 rbdf
->cbd_sc
|= BD_SC_EMPTY
| BD_SC_WRAP
;
219 /* Single character receive.
224 /* Initialize Tx/Rx parameters.
226 cp
->cp_cpcr
= mk_cr_cmd(CPM_CR_CH_CONS
, CPM_CR_INIT_TRX
) | CPM_CR_FLG
;
227 while (cp
->cp_cpcr
& CPM_CR_FLG
);
229 /* Enable transmitter/receiver.
231 sp
->smc_smcmr
|= SMCMR_REN
| SMCMR_TEN
;
239 serial_putc(void *ignored
, const char c
)
241 volatile cbd_t
*tbdf
;
243 volatile smc_uart_t
*up
;
245 up
= (smc_uart_t
*)&cpmp
->cp_dparam
[PROFF_CONS
];
246 tbdf
= (cbd_t
*)&cpmp
->cp_dpmem
[up
->smc_tbase
];
248 /* Wait for last character to go.
250 buf
= (char *)tbdf
->cbd_bufaddr
;
251 while (tbdf
->cbd_sc
& BD_SC_READY
);
254 tbdf
->cbd_datlen
= 1;
255 tbdf
->cbd_sc
|= BD_SC_READY
;
259 serial_getc(void *ignored
)
261 volatile cbd_t
*rbdf
;
263 volatile smc_uart_t
*up
;
266 up
= (smc_uart_t
*)&cpmp
->cp_dparam
[PROFF_CONS
];
267 rbdf
= (cbd_t
*)&cpmp
->cp_dpmem
[up
->smc_rbase
];
269 /* Wait for character to show up.
271 buf
= (char *)rbdf
->cbd_bufaddr
;
272 while (rbdf
->cbd_sc
& BD_SC_EMPTY
);
274 rbdf
->cbd_sc
|= BD_SC_EMPTY
;
280 serial_tstc(void *ignored
)
282 volatile cbd_t
*rbdf
;
283 volatile smc_uart_t
*up
;
285 up
= (smc_uart_t
*)&cpmp
->cp_dparam
[PROFF_CONS
];
286 rbdf
= (cbd_t
*)&cpmp
->cp_dpmem
[up
->smc_rbase
];
288 return(!(rbdf
->cbd_sc
& BD_SC_EMPTY
));