scif.S 8 KB
Newer Older
1
/*
2
 * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
3
4
5
6
7
8
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <arch.h>
#include <asm_macros.S>
9
10
#include <console_macros.S>
#include <drivers/renesas/rcar/console/console.h>
11

12
13
14
#define SCIF_INTERNAL_CLK	0
#define SCIF_EXTARNAL_CLK	1
#define SCIF_CLK		SCIF_INTERNAL_CLK
15
16

/* product register */
17
18
19
20
21
22
#define PRR			(0xFFF00044)
#define PRR_PRODUCT_MASK	(0x00007F00)
#define PRR_CUT_MASK		(0x000000FF)
#define PRR_PRODUCT_H3_VER_10	(0x00004F00)
#define PRR_PRODUCT_E3		(0x00005700)
#define PRR_PRODUCT_D3		(0x00005800)
23
24

/* module stop */
25
26
27
#define CPG_BASE		(0xE6150000)
#define CPG_SMSTPCR2		(0x0138)
#define CPG_SMSTPCR3		(0x013C)
28
#define CPG_MSTPSR2		(0x0040)
29
30
31
32
#define CPG_MSTPSR3		(0x0048)
#define MSTP207			(1 << 7)
#define MSTP310			(1 << 10)
#define CPG_CPGWPR		(0x0900)
33
34

/* scif */
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#define SCIF0_BASE		(0xE6E60000)
#define SCIF2_BASE		(0xE6E88000)
#define SCIF_SCSMR		(0x00)
#define SCIF_SCBRR		(0x04)
#define SCIF_SCSCR		(0x08)
#define SCIF_SCFTDR		(0x0C)
#define SCIF_SCFSR		(0x10)
#define SCIF_SCFRDR		(0x14)
#define SCIF_SCFCR		(0x18)
#define SCIF_SCFDR		(0x1C)
#define SCIF_SCSPTR		(0x20)
#define SCIF_SCLSR		(0x24)
#define SCIF_DL			(0x30)
#define SCIF_CKS		(0x34)
49

50
51
52
53
54
55
56
57
58
59
60
61
#if RCAR_LSI == RCAR_V3M
#define SCIF_BASE		SCIF0_BASE
#define CPG_SMSTPCR		CPG_SMSTPCR2
#define CPG_MSTPSR		CPG_MSTPSR2
#define MSTP			MSTP207
#else
#define SCIF_BASE		SCIF2_BASE
#define CPG_SMSTPCR		CPG_SMSTPCR3
#define CPG_MSTPSR		CPG_MSTPSR3
#define MSTP			MSTP310
#endif

62
/* mode pin */
63
64
#define RST_MODEMR		(0xE6160060)
#define MODEMR_MD12		(0x00001000)
65

66
67
68
69
70
71
72
73
74
75
76
#define SCSMR_CA_MASK		(1 << 7)
#define SCSMR_CA_ASYNC		(0x0000)
#define SCSMR_CHR_MASK		(1 << 6)
#define SCSMR_CHR_8		(0x0000)
#define SCSMR_PE_MASK		(1 << 5)
#define SCSMR_PE_DIS		(0x0000)
#define SCSMR_STOP_MASK		(1 << 3)
#define SCSMR_STOP_1		(0x0000)
#define SCSMR_CKS_MASK		(3 << 0)
#define SCSMR_CKS_DIV1		(0x0000)
#define SCSMR_INIT_DATA		(SCSMR_CA_ASYNC +	\
77
78
79
80
					 SCSMR_CHR_8 +		\
					 SCSMR_PE_DIS +		\
					 SCSMR_STOP_1 +		\
					 SCSMR_CKS_DIV1)
81
82
83
84
#define SCBRR_115200BPS		(17)
#define SCBRR_115200BPSON	(16)
#define SCBRR_115200BPS_E3_SSCG	(15)
#define SCBRR_230400BPS		(8)
85

