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