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