86
87
88
89
90
91
92
93
94
#define SCSCR_TE_MASK		(1 << 5)
#define SCSCR_TE_DIS		(0x0000)
#define SCSCR_TE_EN		(0x0020)
#define SCSCR_RE_MASK		(1 << 4)
#define SCSCR_RE_DIS		(0x0000)
#define SCSCR_RE_EN		(0x0010)
#define SCSCR_CKE_MASK		(3 << 0)
#define SCSCR_CKE_INT		(0x0000)
#define SCSCR_CKE_BRG		(0x0002)
95
#if SCIF_CLK == SCIF_EXTARNAL_CLK
96
#define SCSCR_CKE_INT_CLK	(SCSCR_CKE_BRG)
97
#else
98
99
100
#define SCFSR_TEND_MASK		(1 << 6)
#define SCFSR_TEND_TRANS_END	(0x0040)
#define SCSCR_CKE_INT_CLK	(SCSCR_CKE_INT)
101
#endif
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#define SCFSR_INIT_DATA		(0x0000)
#define SCFCR_TTRG_MASK		(3 << 4)
#define SCFCR_TTRG_8		(0x0000)
#define SCFCR_TTRG_0		(0x0030)
#define SCFCR_TFRST_MASK	(1 << 2)
#define SCFCR_TFRST_DIS		(0x0000)
#define SCFCR_TFRST_EN		(0x0004)
#define SCFCR_RFRS_MASK		(1 << 1)
#define SCFCR_RFRS_DIS		(0x0000)
#define SCFCR_RFRS_EN		(0x0002)
#define SCFCR_INIT_DATA		(SCFCR_TTRG_8)
#define SCFDR_T_MASK		(0x1f << 8)
#define DL_INIT_DATA		(8)
#define CKS_CKS_DIV_MASK	(1 << 15)
#define CKS_CKS_DIV_CLK		(0x0000)
#define CKS_XIN_MASK		(1 << 14)
#define CKS_XIN_SCIF_CLK	(0x0000)
#define CKS_INIT_DATA		(CKS_CKS_DIV_CLK + CKS_XIN_SCIF_CLK)
120

121
122
123
124
	.globl	console_rcar_register
	.globl	console_rcar_init
	.globl	console_rcar_putc
	.globl	console_rcar_flush
125

126
127
	/*
	 * -----------------------------------------------
128
129
	 * int console_rcar_register(
	 *      uintptr_t base, uint32_t clk, uint32_t baud,
130
	 *      console_t *console)
131
132
133
134
135
	 * Function to initialize and register a new rcar
	 * console. Storage passed in for the console struct
	 * *must* be persistent (i.e. not from the stack).
	 * In: x0 - UART register base address
	 *     w1 - UART clock in Hz
136
	 *     w2 - Baud rate
137
	 *     x3 - pointer to empty console_t struct
138
139
	 * Out: return 1 on success, 0 on error
	 * Clobber list : x0, x1, x2, x6, x7, x14
140
141
	 * -----------------------------------------------
	 */
142
143
144
145
func console_rcar_register
	mov	x7, x30
	mov	x6, x3
	cbz	x6, register_fail
