xref: /rk3399_ARM-atf/drivers/renesas/rcar_gen4/scif/scif.c (revision b45b5bacb95d0e2d4539a7869c1ccf90da041498)
1*b45b5bacSMarek Vasut /*
2*b45b5bacSMarek Vasut  * Copyright (c) 2021-2025, Renesas Electronics Corporation. All rights reserved.
3*b45b5bacSMarek Vasut  *
4*b45b5bacSMarek Vasut  * SPDX-License-Identifier: BSD-3-Clause
5*b45b5bacSMarek Vasut  */
6*b45b5bacSMarek Vasut 
7*b45b5bacSMarek Vasut #include <stddef.h>
8*b45b5bacSMarek Vasut #include <stdint.h>
9*b45b5bacSMarek Vasut 
10*b45b5bacSMarek Vasut #include <drivers/console.h>
11*b45b5bacSMarek Vasut #include <lib/mmio.h>
12*b45b5bacSMarek Vasut #include <lib/utils_def.h>
13*b45b5bacSMarek Vasut #include "scif.h"
14*b45b5bacSMarek Vasut 
15*b45b5bacSMarek Vasut #include "rcar_def.h"
16*b45b5bacSMarek Vasut 
17*b45b5bacSMarek Vasut /* RST */
18*b45b5bacSMarek Vasut #define RST_BASE		(0xE6160000UL + (RCAR_DOMAIN * 0x4000UL))
19*b45b5bacSMarek Vasut #define RST_MODEMR0		RST_BASE
20*b45b5bacSMarek Vasut #define RST_MODEMR1		(RST_BASE + 4UL)
21*b45b5bacSMarek Vasut #define RST_MODEMR0_MD31	BIT(31)
22*b45b5bacSMarek Vasut #define RST_MODEMR1_MD32	BIT(0)
23*b45b5bacSMarek Vasut 
24*b45b5bacSMarek Vasut /* SCIF/HSCIF */
25*b45b5bacSMarek Vasut #define SCIF0_BASE		0xE6E60000UL
26*b45b5bacSMarek Vasut #define SCIF3_BASE		0xE6C50000UL
27*b45b5bacSMarek Vasut #define HSCIF0_BASE		0xE6540000UL
28*b45b5bacSMarek Vasut #define SCIF_SCFSR_TEND		BIT(6)
29*b45b5bacSMarek Vasut #define SCIF_SCFSR_TDFE		BIT(5)
30*b45b5bacSMarek Vasut #define TRANS_END_CHECK		(SCIF_SCFSR_TEND | SCIF_SCFSR_TDFE)
31*b45b5bacSMarek Vasut 
32*b45b5bacSMarek Vasut /* SCIF */
33*b45b5bacSMarek Vasut #if (RCAR_LSI == RCAR_S4) /* S4 */
34*b45b5bacSMarek Vasut #define SCIF_BASE	SCIF3_BASE
35*b45b5bacSMarek Vasut #else
36*b45b5bacSMarek Vasut #define SCIF_BASE	SCIF0_BASE
37*b45b5bacSMarek Vasut #endif
38*b45b5bacSMarek Vasut #define SCIF_SCFTDR	(SCIF_BASE + 0x000CU)	/*  8 Transmit FIFO data register */
39*b45b5bacSMarek Vasut #define SCIF_SCFSR	(SCIF_BASE + 0x0010U)	/* 16 Serial status register */
40*b45b5bacSMarek Vasut 
41*b45b5bacSMarek Vasut /* HSCIF */
42*b45b5bacSMarek Vasut #define HSCIF_BASE	HSCIF0_BASE
43*b45b5bacSMarek Vasut #define HSCIF_HSFTDR	(HSCIF_BASE + 0x000CU) /*  8 Transmit FIFO data register */
44*b45b5bacSMarek Vasut #define HSCIF_HSFSR	(HSCIF_BASE + 0x0010U) /* 16 Serial status register */
45*b45b5bacSMarek Vasut 
46*b45b5bacSMarek Vasut /* Mode */
47*b45b5bacSMarek Vasut #define MODEMR_SCIF_DLMODE		0U
48*b45b5bacSMarek Vasut #define MODEMR_HSCIF_DLMODE_921600	1U
49*b45b5bacSMarek Vasut #define MODEMR_HSCIF_DLMODE_1843200	2U
50*b45b5bacSMarek Vasut #define MODEMR_HSCIF_DLMODE_3000000	3U
51*b45b5bacSMarek Vasut 
52*b45b5bacSMarek Vasut static void (*rcar_putc)(uint8_t outchar);
53*b45b5bacSMarek Vasut 
54*b45b5bacSMarek Vasut static inline void scif_clrbits_16(uintptr_t addr, uint32_t clear)
55*b45b5bacSMarek Vasut {
56*b45b5bacSMarek Vasut 	mmio_write_16(addr, mmio_read_16(addr) & ~clear);
57*b45b5bacSMarek Vasut }
58*b45b5bacSMarek Vasut 
59*b45b5bacSMarek Vasut static void scif_console_trans_end_poll(uint32_t reg)
60*b45b5bacSMarek Vasut {
61*b45b5bacSMarek Vasut 	/* Check that transfer of SCIF is completed */
62*b45b5bacSMarek Vasut 	while ((mmio_read_16(reg) & TRANS_END_CHECK) != TRANS_END_CHECK)
63*b45b5bacSMarek Vasut 		;
64*b45b5bacSMarek Vasut }
65*b45b5bacSMarek Vasut 
66*b45b5bacSMarek Vasut static void scif_console_putc_common(uint32_t fsr, uint32_t tdr, uint8_t chr)
67*b45b5bacSMarek Vasut {
68*b45b5bacSMarek Vasut 	scif_console_trans_end_poll(fsr);
69*b45b5bacSMarek Vasut 	mmio_write_8(tdr, chr);			/* Transfer one character */
70*b45b5bacSMarek Vasut 	scif_clrbits_16(fsr, TRANS_END_CHECK);	/* TEND,TDFE clear */
71*b45b5bacSMarek Vasut 	scif_console_trans_end_poll(fsr);
72*b45b5bacSMarek Vasut }
73*b45b5bacSMarek Vasut 
74*b45b5bacSMarek Vasut static void scif_console_putc(uint8_t outchar)
75*b45b5bacSMarek Vasut {
76*b45b5bacSMarek Vasut 	scif_console_putc_common(SCIF_SCFSR, SCIF_SCFTDR, outchar);
77*b45b5bacSMarek Vasut }
78*b45b5bacSMarek Vasut 
79*b45b5bacSMarek Vasut static void hscif_console_putc(uint8_t outchar)
80*b45b5bacSMarek Vasut {
81*b45b5bacSMarek Vasut 	scif_console_putc_common(HSCIF_HSFSR, HSCIF_HSFTDR, outchar);
82*b45b5bacSMarek Vasut }
83*b45b5bacSMarek Vasut 
84*b45b5bacSMarek Vasut static void scif_console_init(uint32_t modemr)
85*b45b5bacSMarek Vasut {
86*b45b5bacSMarek Vasut 	switch (modemr) {
87*b45b5bacSMarek Vasut 	case MODEMR_HSCIF_DLMODE_3000000:
88*b45b5bacSMarek Vasut 	case MODEMR_HSCIF_DLMODE_1843200:
89*b45b5bacSMarek Vasut 	case MODEMR_HSCIF_DLMODE_921600:
90*b45b5bacSMarek Vasut 		/* Set the pointer to a function that outputs one character. */
91*b45b5bacSMarek Vasut 		rcar_putc = hscif_console_putc;
92*b45b5bacSMarek Vasut 		break;
93*b45b5bacSMarek Vasut 	case MODEMR_SCIF_DLMODE:
94*b45b5bacSMarek Vasut 	default:
95*b45b5bacSMarek Vasut 		/* Set the pointer to a function that outputs one character. */
96*b45b5bacSMarek Vasut 		rcar_putc = scif_console_putc;
97*b45b5bacSMarek Vasut 		break;
98*b45b5bacSMarek Vasut 	}
99*b45b5bacSMarek Vasut }
100*b45b5bacSMarek Vasut 
101*b45b5bacSMarek Vasut int console_rcar_init(uintptr_t base_addr, uint32_t uart_clk,
102*b45b5bacSMarek Vasut 		      uint32_t baud_rate)
103*b45b5bacSMarek Vasut {
104*b45b5bacSMarek Vasut 	uint32_t modemr;
105*b45b5bacSMarek Vasut 
106*b45b5bacSMarek Vasut 	modemr = ((mmio_read_32(RST_MODEMR0) & RST_MODEMR0_MD31) >> 31U) |
107*b45b5bacSMarek Vasut 		 ((mmio_read_32(RST_MODEMR1) & RST_MODEMR1_MD32) << 1U);
108*b45b5bacSMarek Vasut 
109*b45b5bacSMarek Vasut 	scif_console_init(modemr);
110*b45b5bacSMarek Vasut 
111*b45b5bacSMarek Vasut 	return 1;
112*b45b5bacSMarek Vasut }
113*b45b5bacSMarek Vasut 
114*b45b5bacSMarek Vasut int console_rcar_putc(int c, console_t *pconsole)
115*b45b5bacSMarek Vasut {
116*b45b5bacSMarek Vasut 	if (rcar_putc == NULL)
117*b45b5bacSMarek Vasut 		return -1;
118*b45b5bacSMarek Vasut 
119*b45b5bacSMarek Vasut 	if (c == '\n')	/* add 'CR' before 'LF' */
120*b45b5bacSMarek Vasut 		rcar_putc('\r');
121*b45b5bacSMarek Vasut 
122*b45b5bacSMarek Vasut 	rcar_putc(c);
123*b45b5bacSMarek Vasut 
124*b45b5bacSMarek Vasut 	return c;
125*b45b5bacSMarek Vasut }
126*b45b5bacSMarek Vasut 
127*b45b5bacSMarek Vasut int console_rcar_flush(console_t *pconsole)
128*b45b5bacSMarek Vasut {
129*b45b5bacSMarek Vasut 	/* Nothing to do */
130*b45b5bacSMarek Vasut 	return 0;
131*b45b5bacSMarek Vasut }
132