This patch was triggered by a remark from Russell that
introducing a call to the waituart (needed to fix debug prints
on the Qualcomm platforms) was dangerous because in some cases
this will involve waiting for a modem CTS (clear to send)
signal, and debug messages would maybe not work on platforms
with no modem connected to the UART port: they will just
hang waiting for the modem to assert CTS and this might never
happen.
Looking through all UART debug drivers implementing the waituart
macro I discovered that all users except two actually use this
macro to check if the UART is ready for TX, let's call this
TXRDY.
Only two debug UART drivers actually check for CTS:
- arch/arm/include/debug/8250.S
- arch/arm/include/debug/tegra.S
The former is very significant since the 8250 is possibly
the most common UART on the planet.
We have the following problem: the semantics of waituart are
ambiguous making it dangerous to introduce the macro to debug
code fixing debug prints for Qualcomm. To start to pry this
problem apart, this patch does the following:
- Convert all debug UART drivers to define two macros:
- waituartcts with the clear semantic to wait for CTS
to be asserted
- waituarttxrdy with the clear semantic to wait for the TX
capability of the UART to be ready
- When doing this take care to assign the right function to
each drivers macro, so they now do exactly the above.
- Update the three sites in the kernel invoking the waituart
macro to call waituartcts/waituarttxrdy in sequence, so that
the functional impact on the kernel should be zero.
After this we can start to change the code sites using this
code to do the right thing.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
177 lines
5.6 KiB
ArmAsm
177 lines
5.6 KiB
ArmAsm
/*
|
|
* Copyright (C) 2016 Broadcom
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation version 2.
|
|
*
|
|
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
|
* kind, whether express or implied; 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>
|
|
#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_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_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, 0x72160000, 7216)
|
|
22: checkuart(\rp, \rv, 0x72500000, 7250)
|
|
23: checkuart(\rp, \rv, 0x72550000, 7255)
|
|
24: checkuart(\rp, \rv, 0x72600000, 7260)
|
|
25: checkuart(\rp, \rv, 0x72680000, 7268)
|
|
26: checkuart(\rp, \rv, 0x72710000, 7271)
|
|
27: checkuart(\rp, \rv, 0x72780000, 7278)
|
|
28: checkuart(\rp, \rv, 0x73640000, 7364)
|
|
29: checkuart(\rp, \rv, 0x73660000, 7366)
|
|
30: checkuart(\rp, \rv, 0x07437100, 74371)
|
|
31: checkuart(\rp, \rv, 0x74390000, 7439)
|
|
32: 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
|