xref: /rk3399_rockchip-uboot/drivers/serial/serial_sh.c (revision a03c09c5fdb8430fe2ae6a03f88a0cf7bcc0aa57)
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
29ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF3)
30ab09f433SNobuhiro Iwamatsu # define SCIF_BASE	SCIF3_BASE
31ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF4)
32ab09f433SNobuhiro Iwamatsu # define SCIF_BASE	SCIF4_BASE
33ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF5)
34ab09f433SNobuhiro Iwamatsu # define SCIF_BASE	SCIF5_BASE
3529592ecbSNobuhiro Iwamatsu #else
3629592ecbSNobuhiro Iwamatsu # error "Default SCIF doesn't set....."
3729592ecbSNobuhiro Iwamatsu #endif
3829592ecbSNobuhiro Iwamatsu 
3976e49aa7SNobuhiro Iwamatsu /* Base register */
4029592ecbSNobuhiro Iwamatsu #define SCSMR	(vu_short *)(SCIF_BASE + 0x0)
4129592ecbSNobuhiro Iwamatsu #define SCBRR	(vu_char  *)(SCIF_BASE + 0x4)
4229592ecbSNobuhiro Iwamatsu #define SCSCR	(vu_short *)(SCIF_BASE + 0x8)
4376e49aa7SNobuhiro Iwamatsu #define SCFCR	(vu_short *)(SCIF_BASE + 0x18)
4476e49aa7SNobuhiro Iwamatsu #define SCFDR	(vu_short *)(SCIF_BASE + 0x1C)
45ab09f433SNobuhiro Iwamatsu #if defined(CONFIG_CPU_SH7720) || \
46ab09f433SNobuhiro Iwamatsu 	(defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A))
4776e49aa7SNobuhiro Iwamatsu # define SCFSR	(vu_short *)(SCIF_BASE + 0x14)	/* SCSSR */
4876e49aa7SNobuhiro Iwamatsu # define SCFTDR	(vu_char  *)(SCIF_BASE + 0x20)
4976e49aa7SNobuhiro Iwamatsu # define SCFRDR	(vu_char  *)(SCIF_BASE + 0x24)
5076e49aa7SNobuhiro Iwamatsu #else
5129592ecbSNobuhiro Iwamatsu # define SCFTDR (vu_char  *)(SCIF_BASE + 0xC)
5229592ecbSNobuhiro Iwamatsu # define SCFSR 	(vu_short *)(SCIF_BASE + 0x10)
5329592ecbSNobuhiro Iwamatsu # define SCFRDR (vu_char  *)(SCIF_BASE + 0x14)
547c10c572SYoshihiro Shimoda #endif
557c10c572SYoshihiro Shimoda 
56b55523efSYusuke Goda #if	defined(CONFIG_CPU_SH7780) || \
57b55523efSYusuke Goda 	defined(CONFIG_CPU_SH7785)
5829592ecbSNobuhiro Iwamatsu # define SCRFDR	(vu_short *)(SCIF_BASE + 0x20)
5929592ecbSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x24)
6029592ecbSNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x28)
6129592ecbSNobuhiro Iwamatsu # define SCRER	(vu_short *)(SCIF_BASE + 0x2C)
627c10c572SYoshihiro Shimoda # define LSR_ORER	1
633ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0xFF
6408c5fabeSNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7763)
6508c5fabeSNobuhiro Iwamatsu # if defined(CONFIG_CONS_SCIF2)
6608c5fabeSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x20)
6708c5fabeSNobuhiro Iwamatsu # define SCLSR 	(vu_short *)(SCIF_BASE + 0x24)
6808c5fabeSNobuhiro Iwamatsu # define LSR_ORER	1
6908c5fabeSNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
7008c5fabeSNobuhiro Iwamatsu # else
7108c5fabeSNobuhiro Iwamatsu # define SCRFDR	(vu_short *)(SCIF_BASE + 0x20)
7208c5fabeSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x24)
7308c5fabeSNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x28)
7408c5fabeSNobuhiro Iwamatsu # define SCRER	(vu_short *)(SCIF_BASE + 0x2C)
7508c5fabeSNobuhiro Iwamatsu # define LSR_ORER	1
7608c5fabeSNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0xFF
7708c5fabeSNobuhiro Iwamatsu # endif
78ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7723)
79*a03c09c5SNobuhiro Iwamatsu # if defined(CONFIG_SCIF_A)
80ab09f433SNobuhiro Iwamatsu # define SCLSR	SCFSR
81ab09f433SNobuhiro Iwamatsu # define LSR_ORER	0x0200
82ab09f433SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x3F
83ab09f433SNobuhiro Iwamatsu #else
84ab09f433SNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x24)
85ab09f433SNobuhiro Iwamatsu # define LSR_ORER	1
86ab09f433SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
87ab09f433SNobuhiro Iwamatsu #endif
88b55523efSYusuke Goda #elif defined(CONFIG_CPU_SH7750) || \
8956693327SNobuhiro Iwamatsu 	defined(CONFIG_CPU_SH7751) || \
906ede753dSNobuhiro Iwamatsu 	defined(CONFIG_CPU_SH7722) || \
916ede753dSNobuhiro Iwamatsu 	defined(CONFIG_CPU_SH7203)
9229592ecbSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x20)
9329592ecbSNobuhiro Iwamatsu # define SCLSR 	(vu_short *)(SCIF_BASE + 0x24)
947c10c572SYoshihiro Shimoda # define LSR_ORER	1
953ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
96b55523efSYusuke Goda #elif defined(CONFIG_CPU_SH7720)
9776e49aa7SNobuhiro Iwamatsu # define SCLSR		(vu_short *)(SCIF_BASE + 0x24)
987c10c572SYoshihiro Shimoda # define LSR_ORER	0x0200
993ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
10008c5fabeSNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7710) || \
101b55523efSYusuke Goda 	defined(CONFIG_CPU_SH7712)
102ac331da0SNobuhiro Iwamatsu # define SCLSR	SCFSR		/* SCSSR */
103ac331da0SNobuhiro Iwamatsu # define LSR_ORER	1
1043ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
105ac331da0SNobuhiro Iwamatsu #endif
106ac331da0SNobuhiro Iwamatsu 
107b55523efSYusuke Goda /* SCBRR register value setting */
108ac331da0SNobuhiro Iwamatsu #if defined(CONFIG_CPU_SH7720)
109ac331da0SNobuhiro Iwamatsu # define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
110ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A)
111ab09f433SNobuhiro Iwamatsu /* SH7723 SCIFA use bus clock. So clock *2 */
112ab09f433SNobuhiro Iwamatsu # define SCBRR_VALUE(bps, clk) (((clk*2*2)+16*bps)/(32*bps)-1)
113ac331da0SNobuhiro Iwamatsu #else /* Generic SuperH */
114ac331da0SNobuhiro Iwamatsu # define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
11529592ecbSNobuhiro Iwamatsu #endif
11629592ecbSNobuhiro Iwamatsu 
11729592ecbSNobuhiro Iwamatsu #define SCR_RE 		(1 << 4)
11829592ecbSNobuhiro Iwamatsu #define SCR_TE 		(1 << 5)
11929592ecbSNobuhiro Iwamatsu #define FCR_RFRST	(1 << 1)	/* RFCL */
12029592ecbSNobuhiro Iwamatsu #define FCR_TFRST	(1 << 2)	/* TFCL */
12129592ecbSNobuhiro Iwamatsu #define FSR_DR   	(1 << 0)
12229592ecbSNobuhiro Iwamatsu #define FSR_RDF  	(1 << 1)
12329592ecbSNobuhiro Iwamatsu #define FSR_FER  	(1 << 3)
12429592ecbSNobuhiro Iwamatsu #define FSR_BRK  	(1 << 4)
12529592ecbSNobuhiro Iwamatsu #define FSR_FER  	(1 << 3)
12629592ecbSNobuhiro Iwamatsu #define FSR_TEND 	(1 << 6)
12729592ecbSNobuhiro Iwamatsu #define FSR_ER   	(1 << 7)
12829592ecbSNobuhiro Iwamatsu 
12929592ecbSNobuhiro Iwamatsu /*----------------------------------------------------------------------*/
13029592ecbSNobuhiro Iwamatsu 
13129592ecbSNobuhiro Iwamatsu void serial_setbrg(void)
13229592ecbSNobuhiro Iwamatsu {
13329592ecbSNobuhiro Iwamatsu 	DECLARE_GLOBAL_DATA_PTR;
134ac331da0SNobuhiro Iwamatsu 	*SCBRR = SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ);
13529592ecbSNobuhiro Iwamatsu }
13629592ecbSNobuhiro Iwamatsu 
13729592ecbSNobuhiro Iwamatsu int serial_init(void)
13829592ecbSNobuhiro Iwamatsu {
13929592ecbSNobuhiro Iwamatsu 	*SCSCR = (SCR_RE | SCR_TE);
14029592ecbSNobuhiro Iwamatsu 	*SCSMR = 0;
14129592ecbSNobuhiro Iwamatsu 	*SCSMR = 0;
14229592ecbSNobuhiro Iwamatsu 	*SCFCR = (FCR_RFRST | FCR_TFRST);
14329592ecbSNobuhiro Iwamatsu 	*SCFCR;
14429592ecbSNobuhiro Iwamatsu 	*SCFCR = 0;
14529592ecbSNobuhiro Iwamatsu 
14629592ecbSNobuhiro Iwamatsu 	serial_setbrg();
14729592ecbSNobuhiro Iwamatsu 	return 0;
14829592ecbSNobuhiro Iwamatsu }
14929592ecbSNobuhiro Iwamatsu 
15029592ecbSNobuhiro Iwamatsu static int serial_rx_fifo_level(void)
15129592ecbSNobuhiro Iwamatsu {
15208c5fabeSNobuhiro Iwamatsu #if defined(SCRFDR)
1533ecff1d7SNobuhiro Iwamatsu 	return (*SCRFDR >> 0) & FIFOLEVEL_MASK;
1543ecff1d7SNobuhiro Iwamatsu #else
1553ecff1d7SNobuhiro Iwamatsu 	return (*SCFDR >> 0) & FIFOLEVEL_MASK;
1563ecff1d7SNobuhiro Iwamatsu #endif
15729592ecbSNobuhiro Iwamatsu }
15829592ecbSNobuhiro Iwamatsu 
15929592ecbSNobuhiro Iwamatsu void serial_raw_putc(const char c)
16029592ecbSNobuhiro Iwamatsu {
16129592ecbSNobuhiro Iwamatsu 	unsigned int fsr_bits_to_clear;
16229592ecbSNobuhiro Iwamatsu 
16329592ecbSNobuhiro Iwamatsu 	while (1) {
16429592ecbSNobuhiro Iwamatsu 		if (*SCFSR & FSR_TEND) {	/* Tx fifo is empty */
16529592ecbSNobuhiro Iwamatsu 			fsr_bits_to_clear = FSR_TEND;
16629592ecbSNobuhiro Iwamatsu 			break;
16729592ecbSNobuhiro Iwamatsu 		}
16829592ecbSNobuhiro Iwamatsu 	}
16929592ecbSNobuhiro Iwamatsu 
17029592ecbSNobuhiro Iwamatsu 	*SCFTDR = c;
17129592ecbSNobuhiro Iwamatsu 	if (fsr_bits_to_clear != 0)
17229592ecbSNobuhiro Iwamatsu 		*SCFSR &= ~fsr_bits_to_clear;
17329592ecbSNobuhiro Iwamatsu }
17429592ecbSNobuhiro Iwamatsu 
17529592ecbSNobuhiro Iwamatsu void serial_putc(const char c)
17629592ecbSNobuhiro Iwamatsu {
17729592ecbSNobuhiro Iwamatsu 	if (c == '\n')
17829592ecbSNobuhiro Iwamatsu 		serial_raw_putc('\r');
17929592ecbSNobuhiro Iwamatsu 	serial_raw_putc(c);
18029592ecbSNobuhiro Iwamatsu }
18129592ecbSNobuhiro Iwamatsu 
18229592ecbSNobuhiro Iwamatsu void serial_puts(const char *s)
18329592ecbSNobuhiro Iwamatsu {
18429592ecbSNobuhiro Iwamatsu 	char c;
18529592ecbSNobuhiro Iwamatsu 	while ((c = *s++) != 0)
18629592ecbSNobuhiro Iwamatsu 		serial_putc(c);
18729592ecbSNobuhiro Iwamatsu }
18829592ecbSNobuhiro Iwamatsu 
18929592ecbSNobuhiro Iwamatsu int serial_tstc(void)
19029592ecbSNobuhiro Iwamatsu {
19129592ecbSNobuhiro Iwamatsu 	return serial_rx_fifo_level() ? 1 : 0;
19229592ecbSNobuhiro Iwamatsu }
19329592ecbSNobuhiro Iwamatsu 
19429592ecbSNobuhiro Iwamatsu #define FSR_ERR_CLEAR   0x0063
19529592ecbSNobuhiro Iwamatsu #define RDRF_CLEAR      0x00fc
19608c5fabeSNobuhiro Iwamatsu void handle_error(void)
19708c5fabeSNobuhiro Iwamatsu {
19829592ecbSNobuhiro Iwamatsu 
19929592ecbSNobuhiro Iwamatsu 	(void)*SCFSR;
20029592ecbSNobuhiro Iwamatsu 	*SCFSR = FSR_ERR_CLEAR;
20129592ecbSNobuhiro Iwamatsu 	(void)*SCLSR;
20229592ecbSNobuhiro Iwamatsu 	*SCLSR = 0x00;
20329592ecbSNobuhiro Iwamatsu }
20429592ecbSNobuhiro Iwamatsu 
20508c5fabeSNobuhiro Iwamatsu int serial_getc_check(void)
20608c5fabeSNobuhiro Iwamatsu {
20729592ecbSNobuhiro Iwamatsu 	unsigned short status;
20829592ecbSNobuhiro Iwamatsu 
20929592ecbSNobuhiro Iwamatsu 	status = *SCFSR;
21029592ecbSNobuhiro Iwamatsu 
21108c5fabeSNobuhiro Iwamatsu 	if (status & (FSR_FER | FSR_ER | FSR_BRK))
21229592ecbSNobuhiro Iwamatsu 		handle_error();
21329592ecbSNobuhiro Iwamatsu 	if (*SCLSR & LSR_ORER)
21429592ecbSNobuhiro Iwamatsu 		handle_error();
215ab09f433SNobuhiro Iwamatsu 	return status & (FSR_DR | FSR_RDF);
21629592ecbSNobuhiro Iwamatsu }
21729592ecbSNobuhiro Iwamatsu 
21829592ecbSNobuhiro Iwamatsu int serial_getc(void)
21929592ecbSNobuhiro Iwamatsu {
22029592ecbSNobuhiro Iwamatsu 	unsigned short status;
22129592ecbSNobuhiro Iwamatsu 	char ch;
222ab09f433SNobuhiro Iwamatsu 
223ab09f433SNobuhiro Iwamatsu 	while (!serial_getc_check())
224ab09f433SNobuhiro Iwamatsu 		;
22529592ecbSNobuhiro Iwamatsu 
22629592ecbSNobuhiro Iwamatsu 	ch = *SCFRDR;
22729592ecbSNobuhiro Iwamatsu 	status = *SCFSR;
22829592ecbSNobuhiro Iwamatsu 
22929592ecbSNobuhiro Iwamatsu 	*SCFSR = RDRF_CLEAR;
23029592ecbSNobuhiro Iwamatsu 
23129592ecbSNobuhiro Iwamatsu 	if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK))
23229592ecbSNobuhiro Iwamatsu 		handle_error();
23329592ecbSNobuhiro Iwamatsu 
23429592ecbSNobuhiro Iwamatsu 	if (*SCLSR & LSR_ORER)
23529592ecbSNobuhiro Iwamatsu 		handle_error();
23629592ecbSNobuhiro Iwamatsu 
23729592ecbSNobuhiro Iwamatsu 	return ch;
23829592ecbSNobuhiro Iwamatsu }
239