1/* 2 * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. 3 * Copyright (c) 2025, Arm Limited. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8#include <arch.h> 9#include <asm_macros.S> 10#include <console_macros.S> 11#include <drivers/renesas/rcar/console/console.h> 12#include <platform_def.h> 13 14#define SCIF_INTERNAL_CLK 0 15#define SCIF_EXTARNAL_CLK 1 16#define SCIF_CLK SCIF_INTERNAL_CLK 17 18#define PRR_PRODUCT_H3_VER_10 (0x00004F00) 19 20/* module stop */ 21#define CPG_BASE (0xE6150000) 22#define CPG_SMSTPCR2 (0x0138) 23#define CPG_SMSTPCR3 (0x013C) 24#define CPG_MSTPSR2 (0x0040) 25#define CPG_MSTPSR3 (0x0048) 26#define MSTP207 (1 << 7) 27#define MSTP310 (1 << 10) 28#define CPG_CPGWPR (0x0900) 29 30/* scif */ 31#define SCIF0_BASE (0xE6E60000) 32#define SCIF2_BASE (0xE6E88000) 33#define SCIF_SCSMR (0x00) 34#define SCIF_SCBRR (0x04) 35#define SCIF_SCSCR (0x08) 36#define SCIF_SCFTDR (0x0C) 37#define SCIF_SCFSR (0x10) 38#define SCIF_SCFRDR (0x14) 39#define SCIF_SCFCR (0x18) 40#define SCIF_SCFDR (0x1C) 41#define SCIF_SCSPTR (0x20) 42#define SCIF_SCLSR (0x24) 43#define SCIF_DL (0x30) 44#define SCIF_CKS (0x34) 45 46#if RCAR_LSI == RCAR_V3M 47#define SCIF_BASE SCIF0_BASE 48#define CPG_SMSTPCR CPG_SMSTPCR2 49#define CPG_MSTPSR CPG_MSTPSR2 50#define MSTP MSTP207 51#else 52#define SCIF_BASE SCIF2_BASE 53#define CPG_SMSTPCR CPG_SMSTPCR3 54#define CPG_MSTPSR CPG_MSTPSR3 55#define MSTP MSTP310 56#endif 57 58/* mode pin */ 59#define MODEMR_MD12 (0x00001000) 60 61#define SCSMR_CA_MASK (1 << 7) 62#define SCSMR_CA_ASYNC (0x0000) 63#define SCSMR_CHR_MASK (1 << 6) 64#define SCSMR_CHR_8 (0x0000) 65#define SCSMR_PE_MASK (1 << 5) 66#define SCSMR_PE_DIS (0x0000) 67#define SCSMR_STOP_MASK (1 << 3) 68#define SCSMR_STOP_1 (0x0000) 69#define SCSMR_CKS_MASK (3 << 0) 70#define SCSMR_CKS_DIV1 (0x0000) 71#define SCSMR_INIT_DATA (SCSMR_CA_ASYNC + \ 72 SCSMR_CHR_8 + \ 73 SCSMR_PE_DIS + \ 74 SCSMR_STOP_1 + \ 75 SCSMR_CKS_DIV1) 76#define SCBRR_115200BPS (17) 77#define SCBRR_115200BPS_D3_SSCG (16) 78#define SCBRR_115200BPS_E3_SSCG (15) 79#define SCBRR_230400BPS (8) 80 81#define SCSCR_TE_MASK (1 << 5) 82#define SCSCR_TE_DIS (0x0000) 83#define SCSCR_TE_EN (0x0020) 84#define SCSCR_RE_MASK (1 << 4) 85#define SCSCR_RE_DIS (0x0000) 86#define SCSCR_RE_EN (0x0010) 87#define SCSCR_CKE_MASK (3 << 0) 88#define SCSCR_CKE_INT (0x0000) 89#define SCSCR_CKE_BRG (0x0002) 90#if SCIF_CLK == SCIF_EXTARNAL_CLK 91#define SCSCR_CKE_INT_CLK (SCSCR_CKE_BRG) 92#else 93#define SCFSR_TEND_MASK (1 << 6) 94#define SCFSR_TEND_TRANS_END (0x0040) 95#define SCSCR_CKE_INT_CLK (SCSCR_CKE_INT) 96#endif 97#define SCFSR_INIT_DATA (0x0000) 98#define SCFCR_TTRG_MASK (3 << 4) 99#define SCFCR_TTRG_8 (0x0000) 100#define SCFCR_TTRG_0 (0x0030) 101#define SCFCR_TFRST_MASK (1 << 2) 102#define SCFCR_TFRST_DIS (0x0000) 103#define SCFCR_TFRST_EN (0x0004) 104#define SCFCR_RFRS_MASK (1 << 1) 105#define SCFCR_RFRS_DIS (0x0000) 106#define SCFCR_RFRS_EN (0x0002) 107#define SCFCR_INIT_DATA (SCFCR_TTRG_8) 108#define SCFDR_T_MASK (0x1f << 8) 109#define DL_INIT_DATA (8) 110#define CKS_CKS_DIV_MASK (1 << 15) 111#define CKS_CKS_DIV_CLK (0x0000) 112#define CKS_XIN_MASK (1 << 14) 113#define CKS_XIN_SCIF_CLK (0x0000) 114#define CKS_INIT_DATA (CKS_CKS_DIV_CLK + CKS_XIN_SCIF_CLK) 115 116 .globl console_rcar_register 117 .globl console_rcar_init 118 .globl console_rcar_putc 119 .globl console_rcar_flush 120 121 /* 122 * ----------------------------------------------- 123 * int console_rcar_register( 124 * uintptr_t base, uint32_t clk, uint32_t baud, 125 * console_t *console) 126 * Function to initialize and register a new rcar 127 * console. Storage passed in for the console struct 128 * *must* be persistent (i.e. not from the stack). 129 * In: x0 - UART register base address 130 * w1 - UART clock in Hz 131 * w2 - Baud rate 132 * x3 - pointer to empty console_t struct 133 * Out: return 1 on success, 0 on error 134 * Clobber list : x0, x1, x2, x6, x7, x14 135 * ----------------------------------------------- 136 */ 137func console_rcar_register 138 mov x7, x30 139 mov x6, x3 140 cbz x6, register_fail 141 str x0, [x6, #CONSOLE_T_BASE] 142 143 bl console_rcar_init 144 145 mov x0, x6 146 mov x30, x7 147 finish_console_register rcar, putc=1, getc=0, flush=1 148 149register_fail: 150 ret x7 151endfunc console_rcar_register 152 153 /* 154 * int console_rcar_init(unsigned long base_addr, 155 * unsigned int uart_clk, unsigned int baud_rate) 156 * Function to initialize the console without a 157 * C Runtime to print debug information. This 158 * function will be accessed by console_rcar_register 159 * and crash reporting. 160 * In: x0 - console base address 161 * w1 - Uart clock in Hz 162 * w2 - Baud rate 163 * Out: return 1 on success 164 * Clobber list : x1, x2 165 */ 166func console_rcar_init 167 ldr x0, =CPG_BASE 168 ldr w1, [x0, #CPG_SMSTPCR] 169 and w1, w1, #~MSTP 170 mvn w2, w1 171 str w2, [x0, #CPG_CPGWPR] 172 str w1, [x0, #CPG_SMSTPCR] 1735: 174 ldr w1, [x0, #CPG_MSTPSR] 175 and w1, w1, #MSTP 176 cbnz w1, 5b 177 178 ldr x0, =SCIF_BASE 179 /* Clear bits TE and RE in SCSCR to 0 */ 180 mov w1, #(SCSCR_TE_DIS + SCSCR_RE_DIS) 181 strh w1, [x0, #SCIF_SCSCR] 182 /* Set bits TFRST and RFRST in SCFCR to 1 */ 183 ldrh w1, [x0, #SCIF_SCFCR] 184 orr w1, w1, #(SCFCR_TFRST_EN + SCFCR_RFRS_EN) 185 strh w1, [x0, #SCIF_SCFCR] 186 /* 187 * Read flags of ER, DR, BRK, and RDF in SCFSR and those of TO and ORER 188 * in SCLSR, then clear them to 0 189 */ 190 mov w1, #SCFSR_INIT_DATA 191 strh w1, [x0, #SCIF_SCFSR] 192 mov w1, #0 193 strh w1, [x0, #SCIF_SCLSR] 194 /* Set bits CKE[1:0] in SCSCR */ 195 ldrh w1, [x0, #SCIF_SCSCR] 196 and w1, w1, #~SCSCR_CKE_MASK 197 mov w2, #SCSCR_CKE_INT_CLK 198 orr w1, w1, w2 199 strh w1, [x0, #SCIF_SCSCR] 200 /* Set data transfer format in SCSMR */ 201 mov w1, #SCSMR_INIT_DATA 202 strh w1, [x0, #SCIF_SCSMR] 203 /* Set value in SCBRR */ 204#if SCIF_CLK == SCIF_INTERNAL_CLK 205 ldr x1, =PRR 206 ldr w1, [x1] 207 and w1, w1, #(PRR_PRODUCT_MASK | PRR_CUT_MASK) 208 mov w2, #PRR_PRODUCT_H3_VER_10 209 cmp w1, w2 210 beq 3f 211 and w1, w1, #PRR_PRODUCT_MASK 212 mov w2, #PRR_PRODUCT_D3 213 cmp w1, w2 214 beq 5f 215 and w1, w1, #PRR_PRODUCT_MASK 216 mov w2, #PRR_PRODUCT_E3 217 cmp w1, w2 218 bne 4f 219 220 /* When SSCG(MD12) on (E3) */ 221 ldr x1, =RST_MODEMR 222 ldr w1, [x1] 223 and w1, w1, #MODEMR_MD12 224 mov w2, #MODEMR_MD12 225 cmp w1, w2 226 bne 4f 227 228 /* When SSCG(MD12) on (E3) */ 229 mov w1, #SCBRR_115200BPS_E3_SSCG 230 b 2f 2315: 232 /* In case of D3 */ 233 ldr x1, =RST_MODEMR 234 ldr w1, [x1] 235 and w1, w1, #MODEMR_MD12 236 mov w2, #MODEMR_MD12 237 cmp w1, w2 238 bne 4f 239 240 /* When SSCG(MD12) on (D3) */ 241 mov w1, #SCBRR_115200BPS_D3_SSCG 242 b 2f 2434: 244 /* In case of H3/M3/M3N or when SSCG(MD12) is off in E3/D3 */ 245 mov w1, #SCBRR_115200BPS 246 b 2f 2473: 248 mov w1, #SCBRR_230400BPS 2492: 250 strb w1, [x0, SCIF_SCBRR] 251#else 252 mov w1, #DL_INIT_DATA 253 strh w1, [x0, #SCIF_DL] 254 mov w1, #CKS_INIT_DATA 255 strh w1, [x0, #SCIF_CKS] 256#endif 257 /* 1-bit interval elapsed */ 258 mov w1, #100 2591: 260 subs w1, w1, #1 261 cbnz w1, 1b 262 /* 263 * Set bits RTRG[1:0], TTRG[1:0], and MCE in SCFCR 264 * Clear bits FRST and RFRST to 0 265 */ 266 mov w1, #SCFCR_INIT_DATA 267 strh w1, [x0, #SCIF_SCFCR] 268 /* Set bits TE and RE in SCSCR to 1 */ 269 ldrh w1, [x0, #SCIF_SCSCR] 270 orr w1, w1, #(SCSCR_TE_EN + SCSCR_RE_EN) 271 strh w1, [x0, #SCIF_SCSCR] 272 mov x0, #1 273 274 ret 275endfunc console_rcar_init 276 277 /* 278 * int console_rcar_putc(int c, unsigned int base_addr) 279 * Function to output a character over the console. It 280 * returns the character printed on success or -1 on error. 281 * In : w0 - character to be printed 282 * x1 - pointer to console_t structure 283 * Out : return -1 on error else return character. 284 * Clobber list : x2 285 */ 286func console_rcar_putc 287 ldr x1, =SCIF_BASE 288 cmp w0, #0xA 289 /* Prepend '\r' to '\n' */ 290 bne 2f 2911: 292 /* Check if the transmit FIFO is full */ 293 ldrh w2, [x1, #SCIF_SCFDR] 294 ubfx w2, w2, #8, #5 295 cmp w2, #16 296 bcs 1b 297 mov w2, #0x0D 298 strb w2, [x1, #SCIF_SCFTDR] 2992: 300 /* Check if the transmit FIFO is full */ 301 ldrh w2, [x1, #SCIF_SCFDR] 302 ubfx w2, w2, #8, #5 303 cmp w2, #16 304 bcs 2b 305 strb w0, [x1, #SCIF_SCFTDR] 306 307 /* Clear TEND flag */ 308 ldrh w2, [x1, #SCIF_SCFSR] 309 and w2, w2, #~SCFSR_TEND_MASK 310 strh w2, [x1, #SCIF_SCFSR] 311 312 ret 313endfunc console_rcar_putc 314 315 /* 316 * void console_rcar_flush(void) 317 * Function to force a write of all buffered 318 * data that hasn't been output. It returns void 319 * Clobber list : x0, x1 320 */ 321func console_rcar_flush 322 ldr x0, =SCIF_BASE 3231: 324 /* Check TEND flag */ 325 ldrh w1, [x0, #SCIF_SCFSR] 326 and w1, w1, #SCFSR_TEND_MASK 327 cmp w1, #SCFSR_TEND_TRANS_END 328 bne 1b 329 330 ldr x0, =SCIF_BASE 331 ldrh w1, [x0, #SCIF_SCSCR] 332 and w1, w1, #~(SCSCR_TE_EN + SCSCR_RE_EN) 333 strh w1, [x0, #SCIF_SCSCR] 334 335 ret 336endfunc console_rcar_flush 337