 9f3ba4567e
			
		
	
	
	9f3ba4567e
	
	
	
		
			
			In a combined ARMv6/v7 kernel, we cannot use the movt/movw instructions to load an immediate, as they are not valid on ARMv6. This changes the file to use an indirect load instead, as lots of other implementations do. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Tested-by: Stephen Warren <swarren@wwwdotorg.org> Acked-by: Stephen Warren <swarren@wwwdotorg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: linux-tegra@vger.kernel.org
		
			
				
	
	
		
			226 lines
		
	
	
	
		
			6.7 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			226 lines
		
	
	
	
		
			6.7 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2010,2011 Google, Inc.
 | |
|  * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
 | |
|  *
 | |
|  * Author:
 | |
|  *	Colin Cross <ccross@google.com>
 | |
|  *	Erik Gilling <konkers@google.com>
 | |
|  *	Doug Anderson <dianders@chromium.org>
 | |
|  *	Stephen Warren <swarren@nvidia.com>
 | |
|  *
 | |
|  * Portions based on mach-omap2's debug-macro.S
 | |
|  * Copyright (C) 1994-1999 Russell King
 | |
|  *
 | |
|  * This software is licensed under the terms of the GNU General Public
 | |
|  * License version 2, as published by the Free Software Foundation, and
 | |
|  * may be copied, distributed, and modified under those terms.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU General Public License for more details.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <linux/serial_reg.h>
 | |
| 
 | |
| #define UART_SHIFT 2
 | |
| 
 | |
| /* Physical addresses */
 | |
| #define TEGRA_CLK_RESET_BASE		0x60006000
 | |
| #define TEGRA_APB_MISC_BASE		0x70000000
 | |
| #define TEGRA_UARTA_BASE		0x70006000
 | |
| #define TEGRA_UARTB_BASE		0x70006040
 | |
| #define TEGRA_UARTC_BASE		0x70006200
 | |
| #define TEGRA_UARTD_BASE		0x70006300
 | |
| #define TEGRA_UARTE_BASE		0x70006400
 | |
| #define TEGRA_PMC_BASE			0x7000e400
 | |
| 
 | |
| #define TEGRA_CLK_RST_DEVICES_L		(TEGRA_CLK_RESET_BASE + 0x04)
 | |
| #define TEGRA_CLK_RST_DEVICES_H		(TEGRA_CLK_RESET_BASE + 0x08)
 | |
| #define TEGRA_CLK_RST_DEVICES_U		(TEGRA_CLK_RESET_BASE + 0x0c)
 | |
| #define TEGRA_CLK_OUT_ENB_L		(TEGRA_CLK_RESET_BASE + 0x10)
 | |
| #define TEGRA_CLK_OUT_ENB_H		(TEGRA_CLK_RESET_BASE + 0x14)
 | |
| #define TEGRA_CLK_OUT_ENB_U		(TEGRA_CLK_RESET_BASE + 0x18)
 | |
| #define TEGRA_PMC_SCRATCH20		(TEGRA_PMC_BASE + 0xa0)
 | |
| #define TEGRA_APB_MISC_GP_HIDREV	(TEGRA_APB_MISC_BASE + 0x804)
 | |
| 
 | |
| /*
 | |
|  * Must be section-aligned since a section mapping is used early on.
 | |
|  * Must not overlap with regions in mach-tegra/io.c:tegra_io_desc[].
 | |
|  */
 | |
| #define UART_VIRTUAL_BASE		0xfe800000
 | |
| 
 | |
| #define checkuart(rp, rv, lhu, bit, uart) \
 | |
| 		/* Load address of CLK_RST register */ \
 | |
| 		ldr	rp, =TEGRA_CLK_RST_DEVICES_##lhu ; \
 | |
| 		/* Load value from CLK_RST register */ \
 | |
