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