Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/broadcom/bcm2835/bcm2835_vcbus.c
39566 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2019 Kyle Evans <[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 <sys/cdefs.h>
29
/*
30
* This file contains facilities for runtime determination of address space
31
* mappings for use in DMA/mailbox interactions. This is only used for the
32
* arm64 SoC because the 32-bit SoC used the same mappings.
33
*/
34
35
#include <sys/types.h>
36
#include <sys/systm.h>
37
38
#include <dev/ofw/openfirm.h>
39
#include <dev/ofw/ofw_bus.h>
40
#include <dev/ofw/ofw_bus_subr.h>
41
42
#include <machine/bus.h>
43
44
#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
45
46
/*
47
* This structure describes mappings that need to take place when transforming
48
* ARM core addresses into vcbus addresses for use with the DMA/mailbox
49
* interfaces. Currently, we only deal with peripheral/SDRAM address spaces
50
* here.
51
*
52
* The SDRAM address space is consistently mapped starting at 0 and extends to
53
* the size of the installed SDRAM.
54
*
55
* Peripherals are mapped further up at spots that vary per-SOC.
56
*/
57
struct bcm283x_memory_mapping {
58
vm_paddr_t armc_start;
59
vm_paddr_t armc_size;
60
vm_paddr_t vcbus_start;
61
};
62
63
static struct bcm283x_memory_mapping bcm2835_memmap[] = {
64
{
65
/* SDRAM */
66
.armc_start = 0x00000000,
67
.armc_size = BCM2835_ARM_IO_BASE,
68
.vcbus_start = BCM2835_VCBUS_SDRAM_BASE,
69
},
70
{
71
/* Peripherals */
72
.armc_start = BCM2835_ARM_IO_BASE,
73
.armc_size = BCM28XX_ARM_IO_SIZE,
74
.vcbus_start = BCM2835_VCBUS_IO_BASE,
75
},
76
{ 0, 0, 0 },
77
};
78
79
static struct bcm283x_memory_mapping bcm2836_memmap[] = {
80
{
81
/* SDRAM */
82
.armc_start = 0x00000000,
83
.armc_size = BCM2836_ARM_IO_BASE,
84
.vcbus_start = BCM2836_VCBUS_SDRAM_BASE,
85
},
86
{
87
/* Peripherals */
88
.armc_start = BCM2836_ARM_IO_BASE,
89
.armc_size = BCM28XX_ARM_IO_SIZE,
90
.vcbus_start = BCM2836_VCBUS_IO_BASE,
91
},
92
{ 0, 0, 0 },
93
};
94
95
static struct bcm283x_memory_mapping bcm2837_memmap[] = {
96
{
97
/* SDRAM */
98
.armc_start = 0x00000000,
99
.armc_size = BCM2837_ARM_IO_BASE,
100
.vcbus_start = BCM2837_VCBUS_SDRAM_BASE,
101
},
102
{
103
/* Peripherals */
104
.armc_start = BCM2837_ARM_IO_BASE,
105
.armc_size = BCM28XX_ARM_IO_SIZE,
106
.vcbus_start = BCM2837_VCBUS_IO_BASE,
107
},
108
{ 0, 0, 0 },
109
};
110
111
/*
112
* The BCM2838 supports up to 4GB of SDRAM, but unfortunately we can still only
113
* map the first 1GB into the "legacy master view" (vcbus) address space. Thus,
114
* peripherals can still only access the lower end of SDRAM. For this reason,
115
* we also capture the main-peripheral busdma restriction below.
116
*/
117
static struct bcm283x_memory_mapping bcm2838_memmap[] = {
118
{
119
/* SDRAM */
120
.armc_start = 0x00000000,
121
.armc_size = 0x40000000,
122
.vcbus_start = BCM2838_VCBUS_SDRAM_BASE,
123
},
124
{
125
/* Main peripherals */
126
.armc_start = BCM2838_ARM_IO_BASE,
127
.armc_size = BCM28XX_ARM_IO_SIZE,
128
.vcbus_start = BCM2838_VCBUS_IO_BASE,
129
},
130
{ 0, 0, 0 },
131
};
132
133
static struct bcm283x_memory_soc_cfg {
134
struct bcm283x_memory_mapping *memmap;
135
const char *soc_compat;
136
bus_addr_t busdma_lowaddr;
137
} bcm283x_memory_configs[] = {
138
/* Legacy */
139
{
140
.memmap = bcm2835_memmap,
141
.soc_compat = "raspberrypi,model-b",
142
.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
143
},
144
/* Modern */
145
{
146
.memmap = bcm2835_memmap,
147
.soc_compat = "brcm,bcm2835",
148
.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
149
},
150
/* Legacy */
151
{
152
.memmap = bcm2836_memmap,
153
.soc_compat = "brcm,bcm2709",
154
.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
155
},
156
/* Modern */
157
{
158
.memmap = bcm2836_memmap,
159
.soc_compat = "brcm,bcm2836",
160
.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
161
},
162
{
163
.memmap = bcm2837_memmap,
164
.soc_compat = "brcm,bcm2837",
165
.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
166
},
167
{
168
.memmap = bcm2838_memmap,
169
.soc_compat = "brcm,bcm2711",
170
.busdma_lowaddr = BCM2838_PERIPH_MAXADDR,
171
},
172
{
173
.memmap = bcm2838_memmap,
174
.soc_compat = "brcm,bcm2838",
175
.busdma_lowaddr = BCM2838_PERIPH_MAXADDR,
176
},
177
};
178
179
static struct bcm283x_memory_soc_cfg *booted_soc_memcfg;
180
181
static struct bcm283x_memory_soc_cfg *
182
bcm283x_get_current_memcfg(void)
183
{
184
phandle_t root;
185
int i;
186
187
/* We'll cache it once we decide, because it won't change per-boot. */
188
if (booted_soc_memcfg != NULL)
189
return (booted_soc_memcfg);
190
191
KASSERT(nitems(bcm283x_memory_configs) != 0,
192
("No SOC memory configurations enabled!"));
193
194
root = OF_finddevice("/");
195
for (i = 0; i < nitems(bcm283x_memory_configs); ++i) {
196
booted_soc_memcfg = &bcm283x_memory_configs[i];
197
if (bootverbose)
198
printf("Checking root against %s\n",
199
booted_soc_memcfg->soc_compat);
200
if (ofw_bus_node_is_compatible(root,
201
booted_soc_memcfg->soc_compat))
202
return (booted_soc_memcfg);
203
}
204
205
/*
206
* The kernel doesn't fit the board; we can't really make a reasonable
207
* guess, as these SOC are different enough that something will blow up
208
* later.
209
*/
210
panic("No suitable SOC memory configuration found.");
211
}
212
213
#define BCM283X_MEMMAP_ISTERM(ent) \
214
((ent)->armc_start == 0 && (ent)->armc_size == 0 && \
215
(ent)->vcbus_start == 0)
216
217
vm_paddr_t
218
bcm283x_armc_to_vcbus(vm_paddr_t pa)
219
{
220
struct bcm283x_memory_soc_cfg *cfg;
221
struct bcm283x_memory_mapping *map, *ment;
222
223
/* Guaranteed not NULL if we haven't panicked yet. */
224
cfg = bcm283x_get_current_memcfg();
225
map = cfg->memmap;
226
for (ment = map; !BCM283X_MEMMAP_ISTERM(ment); ++ment) {
227
if (pa >= ment->armc_start &&
228
pa < ment->armc_start + ment->armc_size) {
229
return (pa - ment->armc_start) + ment->vcbus_start;
230
}
231
}
232
233
/*
234
* Assume 1:1 mapping for anything else, but complain about it on
235
* verbose boots.
236
*/
237
if (bootverbose)
238
printf("bcm283x_vcbus: No armc -> vcbus mapping found: %jx\n",
239
(uintmax_t)pa);
240
return (pa);
241
}
242
243
vm_paddr_t
244
bcm283x_vcbus_to_armc(vm_paddr_t vca)
245
{
246
struct bcm283x_memory_soc_cfg *cfg;
247
struct bcm283x_memory_mapping *map, *ment;
248
249
/* Guaranteed not NULL if we haven't panicked yet. */
250
cfg = bcm283x_get_current_memcfg();
251
map = cfg->memmap;
252
for (ment = map; !BCM283X_MEMMAP_ISTERM(ment); ++ment) {
253
if (vca >= ment->vcbus_start &&
254
vca < ment->vcbus_start + ment->armc_size) {
255
return (vca - ment->vcbus_start) + ment->armc_start;
256
}
257
}
258
259
/*
260
* Assume 1:1 mapping for anything else, but complain about it on
261
* verbose boots.
262
*/
263
if (bootverbose)
264
printf("bcm283x_vcbus: No vcbus -> armc mapping found: %jx\n",
265
(uintmax_t)vca);
266
return (vca);
267
}
268
269
bus_addr_t
270
bcm283x_dmabus_peripheral_lowaddr(void)
271
{
272
struct bcm283x_memory_soc_cfg *cfg;
273
274
cfg = bcm283x_get_current_memcfg();
275
return (cfg->busdma_lowaddr);
276
}
277
278