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