1/* 2 * (C) Copyright 2003 3 * Martin Winistoerfer, martinwinistoerfer@gmx.ch. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8/* 9 * File: serial.c 10 * 11 * Discription: Serial interface driver for SCI1 and SCI2. 12 * Since this code will be called from ROM use 13 * only non-static local variables. 14 * 15 */ 16 17#include <common.h> 18#include <watchdog.h> 19#include <command.h> 20#include <mpc5xx.h> 21#include <serial.h> 22#include <linux/compiler.h> 23 24DECLARE_GLOBAL_DATA_PTR; 25 26/* 27 * Local functions 28 */ 29 30static int ready_to_send(void) 31{ 32 volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; 33 volatile short status; 34 35 do { 36#if defined(CONFIG_5xx_CONS_SCI1) 37 status = immr->im_qsmcm.qsmcm_sc1sr; 38#else 39 status = immr->im_qsmcm.qsmcm_sc2sr; 40#endif 41 42#if defined(CONFIG_WATCHDOG) 43 reset_5xx_watchdog (immr); 44#endif 45 } while ((status & SCI_TDRE) == 0); 46 return 1; 47 48} 49 50/* 51 * Minimal global serial functions needed to use one of the SCI modules. 52 */ 53 54static int mpc5xx_serial_init(void) 55{ 56 volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; 57 58 serial_setbrg(); 59 60#if defined(CONFIG_5xx_CONS_SCI1) 61 /* 10-Bit, 1 start bit, 8 data bit, no parity, 1 stop bit */ 62 immr->im_qsmcm.qsmcm_scc1r1 = SCI_M_10; 63 immr->im_qsmcm.qsmcm_scc1r1 = SCI_TE | SCI_RE; 64#else 65 immr->im_qsmcm.qsmcm_scc2r1 = SCI_M_10; 66 immr->im_qsmcm.qsmcm_scc2r1 = SCI_TE | SCI_RE; 67#endif 68 return 0; 69} 70 71static void mpc5xx_serial_putc(const char c) 72{ 73 volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; 74 75 /* Test for completition */ 76 if(ready_to_send()) { 77#if defined(CONFIG_5xx_CONS_SCI1) 78 immr->im_qsmcm.qsmcm_sc1dr = (short)c; 79#else 80 immr->im_qsmcm.qsmcm_sc2dr = (short)c; 81#endif 82 if(c == '\n') { 83 if(ready_to_send()); 84#if defined(CONFIG_5xx_CONS_SCI1) 85 immr->im_qsmcm.qsmcm_sc1dr = (short)'\r'; 86#else 87 immr->im_qsmcm.qsmcm_sc2dr = (short)'\r'; 88#endif 89 } 90 } 91} 92 93static int mpc5xx_serial_getc(void) 94{ 95 volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; 96 volatile short status; 97 unsigned char tmp; 98 99 /* New data ? */ 100 do { 101#if defined(CONFIG_5xx_CONS_SCI1) 102 status = immr->im_qsmcm.qsmcm_sc1sr; 103#else 104 status = immr->im_qsmcm.qsmcm_sc2sr; 105#endif 106 107#if defined(CONFIG_WATCHDOG) 108 reset_5xx_watchdog (immr); 109#endif 110 } while ((status & SCI_RDRF) == 0); 111 112 /* Read data */ 113#if defined(CONFIG_5xx_CONS_SCI1) 114 tmp = (unsigned char)(immr->im_qsmcm.qsmcm_sc1dr & SCI_SCXDR_MK); 115#else 116 tmp = (unsigned char)( immr->im_qsmcm.qsmcm_sc2dr & SCI_SCXDR_MK); 117#endif 118 return tmp; 119} 120 121static int mpc5xx_serial_tstc(void) 122{ 123 volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; 124 short status; 125 126 /* New data character ? */ 127#if defined(CONFIG_5xx_CONS_SCI1) 128 status = immr->im_qsmcm.qsmcm_sc1sr; 129#else 130 status = immr->im_qsmcm.qsmcm_sc2sr; 131#endif 132 return (status & SCI_RDRF); 133} 134 135static void mpc5xx_serial_setbrg(void) 136{ 137 volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; 138 short scxbr; 139 140 /* Set baudrate */ 141 scxbr = (gd->cpu_clk / (32 * gd->baudrate)); 142#if defined(CONFIG_5xx_CONS_SCI1) 143 immr->im_qsmcm.qsmcm_scc1r0 = (scxbr & SCI_SCXBR_MK); 144#else 145 immr->im_qsmcm.qsmcm_scc2r0 = (scxbr & SCI_SCXBR_MK); 146#endif 147} 148 149static struct serial_device mpc5xx_serial_drv = { 150 .name = "mpc5xx_serial", 151 .start = mpc5xx_serial_init, 152 .stop = NULL, 153 .setbrg = mpc5xx_serial_setbrg, 154 .putc = mpc5xx_serial_putc, 155 .puts = default_serial_puts, 156 .getc = mpc5xx_serial_getc, 157 .tstc = mpc5xx_serial_tstc, 158}; 159 160void mpc5xx_serial_initialize(void) 161{ 162 serial_register(&mpc5xx_serial_drv); 163} 164 165__weak struct serial_device *default_serial_console(void) 166{ 167 return &mpc5xx_serial_drv; 168} 169