| 		ldr	rp, [rp, #0] ; \
 | |
| 		/* Test UART's reset bit */ \
 | |
| 		tst	rp, #(1 << bit) ; \
 | |
| 		/* If set, can't use UART; jump to save no UART */ \
 | |
| 		bne	90f ; \
 | |
| 		/* Load address of CLK_OUT_ENB register */ \
 | |
| 		ldr	rp, =TEGRA_CLK_OUT_ENB_##lhu ; \
 | |
| 		/* Load value from CLK_OUT_ENB register */ \
 | |
| 		ldr	rp, [rp, #0] ; \
 | |
| 		/* Test UART's clock enable bit */ \
 | |
| 		tst	rp, #(1 << bit) ; \
 | |
| 		/* If clear, can't use UART; jump to save no UART */ \
 | |
| 		beq	90f ; \
 | |
| 		/* Passed all tests, load address of UART registers */ \
 | |
| 		ldr	rp, =TEGRA_UART##uart##_BASE ; \
 | |
| 		/* Jump to save UART address */ \
 | |
| 		b 91f
 | |
| 
 | |
| 		.macro  addruart, rp, rv, tmp
 | |
| 		adr	\rp, 99f		@ actual addr of 99f
 | |
| 		ldr	\rv, [\rp]		@ linked addr is stored there
 | |
| 		sub	\rv, \rv, \rp		@ offset between the two
 | |
| 		ldr	\rp, [\rp, #4]		@ linked tegra_uart_config
 | |
| 		sub	\tmp, \rp, \rv		@ actual tegra_uart_config
 | |
| 		ldr	\rp, [\tmp]		@ Load tegra_uart_config
 | |
| 		cmp	\rp, #1			@ needs initialization?
 | |
| 		bne	100f			@ no; go load the addresses
 | |
| 		mov	\rv, #0			@ yes; record init is done
 | |
| 		str	\rv, [\tmp]
 | |
| 
 | |
| #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
 | |
| 		/* Check ODMDATA */
 | |
| 10:		ldr	\rp, =TEGRA_PMC_SCRATCH20
 | |
| 		ldr	\rp, [\rp, #0]		@ Load PMC_SCRATCH20
 | |
| 		lsr	\rv, \rp, #18		@ 19:18 are console type
 | |
| 		and	\rv, \rv, #3
 | |
| 		cmp	\rv, #2			@ 2 and 3 mean DCC, UART
 | |
| 		beq	11f			@ some boards swap the meaning
 | |
| 		cmp	\rv, #3			@ so accept either
 | |
| 		bne	90f
 | |
| 11:		lsr	\rv, \rp, #15		@ 17:15 are UART ID
 | |
| 		and	\rv, #7	
 | |
| 		cmp	\rv, #0			@ UART 0?
 | |
| 		beq	20f
 | |
| 		cmp	\rv, #1			@ UART 1?
 | |
| 		beq	21f
 | |
| 		cmp	\rv, #2			@ UART 2?
 | |
| 		beq	22f
 | |
| 		cmp	\rv, #3			@ UART 3?
 | |
| 		beq	23f
 | |
| 		cmp	\rv, #4			@ UART 4?
 | |
| 		beq	24f
 | |
| 		b	90f			@ invalid
 | |
| #endif
 | |
| 
 | |
| #if defined(CONFIG_TEGRA_DEBUG_UARTA) || \
 | |
|     defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
 | |
| 		/* Check UART A validity */
 | |
| 20:		checkuart(\rp, \rv, L, 6, A)
 | |
| #endif
 | |
| 
 | |
| #if defined(CONFIG_TEGRA_DEBUG_UARTB) || \
 | |
|     defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
 | |
| 		/* Check UART B validity */
 | |
| 21:		checkuart(\rp, \rv, L, 7, B)
 | |
| #endif
 | |
| 
 | |
| #if defined(CONFIG_TEGRA_DEBUG_UARTC) || \
 | |
|     defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
 | |
| 		/* Check UART C validity */
 | |
| 22:		checkuart(\rp, \rv, H, 23, C)
 | |
| #endif
 | |
| 
 | |
| #if defined(CONFIG_TEGRA_DEBUG_UARTD) || \
 | |
|     defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
 | |
| 		/* Check UART D validity */
 | |
| 23:		checkuart(\rp, \rv, U, 1, D)
 | |
| #endif
 | |
| 
 | |
| #if defined(CONFIG_TEGRA_DEBUG_UARTE) || \
 | |
|     defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
 | |
| 		/* Check UART E validity */
 | |
| 24:
 | |
| 		checkuart(\rp, \rv, U, 2, E)
 | |
| #endif
 | |
| 
 | |
| 		/* No valid UART found */
 | |
| 90:		mov	\rp, #0
 | |
| 		/* fall through */
 | |
| 
 | |
| 		/* Record whichever UART we chose */
 | |
| 91:		str	\rp, [\tmp, #4]		@ Store in tegra_uart_phys
 | |
| 		cmp	\rp, #0			@ Valid UART address?
 | |
| 		bne	92f			@ Yes, go process it
 | |
| 		str	\rp, [\tmp, #8]		@ Store 0 in tegra_uart_virt
 | |
| 		b	100f			@ Done
 | |
| 92:		and	\rv, \rp, #0xffffff	@ offset within 1MB section
 | |
| 		add	\rv, \rv, #UART_VIRTUAL_BASE
 | |
| 		str	\rv, [\tmp, #8]		@ Store in tegra_uart_virt
 | |
| 		b	100f
 | |
| 
 | |
| 		.align
 | |
| 99:		.word	.
 | |
| 		.word	tegra_uart_config
 | |
| 		.ltorg
 | |
| 
 | |
| 		/* Load previously selected UART address */
 | |
| 100:		ldr	\rp, [\tmp, #4]		@ Load tegra_uart_phys
 | |
| 		ldr	\rv, [\tmp, #8]		@ Load tegra_uart_virt
 | |
| 		.endm
 | |
| 
 | |
| /*
 | |
|  * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
 | |
|  * check to make sure that the UART address is actually valid.
 | |
|  */
 | |
| 
 | |
| 		.macro	senduart, rd, rx
 | |
| 		cmp	\rx, #0
 | |
| 		strneb	\rd, [\rx, #UART_TX << UART_SHIFT]
 | |
| 1001:
 | |
| 		.endm
 | |
| 
 | |
| 		.macro	busyuart, rd, rx
 | |
| 		cmp	\rx, #0
 | |
| 		beq	1002f
 | |
| 1001:		ldrb	\rd, [\rx, #UART_LSR << UART_SHIFT]
 | |
| 		and	\rd, \rd, #UART_LSR_THRE
 | |
| 		teq	\rd, #UART_LSR_THRE
 | |
| 		bne	1001b
 | |
| 1002:
 | |
| 		.endm
 | |
| 
 | |
| 		.macro	waituart, rd, rx
 | |
| #ifdef FLOW_CONTROL
 | |
| 		cmp	\rx, #0
 | |
| 		beq	1002f
 | |
| 1001:		ldrb	\rd, [\rx, #UART_MSR << UART_SHIFT]
 | |
| 		tst	\rd, #UART_MSR_CTS
 | |
| 		beq	1001b
 | |
| 1002:
 | |
| #endif
 | |
| 		.endm
 | |
| 
 | |
| /*
 | |
|  * Storage for the state maintained by the macros above.
 | |
|  *
 | |
|  * In the kernel proper, this data is located in arch/arm/mach-tegra/tegra.c.
 | |
|  * That's because this header is included from multiple files, and we only
 | |
|  * want a single copy of the data. In particular, the UART probing code above
 | |
|  * assumes it's running using physical addresses. This is true when this file
 | |
|  * is included from head.o, but not when included from debug.o. So we need
 | |
|  * to share the probe results between the two copies, rather than having
 | |
|  * to re-run the probing again later.
 | |
|  *
 | |
|  * In the decompressor, we put the symbol/storage right here, since common.c
 | |
|  * isn't included in the decompressor build. This symbol gets put in .text
 | |
|  * even though it's really data, since .data is discarded from the
 | |
|  * decompressor. Luckily, .text is writeable in the decompressor, unless
 | |
|  * CONFIG_ZBOOT_ROM. That dependency is handled in arch/arm/Kconfig.debug.
 | |
|  */
 | |
| #if defined(ZIMAGE)
 | |
| tegra_uart_config:
 | |
| 	/* Debug UART initialization required */
 | |
| 	.word 1
 | |
| 	/* Debug UART physical address */
 | |
| 	.word 0
 | |
| 	/* Debug UART virtual address */
 | |
| 	.word 0
 | |
| #endif
 |