1*a47a12beSStefan Roese /* 2*a47a12beSStefan Roese * (C) Copyright 2003 Motorola Inc. 3*a47a12beSStefan Roese * Xianghua Xiao (X.Xiao@motorola.com) 4*a47a12beSStefan Roese * Modified based on 8260 for 8560. 5*a47a12beSStefan Roese * 6*a47a12beSStefan Roese * (C) Copyright 2000 7*a47a12beSStefan Roese * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 8*a47a12beSStefan Roese * 9*a47a12beSStefan Roese * See file CREDITS for list of people who contributed to this 10*a47a12beSStefan Roese * project. 11*a47a12beSStefan Roese * 12*a47a12beSStefan Roese * This program is free software; you can redistribute it and/or 13*a47a12beSStefan Roese * modify it under the terms of the GNU General Public License as 14*a47a12beSStefan Roese * published by the Free Software Foundation; either version 2 of 15*a47a12beSStefan Roese * the License, or (at your option) any later version. 16*a47a12beSStefan Roese * 17*a47a12beSStefan Roese * This program is distributed in the hope that it will be useful, 18*a47a12beSStefan Roese * but WITHOUT ANY WARRANTY; without even the implied warranty of 19*a47a12beSStefan Roese * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20*a47a12beSStefan Roese * GNU General Public License for more details. 21*a47a12beSStefan Roese * 22*a47a12beSStefan Roese * You should have received a copy of the GNU General Public License 23*a47a12beSStefan Roese * along with this program; if not, write to the Free Software 24*a47a12beSStefan Roese * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25*a47a12beSStefan Roese * MA 02111-1307 USA 26*a47a12beSStefan Roese * 27*a47a12beSStefan Roese * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00. 28*a47a12beSStefan Roese */ 29*a47a12beSStefan Roese 30*a47a12beSStefan Roese /* 31*a47a12beSStefan Roese * Minimal serial functions needed to use one of the SCC ports 32*a47a12beSStefan Roese * as serial console interface. 33*a47a12beSStefan Roese */ 34*a47a12beSStefan Roese 35*a47a12beSStefan Roese #include <common.h> 36*a47a12beSStefan Roese #include <asm/cpm_85xx.h> 37*a47a12beSStefan Roese 38*a47a12beSStefan Roese DECLARE_GLOBAL_DATA_PTR; 39*a47a12beSStefan Roese 40*a47a12beSStefan Roese #if defined(CONFIG_CONS_ON_SCC) 41*a47a12beSStefan Roese 42*a47a12beSStefan Roese #if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */ 43*a47a12beSStefan Roese 44*a47a12beSStefan Roese #define SCC_INDEX 0 45*a47a12beSStefan Roese #define PROFF_SCC PROFF_SCC1 46*a47a12beSStefan Roese #define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\ 47*a47a12beSStefan Roese CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK) 48*a47a12beSStefan Roese #define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1) 49*a47a12beSStefan Roese #define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE 50*a47a12beSStefan Roese #define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK 51*a47a12beSStefan Roese 52*a47a12beSStefan Roese #elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */ 53*a47a12beSStefan Roese 54*a47a12beSStefan Roese #define SCC_INDEX 1 55*a47a12beSStefan Roese #define PROFF_SCC PROFF_SCC2 56*a47a12beSStefan Roese #define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\ 57*a47a12beSStefan Roese CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK) 58*a47a12beSStefan Roese #define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2) 59*a47a12beSStefan Roese #define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE 60*a47a12beSStefan Roese #define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK 61*a47a12beSStefan Roese 62*a47a12beSStefan Roese #elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */ 63*a47a12beSStefan Roese 64*a47a12beSStefan Roese #define SCC_INDEX 2 65*a47a12beSStefan Roese #define PROFF_SCC PROFF_SCC3 66*a47a12beSStefan Roese #define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\ 67*a47a12beSStefan Roese CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK) 68*a47a12beSStefan Roese #define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3) 69*a47a12beSStefan Roese #define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE 70*a47a12beSStefan Roese #define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK 71*a47a12beSStefan Roese 72*a47a12beSStefan Roese #elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */ 73*a47a12beSStefan Roese 74*a47a12beSStefan Roese #define SCC_INDEX 3 75*a47a12beSStefan Roese #define PROFF_SCC PROFF_SCC4 76*a47a12beSStefan Roese #define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\ 77*a47a12beSStefan Roese CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK) 78*a47a12beSStefan Roese #define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4) 79*a47a12beSStefan Roese #define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE 80*a47a12beSStefan Roese #define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK 81*a47a12beSStefan Roese 82*a47a12beSStefan Roese #else 83*a47a12beSStefan Roese 84*a47a12beSStefan Roese #error "console not correctly defined" 85*a47a12beSStefan Roese 86*a47a12beSStefan Roese #endif 87*a47a12beSStefan Roese 88*a47a12beSStefan Roese int serial_init (void) 89*a47a12beSStefan Roese { 90*a47a12beSStefan Roese volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 91*a47a12beSStefan Roese volatile ccsr_cpm_scc_t *sp; 92*a47a12beSStefan Roese volatile scc_uart_t *up; 93*a47a12beSStefan Roese volatile cbd_t *tbdf, *rbdf; 94*a47a12beSStefan Roese volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp); 95*a47a12beSStefan Roese uint dpaddr; 96*a47a12beSStefan Roese 97*a47a12beSStefan Roese /* initialize pointers to SCC */ 98*a47a12beSStefan Roese 99*a47a12beSStefan Roese sp = (ccsr_cpm_scc_t *) &(cpm->im_cpm_scc[SCC_INDEX]); 100*a47a12beSStefan Roese up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]); 101*a47a12beSStefan Roese 102*a47a12beSStefan Roese /* Disable transmitter/receiver. 103*a47a12beSStefan Roese */ 104*a47a12beSStefan Roese sp->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); 105*a47a12beSStefan Roese 106*a47a12beSStefan Roese /* put the SCC channel into NMSI (non multiplexd serial interface) 107*a47a12beSStefan Roese * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15). 108*a47a12beSStefan Roese */ 109*a47a12beSStefan Roese cpm->im_cpm_mux.cmxscr = \ 110*a47a12beSStefan Roese (cpm->im_cpm_mux.cmxscr&~CMXSCR_MASK)|CMXSCR_VALUE; 111*a47a12beSStefan Roese 112*a47a12beSStefan Roese /* Set up the baud rate generator. 113*a47a12beSStefan Roese */ 114*a47a12beSStefan Roese serial_setbrg (); 115*a47a12beSStefan Roese 116*a47a12beSStefan Roese /* Allocate space for two buffer descriptors in the DP ram. 117*a47a12beSStefan Roese * damm: allocating space after the two buffers for rx/tx data 118*a47a12beSStefan Roese */ 119*a47a12beSStefan Roese 120*a47a12beSStefan Roese dpaddr = m8560_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16); 121*a47a12beSStefan Roese 122*a47a12beSStefan Roese /* Set the physical address of the host memory buffers in 123*a47a12beSStefan Roese * the buffer descriptors. 124*a47a12beSStefan Roese */ 125*a47a12beSStefan Roese rbdf = (cbd_t *)&(cpm->im_dprambase[dpaddr]); 126*a47a12beSStefan Roese rbdf->cbd_bufaddr = (uint) (rbdf+2); 127*a47a12beSStefan Roese rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP; 128*a47a12beSStefan Roese tbdf = rbdf + 1; 129*a47a12beSStefan Roese tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1; 130*a47a12beSStefan Roese tbdf->cbd_sc = BD_SC_WRAP; 131*a47a12beSStefan Roese 132*a47a12beSStefan Roese /* Set up the uart parameters in the parameter ram. 133*a47a12beSStefan Roese */ 134*a47a12beSStefan Roese up->scc_genscc.scc_rbase = dpaddr; 135*a47a12beSStefan Roese up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t); 136*a47a12beSStefan Roese up->scc_genscc.scc_rfcr = CPMFCR_EB; 137*a47a12beSStefan Roese up->scc_genscc.scc_tfcr = CPMFCR_EB; 138*a47a12beSStefan Roese up->scc_genscc.scc_mrblr = 1; 139*a47a12beSStefan Roese up->scc_maxidl = 0; 140*a47a12beSStefan Roese up->scc_brkcr = 1; 141*a47a12beSStefan Roese up->scc_parec = 0; 142*a47a12beSStefan Roese up->scc_frmec = 0; 143*a47a12beSStefan Roese up->scc_nosec = 0; 144*a47a12beSStefan Roese up->scc_brkec = 0; 145*a47a12beSStefan Roese up->scc_uaddr1 = 0; 146*a47a12beSStefan Roese up->scc_uaddr2 = 0; 147*a47a12beSStefan Roese up->scc_toseq = 0; 148*a47a12beSStefan Roese up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000; 149*a47a12beSStefan Roese up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000; 150*a47a12beSStefan Roese up->scc_rccm = 0xc0ff; 151*a47a12beSStefan Roese 152*a47a12beSStefan Roese /* Mask all interrupts and remove anything pending. 153*a47a12beSStefan Roese */ 154*a47a12beSStefan Roese sp->sccm = 0; 155*a47a12beSStefan Roese sp->scce = 0xffff; 156*a47a12beSStefan Roese 157*a47a12beSStefan Roese /* Set 8 bit FIFO, 16 bit oversampling and UART mode. 158*a47a12beSStefan Roese */ 159*a47a12beSStefan Roese sp->gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */ 160*a47a12beSStefan Roese sp->gsmrl = \ 161*a47a12beSStefan Roese SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART; 162*a47a12beSStefan Roese 163*a47a12beSStefan Roese /* Set CTS no flow control, 1 stop bit, 8 bit character length, 164*a47a12beSStefan Roese * normal async UART mode, no parity 165*a47a12beSStefan Roese */ 166*a47a12beSStefan Roese sp->psmr = SCU_PSMR_CL; 167*a47a12beSStefan Roese 168*a47a12beSStefan Roese /* execute the "Init Rx and Tx params" CP command. 169*a47a12beSStefan Roese */ 170*a47a12beSStefan Roese 171*a47a12beSStefan Roese while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */ 172*a47a12beSStefan Roese ; 173*a47a12beSStefan Roese 174*a47a12beSStefan Roese cp->cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK, 175*a47a12beSStefan Roese 0, CPM_CR_INIT_TRX) | CPM_CR_FLG; 176*a47a12beSStefan Roese 177*a47a12beSStefan Roese while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */ 178*a47a12beSStefan Roese ; 179*a47a12beSStefan Roese 180*a47a12beSStefan Roese /* Enable transmitter/receiver. 181*a47a12beSStefan Roese */ 182*a47a12beSStefan Roese sp->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT; 183*a47a12beSStefan Roese 184*a47a12beSStefan Roese return (0); 185*a47a12beSStefan Roese } 186*a47a12beSStefan Roese 187*a47a12beSStefan Roese void 188*a47a12beSStefan Roese serial_setbrg (void) 189*a47a12beSStefan Roese { 190*a47a12beSStefan Roese #if defined(CONFIG_CONS_USE_EXTC) 191*a47a12beSStefan Roese m8560_cpm_extcbrg(SCC_INDEX, gd->baudrate, 192*a47a12beSStefan Roese CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL); 193*a47a12beSStefan Roese #else 194*a47a12beSStefan Roese m8560_cpm_setbrg(SCC_INDEX, gd->baudrate); 195*a47a12beSStefan Roese #endif 196*a47a12beSStefan Roese } 197*a47a12beSStefan Roese 198*a47a12beSStefan Roese void 199*a47a12beSStefan Roese serial_putc(const char c) 200*a47a12beSStefan Roese { 201*a47a12beSStefan Roese volatile scc_uart_t *up; 202*a47a12beSStefan Roese volatile cbd_t *tbdf; 203*a47a12beSStefan Roese volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 204*a47a12beSStefan Roese 205*a47a12beSStefan Roese if (c == '\n') 206*a47a12beSStefan Roese serial_putc ('\r'); 207*a47a12beSStefan Roese 208*a47a12beSStefan Roese up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]); 209*a47a12beSStefan Roese tbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_tbase]); 210*a47a12beSStefan Roese 211*a47a12beSStefan Roese /* Wait for last character to go. 212*a47a12beSStefan Roese */ 213*a47a12beSStefan Roese while (tbdf->cbd_sc & BD_SC_READY) 214*a47a12beSStefan Roese ; 215*a47a12beSStefan Roese 216*a47a12beSStefan Roese /* Load the character into the transmit buffer. 217*a47a12beSStefan Roese */ 218*a47a12beSStefan Roese *(volatile char *)tbdf->cbd_bufaddr = c; 219*a47a12beSStefan Roese tbdf->cbd_datlen = 1; 220*a47a12beSStefan Roese tbdf->cbd_sc |= BD_SC_READY; 221*a47a12beSStefan Roese } 222*a47a12beSStefan Roese 223*a47a12beSStefan Roese void 224*a47a12beSStefan Roese serial_puts (const char *s) 225*a47a12beSStefan Roese { 226*a47a12beSStefan Roese while (*s) { 227*a47a12beSStefan Roese serial_putc (*s++); 228*a47a12beSStefan Roese } 229*a47a12beSStefan Roese } 230*a47a12beSStefan Roese 231*a47a12beSStefan Roese int 232*a47a12beSStefan Roese serial_getc(void) 233*a47a12beSStefan Roese { 234*a47a12beSStefan Roese volatile cbd_t *rbdf; 235*a47a12beSStefan Roese volatile scc_uart_t *up; 236*a47a12beSStefan Roese volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 237*a47a12beSStefan Roese unsigned char c; 238*a47a12beSStefan Roese 239*a47a12beSStefan Roese up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]); 240*a47a12beSStefan Roese rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]); 241*a47a12beSStefan Roese 242*a47a12beSStefan Roese /* Wait for character to show up. 243*a47a12beSStefan Roese */ 244*a47a12beSStefan Roese while (rbdf->cbd_sc & BD_SC_EMPTY) 245*a47a12beSStefan Roese ; 246*a47a12beSStefan Roese 247*a47a12beSStefan Roese /* Grab the char and clear the buffer again. 248*a47a12beSStefan Roese */ 249*a47a12beSStefan Roese c = *(volatile unsigned char *)rbdf->cbd_bufaddr; 250*a47a12beSStefan Roese rbdf->cbd_sc |= BD_SC_EMPTY; 251*a47a12beSStefan Roese 252*a47a12beSStefan Roese return (c); 253*a47a12beSStefan Roese } 254*a47a12beSStefan Roese 255*a47a12beSStefan Roese int 256*a47a12beSStefan Roese serial_tstc() 257*a47a12beSStefan Roese { 258*a47a12beSStefan Roese volatile cbd_t *rbdf; 259*a47a12beSStefan Roese volatile scc_uart_t *up; 260*a47a12beSStefan Roese volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 261*a47a12beSStefan Roese 262*a47a12beSStefan Roese up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]); 263*a47a12beSStefan Roese rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]); 264*a47a12beSStefan Roese 265*a47a12beSStefan Roese return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0); 266*a47a12beSStefan Roese } 267*a47a12beSStefan Roese 268*a47a12beSStefan Roese #endif /* CONFIG_CONS_ON_SCC */ 269