xref: /openbmc/linux/arch/arm/include/debug/tegra.S (revision d0b73b48)
1/*
2 * Copyright (C) 2010,2011 Google, Inc.
3 * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
4 *
5 * Author:
6 *	Colin Cross <ccross@google.com>
7 *	Erik Gilling <konkers@google.com>
8 *	Doug Anderson <dianders@chromium.org>
9 *	Stephen Warren <swarren@nvidia.com>
10 *
11 * Portions based on mach-omap2's debug-macro.S
12 * Copyright (C) 1994-1999 Russell King
13 *
14 * This software is licensed under the terms of the GNU General Public
15 * License version 2, as published by the Free Software Foundation, and
16 * may be copied, distributed, and modified under those terms.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 */
24
25#include <linux/serial_reg.h>
26
27#define UART_SHIFT 2
28
29/* Physical addresses */
30#define TEGRA_CLK_RESET_BASE		0x60006000
31#define TEGRA_APB_MISC_BASE		0x70000000
32#define TEGRA_UARTA_BASE		0x70006000
33#define TEGRA_UARTB_BASE		0x70006040
34#define TEGRA_UARTC_BASE		0x70006200
35#define TEGRA_UARTD_BASE		0x70006300
36#define TEGRA_UARTE_BASE		0x70006400
37#define TEGRA_PMC_BASE			0x7000e400
38
39#define TEGRA_CLK_RST_DEVICES_L		(TEGRA_CLK_RESET_BASE + 0x04)
40#define TEGRA_CLK_RST_DEVICES_H		(TEGRA_CLK_RESET_BASE + 0x08)
41#define TEGRA_CLK_RST_DEVICES_U		(TEGRA_CLK_RESET_BASE + 0x0c)
42#define TEGRA_CLK_OUT_ENB_L		(TEGRA_CLK_RESET_BASE + 0x10)
43#define TEGRA_CLK_OUT_ENB_H		(TEGRA_CLK_RESET_BASE + 0x14)
44#define TEGRA_CLK_OUT_ENB_U		(TEGRA_CLK_RESET_BASE + 0x18)
45#define TEGRA_PMC_SCRATCH20		(TEGRA_PMC_BASE + 0xa0)
46#define TEGRA_APB_MISC_GP_HIDREV	(TEGRA_APB_MISC_BASE + 0x804)
47
48/*
49 * Must be 1MB-aligned since a 1MB mapping is used early on.
50 * Must not overlap with regions in mach-tegra/io.c:tegra_io_desc[].
51 */
52#define UART_VIRTUAL_BASE		0xfe100000
53
54#define checkuart(rp, rv, lhu, bit, uart) \
55		/* Load address of CLK_RST register */ \
56		movw	rp, #TEGRA_CLK_RST_DEVICES_##lhu & 0xffff ; \
57		movt	rp, #TEGRA_CLK_RST_DEVICES_##lhu >> 16 ; \
58		/* Load value from CLK_RST register */ \
59		ldr	rp, [rp, #0] ; \
60		/* Test UART's reset bit */ \
61		tst	rp, #(1 << bit) ; \
62		/* If set, can't use UART; jump to save no UART */ \
63		bne	90f ; \
64		/* Load address of CLK_OUT_ENB register */ \
65		movw	rp, #TEGRA_CLK_OUT_ENB_##lhu & 0xffff ; \
66		movt	rp, #TEGRA_CLK_OUT_ENB_##lhu >> 16 ; \
67		/* Load value from CLK_OUT_ENB register */ \
68		ldr	rp, [rp, #0] ; \
69		/* Test UART's clock enable bit */ \
70		tst	rp, #(1 << bit) ; \
71		/* If clear, can't use UART; jump to save no UART */ \
72		beq	90f ; \
73		/* Passed all tests, load address of UART registers */ \
74		movw	rp, #TEGRA_UART##uart##_BASE & 0xffff ; \
75		movt	rp, #TEGRA_UART##uart##_BASE >> 16 ; \
76		/* Jump to save UART address */ \
77		b 91f
78
79		.macro  addruart, rp, rv, tmp
80		adr	\rp, 99f		@ actual addr of 99f
81		ldr	\rv, [\rp]		@ linked addr is stored there
82		sub	\rv, \rv, \rp		@ offset between the two
83		ldr	\rp, [\rp, #4]		@ linked tegra_uart_config
84		sub	\tmp, \rp, \rv		@ actual tegra_uart_config
85		ldr	\rp, [\tmp]		@ Load tegra_uart_config
86		cmp	\rp, #1			@ needs initialization?
87		bne	100f			@ no; go load the addresses
88		mov	\rv, #0			@ yes; record init is done
89		str	\rv, [\tmp]
90
91#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
92		/* Check ODMDATA */
9310:		movw	\rp, #TEGRA_PMC_SCRATCH20 & 0xffff
94		movt	\rp, #TEGRA_PMC_SCRATCH20 >> 16
95		ldr	\rp, [\rp, #0]		@ Load PMC_SCRATCH20
96		ubfx	\rv, \rp, #18, #2	@ 19:18 are console type
97		cmp	\rv, #2			@ 2 and 3 mean DCC, UART
98		beq	11f			@ some boards swap the meaning
99		cmp	\rv, #3			@ so accept either
100		bne	90f
10111:		ubfx	\rv, \rp, #15, #3	@ 17:15 are UART ID
102		cmp	\rv, #0			@ UART 0?
103		beq	20f
104		cmp	\rv, #1			@ UART 1?
105		beq	21f
106		cmp	\rv, #2			@ UART 2?
107		beq	22f
108		cmp	\rv, #3			@ UART 3?
109		beq	23f
110		cmp	\rv, #4			@ UART 4?
111		beq	24f
112		b	90f			@ invalid
113#endif
114
115#if defined(CONFIG_TEGRA_DEBUG_UARTA) || \
116    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
117		/* Check UART A validity */
11820:		checkuart(\rp, \rv, L, 6, A)
119#endif
120
121#if defined(CONFIG_TEGRA_DEBUG_UARTB) || \
122    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
123		/* Check UART B validity */
12421:		checkuart(\rp, \rv, L, 7, B)
125#endif
126
127#if defined(CONFIG_TEGRA_DEBUG_UARTC) || \
128    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
129		/* Check UART C validity */
13022:		checkuart(\rp, \rv, H, 23, C)
131#endif
132
133#if defined(CONFIG_TEGRA_DEBUG_UARTD) || \
134    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
135		/* Check UART D validity */
13623:		checkuart(\rp, \rv, U, 1, D)
137#endif
138
139#if defined(CONFIG_TEGRA_DEBUG_UARTE) || \
140    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
141		/* Check UART E validity */
14224:
143		checkuart(\rp, \rv, U, 2, E)
144#endif
145
146		/* No valid UART found */
14790:		mov	\rp, #0
148		/* fall through */
149
150		/* Record whichever UART we chose */
15191:		str	\rp, [\tmp, #4]		@ Store in tegra_uart_phys
152		cmp	\rp, #0			@ Valid UART address?
153		bne	92f			@ Yes, go process it
154		str	\rp, [\tmp, #8]		@ Store 0 in tegra_uart_virt
155		b	100f			@ Done
15692:		and	\rv, \rp, #0xffffff	@ offset within 1MB section
157		add	\rv, \rv, #UART_VIRTUAL_BASE
158		str	\rv, [\tmp, #8]		@ Store in tegra_uart_virt
159		movw	\rv, #TEGRA_APB_MISC_GP_HIDREV & 0xffff
160		movt	\rv, #TEGRA_APB_MISC_GP_HIDREV >> 16
161		ldr	\rv, [\rv, #0]		@ Load HIDREV
162		ubfx	\rv, \rv, #8, #8	@ 15:8 are SoC version
163		cmp	\rv, #0x20		@ Tegra20?
164		moveq	\rv, #0x75		@ Tegra20 divisor
165		movne	\rv, #0xdd		@ Tegra30 divisor
166		str	\rv, [\tmp, #12]	@ Save divisor to scratch
167		/* uart[UART_LCR] = UART_LCR_WLEN8 | UART_LCR_DLAB; */
168		mov	\rv, #UART_LCR_WLEN8 | UART_LCR_DLAB
169		str	\rv, [\rp, #UART_LCR << UART_SHIFT]
170		/* uart[UART_DLL] = div & 0xff; */
171		ldr	\rv, [\tmp, #12]
172		and	\rv, \rv, #0xff
173		str	\rv, [\rp, #UART_DLL << UART_SHIFT]
174		/* uart[UART_DLM] = div >> 8; */
175		ldr	\rv, [\tmp, #12]
176		lsr	\rv, \rv, #8
177		str	\rv, [\rp, #UART_DLM << UART_SHIFT]
178		/* uart[UART_LCR] = UART_LCR_WLEN8; */
179		mov	\rv, #UART_LCR_WLEN8
180		str	\rv, [\rp, #UART_LCR << UART_SHIFT]
181		b	100f
182
183		.align
18499:		.word	.
185		.word	tegra_uart_config
186		.ltorg
187
188		/* Load previously selected UART address */
189100:		ldr	\rp, [\tmp, #4]		@ Load tegra_uart_phys
190		ldr	\rv, [\tmp, #8]		@ Load tegra_uart_virt
191		.endm
192
193/*
194 * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
195 * check to make sure that the UART address is actually valid.
196 */
197
198		.macro	senduart, rd, rx
199		cmp	\rx, #0
200		strneb	\rd, [\rx, #UART_TX << UART_SHIFT]
2011001:
202		.endm
203
204		.macro	busyuart, rd, rx
205		cmp	\rx, #0
206		beq	1002f
2071001:		ldrb	\rd, [\rx, #UART_LSR << UART_SHIFT]
208		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
209		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
210		bne	1001b
2111002:
212		.endm
213
214		.macro	waituart, rd, rx
215#ifdef FLOW_CONTROL
216		cmp	\rx, #0
217		beq	1002f
2181001:		ldrb	\rd, [\rx, #UART_MSR << UART_SHIFT]
219		tst	\rd, #UART_MSR_CTS
220		beq	1001b
2211002:
222#endif
223		.endm
224