3 /* Minimal serial functions needed to send messages out the serial
4 * port on the MBX console.
6 * The MBX uxes SMC1 for the serial port. We reset the port and use
7 * only the first BD that EPPC-Bug set up as a character FIFO.
9 * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug
10 * use COM1 instead of SMC1 as the console port. This kinda sucks
11 * for the rest of the kernel, so here we force the use of SMC1 again.
12 * I f**ked around for a day trying to figure out how to make EPPC-Bug
13 * use SMC1, but gave up and decided to fix it here.
15 #include <linux/config.h>
16 #include <linux/types.h>
23 #include "../8xx_io/commproc.h"
26 #define MBX_CSR1 ((volatile u_char *)0xfa100000)
27 #define CSR1_COMEN (u_char)0x02
30 static cpm8xx_t
*cpmp
= (cpm8xx_t
*)&(((immap_t
*)IMAP_ADDR
)->im_cpm
);
36 volatile smc_uart_t
*up
;
37 volatile cbd_t
*tbdf
, *rbdf
;
38 volatile cpm8xx_t
*cp
;
42 sp
= (smc_t
*)&(cp
->cp_smc
[0]);
43 up
= (smc_uart_t
*)&cp
->cp_dparam
[PROFF_SMC1
];
45 /* Disable transmitter/receiver.
47 sp
->smc_smcmr
&= ~(SMCMR_REN
| SMCMR_TEN
);
50 if (*MBX_CSR1
& CSR1_COMEN
) {
51 /* COM1 is enabled. Initialize SMC1 and use it for
57 ((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_sdcr
= 1;
59 /* Use Port B for SMCs instead of other functions.
61 cp
->cp_pbpar
|= 0x00000cc0;
62 cp
->cp_pbdir
&= ~0x00000cc0;
63 cp
->cp_pbodr
&= ~0x00000cc0;
65 /* Allocate space for two buffer descriptors in the DP ram.
66 * For now, this address seems OK, but it may have to
67 * change with newer versions of the firmware.
71 /* Grab a few bytes from the top of memory. EPPC-Bug isn't
72 * running any more, so we can do this.
74 memaddr
= (bd
->bi_memsize
- 32) & ~15;
76 /* Set the physical address of the host memory buffers in
77 * the buffer descriptors.
79 rbdf
= (cbd_t
*)&cp
->cp_dpmem
[dpaddr
];
80 rbdf
->cbd_bufaddr
= memaddr
;
83 tbdf
->cbd_bufaddr
= memaddr
+4;
86 /* Set up the uart parameters in the parameter ram.
88 up
->smc_rbase
= dpaddr
;
89 up
->smc_tbase
= dpaddr
+sizeof(cbd_t
);
90 up
->smc_rfcr
= SMC_EB
;
91 up
->smc_tfcr
= SMC_EB
;
93 /* Set UART mode, 8 bit, no parity, one stop.
94 * Enable receive and transmit.
96 sp
->smc_smcmr
= smcr_mk_clen(9) | SMCMR_SM_UART
;
98 /* Mask all interrupts and remove anything pending.
103 /* Set up the baud rate generator.
104 * See 8xx_io/commproc.c for details.
106 cp
->cp_simode
= 0x10000000;
108 ((((bd
->bi_intfreq
* 1000000)/16) / 9600) << 1) | CPM_BRG_EN
;
110 /* Enable SMC1 for console output.
112 *MBX_CSR1
&= ~CSR1_COMEN
;
116 /* SMC1 is used as console port.
118 tbdf
= (cbd_t
*)&cp
->cp_dpmem
[up
->smc_tbase
];
119 rbdf
= (cbd_t
*)&cp
->cp_dpmem
[up
->smc_rbase
];
121 /* Issue a stop transmit, and wait for it.
123 cp
->cp_cpcr
= mk_cr_cmd(CPM_CR_CH_SMC1
,
124 CPM_CR_STOP_TX
) | CPM_CR_FLG
;
125 while (cp
->cp_cpcr
& CPM_CR_FLG
);
130 /* Make the first buffer the only buffer.
132 tbdf
->cbd_sc
|= BD_SC_WRAP
;
133 rbdf
->cbd_sc
|= BD_SC_EMPTY
| BD_SC_WRAP
;
135 /* Single character receive.
140 /* Initialize Tx/Rx parameters.
142 cp
->cp_cpcr
= mk_cr_cmd(CPM_CR_CH_SMC1
, CPM_CR_INIT_TRX
) | CPM_CR_FLG
;
143 while (cp
->cp_cpcr
& CPM_CR_FLG
);
145 /* Enable transmitter/receiver.
147 sp
->smc_smcmr
|= SMCMR_REN
| SMCMR_TEN
;
151 serial_putchar(const char c
)
153 volatile cbd_t
*tbdf
;
155 volatile smc_uart_t
*up
;
157 up
= (smc_uart_t
*)&cpmp
->cp_dparam
[PROFF_SMC1
];
158 tbdf
= (cbd_t
*)&cpmp
->cp_dpmem
[up
->smc_tbase
];
160 /* Wait for last character to go.
162 buf
= (char *)tbdf
->cbd_bufaddr
;
163 while (tbdf
->cbd_sc
& BD_SC_READY
);
166 tbdf
->cbd_datlen
= 1;
167 tbdf
->cbd_sc
|= BD_SC_READY
;
173 volatile cbd_t
*rbdf
;
175 volatile smc_uart_t
*up
;
178 up
= (smc_uart_t
*)&cpmp
->cp_dparam
[PROFF_SMC1
];
179 rbdf
= (cbd_t
*)&cpmp
->cp_dpmem
[up
->smc_rbase
];
181 /* Wait for character to show up.
183 buf
= (char *)rbdf
->cbd_bufaddr
;
184 while (rbdf
->cbd_sc
& BD_SC_EMPTY
);
186 rbdf
->cbd_sc
|= BD_SC_EMPTY
;
194 volatile cbd_t
*rbdf
;
195 volatile smc_uart_t
*up
;
197 up
= (smc_uart_t
*)&cpmp
->cp_dparam
[PROFF_SMC1
];
198 rbdf
= (cbd_t
*)&cpmp
->cp_dpmem
[up
->smc_rbase
];
200 return(!(rbdf
->cbd_sc
& BD_SC_EMPTY
));