xref: /rk3399_ARM-atf/drivers/renesas/common/scif/scif.S (revision f05b4894acfb681017bfda71fb16e6079a4f6a43)
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