/* SPDX-License-Identifier: GPL-2.0-only *//* Copyright (C) 2016 Broadcom */#include <linux/serial_reg.h>#include <asm/cputype.h> /* Physical register offset and virtual register offset */#define REG_PHYS_BASE 0xf0000000#define REG_PHYS_BASE_V7 0x08000000#define REG_VIRT_BASE 0xfc000000#define REG_PHYS_ADDR(x) ((x) + REG_PHYS_BASE)#define REG_PHYS_ADDR_V7(x) ((x) + REG_PHYS_BASE_V7) /* Product id can be read from here */#define SUN_TOP_CTRL_BASE REG_PHYS_ADDR(0x404000)#define SUN_TOP_CTRL_BASE_V7 REG_PHYS_ADDR_V7(0x404000) #define UARTA_3390 REG_PHYS_ADDR(0x40a900)#define UARTA_72116 UARTA_7255#define UARTA_7250 REG_PHYS_ADDR(0x40b400)#define UARTA_7255 REG_PHYS_ADDR(0x40c000)#define UARTA_7260 UARTA_7255#define UARTA_7268 UARTA_7255#define UARTA_7271 UARTA_7268#define UARTA_7278 REG_PHYS_ADDR_V7(0x40c000)#define UARTA_7216 UARTA_7278#define UARTA_72164 UARTA_7278#define UARTA_72165 UARTA_7278#define UARTA_7364 REG_PHYS_ADDR(0x40b000)#define UARTA_7366 UARTA_7364#define UARTA_74165 UARTA_7278#define UARTA_74371 REG_PHYS_ADDR(0x406b00)#define UARTA_7439 REG_PHYS_ADDR(0x40a900)#define UARTA_7445 REG_PHYS_ADDR(0x40ab00) #define UART_SHIFT 2 #define checkuart(rp, rv, family_id, family) \ /* Load family id */ \ ldr rp, =family_id ; \ /* Compare SUN_TOP_CTRL value against it */ \ cmp rp, rv ; \ /* Passed test, load address */ \ ldreq rp, =UARTA_##family ; \ /* Jump to save UART address */ \ beq 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 brcmstb_uart_config sub \tmp, \rp, \rv @ actual brcmstb_uart_config ldr \rp, [\tmp] @ Load brcmstb_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] /* Check for V7 memory map if B53 */ mrc p15, 0, \rv, c0, c0, 0 @ get Main ID register ldr \rp, =ARM_CPU_PART_MASK and \rv, \rv, \rp ldr \rp, =ARM_CPU_PART_BRAHMA_B53 @ check for B53 CPU cmp \rv, \rp bne 10f /* if PERIPHBASE doesn't overlap REG_PHYS_BASE use V7 map */ mrc p15, 1, \rv, c15, c3, 0 @ get PERIPHBASE from CBAR ands \rv, \rv, #REG_PHYS_BASE ldreq \rp, =SUN_TOP_CTRL_BASE_V7 /* Check SUN_TOP_CTRL base */10: ldrne \rp, =SUN_TOP_CTRL_BASE @ load SUN_TOP_CTRL PA ldr \rv, [\rp, #0] @ get register contentsARM_BE8( rev \rv, \rv ) and \rv, \rv, #0xffffff00 @ strip revision bits [7:0] /* Chip specific detection starts here */20: checkuart(\rp, \rv, 0x33900000, 3390)21: checkuart(\rp, \rv, 0x07211600, 72116)22: checkuart(\rp, \rv, 0x72160000, 7216)23: checkuart(\rp, \rv, 0x07216400, 72164)24: checkuart(\rp, \rv, 0x07216500, 72165)25: checkuart(\rp, \rv, 0x72500000, 7250)26: checkuart(\rp, \rv, 0x72550000, 7255)27: checkuart(\rp, \rv, 0x72600000, 7260)28: checkuart(\rp, \rv, 0x72680000, 7268)29: checkuart(\rp, \rv, 0x72710000, 7271)30: checkuart(\rp, \rv, 0x72780000, 7278)31: checkuart(\rp, \rv, 0x73640000, 7364)32: checkuart(\rp, \rv, 0x73660000, 7366)33: checkuart(\rp, \rv, 0x07416500, 74165)34: checkuart(\rp, \rv, 0x07437100, 74371)35: checkuart(\rp, \rv, 0x74390000, 7439)36: checkuart(\rp, \rv, 0x74450000, 7445) /* No valid UART found */90: mov \rp, #0 /* fall through */ /* Record whichever UART we chose */91: str \rp, [\tmp, #4] @ Store in brcmstb_uart_phys cmp \rp, #0 @ Valid UART address? bne 92f @ Yes, go process it str \rp, [\tmp, #8] @ Store 0 in brcmstb_uart_virt b 100f @ Done92: and \rv, \rp, #0xffffff @ offset within 16MB section add \rv, \rv, #REG_VIRT_BASE str \rv, [\tmp, #8] @ Store in brcmstb_uart_virt b 100f .align99: .word . .word brcmstb_uart_config .ltorg /* Load previously selected UART address */100: ldr \rp, [\tmp, #4] @ Load brcmstb_uart_phys ldr \rv, [\tmp, #8] @ Load brcmstb_uart_virt .endm .macro store, rd, rx:varargARM_BE8( rev \rd, \rd ) str \rd, \rx .endm .macro load, rd, rx:vararg ldr \rd, \rxARM_BE8( rev \rd, \rd ) .endm .macro senduart,rd,rx store \rd, [\rx, #UART_TX << UART_SHIFT] .endm .macro busyuart,rd,rx1002: load \rd, [\rx, #UART_LSR << UART_SHIFT] and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE teq \rd, #UART_LSR_TEMT | UART_LSR_THRE bne 1002b .endm .macro waituarttxrdy,rd,rx .endm .macro waituartcts,rd,rx .endm /* * Storage for the state maintained by the macros above. * * In the kernel proper, this data is located in arch/arm/mach-bcm/brcmstb.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)brcmstb_uart_config: /* Debug UART initialization required */ .word 1 /* Debug UART physical address */ .word 0 /* Debug UART virtual address */ .word 0#endif
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (C) 2016 Broadcom */
#include <linux/serial_reg.h>
#include <asm/cputype.h>
/* Physical register offset and virtual register offset */
#define REG_PHYS_BASE 0xf0000000
#define REG_PHYS_BASE_V7 0x08000000
#define REG_VIRT_BASE 0xfc000000
#define REG_PHYS_ADDR(x) ((x) + REG_PHYS_BASE)
#define REG_PHYS_ADDR_V7(x) ((x) + REG_PHYS_BASE_V7)
/* Product id can be read from here */
#define SUN_TOP_CTRL_BASE REG_PHYS_ADDR(0x404000)
#define SUN_TOP_CTRL_BASE_V7 REG_PHYS_ADDR_V7(0x404000)
#define UARTA_3390 REG_PHYS_ADDR(0x40a900)
#define UARTA_72116 UARTA_7255
#define UARTA_7250 REG_PHYS_ADDR(0x40b400)
#define UARTA_7255 REG_PHYS_ADDR(0x40c000)
#define UARTA_7260 UARTA_7255
#define UARTA_7268 UARTA_7255
#define UARTA_7271 UARTA_7268
#define UARTA_7278 REG_PHYS_ADDR_V7(0x40c000)
#define UARTA_7216 UARTA_7278
#define UARTA_72164 UARTA_7278
#define UARTA_72165 UARTA_7278
#define UARTA_7364 REG_PHYS_ADDR(0x40b000)
#define UARTA_7366 UARTA_7364
#define UARTA_74165 UARTA_7278
#define UARTA_74371 REG_PHYS_ADDR(0x406b00)
#define UARTA_7439 REG_PHYS_ADDR(0x40a900)
#define UARTA_7445 REG_PHYS_ADDR(0x40ab00)
#define UART_SHIFT 2
#define checkuart(rp, rv, family_id, family) \
/* Load family id */ \
ldr rp, =family_id ; \
/* Compare SUN_TOP_CTRL value against it */ \
cmp rp, rv ; \
/* Passed test, load address */ \
ldreq rp, =UARTA_##family ; \
/* Jump to save UART address */ \
beq 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 brcmstb_uart_config
sub \tmp, \rp, \rv @ actual brcmstb_uart_config
ldr \rp, [\tmp] @ Load brcmstb_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]
/* Check for V7 memory map if B53 */
mrc p15, 0, \rv, c0, c0, 0 @ get Main ID register
ldr \rp, =ARM_CPU_PART_MASK
and \rv, \rv, \rp
ldr \rp, =ARM_CPU_PART_BRAHMA_B53 @ check for B53 CPU
cmp \rv, \rp
bne 10f
/* if PERIPHBASE doesn't overlap REG_PHYS_BASE use V7 map */
mrc p15, 1, \rv, c15, c3, 0 @ get PERIPHBASE from CBAR
ands \rv, \rv, #REG_PHYS_BASE
ldreq \rp, =SUN_TOP_CTRL_BASE_V7
/* Check SUN_TOP_CTRL base */
10: ldrne \rp, =SUN_TOP_CTRL_BASE @ load SUN_TOP_CTRL PA
ldr \rv, [\rp, #0] @ get register contents
ARM_BE8( rev \rv, \rv )
and \rv, \rv, #0xffffff00 @ strip revision bits [7:0]
/* Chip specific detection starts here */
20: checkuart(\rp, \rv, 0x33900000, 3390)
21: checkuart(\rp, \rv, 0x07211600, 72116)
22: checkuart(\rp, \rv, 0x72160000, 7216)
23: checkuart(\rp, \rv, 0x07216400, 72164)
24: checkuart(\rp, \rv, 0x07216500, 72165)
25: checkuart(\rp, \rv, 0x72500000, 7250)
26: checkuart(\rp, \rv, 0x72550000, 7255)
27: checkuart(\rp, \rv, 0x72600000, 7260)
28: checkuart(\rp, \rv, 0x72680000, 7268)
29: checkuart(\rp, \rv, 0x72710000, 7271)
30: checkuart(\rp, \rv, 0x72780000, 7278)
31: checkuart(\rp, \rv, 0x73640000, 7364)
32: checkuart(\rp, \rv, 0x73660000, 7366)
33: checkuart(\rp, \rv, 0x07416500, 74165)
34: checkuart(\rp, \rv, 0x07437100, 74371)
35: checkuart(\rp, \rv, 0x74390000, 7439)
36: checkuart(\rp, \rv, 0x74450000, 7445)
/* No valid UART found */
90: mov \rp, #0
/* fall through */
/* Record whichever UART we chose */
91: str \rp, [\tmp, #4] @ Store in brcmstb_uart_phys
cmp \rp, #0 @ Valid UART address?
bne 92f @ Yes, go process it
str \rp, [\tmp, #8] @ Store 0 in brcmstb_uart_virt
b 100f @ Done
92: and \rv, \rp, #0xffffff @ offset within 16MB section
add \rv, \rv, #REG_VIRT_BASE
str \rv, [\tmp, #8] @ Store in brcmstb_uart_virt
b 100f
.align
99: .word .
.word brcmstb_uart_config
.ltorg
/* Load previously selected UART address */
100: ldr \rp, [\tmp, #4] @ Load brcmstb_uart_phys
ldr \rv, [\tmp, #8] @ Load brcmstb_uart_virt
.endm
.macro store, rd, rx:vararg
ARM_BE8( rev \rd, \rd )
str \rd, \rx
.endm
.macro load, rd, rx:vararg
ldr \rd, \rx
ARM_BE8( rev \rd, \rd )
.endm
.macro senduart,rd,rx
store \rd, [\rx, #UART_TX << UART_SHIFT]
.endm
.macro busyuart,rd,rx
1002: load \rd, [\rx, #UART_LSR << UART_SHIFT]
and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
teq \rd, #UART_LSR_TEMT | UART_LSR_THRE
bne 1002b
.endm
.macro waituarttxrdy,rd,rx
.endm
.macro waituartcts,rd,rx
.endm
/*
* Storage for the state maintained by the macros above.
*
* In the kernel proper, this data is located in arch/arm/mach-bcm/brcmstb.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)
brcmstb_uart_config:
/* Debug UART initialization required */
.word 1
/* Debug UART physical address */
.word 0
/* Debug UART virtual address */
.word 0
#endif