X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fserial%2Fserial_sh.c;h=0826d59ab2adbba604665b520278898130e9fa59;hb=a2e0a45d2e1e258cbe9bd3dbbe7bc7cacbf7a84e;hp=aa4ff35333ac1c5a363eb739877dec419a9a5cfe;hpb=53677ef18e25c97ac613349087c5cb33ae5a2741;p=u-boot diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index aa4ff35333..0826d59ab2 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -1,201 +1,202 @@ /* * SuperH SCIF device driver. - * Copyright (c) 2007,2008 Nobuhiro Iwamatsu + * Copyright (C) 2013 Renesas Electronics Corporation + * Copyright (C) 2007,2008,2010 Nobuhiro Iwamatsu + * Copyright (C) 2002 - 2008 Paul Mundt * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include +#include #include - -#ifdef CFG_SCIF_CONSOLE - -#if defined (CONFIG_CONS_SCIF0) -#define SCIF_BASE SCIF0_BASE -#elif defined (CONFIG_CONS_SCIF1) -#define SCIF_BASE SCIF1_BASE +#include "serial_sh.h" +#include +#include + +#if defined(CONFIG_CONS_SCIF0) +# define SCIF_BASE SCIF0_BASE +#elif defined(CONFIG_CONS_SCIF1) +# define SCIF_BASE SCIF1_BASE +#elif defined(CONFIG_CONS_SCIF2) +# define SCIF_BASE SCIF2_BASE +#elif defined(CONFIG_CONS_SCIF3) +# define SCIF_BASE SCIF3_BASE +#elif defined(CONFIG_CONS_SCIF4) +# define SCIF_BASE SCIF4_BASE +#elif defined(CONFIG_CONS_SCIF5) +# define SCIF_BASE SCIF5_BASE +#elif defined(CONFIG_CONS_SCIF6) +# define SCIF_BASE SCIF6_BASE +#elif defined(CONFIG_CONS_SCIF7) +# define SCIF_BASE SCIF7_BASE #else -#error "Default SCIF doesn't set....." +# error "Default SCIF doesn't set....." #endif -/* Base register */ -#define SCSMR (vu_short *)(SCIF_BASE + 0x0) -#define SCBRR (vu_char *)(SCIF_BASE + 0x4) -#define SCSCR (vu_short *)(SCIF_BASE + 0x8) -#define SCFCR (vu_short *)(SCIF_BASE + 0x18) -#define SCFDR (vu_short *)(SCIF_BASE + 0x1C) -#ifdef CONFIG_CPU_SH7720 /* SH7720 specific */ -# define SCFSR (vu_short *)(SCIF_BASE + 0x14) /* SCSSR */ -# define SCFTDR (vu_char *)(SCIF_BASE + 0x20) -# define SCFRDR (vu_char *)(SCIF_BASE + 0x24) +#if defined(CONFIG_SCIF_A) + #define SCIF_BASE_PORT PORT_SCIFA #else -# define SCFTDR (vu_char *)(SCIF_BASE + 0xC) -# define SCFSR (vu_short *)(SCIF_BASE + 0x10) -# define SCFRDR (vu_char *)(SCIF_BASE + 0x14) + #define SCIF_BASE_PORT PORT_SCIF #endif -#if defined(CONFIG_CPU_SH7780) || \ - defined(CONFIG_CPU_SH7785) -# define SCRFDR (vu_short *)(SCIF_BASE + 0x20) -# define SCSPTR (vu_short *)(SCIF_BASE + 0x24) -# define SCLSR (vu_short *)(SCIF_BASE + 0x28) -# define SCRER (vu_short *)(SCIF_BASE + 0x2C) -# define LSR_ORER 1 -# define FIFOLEVEL_MASK 0xFF -#elif defined(CONFIG_CPU_SH7750) || \ - defined(CONFIG_CPU_SH7751) || \ - defined(CONFIG_CPU_SH7722) -# define SCSPTR (vu_short *)(SCIF_BASE + 0x20) -# define SCLSR (vu_short *)(SCIF_BASE + 0x24) -# define LSR_ORER 1 -# define FIFOLEVEL_MASK 0x1F -#elif defined(CONFIG_CPU_SH7720) -# define SCLSR (vu_short *)(SCIF_BASE + 0x24) -# define LSR_ORER 0x0200 -# define FIFOLEVEL_MASK 0x1F -#elif defined(CONFIG_CPU_SH7710) - defined(CONFIG_CPU_SH7712) -# define SCLSR SCFSR /* SCSSR */ -# define LSR_ORER 1 -# define FIFOLEVEL_MASK 0x1F -#endif +static struct uart_port sh_sci = { + .membase = (unsigned char*)SCIF_BASE, + .mapbase = SCIF_BASE, + .type = SCIF_BASE_PORT, +}; -/* SCBRR register value setting */ -#if defined(CONFIG_CPU_SH7720) -# define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) -#else /* Generic SuperH */ -# define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1) -#endif - -#define SCR_RE (1 << 4) -#define SCR_TE (1 << 5) -#define FCR_RFRST (1 << 1) /* RFCL */ -#define FCR_TFRST (1 << 2) /* TFCL */ -#define FSR_DR (1 << 0) -#define FSR_RDF (1 << 1) -#define FSR_FER (1 << 3) -#define FSR_BRK (1 << 4) -#define FSR_FER (1 << 3) -#define FSR_TEND (1 << 6) -#define FSR_ER (1 << 7) - -/*----------------------------------------------------------------------*/ - -void serial_setbrg (void) +static void sh_serial_setbrg(void) { DECLARE_GLOBAL_DATA_PTR; - *SCBRR = SCBRR_VALUE(gd->baudrate,CONFIG_SYS_CLK_FREQ); + + sci_out(&sh_sci, SCBRR, + SCBRR_VALUE(gd->baudrate, CONFIG_SH_SCIF_CLK_FREQ)); } -int serial_init (void) +static int sh_serial_init(void) { - *SCSCR = (SCR_RE | SCR_TE); - *SCSMR = 0 ; - *SCSMR = 0; - *SCFCR = (FCR_RFRST | FCR_TFRST); - *SCFCR; - *SCFCR = 0; + sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); + sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); + sci_out(&sh_sci, SCSMR, 0); + sci_out(&sh_sci, SCSMR, 0); + sci_out(&sh_sci, SCFCR, SCFCR_RFRST|SCFCR_TFRST); + sci_in(&sh_sci, SCFCR); + sci_out(&sh_sci, SCFCR, 0); serial_setbrg(); return 0; } -static int serial_rx_fifo_level (void) +#if defined(CONFIG_CPU_SH7760) || \ + defined(CONFIG_CPU_SH7780) || \ + defined(CONFIG_CPU_SH7785) || \ + defined(CONFIG_CPU_SH7786) +static int scif_rxfill(struct uart_port *port) { -#if defined(CONFIG_SH4A) - return (*SCRFDR >> 0) & FIFOLEVEL_MASK; + return sci_in(port, SCRFDR) & 0xff; +} +#elif defined(CONFIG_CPU_SH7763) +static int scif_rxfill(struct uart_port *port) +{ + if ((port->mapbase == 0xffe00000) || + (port->mapbase == 0xffe08000)) { + /* SCIF0/1*/ + return sci_in(port, SCRFDR) & 0xff; + } else { + /* SCIF2 */ + return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; + } +} +#elif defined(CONFIG_ARCH_SH7372) +static int scif_rxfill(struct uart_port *port) +{ + if (port->type == PORT_SCIFA) + return sci_in(port, SCFDR) & SCIF_RFDC_MASK; + else + return sci_in(port, SCRFDR); +} #else - return (*SCFDR >> 0) & FIFOLEVEL_MASK; +static int scif_rxfill(struct uart_port *port) +{ + return sci_in(port, SCFDR) & SCIF_RFDC_MASK; +} #endif + +static int serial_rx_fifo_level(void) +{ + return scif_rxfill(&sh_sci); } -void serial_raw_putc (const char c) +static void handle_error(void) { - unsigned int fsr_bits_to_clear; + sci_in(&sh_sci, SCxSR); + sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci)); + sci_in(&sh_sci, SCLSR); + sci_out(&sh_sci, SCLSR, 0x00); +} +void serial_raw_putc(const char c) +{ while (1) { - if (*SCFSR & FSR_TEND) { /* Tx fifo is empty */ - fsr_bits_to_clear = FSR_TEND; + /* Tx fifo is empty */ + if (sci_in(&sh_sci, SCxSR) & SCxSR_TEND(&sh_sci)) break; - } } - *SCFTDR = c; - if (fsr_bits_to_clear != 0) - *SCFSR &= ~fsr_bits_to_clear; + sci_out(&sh_sci, SCxTDR, c); + sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci)); } -void serial_putc (const char c) +static void sh_serial_putc(const char c) { if (c == '\n') - serial_raw_putc ('\r'); - serial_raw_putc (c); + serial_raw_putc('\r'); + serial_raw_putc(c); } -void serial_puts (const char *s) +static int sh_serial_tstc(void) { - char c; - while ((c = *s++) != 0) - serial_putc (c); -} + if (sci_in(&sh_sci, SCxSR) & SCIF_ERRORS) { + handle_error(); + return 0; + } -int serial_tstc (void) -{ return serial_rx_fifo_level() ? 1 : 0; } -#define FSR_ERR_CLEAR 0x0063 -#define RDRF_CLEAR 0x00fc -void handle_error( void ){ - - (void)*SCFSR ; - *SCFSR = FSR_ERR_CLEAR ; - (void)*SCLSR ; - *SCLSR = 0x00 ; -} -int serial_getc_check( void ){ +int serial_getc_check(void) +{ unsigned short status; - status = *SCFSR ; + status = sci_in(&sh_sci, SCxSR); - if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK)) + if (status & SCIF_ERRORS) handle_error(); - if( *SCLSR & LSR_ORER ) + if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) handle_error(); - return (status & ( FSR_DR | FSR_RDF )); + return status & (SCIF_DR | SCxSR_RDxF(&sh_sci)); } -int serial_getc (void) +static int sh_serial_getc(void) { - unsigned short status ; + unsigned short status; char ch; - while(!serial_getc_check()); - ch = *SCFRDR; - status = *SCFSR ; + while (!serial_getc_check()) + ; - *SCFSR = RDRF_CLEAR ; + ch = sci_in(&sh_sci, SCxRDR); + status = sci_in(&sh_sci, SCxSR); - if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK)) - handle_error(); + sci_out(&sh_sci, SCxSR, SCxSR_RDxF_CLEAR(&sh_sci)); + + if (status & SCIF_ERRORS) + handle_error(); - if( *SCLSR & LSR_ORER ) + if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) handle_error(); + return ch; +} - return ch ; +static struct serial_device sh_serial_drv = { + .name = "sh_serial", + .start = sh_serial_init, + .stop = NULL, + .setbrg = sh_serial_setbrg, + .putc = sh_serial_putc, + .puts = default_serial_puts, + .getc = sh_serial_getc, + .tstc = sh_serial_tstc, +}; + +void sh_serial_initialize(void) +{ + serial_register(&sh_serial_drv); } -#endif /* CFG_SCIF_CONSOLE */ +__weak struct serial_device *default_serial_console(void) +{ + return &sh_serial_drv; +}