/* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (C) 2016 Broadcom */ #include #include /* 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_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, 0x07437100, 74371) 34: checkuart(\rp, \rv, 0x74390000, 7439) 35: 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