1 /* 2 * (C) Copyright 2000 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <commproc.h> 10 #include <command.h> 11 #include <serial.h> 12 #include <watchdog.h> 13 #include <linux/compiler.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 #if defined(CONFIG_8xx_CONS_SMC1) /* Console on SMC1 */ 18 #define SMC_INDEX 0 19 #define PROFF_SMC PROFF_SMC1 20 #define CPM_CR_CH_SMC CPM_CR_CH_SMC1 21 #define IOPINS 0xc0 22 23 #elif defined(CONFIG_8xx_CONS_SMC2) /* Console on SMC2 */ 24 #define SMC_INDEX 1 25 #define PROFF_SMC PROFF_SMC2 26 #define CPM_CR_CH_SMC CPM_CR_CH_SMC2 27 #define IOPINS 0xc00 28 29 #endif /* CONFIG_8xx_CONS_SMCx */ 30 31 struct serialbuffer { 32 cbd_t rxbd; /* Rx BD */ 33 cbd_t txbd; /* Tx BD */ 34 uint rxindex; /* index for next character to read */ 35 uchar rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */ 36 uchar txbuf; /* tx buffers */ 37 }; 38 39 static void serial_setdivisor(cpm8xx_t __iomem *cp) 40 { 41 int divisor = (gd->cpu_clk + 8 * gd->baudrate) / 16 / gd->baudrate; 42 43 if (divisor / 16 > 0x1000) { 44 /* bad divisor, assume 50MHz clock and 9600 baud */ 45 divisor = (50 * 1000 * 1000 + 8 * 9600) / 16 / 9600; 46 } 47 48 divisor /= CONFIG_SYS_BRGCLK_PRESCALE; 49 50 if (divisor <= 0x1000) 51 out_be32(&cp->cp_brgc1, ((divisor - 1) << 1) | CPM_BRG_EN); 52 else 53 out_be32(&cp->cp_brgc1, ((divisor / 16 - 1) << 1) | CPM_BRG_EN | 54 CPM_BRG_DIV16); 55 } 56 57 /* 58 * Minimal serial functions needed to use one of the SMC ports 59 * as serial console interface. 60 */ 61 62 static void smc_setbrg(void) 63 { 64 immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; 65 cpm8xx_t __iomem *cp = &(im->im_cpm); 66 67 /* Set up the baud rate generator. 68 * See 8xx_io/commproc.c for details. 69 * 70 * Wire BRG1 to SMCx 71 */ 72 73 out_be32(&cp->cp_simode, 0); 74 75 serial_setdivisor(cp); 76 } 77 78 static int smc_init(void) 79 { 80 immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; 81 smc_t __iomem *sp; 82 smc_uart_t __iomem *up; 83 cpm8xx_t __iomem *cp = &(im->im_cpm); 84 struct serialbuffer __iomem *rtx; 85 86 /* initialize pointers to SMC */ 87 88 sp = cp->cp_smc + SMC_INDEX; 89 up = (smc_uart_t __iomem *)&cp->cp_dparam[PROFF_SMC]; 90 /* Disable relocation */ 91 out_be16(&up->smc_rpbase, 0); 92 93 /* Disable transmitter/receiver. */ 94 clrbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN); 95 96 /* Enable SDMA. */ 97 out_be32(&im->im_siu_conf.sc_sdcr, 1); 98 99 /* clear error conditions */ 100 out_8(&im->im_sdma.sdma_sdsr, CONFIG_SYS_SDSR); 101 102 /* clear SDMA interrupt mask */ 103 out_8(&im->im_sdma.sdma_sdmr, CONFIG_SYS_SDMR); 104 105 /* Use Port B for SMCx instead of other functions. */ 106 setbits_be32(&cp->cp_pbpar, IOPINS); 107 clrbits_be32(&cp->cp_pbdir, IOPINS); 108 clrbits_be16(&cp->cp_pbodr, IOPINS); 109 110 /* Set the physical address of the host memory buffers in 111 * the buffer descriptors. 112 */ 113 rtx = (struct serialbuffer __iomem *)&cp->cp_dpmem[CPM_SERIAL_BASE]; 114 /* Allocate space for two buffer descriptors in the DP ram. 115 * For now, this address seems OK, but it may have to 116 * change with newer versions of the firmware. 117 * damm: allocating space after the two buffers for rx/tx data 118 */ 119 120 out_be32(&rtx->rxbd.cbd_bufaddr, (__force uint)&rtx->rxbuf); 121 out_be16(&rtx->rxbd.cbd_sc, 0); 122 123 out_be32(&rtx->txbd.cbd_bufaddr, (__force uint)&rtx->txbuf); 124 out_be16(&rtx->txbd.cbd_sc, 0); 125 126 /* Set up the uart parameters in the parameter ram. */ 127 out_be16(&up->smc_rbase, CPM_SERIAL_BASE); 128 out_be16(&up->smc_tbase, CPM_SERIAL_BASE + sizeof(cbd_t)); 129 out_8(&up->smc_rfcr, SMC_EB); 130 out_8(&up->smc_tfcr, SMC_EB); 131 132 /* Set UART mode, 8 bit, no parity, one stop. 133 * Enable receive and transmit. 134 */ 135 out_be16(&sp->smc_smcmr, smcr_mk_clen(9) | SMCMR_SM_UART); 136 137 /* Mask all interrupts and remove anything pending. 138 */ 139 out_8(&sp->smc_smcm, 0); 140 out_8(&sp->smc_smce, 0xff); 141 142 /* Set up the baud rate generator */ 143 smc_setbrg(); 144 145 /* Make the first buffer the only buffer. */ 146 setbits_be16(&rtx->txbd.cbd_sc, BD_SC_WRAP); 147 setbits_be16(&rtx->rxbd.cbd_sc, BD_SC_EMPTY | BD_SC_WRAP); 148 149 /* single/multi character receive. */ 150 out_be16(&up->smc_mrblr, CONFIG_SYS_SMC_RXBUFLEN); 151 out_be16(&up->smc_maxidl, CONFIG_SYS_MAXIDLE); 152 out_be32(&rtx->rxindex, 0); 153 154 /* Initialize Tx/Rx parameters. */ 155 while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */ 156 ; 157 158 out_be16(&cp->cp_cpcr, 159 mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG); 160 161 while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */ 162 ; 163 164 /* Enable transmitter/receiver. */ 165 setbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN); 166 167 return 0; 168 } 169 170 static void smc_putc(const char c) 171 { 172 immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; 173 cpm8xx_t __iomem *cpmp = &(im->im_cpm); 174 struct serialbuffer __iomem *rtx; 175 176 if (c == '\n') 177 smc_putc('\r'); 178 179 rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE]; 180 181 /* Wait for last character to go. */ 182 out_8(&rtx->txbuf, c); 183 out_be16(&rtx->txbd.cbd_datlen, 1); 184 setbits_be16(&rtx->txbd.cbd_sc, BD_SC_READY); 185 186 while (in_be16(&rtx->txbd.cbd_sc) & BD_SC_READY) 187 WATCHDOG_RESET(); 188 } 189 190 static void smc_puts(const char *s) 191 { 192 while (*s) 193 smc_putc(*s++); 194 } 195 196 static int smc_getc(void) 197 { 198 immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; 199 cpm8xx_t __iomem *cpmp = &(im->im_cpm); 200 struct serialbuffer __iomem *rtx; 201 unsigned char c; 202 uint rxindex; 203 204 rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE]; 205 206 /* Wait for character to show up. */ 207 while (in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY) 208 WATCHDOG_RESET(); 209 210 /* the characters are read one by one, 211 * use the rxindex to know the next char to deliver 212 */ 213 rxindex = in_be32(&rtx->rxindex); 214 c = in_8(rtx->rxbuf + rxindex); 215 rxindex++; 216 217 /* check if all char are readout, then make prepare for next receive */ 218 if (rxindex >= in_be16(&rtx->rxbd.cbd_datlen)) { 219 rxindex = 0; 220 setbits_be16(&rtx->rxbd.cbd_sc, BD_SC_EMPTY); 221 } 222 out_be32(&rtx->rxindex, rxindex); 223 return c; 224 } 225 226 static int smc_tstc(void) 227 { 228 immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; 229 cpm8xx_t __iomem *cpmp = &(im->im_cpm); 230 struct serialbuffer __iomem *rtx; 231 232 rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE]; 233 234 return !(in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY); 235 } 236 237 struct serial_device serial_smc_device = { 238 .name = "serial_smc", 239 .start = smc_init, 240 .stop = NULL, 241 .setbrg = smc_setbrg, 242 .getc = smc_getc, 243 .tstc = smc_tstc, 244 .putc = smc_putc, 245 .puts = smc_puts, 246 }; 247 248 __weak struct serial_device *default_serial_console(void) 249 { 250 return &serial_smc_device; 251 } 252 253 void mpc8xx_serial_initialize(void) 254 { 255 serial_register(&serial_smc_device); 256 } 257