xref: /rk3399_ARM-atf/drivers/renesas/rcar_gen4/scif/scif.c (revision b21216f716e0ad975ed65e70735f82e05d55b5ca)
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 uint32_t rcar_putc_fsr;
53 static uint32_t rcar_putc_tdr;
54 
55 static inline void scif_clrbits_16(uintptr_t addr, uint32_t clear)
56 {
57 	mmio_write_16(addr, mmio_read_16(addr) & ~clear);
58 }
59 
60 static void scif_console_trans_end_poll(uint32_t reg)
61 {
62 	/* Check that transfer of SCIF is completed */
63 	while ((mmio_read_16(reg) & TRANS_END_CHECK) != TRANS_END_CHECK)
64 		;
65 }
66 
67 static void scif_console_putc_common(uint8_t chr)
68 {
69 	scif_console_trans_end_poll(rcar_putc_fsr);
70 	mmio_write_8(rcar_putc_tdr, chr);	/* Transfer one character */
71 	scif_clrbits_16(rcar_putc_fsr, TRANS_END_CHECK); /* TEND,TDFE clear */
72 	scif_console_trans_end_poll(rcar_putc_fsr);
73 }
74 
75 static void scif_console_set_regs(uint32_t fsr, uint32_t tdr)
76 {
77 	rcar_putc_fsr = fsr;
78 	rcar_putc_tdr = tdr;
79 }
80 
81 int console_rcar_init(uintptr_t base_addr, uint32_t uart_clk,
82 		      uint32_t baud_rate)
83 {
84 	uint32_t modemr;
85 
86 	modemr = ((mmio_read_32(RST_MODEMR0) & RST_MODEMR0_MD31) >> 31U) |
87 		 ((mmio_read_32(RST_MODEMR1) & RST_MODEMR1_MD32) << 1U);
88 
89 	if (modemr == MODEMR_HSCIF_DLMODE_3000000 ||
90 	    modemr == MODEMR_HSCIF_DLMODE_1843200 ||
91 	    modemr == MODEMR_HSCIF_DLMODE_921600) {
92 		scif_console_set_regs(HSCIF_HSFSR, HSCIF_HSFTDR);
93 	} else {
94 		scif_console_set_regs(SCIF_SCFSR, SCIF_SCFTDR);
95 	}
96 
97 	return 1;
98 }
99 
100 int console_rcar_putc(int c, console_t *pconsole)
101 {
102 	if (rcar_putc_fsr == 0 || rcar_putc_tdr == 0)
103 		return -1;
104 
105 	if (c == '\n')	/* add 'CR' before 'LF' */
106 		scif_console_putc_common('\r');
107 
108 	scif_console_putc_common(c);
109 
110 	return c;
111 }
112 
113 int console_rcar_flush(console_t *pconsole)
114 {
115 	/* Nothing to do */
116 	return 0;
117 }
118