hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * 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_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, 0x72160000, 7216)
22:        checkuart(\rp, \rv, 0x07216400, 72164)
23:        checkuart(\rp, \rv, 0x07216500, 72165)
24:        checkuart(\rp, \rv, 0x72500000, 7250)
25:        checkuart(\rp, \rv, 0x72550000, 7255)
26:        checkuart(\rp, \rv, 0x72600000, 7260)
27:        checkuart(\rp, \rv, 0x72680000, 7268)
28:        checkuart(\rp, \rv, 0x72710000, 7271)
29:        checkuart(\rp, \rv, 0x72780000, 7278)
30:        checkuart(\rp, \rv, 0x73640000, 7364)
31:        checkuart(\rp, \rv, 0x73660000, 7366)
32:        checkuart(\rp, \rv, 0x07437100, 74371)
33:        checkuart(\rp, \rv, 0x74390000, 7439)
34:        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