1/* Minimal serial functions needed to send messages out the serial 2 * port on the MBX console. 3 * 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. 6 * 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. 10 */ 11#include <linux/types.h> 12#include <asm/uaccess.h> 13#include <asm/mpc8xx.h> 14#include <asm/commproc.h> 15 16#ifdef CONFIG_MBX 17#define MBX_CSR1 ((volatile u_char *)0xfa100000) 18#define CSR1_COMEN (u_char)0x02 19#endif 20 21#ifdef TQM_SMC2_CONSOLE 22#define PROFF_CONS PROFF_SMC2 23#define CPM_CR_CH_CONS CPM_CR_CH_SMC2 24#define SMC_INDEX 1 25static volatile iop8xx_t *iopp = (iop8xx_t *)&(((immap_t *)IMAP_ADDR)->im_ioport); 26#else 27#define PROFF_CONS PROFF_SMC1 28#define CPM_CR_CH_CONS CPM_CR_CH_SMC1 29#define SMC_INDEX 0 30#endif 31 32static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); 33 34unsigned long 35serial_init(int ignored, bd_t *bd) 36{ 37 volatile smc_t *sp; 38 volatile smc_uart_t *up; 39 volatile cbd_t *tbdf, *rbdf; 40 volatile cpm8xx_t *cp; 41 uint dpaddr, memaddr; 42#ifndef CONFIG_MBX 43 uint ui; 44#endif 45 46 cp = cpmp; 47 sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]); 48 up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS]; 49 50 /* Disable transmitter/receiver. 51 */ 52 sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); 53 54#ifdef CONFIG_FADS 55 /* Enable SMC1/2 transceivers. 56 */ 57 *((volatile uint *)BCSR1) &= ~(BCSR1_RS232EN_1|BCSR1_RS232EN_2); 58#endif 59 60#ifndef CONFIG_MBX 61 { 62 /* Initialize SMCx and use it for the console port. 63 */ 64 65 /* Enable SDMA. 66 */ 67 ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1; 68 69#ifdef TQM_SMC2_CONSOLE 70 /* Use Port A for SMC2 instead of other functions. 71 */ 72 iopp->iop_papar |= 0x00c0; 73 iopp->iop_padir &= ~0x00c0; 74 iopp->iop_paodr &= ~0x00c0; 75#else 76 /* Use Port B for SMCs instead of other functions. 77 */ 78 cp->cp_pbpar |= 0x00000cc0; 79 cp->cp_pbdir &= ~0x00000cc0; 80 cp->cp_pbodr &= ~0x00000cc0; 81#endif 82 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. 86 */ 87 dpaddr = 0x0800; 88 89 /* Grab a few bytes from the top of memory for SMC FIFOs. 90 */ 91 memaddr = (bd->bi_memsize - 32) & ~15; 92 93 /* Set the physical address of the host memory buffers in 94 * the buffer descriptors. 95 */ 96 rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr]; 97 rbdf->cbd_bufaddr = memaddr; 98 rbdf->cbd_sc = 0; 99 tbdf = rbdf + 1; 100 tbdf->cbd_bufaddr = memaddr+4; 101 tbdf->cbd_sc = 0; 102 103 /* Set up the uart parameters in the parameter ram. 104 */ 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; 109 110 /* Set UART mode, 8 bit, no parity, one stop. 111 * Enable receive and transmit. 112 */ 113 sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; 114 115 /* Mask all interrupts and remove anything pending. 116 */ 117 sp->smc_smcm = 0; 118 sp->smc_smce = 0xff; 119 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; 123 */ 124 cp->cp_simode = 0x10000000; 125 ui = bd->bi_intfreq / 16 / bd->bi_baudrate; 126#ifdef TQM_SMC2_CONSOLE 127 cp->cp_brgc2 = 128#else 129 cp->cp_brgc1 = 130#endif 131 ((ui - 1) < 4096) 132 ? (((ui - 1) << 1) | CPM_BRG_EN) 133 : ((((ui / 16) - 1) << 1) | CPM_BRG_EN | CPM_BRG_DIV16); 134 135#else /* CONFIG_MBX */ 136 if (*MBX_CSR1 & CSR1_COMEN) { 137 /* COM1 is enabled. Initialize SMC1 and use it for 138 * the console port. 139 */ 140 141 /* Enable SDMA. 142 */ 143 ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1; 144 145 /* Use Port B for SMCs instead of other functions. 146 */ 147 cp->cp_pbpar |= 0x00000cc0; 148 cp->cp_pbdir &= ~0x00000cc0; 149 cp->cp_pbodr &= ~0x00000cc0; 150 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. 154 */ 155 dpaddr = 0x0800; 156 157 /* Grab a few bytes from the top of memory. EPPC-Bug isn't 158 * running any more, so we can do this. 159 */ 160 memaddr = (bd->bi_memsize - 32) & ~15; 161 162 /* Set the physical address of the host memory buffers in 163 * the buffer descriptors. 164 */ 165 rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr]; 166 rbdf->cbd_bufaddr = memaddr; 167 rbdf->cbd_sc = 0; 168 tbdf = rbdf + 1; 169 tbdf->cbd_bufaddr = memaddr+4; 170 tbdf->cbd_sc = 0; 171 172 /* Set up the uart parameters in the parameter ram. 173 */ 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; 178 179 /* Set UART mode, 8 bit, no parity, one stop. 180 * Enable receive and transmit. 181 */ 182 sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; 183 184 /* Mask all interrupts and remove anything pending. 185 */ 186 sp->smc_smcm = 0; 187 sp->smc_smce = 0xff; 188 189 /* Set up the baud rate generator. 190 * See 8xx_io/commproc.c for details. 191 */ 192 cp->cp_simode = 0x10000000; 193 cp->cp_brgc1 = 194 (((bd->bi_intfreq/16) / 9600) << 1) | CPM_BRG_EN; 195 196 /* Enable SMC1 for console output. 197 */ 198 *MBX_CSR1 &= ~CSR1_COMEN; 199 } 200 else { 201#endif /* ndef CONFIG_MBX */ 202 /* SMCx is used as console port. 203 */ 204 tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase]; 205 rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase]; 206 207 /* Issue a stop transmit, and wait for it. 208 */ 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); 212 } 213 214 /* Make the first buffer the only buffer. 215 */ 216 tbdf->cbd_sc |= BD_SC_WRAP; 217 rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; 218 219 /* Single character receive. 220 */ 221 up->smc_mrblr = 1; 222 up->smc_maxidl = 0; 223 224 /* Initialize Tx/Rx parameters. 225 */ 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); 228 229 /* Enable transmitter/receiver. 230 */ 231 sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; 232 233 /* This is ignored. 234 */ 235 return 0; 236} 237 238void 239serial_putc(void *ignored, const char c) 240{ 241 volatile cbd_t *tbdf; 242 volatile char *buf; 243 volatile smc_uart_t *up; 244 245 up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; 246 tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; 247 248 /* Wait for last character to go. 249 */ 250 buf = (char *)tbdf->cbd_bufaddr; 251 while (tbdf->cbd_sc & BD_SC_READY); 252 253 *buf = c; 254 tbdf->cbd_datlen = 1; 255 tbdf->cbd_sc |= BD_SC_READY; 256} 257 258char 259serial_getc(void *ignored) 260{ 261 volatile cbd_t *rbdf; 262 volatile char *buf; 263 volatile smc_uart_t *up; 264 char c; 265 266 up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; 267 rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; 268 269 /* Wait for character to show up. 270 */ 271 buf = (char *)rbdf->cbd_bufaddr; 272 while (rbdf->cbd_sc & BD_SC_EMPTY); 273 c = *buf; 274 rbdf->cbd_sc |= BD_SC_EMPTY; 275 276 return(c); 277} 278 279int 280serial_tstc(void *ignored) 281{ 282 volatile cbd_t *rbdf; 283 volatile smc_uart_t *up; 284 285 up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; 286 rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; 287 288 return(!(rbdf->cbd_sc & BD_SC_EMPTY)); 289} 290