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