129592ecbSNobuhiro Iwamatsu /* 229592ecbSNobuhiro Iwamatsu * SuperH SCIF device driver. 3*3f6c8e36SNobuhiro Iwamatsu * Copyright (C) 2007,2008,2010 Nobuhiro Iwamatsu 4*3f6c8e36SNobuhiro Iwamatsu * Copyright (C) 2002 - 2008 Paul Mundt 529592ecbSNobuhiro Iwamatsu * 629592ecbSNobuhiro Iwamatsu * This program is free software; you can redistribute it and/or modify 729592ecbSNobuhiro Iwamatsu * it under the terms of the GNU General Public License as published by 829592ecbSNobuhiro Iwamatsu * the Free Software Foundation; either version 2 of the License, or 929592ecbSNobuhiro Iwamatsu * (at your option) any later version. 1029592ecbSNobuhiro Iwamatsu * 1129592ecbSNobuhiro Iwamatsu * This program is distributed in the hope that it will be useful, 1229592ecbSNobuhiro Iwamatsu * but WITHOUT ANY WARRANTY; without even the implied warranty of 1329592ecbSNobuhiro Iwamatsu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1429592ecbSNobuhiro Iwamatsu * GNU General Public License for more details. 1529592ecbSNobuhiro Iwamatsu * 1629592ecbSNobuhiro Iwamatsu * You should have received a copy of the GNU General Public License 1729592ecbSNobuhiro Iwamatsu * along with this program; if not, write to the Free Software 1829592ecbSNobuhiro Iwamatsu * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1929592ecbSNobuhiro Iwamatsu */ 2029592ecbSNobuhiro Iwamatsu 2129592ecbSNobuhiro Iwamatsu #include <common.h> 22fc83c927SJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 2329592ecbSNobuhiro Iwamatsu #include <asm/processor.h> 24*3f6c8e36SNobuhiro Iwamatsu #include "serial_sh.h" 2529565326SJohn Rigby 2629592ecbSNobuhiro Iwamatsu #if defined(CONFIG_CONS_SCIF0) 2729592ecbSNobuhiro Iwamatsu # define SCIF_BASE SCIF0_BASE 2829592ecbSNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF1) 2929592ecbSNobuhiro Iwamatsu # define SCIF_BASE SCIF1_BASE 3008c5fabeSNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF2) 3108c5fabeSNobuhiro Iwamatsu # define SCIF_BASE SCIF2_BASE 32ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF3) 33ab09f433SNobuhiro Iwamatsu # define SCIF_BASE SCIF3_BASE 34ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF4) 35ab09f433SNobuhiro Iwamatsu # define SCIF_BASE SCIF4_BASE 36ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF5) 37ab09f433SNobuhiro Iwamatsu # define SCIF_BASE SCIF5_BASE 3829592ecbSNobuhiro Iwamatsu #else 3929592ecbSNobuhiro Iwamatsu # error "Default SCIF doesn't set....." 4029592ecbSNobuhiro Iwamatsu #endif 4129592ecbSNobuhiro Iwamatsu 42a03c09c5SNobuhiro Iwamatsu #if defined(CONFIG_SCIF_A) 43*3f6c8e36SNobuhiro Iwamatsu #define SCIF_BASE_PORT PORT_SCIFA 44ab09f433SNobuhiro Iwamatsu #else 45*3f6c8e36SNobuhiro Iwamatsu #define SCIF_BASE_PORT PORT_SCIF 46ac331da0SNobuhiro Iwamatsu #endif 47ac331da0SNobuhiro Iwamatsu 48*3f6c8e36SNobuhiro Iwamatsu static struct uart_port sh_sci = { 49*3f6c8e36SNobuhiro Iwamatsu .membase = (unsigned char*)SCIF_BASE, 50*3f6c8e36SNobuhiro Iwamatsu .mapbase = SCIF_BASE, 51*3f6c8e36SNobuhiro Iwamatsu .type = SCIF_BASE_PORT, 52*3f6c8e36SNobuhiro Iwamatsu }; 5329592ecbSNobuhiro Iwamatsu 5429592ecbSNobuhiro Iwamatsu void serial_setbrg(void) 5529592ecbSNobuhiro Iwamatsu { 56*3f6c8e36SNobuhiro Iwamatsu DECLARE_GLOBAL_DATA_PTR; 57*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCBRR, SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ)); 5829592ecbSNobuhiro Iwamatsu } 5929592ecbSNobuhiro Iwamatsu 6029592ecbSNobuhiro Iwamatsu int serial_init(void) 6129592ecbSNobuhiro Iwamatsu { 62*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); 63*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); 64*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCSMR, 0); 65*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCSMR, 0); 66*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCFCR, SCFCR_RFRST|SCFCR_TFRST); 67*3f6c8e36SNobuhiro Iwamatsu sci_in(&sh_sci, SCFCR); 68*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCFCR, 0); 6929592ecbSNobuhiro Iwamatsu 7029592ecbSNobuhiro Iwamatsu serial_setbrg(); 7129592ecbSNobuhiro Iwamatsu return 0; 7229592ecbSNobuhiro Iwamatsu } 7329592ecbSNobuhiro Iwamatsu 74*3f6c8e36SNobuhiro Iwamatsu #if defined(CONFIG_CPU_SH7760) || \ 75*3f6c8e36SNobuhiro Iwamatsu defined(CONFIG_CPU_SH7780) || \ 76*3f6c8e36SNobuhiro Iwamatsu defined(CONFIG_CPU_SH7785) || \ 77*3f6c8e36SNobuhiro Iwamatsu defined(CONFIG_CPU_SH7786) 78*3f6c8e36SNobuhiro Iwamatsu static int scif_rxfill(struct uart_port *port) 79*3f6c8e36SNobuhiro Iwamatsu { 80*3f6c8e36SNobuhiro Iwamatsu return sci_in(port, SCRFDR) & 0xff; 81*3f6c8e36SNobuhiro Iwamatsu } 82*3f6c8e36SNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7763) 83*3f6c8e36SNobuhiro Iwamatsu static int scif_rxfill(struct uart_port *port) 84*3f6c8e36SNobuhiro Iwamatsu { 85*3f6c8e36SNobuhiro Iwamatsu if ((port->mapbase == 0xffe00000) || 86*3f6c8e36SNobuhiro Iwamatsu (port->mapbase == 0xffe08000)) { 87*3f6c8e36SNobuhiro Iwamatsu /* SCIF0/1*/ 88*3f6c8e36SNobuhiro Iwamatsu return sci_in(port, SCRFDR) & 0xff; 89*3f6c8e36SNobuhiro Iwamatsu } else { 90*3f6c8e36SNobuhiro Iwamatsu /* SCIF2 */ 91*3f6c8e36SNobuhiro Iwamatsu return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; 92*3f6c8e36SNobuhiro Iwamatsu } 93*3f6c8e36SNobuhiro Iwamatsu } 94*3f6c8e36SNobuhiro Iwamatsu #elif defined(CONFIG_ARCH_SH7372) 95*3f6c8e36SNobuhiro Iwamatsu static int scif_rxfill(struct uart_port *port) 96*3f6c8e36SNobuhiro Iwamatsu { 97*3f6c8e36SNobuhiro Iwamatsu if (port->type == PORT_SCIFA) 98*3f6c8e36SNobuhiro Iwamatsu return sci_in(port, SCFDR) & SCIF_RFDC_MASK; 99*3f6c8e36SNobuhiro Iwamatsu else 100*3f6c8e36SNobuhiro Iwamatsu return sci_in(port, SCRFDR); 101*3f6c8e36SNobuhiro Iwamatsu } 102*3f6c8e36SNobuhiro Iwamatsu #else 103*3f6c8e36SNobuhiro Iwamatsu static int scif_rxfill(struct uart_port *port) 104*3f6c8e36SNobuhiro Iwamatsu { 105*3f6c8e36SNobuhiro Iwamatsu return sci_in(port, SCFDR) & SCIF_RFDC_MASK; 106*3f6c8e36SNobuhiro Iwamatsu } 107*3f6c8e36SNobuhiro Iwamatsu #endif 108*3f6c8e36SNobuhiro Iwamatsu 10929592ecbSNobuhiro Iwamatsu static int serial_rx_fifo_level(void) 11029592ecbSNobuhiro Iwamatsu { 111*3f6c8e36SNobuhiro Iwamatsu return scif_rxfill(&sh_sci); 11229592ecbSNobuhiro Iwamatsu } 11329592ecbSNobuhiro Iwamatsu 11429592ecbSNobuhiro Iwamatsu void serial_raw_putc(const char c) 11529592ecbSNobuhiro Iwamatsu { 11629592ecbSNobuhiro Iwamatsu while (1) { 117*3f6c8e36SNobuhiro Iwamatsu /* Tx fifo is empty */ 118*3f6c8e36SNobuhiro Iwamatsu if (sci_in(&sh_sci, SCxSR) & SCxSR_TEND(&sh_sci)) 11929592ecbSNobuhiro Iwamatsu break; 12029592ecbSNobuhiro Iwamatsu } 12129592ecbSNobuhiro Iwamatsu 122*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCxTDR, c); 123*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci)); 12429592ecbSNobuhiro Iwamatsu } 12529592ecbSNobuhiro Iwamatsu 12629592ecbSNobuhiro Iwamatsu void serial_putc(const char c) 12729592ecbSNobuhiro Iwamatsu { 12829592ecbSNobuhiro Iwamatsu if (c == '\n') 12929592ecbSNobuhiro Iwamatsu serial_raw_putc('\r'); 13029592ecbSNobuhiro Iwamatsu serial_raw_putc(c); 13129592ecbSNobuhiro Iwamatsu } 13229592ecbSNobuhiro Iwamatsu 13329592ecbSNobuhiro Iwamatsu void serial_puts(const char *s) 13429592ecbSNobuhiro Iwamatsu { 13529592ecbSNobuhiro Iwamatsu char c; 13629592ecbSNobuhiro Iwamatsu while ((c = *s++) != 0) 13729592ecbSNobuhiro Iwamatsu serial_putc(c); 13829592ecbSNobuhiro Iwamatsu } 13929592ecbSNobuhiro Iwamatsu 14029592ecbSNobuhiro Iwamatsu int serial_tstc(void) 14129592ecbSNobuhiro Iwamatsu { 14229592ecbSNobuhiro Iwamatsu return serial_rx_fifo_level() ? 1 : 0; 14329592ecbSNobuhiro Iwamatsu } 14429592ecbSNobuhiro Iwamatsu 14508c5fabeSNobuhiro Iwamatsu void handle_error(void) 14608c5fabeSNobuhiro Iwamatsu { 147*3f6c8e36SNobuhiro Iwamatsu sci_in(&sh_sci, SCxSR); 148*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci)); 149*3f6c8e36SNobuhiro Iwamatsu sci_in(&sh_sci, SCLSR); 150*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCLSR, 0x00); 15129592ecbSNobuhiro Iwamatsu } 15229592ecbSNobuhiro Iwamatsu 15308c5fabeSNobuhiro Iwamatsu int serial_getc_check(void) 15408c5fabeSNobuhiro Iwamatsu { 15529592ecbSNobuhiro Iwamatsu unsigned short status; 15629592ecbSNobuhiro Iwamatsu 157*3f6c8e36SNobuhiro Iwamatsu status = sci_in(&sh_sci, SCxSR); 15829592ecbSNobuhiro Iwamatsu 159*3f6c8e36SNobuhiro Iwamatsu if (status & SCIF_ERRORS) 16029592ecbSNobuhiro Iwamatsu handle_error(); 161*3f6c8e36SNobuhiro Iwamatsu if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) 16229592ecbSNobuhiro Iwamatsu handle_error(); 163*3f6c8e36SNobuhiro Iwamatsu return status & (SCIF_DR | SCxSR_RDxF(&sh_sci)); 16429592ecbSNobuhiro Iwamatsu } 16529592ecbSNobuhiro Iwamatsu 16629592ecbSNobuhiro Iwamatsu int serial_getc(void) 16729592ecbSNobuhiro Iwamatsu { 16829592ecbSNobuhiro Iwamatsu unsigned short status; 16929592ecbSNobuhiro Iwamatsu char ch; 170ab09f433SNobuhiro Iwamatsu 171ab09f433SNobuhiro Iwamatsu while (!serial_getc_check()) 172ab09f433SNobuhiro Iwamatsu ; 17329592ecbSNobuhiro Iwamatsu 174*3f6c8e36SNobuhiro Iwamatsu ch = sci_in(&sh_sci, SCxRDR); 175*3f6c8e36SNobuhiro Iwamatsu status = sci_in(&sh_sci, SCxSR); 17629592ecbSNobuhiro Iwamatsu 177*3f6c8e36SNobuhiro Iwamatsu sci_out(&sh_sci, SCxSR, SCxSR_RDxF_CLEAR(&sh_sci)); 17829592ecbSNobuhiro Iwamatsu 179*3f6c8e36SNobuhiro Iwamatsu if (status & SCIF_ERRORS) 18029592ecbSNobuhiro Iwamatsu handle_error(); 18129592ecbSNobuhiro Iwamatsu 182*3f6c8e36SNobuhiro Iwamatsu if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) 18329592ecbSNobuhiro Iwamatsu handle_error(); 18429592ecbSNobuhiro Iwamatsu return ch; 18529592ecbSNobuhiro Iwamatsu } 186