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