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 <dm.h> 10 #include <serial.h> 11 #include <watchdog.h> 12 #include <asm/cpm_8xx.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, int baudrate) 40 { 41 int divisor = (gd->cpu_clk + 8 * baudrate) / 16 / 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 int serial_mpc8xx_setbrg(struct udevice *dev, int baudrate) 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, baudrate); 76 77 return 0; 78 } 79 80 static int serial_mpc8xx_probe(struct udevice *dev) 81 { 82 immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; 83 smc_t __iomem *sp; 84 smc_uart_t __iomem *up; 85 cpm8xx_t __iomem *cp = &(im->im_cpm); 86 struct serialbuffer __iomem *rtx; 87 88 /* initialize pointers to SMC */ 89 90 sp = cp->cp_smc + SMC_INDEX; 91 up = (smc_uart_t __iomem *)&cp->cp_dparam[PROFF_SMC]; 92 /* Disable relocation */ 93 out_be16(&up->smc_rpbase, 0); 94 95 /* Disable transmitter/receiver. */ 96 clrbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN); 97 98 /* Enable SDMA. */ 99 out_be32(&im->im_siu_conf.sc_sdcr, 1); 100 101 /* clear error conditions */ 102 out_8(&im->im_sdma.sdma_sdsr, CONFIG_SYS_SDSR); 103 104 /* clear SDMA interrupt mask */ 105 out_8(&im->im_sdma.sdma_sdmr, CONFIG_SYS_SDMR); 106 107 /* Use Port B for SMCx instead of other functions. */ 108 setbits_be32(&cp->cp_pbpar, IOPINS); 109 clrbits_be32(&cp->cp_pbdir, IOPINS); 110 clrbits_be16(&cp->cp_pbodr, IOPINS); 111 112 /* Set the physical address of the host memory buffers in 113 * the buffer descriptors. 114 */ 115 rtx = (struct serialbuffer __iomem *)&cp->cp_dpmem[CPM_SERIAL_BASE]; 116 /* Allocate space for two buffer descriptors in the DP ram. 117 * For now, this address seems OK, but it may have to 118 * change with newer versions of the firmware. 119 * damm: allocating space after the two buffers for rx/tx data 120 */ 121 122 out_be32(&rtx->rxbd.cbd_bufaddr, (__force uint)&rtx->rxbuf); 123 out_be16(&rtx->rxbd.cbd_sc, 0); 124 125 out_be32(&rtx->txbd.cbd_bufaddr, (__force uint)&rtx->txbuf); 126 out_be16(&rtx->txbd.cbd_sc, 0); 127 128 /* Set up the uart parameters in the parameter ram. */ 129 out_be16(&up->smc_rbase, CPM_SERIAL_BASE); 130 out_be16(&up->smc_tbase, CPM_SERIAL_BASE + sizeof(cbd_t)); 131 out_8(&up->smc_rfcr, SMC_EB); 132 out_8(&up->smc_tfcr, SMC_EB); 133 134 /* Set UART mode, 8 bit, no parity, one stop. 135 * Enable receive and transmit. 136 */ 137 out_be16(&sp->smc_smcmr, smcr_mk_clen(9) | SMCMR_SM_UART); 138 139 /* Mask all interrupts and remove anything pending. 140 */ 141 out_8(&sp->smc_smcm, 0); 142 out_8(&sp->smc_smce, 0xff); 143 144 /* Set up the baud rate generator */ 145 serial_mpc8xx_setbrg(dev, gd->baudrate); 146 147 /* Make the first buffer the only buffer. */ 148 setbits_be16(&rtx->txbd.cbd_sc, BD_SC_WRAP); 149 setbits_be16(&rtx->rxbd.cbd_sc, BD_SC_EMPTY | BD_SC_WRAP); 150 151 /* single/multi character receive. */ 152 out_be16(&up->smc_mrblr, CONFIG_SYS_SMC_RXBUFLEN); 153 out_be16(&up->smc_maxidl, CONFIG_SYS_MAXIDLE); 154 out_be32(&rtx->rxindex, 0); 155 156 /* Initialize Tx/Rx parameters. */ 157 while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */ 158 ; 159 160 out_be16(&cp->cp_cpcr, 161 mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG); 162 163 while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */ 164 ; 165 166 /* Enable transmitter/receiver. */ 167 setbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN); 168 169 return 0; 170 } 171 172 static int serial_mpc8xx_putc(struct udevice *dev, const char c) 173 { 174 immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; 175 cpm8xx_t __iomem *cpmp = &(im->im_cpm); 176 struct serialbuffer __iomem *rtx; 177 178 if (c == '\n') 179 serial_mpc8xx_putc(dev, '\r'); 180 181 rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE]; 182 183 /* Wait for last character to go. */ 184 out_8(&rtx->txbuf, c); 185 out_be16(&rtx->txbd.cbd_datlen, 1); 186 setbits_be16(&rtx->txbd.cbd_sc, BD_SC_READY); 187 188 while (in_be16(&rtx->txbd.cbd_sc) & BD_SC_READY) 189 WATCHDOG_RESET(); 190 191 return 0; 192 } 193 194 static int serial_mpc8xx_getc(struct udevice *dev) 195 { 196 immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; 197 cpm8xx_t __iomem *cpmp = &(im->im_cpm); 198 struct serialbuffer __iomem *rtx; 199 unsigned char c; 200 uint rxindex; 201 202 rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE]; 203 204 /* Wait for character to show up. */ 205 while (in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY) 206 WATCHDOG_RESET(); 207 208 /* the characters are read one by one, 209 * use the rxindex to know the next char to deliver 210 */ 211 rxindex = in_be32(&rtx->rxindex); 212 c = in_8(rtx->rxbuf + rxindex); 213 rxindex++; 214 215 /* check if all char are readout, then make prepare for next receive */ 216 if (rxindex >= in_be16(&rtx->rxbd.cbd_datlen)) { 217 rxindex = 0; 218 setbits_be16(&rtx->rxbd.cbd_sc, BD_SC_EMPTY); 219 } 220 out_be32(&rtx->rxindex, rxindex); 221 return c; 222 } 223 224 static int serial_mpc8xx_pending(struct udevice *dev, bool input) 225 { 226 immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; 227 cpm8xx_t __iomem *cpmp = &(im->im_cpm); 228 struct serialbuffer __iomem *rtx; 229 230 if (!input) 231 return 0; 232 233 rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE]; 234 235 return !(in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY); 236 } 237 238 static const struct dm_serial_ops serial_mpc8xx_ops = { 239 .putc = serial_mpc8xx_putc, 240 .pending = serial_mpc8xx_pending, 241 .getc = serial_mpc8xx_getc, 242 .setbrg = serial_mpc8xx_setbrg, 243 }; 244 245 static const struct udevice_id serial_mpc8xx_ids[] = { 246 { .compatible = "fsl,pq1-smc" }, 247 { } 248 }; 249 250 U_BOOT_DRIVER(serial_mpc8xx) = { 251 .name = "serial_mpc8xx", 252 .id = UCLASS_SERIAL, 253 .of_match = serial_mpc8xx_ids, 254 .probe = serial_mpc8xx_probe, 255 .ops = &serial_mpc8xx_ops, 256 .flags = DM_FLAG_PRE_RELOC, 257 }; 258