152e6676eSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 252e6676eSThomas Gleixner/* Copyright (C) 2016 Broadcom */ 3d0cf9d8aSFlorian Fainelli#include <linux/serial_reg.h> 456e4446dSDoug Berger#include <asm/cputype.h> 5d0cf9d8aSFlorian Fainelli 6d0cf9d8aSFlorian Fainelli/* Physical register offset and virtual register offset */ 7d0cf9d8aSFlorian Fainelli#define REG_PHYS_BASE 0xf0000000 856e4446dSDoug Berger#define REG_PHYS_BASE_V7 0x08000000 9d0cf9d8aSFlorian Fainelli#define REG_VIRT_BASE 0xfc000000 10d0cf9d8aSFlorian Fainelli#define REG_PHYS_ADDR(x) ((x) + REG_PHYS_BASE) 1156e4446dSDoug Berger#define REG_PHYS_ADDR_V7(x) ((x) + REG_PHYS_BASE_V7) 12d0cf9d8aSFlorian Fainelli 13d0cf9d8aSFlorian Fainelli/* Product id can be read from here */ 14d0cf9d8aSFlorian Fainelli#define SUN_TOP_CTRL_BASE REG_PHYS_ADDR(0x404000) 1556e4446dSDoug Berger#define SUN_TOP_CTRL_BASE_V7 REG_PHYS_ADDR_V7(0x404000) 16d0cf9d8aSFlorian Fainelli 17d0cf9d8aSFlorian Fainelli#define UARTA_3390 REG_PHYS_ADDR(0x40a900) 18d5d5b7f3SFlorian Fainelli#define UARTA_72116 UARTA_7255 19d0cf9d8aSFlorian Fainelli#define UARTA_7250 REG_PHYS_ADDR(0x40b400) 208f34fe4aSJustin Chen#define UARTA_7255 REG_PHYS_ADDR(0x40c000) 218f34fe4aSJustin Chen#define UARTA_7260 UARTA_7255 228f34fe4aSJustin Chen#define UARTA_7268 UARTA_7255 23d0cf9d8aSFlorian Fainelli#define UARTA_7271 UARTA_7268 2456e4446dSDoug Berger#define UARTA_7278 REG_PHYS_ADDR_V7(0x40c000) 25064f42b2SJustin Chen#define UARTA_7216 UARTA_7278 266b84ca26SFlorian Fainelli#define UARTA_72164 UARTA_7278 274e5cafa8SFlorian Fainelli#define UARTA_72165 UARTA_7278 28d0cf9d8aSFlorian Fainelli#define UARTA_7364 REG_PHYS_ADDR(0x40b000) 29d0cf9d8aSFlorian Fainelli#define UARTA_7366 UARTA_7364 30*3992d06cSFlorian Fainelli#define UARTA_74165 UARTA_7278 31d0cf9d8aSFlorian Fainelli#define UARTA_74371 REG_PHYS_ADDR(0x406b00) 32d0cf9d8aSFlorian Fainelli#define UARTA_7439 REG_PHYS_ADDR(0x40a900) 33d0cf9d8aSFlorian Fainelli#define UARTA_7445 REG_PHYS_ADDR(0x40ab00) 34d0cf9d8aSFlorian Fainelli 35d0cf9d8aSFlorian Fainelli#define UART_SHIFT 2 36d0cf9d8aSFlorian Fainelli 37d0cf9d8aSFlorian Fainelli#define checkuart(rp, rv, family_id, family) \ 38d0cf9d8aSFlorian Fainelli /* Load family id */ \ 39d0cf9d8aSFlorian Fainelli ldr rp, =family_id ; \ 40d0cf9d8aSFlorian Fainelli /* Compare SUN_TOP_CTRL value against it */ \ 41d0cf9d8aSFlorian Fainelli cmp rp, rv ; \ 42d0cf9d8aSFlorian Fainelli /* Passed test, load address */ \ 43d0cf9d8aSFlorian Fainelli ldreq rp, =UARTA_##family ; \ 44d0cf9d8aSFlorian Fainelli /* Jump to save UART address */ \ 45d0cf9d8aSFlorian Fainelli beq 91f 46d0cf9d8aSFlorian Fainelli 47d0cf9d8aSFlorian Fainelli .macro addruart, rp, rv, tmp 48d0cf9d8aSFlorian Fainelli adr \rp, 99f @ actual addr of 99f 49d0cf9d8aSFlorian Fainelli ldr \rv, [\rp] @ linked addr is stored there 50d0cf9d8aSFlorian Fainelli sub \rv, \rv, \rp @ offset between the two 51d0cf9d8aSFlorian Fainelli ldr \rp, [\rp, #4] @ linked brcmstb_uart_config 52d0cf9d8aSFlorian Fainelli sub \tmp, \rp, \rv @ actual brcmstb_uart_config 53d0cf9d8aSFlorian Fainelli ldr \rp, [\tmp] @ Load brcmstb_uart_config 54d0cf9d8aSFlorian Fainelli cmp \rp, #1 @ needs initialization? 55d0cf9d8aSFlorian Fainelli bne 100f @ no; go load the addresses 56d0cf9d8aSFlorian Fainelli mov \rv, #0 @ yes; record init is done 57d0cf9d8aSFlorian Fainelli str \rv, [\tmp] 58d0cf9d8aSFlorian Fainelli 5956e4446dSDoug Berger /* Check for V7 memory map if B53 */ 6056e4446dSDoug Berger mrc p15, 0, \rv, c0, c0, 0 @ get Main ID register 6156e4446dSDoug Berger ldr \rp, =ARM_CPU_PART_MASK 6256e4446dSDoug Berger and \rv, \rv, \rp 6356e4446dSDoug Berger ldr \rp, =ARM_CPU_PART_BRAHMA_B53 @ check for B53 CPU 6456e4446dSDoug Berger cmp \rv, \rp 6556e4446dSDoug Berger bne 10f 6656e4446dSDoug Berger 6756e4446dSDoug Berger /* if PERIPHBASE doesn't overlap REG_PHYS_BASE use V7 map */ 6856e4446dSDoug Berger mrc p15, 1, \rv, c15, c3, 0 @ get PERIPHBASE from CBAR 6956e4446dSDoug Berger ands \rv, \rv, #REG_PHYS_BASE 7056e4446dSDoug Berger ldreq \rp, =SUN_TOP_CTRL_BASE_V7 7156e4446dSDoug Berger 72d0cf9d8aSFlorian Fainelli /* Check SUN_TOP_CTRL base */ 7356e4446dSDoug Berger10: ldrne \rp, =SUN_TOP_CTRL_BASE @ load SUN_TOP_CTRL PA 74d0cf9d8aSFlorian Fainelli ldr \rv, [\rp, #0] @ get register contents 75c1496352SFlorian FainelliARM_BE8( rev \rv, \rv ) 76d0cf9d8aSFlorian Fainelli and \rv, \rv, #0xffffff00 @ strip revision bits [7:0] 77d0cf9d8aSFlorian Fainelli 78d0cf9d8aSFlorian Fainelli /* Chip specific detection starts here */ 79d0cf9d8aSFlorian Fainelli20: checkuart(\rp, \rv, 0x33900000, 3390) 80d5d5b7f3SFlorian Fainelli21: checkuart(\rp, \rv, 0x07211600, 72116) 81d5d5b7f3SFlorian Fainelli22: checkuart(\rp, \rv, 0x72160000, 7216) 82d5d5b7f3SFlorian Fainelli23: checkuart(\rp, \rv, 0x07216400, 72164) 83d5d5b7f3SFlorian Fainelli24: checkuart(\rp, \rv, 0x07216500, 72165) 84d5d5b7f3SFlorian Fainelli25: checkuart(\rp, \rv, 0x72500000, 7250) 85d5d5b7f3SFlorian Fainelli26: checkuart(\rp, \rv, 0x72550000, 7255) 86d5d5b7f3SFlorian Fainelli27: checkuart(\rp, \rv, 0x72600000, 7260) 87d5d5b7f3SFlorian Fainelli28: checkuart(\rp, \rv, 0x72680000, 7268) 88d5d5b7f3SFlorian Fainelli29: checkuart(\rp, \rv, 0x72710000, 7271) 89d5d5b7f3SFlorian Fainelli30: checkuart(\rp, \rv, 0x72780000, 7278) 90d5d5b7f3SFlorian Fainelli31: checkuart(\rp, \rv, 0x73640000, 7364) 91d5d5b7f3SFlorian Fainelli32: checkuart(\rp, \rv, 0x73660000, 7366) 92*3992d06cSFlorian Fainelli33: checkuart(\rp, \rv, 0x07416500, 74165) 93*3992d06cSFlorian Fainelli34: checkuart(\rp, \rv, 0x07437100, 74371) 94*3992d06cSFlorian Fainelli35: checkuart(\rp, \rv, 0x74390000, 7439) 95*3992d06cSFlorian Fainelli36: checkuart(\rp, \rv, 0x74450000, 7445) 96d0cf9d8aSFlorian Fainelli 97d0cf9d8aSFlorian Fainelli /* No valid UART found */ 98d0cf9d8aSFlorian Fainelli90: mov \rp, #0 99d0cf9d8aSFlorian Fainelli /* fall through */ 100d0cf9d8aSFlorian Fainelli 101d0cf9d8aSFlorian Fainelli /* Record whichever UART we chose */ 102d0cf9d8aSFlorian Fainelli91: str \rp, [\tmp, #4] @ Store in brcmstb_uart_phys 103d0cf9d8aSFlorian Fainelli cmp \rp, #0 @ Valid UART address? 104d0cf9d8aSFlorian Fainelli bne 92f @ Yes, go process it 105d0cf9d8aSFlorian Fainelli str \rp, [\tmp, #8] @ Store 0 in brcmstb_uart_virt 106d0cf9d8aSFlorian Fainelli b 100f @ Done 107d0cf9d8aSFlorian Fainelli92: and \rv, \rp, #0xffffff @ offset within 16MB section 108d0cf9d8aSFlorian Fainelli add \rv, \rv, #REG_VIRT_BASE 109d0cf9d8aSFlorian Fainelli str \rv, [\tmp, #8] @ Store in brcmstb_uart_virt 110d0cf9d8aSFlorian Fainelli b 100f 111d0cf9d8aSFlorian Fainelli 112d0cf9d8aSFlorian Fainelli .align 113d0cf9d8aSFlorian Fainelli99: .word . 114d0cf9d8aSFlorian Fainelli .word brcmstb_uart_config 115d0cf9d8aSFlorian Fainelli .ltorg 116d0cf9d8aSFlorian Fainelli 117d0cf9d8aSFlorian Fainelli /* Load previously selected UART address */ 118d0cf9d8aSFlorian Fainelli100: ldr \rp, [\tmp, #4] @ Load brcmstb_uart_phys 119d0cf9d8aSFlorian Fainelli ldr \rv, [\tmp, #8] @ Load brcmstb_uart_virt 120d0cf9d8aSFlorian Fainelli .endm 121d0cf9d8aSFlorian Fainelli 122d0cf9d8aSFlorian Fainelli .macro store, rd, rx:vararg 123c1496352SFlorian FainelliARM_BE8( rev \rd, \rd ) 124d0cf9d8aSFlorian Fainelli str \rd, \rx 125d0cf9d8aSFlorian Fainelli .endm 126d0cf9d8aSFlorian Fainelli 127d0cf9d8aSFlorian Fainelli .macro load, rd, rx:vararg 128d0cf9d8aSFlorian Fainelli ldr \rd, \rx 129c1496352SFlorian FainelliARM_BE8( rev \rd, \rd ) 130d0cf9d8aSFlorian Fainelli .endm 131d0cf9d8aSFlorian Fainelli 132d0cf9d8aSFlorian Fainelli .macro senduart,rd,rx 133d0cf9d8aSFlorian Fainelli store \rd, [\rx, #UART_TX << UART_SHIFT] 134d0cf9d8aSFlorian Fainelli .endm 135d0cf9d8aSFlorian Fainelli 136d0cf9d8aSFlorian Fainelli .macro busyuart,rd,rx 137d0cf9d8aSFlorian Fainelli1002: load \rd, [\rx, #UART_LSR << UART_SHIFT] 138d0cf9d8aSFlorian Fainelli and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE 139d0cf9d8aSFlorian Fainelli teq \rd, #UART_LSR_TEMT | UART_LSR_THRE 140d0cf9d8aSFlorian Fainelli bne 1002b 141d0cf9d8aSFlorian Fainelli .endm 142d0cf9d8aSFlorian Fainelli 1432c50a570SLinus Walleij .macro waituarttxrdy,rd,rx 1442c50a570SLinus Walleij .endm 1452c50a570SLinus Walleij 1462c50a570SLinus Walleij .macro waituartcts,rd,rx 147d0cf9d8aSFlorian Fainelli .endm 148d0cf9d8aSFlorian Fainelli 149d0cf9d8aSFlorian Fainelli/* 150d0cf9d8aSFlorian Fainelli * Storage for the state maintained by the macros above. 151d0cf9d8aSFlorian Fainelli * 152d0cf9d8aSFlorian Fainelli * In the kernel proper, this data is located in arch/arm/mach-bcm/brcmstb.c. 153d0cf9d8aSFlorian Fainelli * That's because this header is included from multiple files, and we only 154d0cf9d8aSFlorian Fainelli * want a single copy of the data. In particular, the UART probing code above 155d0cf9d8aSFlorian Fainelli * assumes it's running using physical addresses. This is true when this file 156d0cf9d8aSFlorian Fainelli * is included from head.o, but not when included from debug.o. So we need 157d0cf9d8aSFlorian Fainelli * to share the probe results between the two copies, rather than having 158d0cf9d8aSFlorian Fainelli * to re-run the probing again later. 159d0cf9d8aSFlorian Fainelli * 160d0cf9d8aSFlorian Fainelli * In the decompressor, we put the symbol/storage right here, since common.c 161d0cf9d8aSFlorian Fainelli * isn't included in the decompressor build. This symbol gets put in .text 162d0cf9d8aSFlorian Fainelli * even though it's really data, since .data is discarded from the 163d0cf9d8aSFlorian Fainelli * decompressor. Luckily, .text is writeable in the decompressor, unless 164d0cf9d8aSFlorian Fainelli * CONFIG_ZBOOT_ROM. That dependency is handled in arch/arm/Kconfig.debug. 165d0cf9d8aSFlorian Fainelli */ 166d0cf9d8aSFlorian Fainelli#if defined(ZIMAGE) 167d0cf9d8aSFlorian Fainellibrcmstb_uart_config: 168d0cf9d8aSFlorian Fainelli /* Debug UART initialization required */ 169d0cf9d8aSFlorian Fainelli .word 1 170d0cf9d8aSFlorian Fainelli /* Debug UART physical address */ 171d0cf9d8aSFlorian Fainelli .word 0 172d0cf9d8aSFlorian Fainelli /* Debug UART virtual address */ 173d0cf9d8aSFlorian Fainelli .word 0 174d0cf9d8aSFlorian Fainelli#endif 175