xref: /rk3399_rockchip-uboot/drivers/serial/serial_sh.c (revision 6ede753ddf52a7b0f992d9bccbe5e4a0968ca475)
129592ecbSNobuhiro Iwamatsu /*
229592ecbSNobuhiro Iwamatsu  * SuperH SCIF device driver.
3ac331da0SNobuhiro Iwamatsu  * Copyright (c) 2007,2008 Nobuhiro Iwamatsu
429592ecbSNobuhiro Iwamatsu  *
529592ecbSNobuhiro Iwamatsu  * This program is free software; you can redistribute it and/or modify
629592ecbSNobuhiro Iwamatsu  * it under the terms of the GNU General Public License as published by
729592ecbSNobuhiro Iwamatsu  * the Free Software Foundation; either version 2 of the License, or
829592ecbSNobuhiro Iwamatsu  * (at your option) any later version.
929592ecbSNobuhiro Iwamatsu  *
1029592ecbSNobuhiro Iwamatsu  * This program is distributed in the hope that it will be useful,
1129592ecbSNobuhiro Iwamatsu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1229592ecbSNobuhiro Iwamatsu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1329592ecbSNobuhiro Iwamatsu  * GNU General Public License for more details.
1429592ecbSNobuhiro Iwamatsu  *
1529592ecbSNobuhiro Iwamatsu  * You should have received a copy of the GNU General Public License
1629592ecbSNobuhiro Iwamatsu  * along with this program; if not, write to the Free Software
1729592ecbSNobuhiro Iwamatsu  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1829592ecbSNobuhiro Iwamatsu  */
1929592ecbSNobuhiro Iwamatsu 
2029592ecbSNobuhiro Iwamatsu #include <common.h>
2129592ecbSNobuhiro Iwamatsu #include <asm/processor.h>
2229592ecbSNobuhiro Iwamatsu 
2329592ecbSNobuhiro Iwamatsu #if defined (CONFIG_CONS_SCIF0)
2429592ecbSNobuhiro Iwamatsu #define SCIF_BASE	SCIF0_BASE
2529592ecbSNobuhiro Iwamatsu #elif defined (CONFIG_CONS_SCIF1)
2629592ecbSNobuhiro Iwamatsu #define SCIF_BASE	SCIF1_BASE
2708c5fabeSNobuhiro Iwamatsu #elif defined (CONFIG_CONS_SCIF2)
2808c5fabeSNobuhiro Iwamatsu #define SCIF_BASE	SCIF2_BASE
2929592ecbSNobuhiro Iwamatsu #else
3029592ecbSNobuhiro Iwamatsu #error "Default SCIF doesn't set....."
3129592ecbSNobuhiro Iwamatsu #endif
3229592ecbSNobuhiro Iwamatsu 
3376e49aa7SNobuhiro Iwamatsu /* Base register */
3429592ecbSNobuhiro Iwamatsu #define SCSMR	(vu_short *)(SCIF_BASE + 0x0)
3529592ecbSNobuhiro Iwamatsu #define SCBRR	(vu_char  *)(SCIF_BASE + 0x4)
3629592ecbSNobuhiro Iwamatsu #define SCSCR	(vu_short *)(SCIF_BASE + 0x8)
3776e49aa7SNobuhiro Iwamatsu #define SCFCR	(vu_short *)(SCIF_BASE + 0x18)
3876e49aa7SNobuhiro Iwamatsu #define SCFDR	(vu_short *)(SCIF_BASE + 0x1C)
39ac331da0SNobuhiro Iwamatsu #ifdef CONFIG_CPU_SH7720	/* SH7720 specific */
4076e49aa7SNobuhiro Iwamatsu # define SCFSR	(vu_short *)(SCIF_BASE + 0x14)	/* SCSSR */
4176e49aa7SNobuhiro Iwamatsu # define SCFTDR	(vu_char  *)(SCIF_BASE + 0x20)
4276e49aa7SNobuhiro Iwamatsu # define SCFRDR	(vu_char  *)(SCIF_BASE + 0x24)
4376e49aa7SNobuhiro Iwamatsu #else
4429592ecbSNobuhiro Iwamatsu # define SCFTDR (vu_char  *)(SCIF_BASE + 0xC)
4529592ecbSNobuhiro Iwamatsu # define SCFSR 	(vu_short *)(SCIF_BASE + 0x10)
4629592ecbSNobuhiro Iwamatsu # define SCFRDR (vu_char  *)(SCIF_BASE + 0x14)
477c10c572SYoshihiro Shimoda #endif
487c10c572SYoshihiro Shimoda 
49b55523efSYusuke Goda #if	defined(CONFIG_CPU_SH7780) || \
50b55523efSYusuke Goda 	defined(CONFIG_CPU_SH7785)
5129592ecbSNobuhiro Iwamatsu # define SCRFDR	(vu_short *)(SCIF_BASE + 0x20)
5229592ecbSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x24)
5329592ecbSNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x28)
5429592ecbSNobuhiro Iwamatsu # define SCRER	(vu_short *)(SCIF_BASE + 0x2C)
557c10c572SYoshihiro Shimoda # define LSR_ORER	1
563ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0xFF
5708c5fabeSNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7763)
5808c5fabeSNobuhiro Iwamatsu # if defined (CONFIG_CONS_SCIF2)
5908c5fabeSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x20)
6008c5fabeSNobuhiro Iwamatsu # define SCLSR 	(vu_short *)(SCIF_BASE + 0x24)
6108c5fabeSNobuhiro Iwamatsu # define LSR_ORER	1
6208c5fabeSNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
6308c5fabeSNobuhiro Iwamatsu # else
6408c5fabeSNobuhiro Iwamatsu # define SCRFDR	(vu_short *)(SCIF_BASE + 0x20)
6508c5fabeSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x24)
6608c5fabeSNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x28)
6708c5fabeSNobuhiro Iwamatsu # define SCRER	(vu_short *)(SCIF_BASE + 0x2C)
6808c5fabeSNobuhiro Iwamatsu # define LSR_ORER	1
6908c5fabeSNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0xFF
7008c5fabeSNobuhiro Iwamatsu # endif
71b55523efSYusuke Goda #elif defined(CONFIG_CPU_SH7750) || \
7256693327SNobuhiro Iwamatsu 	defined(CONFIG_CPU_SH7751) || \
73*6ede753dSNobuhiro Iwamatsu 	defined(CONFIG_CPU_SH7722) || \
74*6ede753dSNobuhiro Iwamatsu 	defined(CONFIG_CPU_SH7203)
7529592ecbSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x20)
7629592ecbSNobuhiro Iwamatsu # define SCLSR 	(vu_short *)(SCIF_BASE + 0x24)
777c10c572SYoshihiro Shimoda # define LSR_ORER	1
783ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
79b55523efSYusuke Goda #elif defined(CONFIG_CPU_SH7720)
8076e49aa7SNobuhiro Iwamatsu # define SCLSR		(vu_short *)(SCIF_BASE + 0x24)
817c10c572SYoshihiro Shimoda # define LSR_ORER	0x0200
823ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
8308c5fabeSNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7710) || \
84b55523efSYusuke Goda 	defined(CONFIG_CPU_SH7712)
85ac331da0SNobuhiro Iwamatsu # define SCLSR	SCFSR		/* SCSSR */
86ac331da0SNobuhiro Iwamatsu # define LSR_ORER	1
873ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
88ac331da0SNobuhiro Iwamatsu #endif
89ac331da0SNobuhiro Iwamatsu 
90b55523efSYusuke Goda /* SCBRR register value setting */
91ac331da0SNobuhiro Iwamatsu #if defined(CONFIG_CPU_SH7720)
92ac331da0SNobuhiro Iwamatsu # define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
93ac331da0SNobuhiro Iwamatsu #else /* Generic SuperH */
94ac331da0SNobuhiro Iwamatsu # define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
9529592ecbSNobuhiro Iwamatsu #endif
9629592ecbSNobuhiro Iwamatsu 
9729592ecbSNobuhiro Iwamatsu #define SCR_RE 		(1 << 4)
9829592ecbSNobuhiro Iwamatsu #define SCR_TE 		(1 << 5)
9929592ecbSNobuhiro Iwamatsu #define FCR_RFRST	(1 << 1)	/* RFCL */
10029592ecbSNobuhiro Iwamatsu #define FCR_TFRST	(1 << 2)	/* TFCL */
10129592ecbSNobuhiro Iwamatsu #define FSR_DR   	(1 << 0)
10229592ecbSNobuhiro Iwamatsu #define FSR_RDF  	(1 << 1)
10329592ecbSNobuhiro Iwamatsu #define FSR_FER  	(1 << 3)
10429592ecbSNobuhiro Iwamatsu #define FSR_BRK  	(1 << 4)
10529592ecbSNobuhiro Iwamatsu #define FSR_FER  	(1 << 3)
10629592ecbSNobuhiro Iwamatsu #define FSR_TEND 	(1 << 6)
10729592ecbSNobuhiro Iwamatsu #define FSR_ER   	(1 << 7)
10829592ecbSNobuhiro Iwamatsu 
10929592ecbSNobuhiro Iwamatsu /*----------------------------------------------------------------------*/
11029592ecbSNobuhiro Iwamatsu 
11129592ecbSNobuhiro Iwamatsu void serial_setbrg(void)
11229592ecbSNobuhiro Iwamatsu {
11329592ecbSNobuhiro Iwamatsu 	DECLARE_GLOBAL_DATA_PTR;
114ac331da0SNobuhiro Iwamatsu 	*SCBRR = SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ);
11529592ecbSNobuhiro Iwamatsu }
11629592ecbSNobuhiro Iwamatsu 
11729592ecbSNobuhiro Iwamatsu int serial_init(void)
11829592ecbSNobuhiro Iwamatsu {
11929592ecbSNobuhiro Iwamatsu 	*SCSCR = (SCR_RE | SCR_TE);
12029592ecbSNobuhiro Iwamatsu 	*SCSMR = 0;
12129592ecbSNobuhiro Iwamatsu 	*SCSMR = 0;
12229592ecbSNobuhiro Iwamatsu 	*SCFCR = (FCR_RFRST | FCR_TFRST);
12329592ecbSNobuhiro Iwamatsu 	*SCFCR;
12429592ecbSNobuhiro Iwamatsu 	*SCFCR = 0;
12529592ecbSNobuhiro Iwamatsu 
12629592ecbSNobuhiro Iwamatsu 	serial_setbrg();
12729592ecbSNobuhiro Iwamatsu 	return 0;
12829592ecbSNobuhiro Iwamatsu }
12929592ecbSNobuhiro Iwamatsu 
13029592ecbSNobuhiro Iwamatsu static int serial_rx_fifo_level(void)
13129592ecbSNobuhiro Iwamatsu {
13208c5fabeSNobuhiro Iwamatsu #if defined(SCRFDR)
1333ecff1d7SNobuhiro Iwamatsu 	return (*SCRFDR >> 0) & FIFOLEVEL_MASK;
1343ecff1d7SNobuhiro Iwamatsu #else
1353ecff1d7SNobuhiro Iwamatsu 	return (*SCFDR >> 0) & FIFOLEVEL_MASK;
1363ecff1d7SNobuhiro Iwamatsu #endif
13729592ecbSNobuhiro Iwamatsu }
13829592ecbSNobuhiro Iwamatsu 
13929592ecbSNobuhiro Iwamatsu void serial_raw_putc(const char c)
14029592ecbSNobuhiro Iwamatsu {
14129592ecbSNobuhiro Iwamatsu 	unsigned int fsr_bits_to_clear;
14229592ecbSNobuhiro Iwamatsu 
14329592ecbSNobuhiro Iwamatsu 	while (1) {
14429592ecbSNobuhiro Iwamatsu 		if (*SCFSR & FSR_TEND) {	/* Tx fifo is empty */
14529592ecbSNobuhiro Iwamatsu 			fsr_bits_to_clear = FSR_TEND;
14629592ecbSNobuhiro Iwamatsu 			break;
14729592ecbSNobuhiro Iwamatsu 		}
14829592ecbSNobuhiro Iwamatsu 	}
14929592ecbSNobuhiro Iwamatsu 
15029592ecbSNobuhiro Iwamatsu 	*SCFTDR = c;
15129592ecbSNobuhiro Iwamatsu 	if (fsr_bits_to_clear != 0)
15229592ecbSNobuhiro Iwamatsu 		*SCFSR &= ~fsr_bits_to_clear;
15329592ecbSNobuhiro Iwamatsu }
15429592ecbSNobuhiro Iwamatsu 
15529592ecbSNobuhiro Iwamatsu void serial_putc(const char c)
15629592ecbSNobuhiro Iwamatsu {
15729592ecbSNobuhiro Iwamatsu 	if (c == '\n')
15829592ecbSNobuhiro Iwamatsu 		serial_raw_putc('\r');
15929592ecbSNobuhiro Iwamatsu 	serial_raw_putc(c);
16029592ecbSNobuhiro Iwamatsu }
16129592ecbSNobuhiro Iwamatsu 
16229592ecbSNobuhiro Iwamatsu void serial_puts(const char *s)
16329592ecbSNobuhiro Iwamatsu {
16429592ecbSNobuhiro Iwamatsu 	char c;
16529592ecbSNobuhiro Iwamatsu 	while ((c = *s++) != 0)
16629592ecbSNobuhiro Iwamatsu 		serial_putc(c);
16729592ecbSNobuhiro Iwamatsu }
16829592ecbSNobuhiro Iwamatsu 
16929592ecbSNobuhiro Iwamatsu int serial_tstc(void)
17029592ecbSNobuhiro Iwamatsu {
17129592ecbSNobuhiro Iwamatsu 	return serial_rx_fifo_level()? 1 : 0;
17229592ecbSNobuhiro Iwamatsu }
17329592ecbSNobuhiro Iwamatsu 
17429592ecbSNobuhiro Iwamatsu #define FSR_ERR_CLEAR   0x0063
17529592ecbSNobuhiro Iwamatsu #define RDRF_CLEAR      0x00fc
17608c5fabeSNobuhiro Iwamatsu void handle_error(void)
17708c5fabeSNobuhiro Iwamatsu {
17829592ecbSNobuhiro Iwamatsu 
17929592ecbSNobuhiro Iwamatsu 	(void)*SCFSR;
18029592ecbSNobuhiro Iwamatsu 	*SCFSR = FSR_ERR_CLEAR;
18129592ecbSNobuhiro Iwamatsu 	(void)*SCLSR;
18229592ecbSNobuhiro Iwamatsu 	*SCLSR = 0x00;
18329592ecbSNobuhiro Iwamatsu }
18429592ecbSNobuhiro Iwamatsu 
18508c5fabeSNobuhiro Iwamatsu int serial_getc_check(void)
18608c5fabeSNobuhiro Iwamatsu {
18729592ecbSNobuhiro Iwamatsu 	unsigned short status;
18829592ecbSNobuhiro Iwamatsu 
18929592ecbSNobuhiro Iwamatsu 	status = *SCFSR;
19029592ecbSNobuhiro Iwamatsu 
19108c5fabeSNobuhiro Iwamatsu 	if (status & (FSR_FER | FSR_ER | FSR_BRK))
19229592ecbSNobuhiro Iwamatsu 		handle_error();
19329592ecbSNobuhiro Iwamatsu 	if (*SCLSR & LSR_ORER)
19429592ecbSNobuhiro Iwamatsu 		handle_error();
19529592ecbSNobuhiro Iwamatsu 	return (status & (FSR_DR | FSR_RDF));
19629592ecbSNobuhiro Iwamatsu }
19729592ecbSNobuhiro Iwamatsu 
19829592ecbSNobuhiro Iwamatsu int serial_getc(void)
19929592ecbSNobuhiro Iwamatsu {
20029592ecbSNobuhiro Iwamatsu 	unsigned short status;
20129592ecbSNobuhiro Iwamatsu 	char ch;
20229592ecbSNobuhiro Iwamatsu 	while (!serial_getc_check()) ;
20329592ecbSNobuhiro Iwamatsu 
20429592ecbSNobuhiro Iwamatsu 	ch = *SCFRDR;
20529592ecbSNobuhiro Iwamatsu 	status = *SCFSR;
20629592ecbSNobuhiro Iwamatsu 
20729592ecbSNobuhiro Iwamatsu 	*SCFSR = RDRF_CLEAR;
20829592ecbSNobuhiro Iwamatsu 
20929592ecbSNobuhiro Iwamatsu 	if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK))
21029592ecbSNobuhiro Iwamatsu 		handle_error();
21129592ecbSNobuhiro Iwamatsu 
21229592ecbSNobuhiro Iwamatsu 	if (*SCLSR & LSR_ORER)
21329592ecbSNobuhiro Iwamatsu 		handle_error();
21429592ecbSNobuhiro Iwamatsu 
21529592ecbSNobuhiro Iwamatsu 	return ch;
21629592ecbSNobuhiro Iwamatsu }
217