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