146
	str	x0, [x6, #CONSOLE_T_BASE]
147

148
149
150
151
152
153
154
155
156
	bl	console_rcar_init

	mov	x0, x6
	mov	x30, x7
	finish_console_register rcar, putc=1, getc=0, flush=1

register_fail:
	ret	x7
endfunc console_rcar_register
157

158
	/*
159
	 * int console_rcar_init(unsigned long base_addr,
160
161
162
	 * unsigned int uart_clk, unsigned int baud_rate)
	 * Function to initialize the console without a
	 * C Runtime to print debug information. This
163
164
	 * function will be accessed by console_rcar_register
	 * and crash reporting.
165
166
167
168
169
170
	 * In: x0 - console base address
	 *     w1 - Uart clock in Hz
	 *     w2 - Baud rate
	 * Out: return 1 on success
	 * Clobber list : x1, x2
	 */
171
func console_rcar_init
172
	ldr	x0, =CPG_BASE
173
174
	ldr	w1, [x0, #CPG_SMSTPCR]
	and	w1, w1, #~MSTP
175
176
	mvn	w2, w1
	str	w2, [x0, #CPG_CPGWPR]
177
	str	w1, [x0, #CPG_SMSTPCR]
178
5:
179
180
	ldr w1, [x0, #CPG_MSTPSR]
	and w1, w1, #MSTP
181
182
	cbnz w1, 5b

183
	ldr	x0, =SCIF_BASE
184
185
186
187
188
189
190
	/* Clear bits TE and RE in SCSCR to 0 */
	mov	w1, #(SCSCR_TE_DIS + SCSCR_RE_DIS)
	strh	w1, [x0, #SCIF_SCSCR]
	/* Set bits TFRST and RFRST in SCFCR to 1 */
	ldrh	w1, [x0, #SCIF_SCFCR]
	orr	w1, w1, #(SCFCR_TFRST_EN + SCFCR_RFRS_EN)
	strh	w1, [x0, #SCIF_SCFCR]
191
192
193
194
	/*
	 * Read flags of ER, DR, BRK, and RDF in SCFSR and those of TO and ORER
	 * in SCLSR, then clear them to 0
	 */
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
	mov	w1, #SCFSR_INIT_DATA
	strh	w1, [x0, #SCIF_SCFSR]
	mov	w1, #0
	strh	w1, [x0, #SCIF_SCLSR]
	/* Set bits CKE[1:0] in SCSCR */
	ldrh	w1, [x0, #SCIF_SCSCR]
	and	w1, w1, #~SCSCR_CKE_MASK
	mov	w2, #SCSCR_CKE_INT_CLK
	orr	w1, w1, w2
	strh	w1, [x0, #SCIF_SCSCR]
	/* Set data transfer format in SCSMR */
	mov	w1, #SCSMR_INIT_DATA
	strh	w1, [x0, #SCIF_SCSMR]
	/* Set value in SCBRR */
#if SCIF_CLK == SCIF_INTERNAL_CLK
	ldr	x1, =PRR
	ldr	w1, [x1]
	and	w1, w1, #(PRR_PRODUCT_MASK | PRR_CUT_MASK)
	mov	w2, #PRR_PRODUCT_H3_VER_10
	cmp	w1, w2
	beq	3f
	and	w1, w1, #PRR_PRODUCT_MASK
217
218
219
220
	mov	w2, #PRR_PRODUCT_D3
	cmp	w1, w2
	beq	4f
	and	w1, w1, #PRR_PRODUCT_MASK
221
222
	mov	w2, #PRR_PRODUCT_E3
	cmp	w1, w2
223
	bne	5f
224
225
226
227
228
229

	ldr	x1, =RST_MODEMR
	ldr	w1, [x1]
	and	w1, w1, #MODEMR_MD12
	mov	w2, #MODEMR_MD12
	cmp	w1, w2
230
	bne	5f
231
232
233

	mov	w1, #SCBRR_115200BPS_E3_SSCG
	b	2f
234
5:
235
236
	mov	w1, #SCBRR_115200BPS
	b	2f
237
238
239
4:
	mov	w1, #SCBRR_115200BPSON
	b	2f
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
3:
	mov	w1, #SCBRR_230400BPS
2:
	strb	w1, [x0, SCIF_SCBRR]
#else
	mov	w1, #DL_INIT_DATA
	strh	w1, [x0, #SCIF_DL]
	mov	w1, #CKS_INIT_DATA
	strh	w1, [x0, #SCIF_CKS]
#endif
	/* 1-bit interval elapsed */
	mov	w1, #100
1:
	subs	w1, w1, #1
	cbnz	w1, 1b
	/*
	 * Set bits RTRG[1:0], TTRG[1:0], and MCE in SCFCR
	 * Clear bits FRST and RFRST to 0
	 */
	mov	w1, #SCFCR_INIT_DATA
	strh	w1, [x0, #SCIF_SCFCR]
	/* Set bits TE and RE in SCSCR to 1 */
	ldrh	w1, [x0, #SCIF_SCSCR]
	orr	w1, w1, #(SCSCR_TE_EN + SCSCR_RE_EN)
	strh	w1, [x0, #SCIF_SCSCR]
	mov	x0, #1

	ret
268
endfunc console_rcar_init
269

270
	/*
271
	 * int console_rcar_putc(int c, unsigned int base_addr)
272
273
274
	 * Function to output a character over the console. It
	 * returns the character printed on success or -1 on error.
	 * In : w0 - character to be printed
275
	 *      x1 - pointer to console_t structure
276
277
278
	 * Out : return -1 on error else return character.
	 * Clobber list : x2
	 */
279
func console_rcar_putc
280
	ldr	x1, =SCIF_BASE
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
	cmp	w0, #0xA
	/* Prepend '\r' to '\n' */
	bne	2f
1:
	/* Check if the transmit FIFO is full */
	ldrh	w2, [x1, #SCIF_SCFDR]
	ubfx	w2, w2, #8, #5
	cmp	w2, #16
	bcs	1b
	mov	w2, #0x0D
	strb	w2, [x1, #SCIF_SCFTDR]
2:
	/* Check if the transmit FIFO is full */
	ldrh	w2, [x1, #SCIF_SCFDR]
	ubfx	w2, w2, #8, #5
	cmp	w2, #16
	bcs	2b
	strb	w0, [x1, #SCIF_SCFTDR]

300
301
302
303
304
	/* Clear TEND flag */
	ldrh	w2, [x1, #SCIF_SCFSR]
	and	w2, w2, #~SCFSR_TEND_MASK
	strh	w2, [x1, #SCIF_SCFSR]

305
	ret
306
endfunc console_rcar_putc
307

308
	/*
309
	 * void console_rcar_flush(void)
310
	 * Function to force a write of all buffered
311
	 * data that hasn't been output. It returns void
312
313
	 * Clobber list : x0, x1
	 */
314
func console_rcar_flush
315
	ldr	x0, =SCIF_BASE
316
1:
317
318
319
320
	/* Check TEND flag */
	ldrh	w1, [x0, #SCIF_SCFSR]
	and	w1, w1, #SCFSR_TEND_MASK
	cmp	w1, #SCFSR_TEND_TRANS_END
321
322
	bne	1b

323
	ldr	x0, =SCIF_BASE
324
325
326
327
328
	ldrh	w1, [x0, #SCIF_SCSCR]
	and	w1, w1, #~(SCSCR_TE_EN + SCSCR_RE_EN)
	strh	w1, [x0, #SCIF_SCSCR]

	ret
329
endfunc console_rcar_flush