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