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 52 sci_out(&sh_sci, SCBRR, 53 SCBRR_VALUE(gd->baudrate, CONFIG_SH_SCIF_CLK_FREQ)); 54 } 55 56 static int sh_serial_init(void) 57 { 58 sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); 59 sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); 60 sci_out(&sh_sci, SCSMR, 0); 61 sci_out(&sh_sci, SCSMR, 0); 62 sci_out(&sh_sci, SCFCR, SCFCR_RFRST|SCFCR_TFRST); 63 sci_in(&sh_sci, SCFCR); 64 sci_out(&sh_sci, SCFCR, 0); 65 66 serial_setbrg(); 67 return 0; 68 } 69 70 #if defined(CONFIG_CPU_SH7760) || \ 71 defined(CONFIG_CPU_SH7780) || \ 72 defined(CONFIG_CPU_SH7785) || \ 73 defined(CONFIG_CPU_SH7786) 74 static int scif_rxfill(struct uart_port *port) 75 { 76 return sci_in(port, SCRFDR) & 0xff; 77 } 78 #elif defined(CONFIG_CPU_SH7763) 79 static int scif_rxfill(struct uart_port *port) 80 { 81 if ((port->mapbase == 0xffe00000) || 82 (port->mapbase == 0xffe08000)) { 83 /* SCIF0/1*/ 84 return sci_in(port, SCRFDR) & 0xff; 85 } else { 86 /* SCIF2 */ 87 return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; 88 } 89 } 90 #elif defined(CONFIG_ARCH_SH7372) 91 static int scif_rxfill(struct uart_port *port) 92 { 93 if (port->type == PORT_SCIFA) 94 return sci_in(port, SCFDR) & SCIF_RFDC_MASK; 95 else 96 return sci_in(port, SCRFDR); 97 } 98 #else 99 static int scif_rxfill(struct uart_port *port) 100 { 101 return sci_in(port, SCFDR) & SCIF_RFDC_MASK; 102 } 103 #endif 104 105 static int serial_rx_fifo_level(void) 106 { 107 return scif_rxfill(&sh_sci); 108 } 109 110 static void handle_error(void) 111 { 112 sci_in(&sh_sci, SCxSR); 113 sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci)); 114 sci_in(&sh_sci, SCLSR); 115 sci_out(&sh_sci, SCLSR, 0x00); 116 } 117 118 void serial_raw_putc(const char c) 119 { 120 while (1) { 121 /* Tx fifo is empty */ 122 if (sci_in(&sh_sci, SCxSR) & SCxSR_TEND(&sh_sci)) 123 break; 124 } 125 126 sci_out(&sh_sci, SCxTDR, c); 127 sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci)); 128 } 129 130 static void sh_serial_putc(const char c) 131 { 132 if (c == '\n') 133 serial_raw_putc('\r'); 134 serial_raw_putc(c); 135 } 136 137 static int sh_serial_tstc(void) 138 { 139 if (sci_in(&sh_sci, SCxSR) & SCIF_ERRORS) { 140 handle_error(); 141 return 0; 142 } 143 144 return serial_rx_fifo_level() ? 1 : 0; 145 } 146 147 148 int serial_getc_check(void) 149 { 150 unsigned short status; 151 152 status = sci_in(&sh_sci, SCxSR); 153 154 if (status & SCIF_ERRORS) 155 handle_error(); 156 if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) 157 handle_error(); 158 return status & (SCIF_DR | SCxSR_RDxF(&sh_sci)); 159 } 160 161 static int sh_serial_getc(void) 162 { 163 unsigned short status; 164 char ch; 165 166 while (!serial_getc_check()) 167 ; 168 169 ch = sci_in(&sh_sci, SCxRDR); 170 status = sci_in(&sh_sci, SCxSR); 171 172 sci_out(&sh_sci, SCxSR, SCxSR_RDxF_CLEAR(&sh_sci)); 173 174 if (status & SCIF_ERRORS) 175 handle_error(); 176 177 if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) 178 handle_error(); 179 return ch; 180 } 181 182 static struct serial_device sh_serial_drv = { 183 .name = "sh_serial", 184 .start = sh_serial_init, 185 .stop = NULL, 186 .setbrg = sh_serial_setbrg, 187 .putc = sh_serial_putc, 188 .puts = default_serial_puts, 189 .getc = sh_serial_getc, 190 .tstc = sh_serial_tstc, 191 }; 192 193 void sh_serial_initialize(void) 194 { 195 serial_register(&sh_serial_drv); 196 } 197 198 __weak struct serial_device *default_serial_console(void) 199 { 200 return &sh_serial_drv; 201 } 202