Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/qualcomm/ipq4018_machdep.c
39507 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2021 Adrian Chadd <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include "opt_platform.h"
29
30
#include <sys/param.h>
31
#include <sys/systm.h>
32
#include <sys/bus.h>
33
#include <sys/reboot.h>
34
#include <sys/devmap.h>
35
#include <sys/physmem.h>
36
#include <sys/lock.h>
37
38
#include <vm/vm.h>
39
40
#include <machine/bus.h>
41
#include <machine/fdt.h>
42
#include <machine/intr.h>
43
#include <machine/machdep.h>
44
#include <machine/platformvar.h>
45
46
#include <dev/fdt/fdt_common.h>
47
#include <dev/ofw/openfirm.h>
48
49
#include <arm/qualcomm/ipq4018_machdep.h>
50
#include <arm/qualcomm/ipq4018_reg.h>
51
52
#include "platform_if.h"
53
54
static int
55
ipq4018_attach(platform_t plat)
56
{
57
return (0);
58
}
59
60
static void
61
ipq4018_late_init(platform_t plat)
62
{
63
/*
64
* XXX FIXME This is needed because we're not parsing
65
* the fdt reserved memory regions in a consistent way
66
* between arm/arm64. Once the reserved region parsing
67
* is fixed up this will become unnecessary.
68
*
69
* These cover the SRAM/TZ regions that are not fully
70
* accessible from the OS. They're in the ipq4018.dtsi
71
* tree.
72
*
73
* Without these, the system fails to boot because we
74
* aren't parsing the regions correctly.
75
*
76
* These will be unnecessary once the parser and setup
77
* code is fixed.
78
*/
79
physmem_exclude_region(IPQ4018_MEM_SMEM_START,
80
IPQ4018_MEM_SMEM_SIZE,
81
EXFLAG_NODUMP | EXFLAG_NOALLOC);
82
physmem_exclude_region(IPQ4018_MEM_TZ_START,
83
IPQ4018_MEM_TZ_SIZE,
84
EXFLAG_NODUMP | EXFLAG_NOALLOC);
85
}
86
87
static int
88
ipq4018_devmap_init(platform_t plat)
89
{
90
/*
91
* This covers the boot UART. Without it we can't boot successfully:
92
* there's a mutex uninit panic in subr_vmem.c that occurs when doing
93
* a call to pmap_mapdev() when the bus space code is doing its thing.
94
*/
95
devmap_add_entry(IPQ4018_MEM_UART1_START, IPQ4018_MEM_UART1_SIZE);
96
97
/*
98
* This covers a bunch of the reset block, which includes the PS-HOLD
99
* register for dropping power.
100
*/
101
devmap_add_entry(IPQ4018_MEM_PSHOLD_START, IPQ4018_MEM_PSHOLD_SIZE);
102
103
return (0);
104
}
105
106
/*
107
* This toggles the PS-HOLD register which on most IPQ devices will toggle
108
* the power control block and reset the SoC.
109
*
110
* However, there are apparently some units out there where this is not
111
* appropriate and instead the watchdog needs to be used.
112
*
113
* For now since there's only going to be one or two initial supported boards
114
* this will be fine. But if this doesn't reboot cleanly, now you know.
115
*/
116
static void
117
ipq4018_cpu_reset_pshold(void)
118
{
119
bus_space_handle_t pshold;
120
121
printf("%s: called\n", __func__);
122
123
bus_space_map(fdtbus_bs_tag, IPQ4018_MEM_PSHOLD_START,
124
IPQ4018_MEM_PSHOLD_SIZE, 0, &pshold);
125
bus_space_write_4(fdtbus_bs_tag, pshold, 0, 0);
126
bus_space_barrier(fdtbus_bs_tag, pshold, 0, 0x4,
127
BUS_SPACE_BARRIER_WRITE);
128
}
129
130
static void
131
ipq4018_cpu_reset(platform_t plat)
132
{
133
spinlock_enter();
134
dsb();
135
136
ipq4018_cpu_reset_pshold();
137
138
/* Spin */
139
printf("%s: spinning\n", __func__);
140
while(1)
141
;
142
}
143
144
/*
145
* Early putc routine for EARLY_PRINTF support. To use, add to kernel config:
146
* option SOCDEV_PA=0x07800000
147
* option SOCDEV_VA=0x07800000
148
* option EARLY_PRINTF
149
* Resist the temptation to change the #if 0 to #ifdef EARLY_PRINTF here. It
150
* makes sense now, but if multiple SOCs do that it will make early_putc another
151
* duplicate symbol to be eliminated on the path to a generic kernel.
152
*/
153
#if 0
154
void
155
qca_msm_early_putc(int c)
156
{
157
static int is_init = 0;
158
159
int limit;
160
/*
161
* This must match what's put into SOCDEV_VA. You have to change them
162
* both together.
163
*
164
* XXX TODO I should really go and just make UART_BASE here depend upon
165
* SOCDEV_VA so they move together.
166
*/
167
#define UART_BASE IPQ4018_MEM_UART1_START
168
volatile uint32_t * UART_DM_TF0 = (uint32_t *)(UART_BASE + 0x70);
169
volatile uint32_t * UART_DM_SR = (uint32_t *)(UART_BASE + 0x08);
170
#define UART_DM_SR_TXEMT (1 << 3)
171
#define UART_DM_SR_TXRDY (1 << 2)
172
volatile uint32_t * UART_DM_ISR = (uint32_t *)(UART_BASE + 0x14);
173
volatile uint32_t * UART_DM_CR = (uint32_t *)(UART_BASE + 0x10);
174
#define UART_DM_TX_READY (1 << 7)
175
#define UART_DM_CLEAR_TX_READY 0x300
176
volatile uint32_t * UART_DM_NO_CHARS_FOR_TX = (uint32_t *)(UART_BASE + 0x40);
177
volatile uint32_t * UART_DM_TFWR = (uint32_t *)(UART_BASE + 0x1c);
178
#define UART_DM_TFW_VALUE 0
179
volatile uint32_t * UART_DM_IPR = (uint32_t *)(UART_BASE + 0x18);
180
#define UART_DM_STALE_TIMEOUT_LSB 0xf
181
182
if (is_init == 0) {
183
is_init = 1;
184
*UART_DM_TFWR = UART_DM_TFW_VALUE;
185
wmb();
186
*UART_DM_IPR = UART_DM_STALE_TIMEOUT_LSB;
187
wmb();
188
}
189
190
/* Wait until TXFIFO is empty via ISR */
191
limit = 100000;
192
if ((*UART_DM_SR & UART_DM_SR_TXEMT) == 0) {
193
while (((*UART_DM_ISR & UART_DM_TX_READY) == 0) && --limit) {
194
/* Note - can't use DELAY here yet, too early */
195
rmb();
196
}
197
*UART_DM_CR = UART_DM_CLEAR_TX_READY;
198
wmb();
199
}
200
201
/* FIFO is ready. Say we're going to write one byte */
202
*UART_DM_NO_CHARS_FOR_TX = 1;
203
wmb();
204
205
limit = 100000;
206
while (((*UART_DM_SR & UART_DM_SR_TXRDY) == 0) && --limit) {
207
/* Note - can't use DELAY here yet, too early */
208
rmb();
209
}
210
211
/* Put character in first fifo slot */
212
*UART_DM_TF0 = c;
213
wmb();
214
}
215
early_putc_t *early_putc = qca_msm_early_putc;
216
#endif
217
218
static platform_method_t ipq4018_methods[] = {
219
PLATFORMMETHOD(platform_attach, ipq4018_attach),
220
PLATFORMMETHOD(platform_devmap_init, ipq4018_devmap_init),
221
PLATFORMMETHOD(platform_late_init, ipq4018_late_init),
222
PLATFORMMETHOD(platform_cpu_reset, ipq4018_cpu_reset),
223
224
#ifdef SMP
225
PLATFORMMETHOD(platform_mp_start_ap, ipq4018_mp_start_ap),
226
PLATFORMMETHOD(platform_mp_setmaxid, ipq4018_mp_setmaxid),
227
#endif
228
229
PLATFORMMETHOD_END,
230
};
231
232
FDT_PLATFORM_DEF2(ipq4018, ipq4018_ac58u, "ASUS RT-AC58U", 0,
233
"asus,rt-ac58u", 80);
234
235