1 /* 2 * SuperH SCIF device driver. 3 * Copyright (C) 2007,2008,2010 Nobuhiro Iwamatsu 4 * Copyright (C) 2002 - 2008 Paul Mundt 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <asm/io.h> 11 #include <asm/processor.h> 12 #include "serial_sh.h" 13 #include <serial.h> 14 #include <linux/compiler.h> 15 16 #if defined(CONFIG_CONS_SCIF0) 17 # define SCIF_BASE SCIF0_BASE 18 #elif defined(CONFIG_CONS_SCIF1) 19 # define SCIF_BASE SCIF1_BASE 20 #elif defined(CONFIG_CONS_SCIF2) 21 # define SCIF_BASE SCIF2_BASE 22 #elif defined(CONFIG_CONS_SCIF3) 23 # define SCIF_BASE SCIF3_BASE 24 #elif defined(CONFIG_CONS_SCIF4) 25 # define SCIF_BASE SCIF4_BASE 26 #elif defined(CONFIG_CONS_SCIF5) 27 # define SCIF_BASE SCIF5_BASE 28 #elif defined(CONFIG_CONS_SCIF6) 29 # define SCIF_BASE SCIF6_BASE 30 #elif defined(CONFIG_CONS_SCIF7) 31 # define SCIF_BASE SCIF7_BASE 32 #else 33 # error "Default SCIF doesn't set....." 34 #endif 35 36 #if defined(CONFIG_SCIF_A) 37 #define SCIF_BASE_PORT PORT_SCIFA 38 #else 39 #define SCIF_BASE_PORT PORT_SCIF 40 #endif 41 42 static struct uart_port sh_sci = { 43 .membase = (unsigned char*)SCIF_BASE, 44 .mapbase = SCIF_BASE, 45 .type = SCIF_BASE_PORT, 46 }; 47 48 static void sh_serial_setbrg(void) 49 { 50 DECLARE_GLOBAL_DATA_PTR; 51 sci_out(&sh_sci, SCBRR, SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ)); 52 } 53 54 static int sh_serial_init(void) 55 { 56 sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); 57 sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); 58 sci_out(&sh_sci, SCSMR, 0); 59 sci_out(&sh_sci, SCSMR, 0); 60 sci_out(&sh_sci, SCFCR, SCFCR_RFRST|SCFCR_TFRST); 61 sci_in(&sh_sci, SCFCR); 62 sci_out(&sh_sci, SCFCR, 0); 63 64 serial_setbrg(); 65 return 0; 66 } 67 68 #if defined(CONFIG_CPU_SH7760) || \ 69 defined(CONFIG_CPU_SH7780) || \ 70 defined(CONFIG_CPU_SH7785) || \ 71 defined(CONFIG_CPU_SH7786) 72 static int scif_rxfill(struct uart_port *port) 73 { 74 return sci_in(port, SCRFDR) & 0xff; 75 } 76 #elif defined(CONFIG_CPU_SH7763) 77 static int scif_rxfill(struct uart_port *port) 78 { 79 if ((port->mapbase == 0xffe00000) || 80 (port->mapbase == 0xffe08000)) { 81 /* SCIF0/1*/ 82 return sci_in(port, SCRFDR) & 0xff; 83 } else { 84 /* SCIF2 */ 85 return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; 86 } 87 } 88 #elif defined(CONFIG_ARCH_SH7372) 89 static int scif_rxfill(struct uart_port *port) 90 { 91 if (port->type == PORT_SCIFA) 92 return sci_in(port, SCFDR) & SCIF_RFDC_MASK; 93 else 94 return sci_in(port, SCRFDR); 95 } 96 #else 97 static int scif_rxfill(struct uart_port *port) 98 { 99 return sci_in(port, SCFDR) & SCIF_RFDC_MASK; 100 } 101 #endif 102 103 static int serial_rx_fifo_level(void) 104 { 105 return scif_rxfill(&sh_sci); 106 } 107 108 static void handle_error(void) 109 { 110 sci_in(&sh_sci, SCxSR); 111 sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci)); 112 sci_in(&sh_sci, SCLSR); 113 sci_out(&sh_sci, SCLSR, 0x00); 114 } 115 116 void serial_raw_putc(const char c) 117 { 118 while (1) { 119 /* Tx fifo is empty */ 120 if (sci_in(&sh_sci, SCxSR) & SCxSR_TEND(&sh_sci)) 121 break; 122 } 123 124 sci_out(&sh_sci, SCxTDR, c); 125 sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci)); 126 } 127 128 static void sh_serial_putc(const char c) 129 { 130 if (c == '\n') 131 serial_raw_putc('\r'); 132 serial_raw_putc(c); 133 } 134 135 static int sh_serial_tstc(void) 136 { 137 if (sci_in(&sh_sci, SCxSR) & SCIF_ERRORS) { 138 handle_error(); 139 return 0; 140 } 141 142 return serial_rx_fifo_level() ? 1 : 0; 143 } 144 145 146 int serial_getc_check(void) 147 { 148 unsigned short status; 149 150 status = sci_in(&sh_sci, SCxSR); 151 152 if (status & SCIF_ERRORS) 153 handle_error(); 154 if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) 155 handle_error(); 156 return status & (SCIF_DR | SCxSR_RDxF(&sh_sci)); 157 } 158 159 static int sh_serial_getc(void) 160 { 161 unsigned short status; 162 char ch; 163 164 while (!serial_getc_check()) 165 ; 166 167 ch = sci_in(&sh_sci, SCxRDR); 168 status = sci_in(&sh_sci, SCxSR); 169 170 sci_out(&sh_sci, SCxSR, SCxSR_RDxF_CLEAR(&sh_sci)); 171 172 if (status & SCIF_ERRORS) 173 handle_error(); 174 175 if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) 176 handle_error(); 177 return ch; 178 } 179 180 static struct serial_device sh_serial_drv = { 181 .name = "sh_serial", 182 .start = sh_serial_init, 183 .stop = NULL, 184 .setbrg = sh_serial_setbrg, 185 .putc = sh_serial_putc, 186 .puts = default_serial_puts, 187 .getc = sh_serial_getc, 188 .tstc = sh_serial_tstc, 189 }; 190 191 void sh_serial_initialize(void) 192 { 193 serial_register(&sh_serial_drv); 194 } 195 196 __weak struct serial_device *default_serial_console(void) 197 { 198 return &sh_serial_drv; 199 } 200