xref: /rk3399_rockchip-uboot/drivers/serial/serial_sh.c (revision fc83c9273cec6e6e542f4a0ea3b653b7d0513ffa)
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>
21*fc83c927SJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h>
2229592ecbSNobuhiro Iwamatsu #include <asm/processor.h>
2329592ecbSNobuhiro Iwamatsu 
2429592ecbSNobuhiro Iwamatsu #if defined(CONFIG_CONS_SCIF0)
2529592ecbSNobuhiro Iwamatsu # define SCIF_BASE	SCIF0_BASE
2629592ecbSNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF1)
2729592ecbSNobuhiro Iwamatsu # define SCIF_BASE	SCIF1_BASE
2808c5fabeSNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF2)
2908c5fabeSNobuhiro Iwamatsu # define SCIF_BASE	SCIF2_BASE
30ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF3)
31ab09f433SNobuhiro Iwamatsu # define SCIF_BASE	SCIF3_BASE
32ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF4)
33ab09f433SNobuhiro Iwamatsu # define SCIF_BASE	SCIF4_BASE
34ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CONS_SCIF5)
35ab09f433SNobuhiro Iwamatsu # define SCIF_BASE	SCIF5_BASE
3629592ecbSNobuhiro Iwamatsu #else
3729592ecbSNobuhiro Iwamatsu # error "Default SCIF doesn't set....."
3829592ecbSNobuhiro Iwamatsu #endif
3929592ecbSNobuhiro Iwamatsu 
4076e49aa7SNobuhiro Iwamatsu /* Base register */
4129592ecbSNobuhiro Iwamatsu #define SCSMR	(vu_short *)(SCIF_BASE + 0x0)
4229592ecbSNobuhiro Iwamatsu #define SCBRR	(vu_char  *)(SCIF_BASE + 0x4)
4329592ecbSNobuhiro Iwamatsu #define SCSCR	(vu_short *)(SCIF_BASE + 0x8)
4476e49aa7SNobuhiro Iwamatsu #define SCFCR	(vu_short *)(SCIF_BASE + 0x18)
4576e49aa7SNobuhiro Iwamatsu #define SCFDR	(vu_short *)(SCIF_BASE + 0x1C)
46ab09f433SNobuhiro Iwamatsu #if defined(CONFIG_CPU_SH7720) || \
47ab09f433SNobuhiro Iwamatsu 	(defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A))
4876e49aa7SNobuhiro Iwamatsu # define SCFSR	(vu_short *)(SCIF_BASE + 0x14)	/* SCSSR */
4976e49aa7SNobuhiro Iwamatsu # define SCFTDR	(vu_char  *)(SCIF_BASE + 0x20)
5076e49aa7SNobuhiro Iwamatsu # define SCFRDR	(vu_char  *)(SCIF_BASE + 0x24)
5176e49aa7SNobuhiro Iwamatsu #else
5229592ecbSNobuhiro Iwamatsu # define SCFTDR (vu_char  *)(SCIF_BASE + 0xC)
5329592ecbSNobuhiro Iwamatsu # define SCFSR	(vu_short *)(SCIF_BASE + 0x10)
5429592ecbSNobuhiro Iwamatsu # define SCFRDR (vu_char  *)(SCIF_BASE + 0x14)
557c10c572SYoshihiro Shimoda #endif
567c10c572SYoshihiro Shimoda 
57b55523efSYusuke Goda #if	defined(CONFIG_CPU_SH7780) || \
58b55523efSYusuke Goda 	defined(CONFIG_CPU_SH7785)
5929592ecbSNobuhiro Iwamatsu # define SCRFDR	(vu_short *)(SCIF_BASE + 0x20)
6029592ecbSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x24)
6129592ecbSNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x28)
6229592ecbSNobuhiro Iwamatsu # define SCRER	(vu_short *)(SCIF_BASE + 0x2C)
637c10c572SYoshihiro Shimoda # define LSR_ORER	1
643ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0xFF
6508c5fabeSNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7763)
6608c5fabeSNobuhiro Iwamatsu # if defined(CONFIG_CONS_SCIF2)
6708c5fabeSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x20)
6808c5fabeSNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x24)
6908c5fabeSNobuhiro Iwamatsu # define LSR_ORER	1
7008c5fabeSNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
7108c5fabeSNobuhiro Iwamatsu # else
7208c5fabeSNobuhiro Iwamatsu # define SCRFDR	(vu_short *)(SCIF_BASE + 0x20)
7308c5fabeSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x24)
7408c5fabeSNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x28)
7508c5fabeSNobuhiro Iwamatsu # define SCRER	(vu_short *)(SCIF_BASE + 0x2C)
7608c5fabeSNobuhiro Iwamatsu # define LSR_ORER	1
7708c5fabeSNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0xFF
7808c5fabeSNobuhiro Iwamatsu # endif
79ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7723)
80a03c09c5SNobuhiro Iwamatsu # if defined(CONFIG_SCIF_A)
81ab09f433SNobuhiro Iwamatsu # define SCLSR	SCFSR
82ab09f433SNobuhiro Iwamatsu # define LSR_ORER	0x0200
83ab09f433SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x3F
84ab09f433SNobuhiro Iwamatsu #else
85ab09f433SNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x24)
86ab09f433SNobuhiro Iwamatsu # define LSR_ORER	1
87ab09f433SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
88ab09f433SNobuhiro Iwamatsu #endif
89b55523efSYusuke Goda #elif defined(CONFIG_CPU_SH7750) || \
9056693327SNobuhiro Iwamatsu 	defined(CONFIG_CPU_SH7751) || \
916ede753dSNobuhiro Iwamatsu 	defined(CONFIG_CPU_SH7722) || \
926ede753dSNobuhiro Iwamatsu 	defined(CONFIG_CPU_SH7203)
9329592ecbSNobuhiro Iwamatsu # define SCSPTR	(vu_short *)(SCIF_BASE + 0x20)
9429592ecbSNobuhiro Iwamatsu # define SCLSR	(vu_short *)(SCIF_BASE + 0x24)
957c10c572SYoshihiro Shimoda # define LSR_ORER	1
963ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
97b55523efSYusuke Goda #elif defined(CONFIG_CPU_SH7720)
9815e2697cSNobuhiro Iwamatsu # define SCLSR		SCFSR
997c10c572SYoshihiro Shimoda # define LSR_ORER	0x0200
1003ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
10108c5fabeSNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7710) || \
102b55523efSYusuke Goda 	defined(CONFIG_CPU_SH7712)
103ac331da0SNobuhiro Iwamatsu # define SCLSR	SCFSR		/* SCSSR */
104ac331da0SNobuhiro Iwamatsu # define LSR_ORER	1
1053ecff1d7SNobuhiro Iwamatsu # define FIFOLEVEL_MASK	0x1F
106ac331da0SNobuhiro Iwamatsu #endif
107ac331da0SNobuhiro Iwamatsu 
108b55523efSYusuke Goda /* SCBRR register value setting */
109ac331da0SNobuhiro Iwamatsu #if defined(CONFIG_CPU_SH7720)
110ac331da0SNobuhiro Iwamatsu # define SCBRR_VALUE(bps, clk) (((clk * 2) + 16 * bps) / (32 * bps) - 1)
111ab09f433SNobuhiro Iwamatsu #elif defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A)
112ab09f433SNobuhiro Iwamatsu /* SH7723 SCIFA use bus clock. So clock *2 */
113ab09f433SNobuhiro Iwamatsu # define SCBRR_VALUE(bps, clk) (((clk * 2 * 2) + 16 * bps) / (32 * bps) - 1)
114ac331da0SNobuhiro Iwamatsu #else /* Generic SuperH */
115ac331da0SNobuhiro Iwamatsu # define SCBRR_VALUE(bps, clk) ((clk + 16 * bps) / (32 * bps) - 1)
11629592ecbSNobuhiro Iwamatsu #endif
11729592ecbSNobuhiro Iwamatsu 
11829592ecbSNobuhiro Iwamatsu #define SCR_RE		(1 << 4)
11929592ecbSNobuhiro Iwamatsu #define SCR_TE		(1 << 5)
12029592ecbSNobuhiro Iwamatsu #define FCR_RFRST	(1 << 1)	/* RFCL */
12129592ecbSNobuhiro Iwamatsu #define FCR_TFRST	(1 << 2)	/* TFCL */
12229592ecbSNobuhiro Iwamatsu #define FSR_DR		(1 << 0)
12329592ecbSNobuhiro Iwamatsu #define FSR_RDF		(1 << 1)
12429592ecbSNobuhiro Iwamatsu #define FSR_FER		(1 << 3)
12529592ecbSNobuhiro Iwamatsu #define FSR_BRK		(1 << 4)
12629592ecbSNobuhiro Iwamatsu #define FSR_FER		(1 << 3)
12729592ecbSNobuhiro Iwamatsu #define FSR_TEND	(1 << 6)
12829592ecbSNobuhiro Iwamatsu #define FSR_ER		(1 << 7)
12929592ecbSNobuhiro Iwamatsu 
13029592ecbSNobuhiro Iwamatsu /*----------------------------------------------------------------------*/
13129592ecbSNobuhiro Iwamatsu 
13229592ecbSNobuhiro Iwamatsu void serial_setbrg(void)
13329592ecbSNobuhiro Iwamatsu {
13429592ecbSNobuhiro Iwamatsu 	DECLARE_GLOBAL_DATA_PTR;
1359e1fa628SJean-Christophe PLAGNIOL-VILLARD 
136*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writeb(SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ), SCBRR);
13729592ecbSNobuhiro Iwamatsu }
13829592ecbSNobuhiro Iwamatsu 
13929592ecbSNobuhiro Iwamatsu int serial_init(void)
14029592ecbSNobuhiro Iwamatsu {
141*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writew((SCR_RE | SCR_TE), SCSCR);
142*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writew(0, SCSMR);
143*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writew(0, SCSMR);
144*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writew((FCR_RFRST | FCR_TFRST), SCFCR);
145*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	readw(SCFCR);
146*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writew(0, SCFCR);
14729592ecbSNobuhiro Iwamatsu 
14829592ecbSNobuhiro Iwamatsu 	serial_setbrg();
14929592ecbSNobuhiro Iwamatsu 	return 0;
15029592ecbSNobuhiro Iwamatsu }
15129592ecbSNobuhiro Iwamatsu 
15229592ecbSNobuhiro Iwamatsu static int serial_rx_fifo_level(void)
15329592ecbSNobuhiro Iwamatsu {
15408c5fabeSNobuhiro Iwamatsu #if defined(SCRFDR)
155*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	return (readw(SCRFDR) >> 0) & FIFOLEVEL_MASK;
1563ecff1d7SNobuhiro Iwamatsu #else
157*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	return (readw(SCFDR) >> 0) & FIFOLEVEL_MASK;
1583ecff1d7SNobuhiro Iwamatsu #endif
15929592ecbSNobuhiro Iwamatsu }
16029592ecbSNobuhiro Iwamatsu 
16129592ecbSNobuhiro Iwamatsu void serial_raw_putc(const char c)
16229592ecbSNobuhiro Iwamatsu {
16329592ecbSNobuhiro Iwamatsu 	unsigned int fsr_bits_to_clear;
16429592ecbSNobuhiro Iwamatsu 
16529592ecbSNobuhiro Iwamatsu 	while (1) {
166*fc83c927SJean-Christophe PLAGNIOL-VILLARD 		if (readw(SCFSR) & FSR_TEND) { /* Tx fifo is empty */
16729592ecbSNobuhiro Iwamatsu 			fsr_bits_to_clear = FSR_TEND;
16829592ecbSNobuhiro Iwamatsu 			break;
16929592ecbSNobuhiro Iwamatsu 		}
17029592ecbSNobuhiro Iwamatsu 	}
17129592ecbSNobuhiro Iwamatsu 
172*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writeb(c, SCFTDR);
17329592ecbSNobuhiro Iwamatsu 	if (fsr_bits_to_clear != 0)
174*fc83c927SJean-Christophe PLAGNIOL-VILLARD 		writew(readw(SCFSR) & ~fsr_bits_to_clear, SCFSR);
17529592ecbSNobuhiro Iwamatsu }
17629592ecbSNobuhiro Iwamatsu 
17729592ecbSNobuhiro Iwamatsu void serial_putc(const char c)
17829592ecbSNobuhiro Iwamatsu {
17929592ecbSNobuhiro Iwamatsu 	if (c == '\n')
18029592ecbSNobuhiro Iwamatsu 		serial_raw_putc('\r');
18129592ecbSNobuhiro Iwamatsu 	serial_raw_putc(c);
18229592ecbSNobuhiro Iwamatsu }
18329592ecbSNobuhiro Iwamatsu 
18429592ecbSNobuhiro Iwamatsu void serial_puts(const char *s)
18529592ecbSNobuhiro Iwamatsu {
18629592ecbSNobuhiro Iwamatsu 	char c;
18729592ecbSNobuhiro Iwamatsu 	while ((c = *s++) != 0)
18829592ecbSNobuhiro Iwamatsu 		serial_putc(c);
18929592ecbSNobuhiro Iwamatsu }
19029592ecbSNobuhiro Iwamatsu 
19129592ecbSNobuhiro Iwamatsu int serial_tstc(void)
19229592ecbSNobuhiro Iwamatsu {
19329592ecbSNobuhiro Iwamatsu 	return serial_rx_fifo_level() ? 1 : 0;
19429592ecbSNobuhiro Iwamatsu }
19529592ecbSNobuhiro Iwamatsu 
19629592ecbSNobuhiro Iwamatsu #define FSR_ERR_CLEAR	0x0063
19729592ecbSNobuhiro Iwamatsu #define RDRF_CLEAR		0x00fc
19808c5fabeSNobuhiro Iwamatsu void handle_error(void)
19908c5fabeSNobuhiro Iwamatsu {
200*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	readw(SCFSR);
201*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writew(FSR_ERR_CLEAR, SCFSR);
202*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	readw(SCLSR);
203*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writew(0x00, SCLSR);
20429592ecbSNobuhiro Iwamatsu }
20529592ecbSNobuhiro Iwamatsu 
20608c5fabeSNobuhiro Iwamatsu int serial_getc_check(void)
20708c5fabeSNobuhiro Iwamatsu {
20829592ecbSNobuhiro Iwamatsu 	unsigned short status;
20929592ecbSNobuhiro Iwamatsu 
210*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	status = readw(SCFSR);
21129592ecbSNobuhiro Iwamatsu 
21208c5fabeSNobuhiro Iwamatsu 	if (status & (FSR_FER | FSR_ER | FSR_BRK))
21329592ecbSNobuhiro Iwamatsu 		handle_error();
214*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	if (readw(SCLSR) & LSR_ORER)
21529592ecbSNobuhiro Iwamatsu 		handle_error();
216ab09f433SNobuhiro Iwamatsu 	return status & (FSR_DR | FSR_RDF);
21729592ecbSNobuhiro Iwamatsu }
21829592ecbSNobuhiro Iwamatsu 
21929592ecbSNobuhiro Iwamatsu int serial_getc(void)
22029592ecbSNobuhiro Iwamatsu {
22129592ecbSNobuhiro Iwamatsu 	unsigned short status;
22229592ecbSNobuhiro Iwamatsu 	char ch;
223ab09f433SNobuhiro Iwamatsu 
224ab09f433SNobuhiro Iwamatsu 	while (!serial_getc_check())
225ab09f433SNobuhiro Iwamatsu 		;
22629592ecbSNobuhiro Iwamatsu 
227*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	ch = readb(SCFRDR);
228*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	status = readw(SCFSR);
22929592ecbSNobuhiro Iwamatsu 
230*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	writew(RDRF_CLEAR, SCFSR);
23129592ecbSNobuhiro Iwamatsu 
23229592ecbSNobuhiro Iwamatsu 	if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK))
23329592ecbSNobuhiro Iwamatsu 		handle_error();
23429592ecbSNobuhiro Iwamatsu 
235*fc83c927SJean-Christophe PLAGNIOL-VILLARD 	if (readw(SCLSR) & LSR_ORER)
23629592ecbSNobuhiro Iwamatsu 		handle_error();
23729592ecbSNobuhiro Iwamatsu 
23829592ecbSNobuhiro Iwamatsu 	return ch;
23929592ecbSNobuhiro Iwamatsu }
240