Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm64/spe/arm_spe_acpi.c
96295 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2024 Arm Ltd
5
* Copyright (c) 2022 The FreeBSD Foundation
6
*
7
* Portions of this software were developed by Andrew Turner under sponsorship
8
* from the FreeBSD Foundation.
9
*
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
12
* are met:
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*/
31
32
#include <sys/param.h>
33
#include <sys/bus.h>
34
#include <sys/kernel.h>
35
#include <sys/lock.h>
36
#include <sys/module.h>
37
#include <sys/mutex.h>
38
39
#include <contrib/dev/acpica/include/acpi.h>
40
#include <dev/acpica/acpivar.h>
41
42
#include <arm64/spe/arm_spe_dev.h>
43
44
static device_identify_t arm_spe_acpi_identify;
45
static device_probe_t arm_spe_acpi_probe;
46
47
static device_method_t arm_spe_acpi_methods[] = {
48
/* Device interface */
49
DEVMETHOD(device_identify, arm_spe_acpi_identify),
50
DEVMETHOD(device_probe, arm_spe_acpi_probe),
51
52
DEVMETHOD_END,
53
};
54
55
DEFINE_CLASS_1(spe, arm_spe_acpi_driver, arm_spe_acpi_methods,
56
sizeof(struct arm_spe_softc), arm_spe_driver);
57
58
DRIVER_MODULE(spe, acpi, arm_spe_acpi_driver, 0, 0);
59
60
struct madt_data {
61
u_int irq;
62
bool found;
63
bool valid;
64
};
65
66
static void
67
madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
68
{
69
ACPI_MADT_GENERIC_INTERRUPT *intr;
70
struct madt_data *madt_data;
71
u_int irq;
72
73
madt_data = (struct madt_data *)arg;
74
75
/* Exit early if we are have decided to not attach */
76
if (!madt_data->valid)
77
return;
78
79
switch(entry->Type) {
80
case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
81
intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry;
82
irq = intr->SpeInterrupt;
83
84
if (irq == 0) {
85
madt_data->valid = false;
86
} else if (!madt_data->found) {
87
madt_data->found = true;
88
madt_data->irq = irq;
89
} else if (madt_data->irq != irq) {
90
madt_data->valid = false;
91
}
92
break;
93
94
default:
95
break;
96
}
97
}
98
99
static void
100
arm_spe_acpi_identify(driver_t *driver, device_t parent)
101
{
102
struct madt_data madt_data;
103
ACPI_TABLE_MADT *madt;
104
device_t dev;
105
vm_paddr_t physaddr;
106
107
physaddr = acpi_find_table(ACPI_SIG_MADT);
108
if (physaddr == 0)
109
return;
110
111
madt = acpi_map_table(physaddr, ACPI_SIG_MADT);
112
if (madt == NULL) {
113
device_printf(parent, "spe: Unable to map the MADT\n");
114
return;
115
}
116
117
madt_data.irq = 0;
118
madt_data.found = false;
119
madt_data.valid = true;
120
121
acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
122
madt_handler, &madt_data);
123
124
if (!madt_data.found || !madt_data.valid)
125
goto out;
126
127
MPASS(madt_data.irq != 0);
128
129
dev = BUS_ADD_CHILD(parent, 0, "spe", -1);
130
if (dev == NULL) {
131
device_printf(parent, "add spe child failed\n");
132
goto out;
133
}
134
135
BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 0, madt_data.irq, 1);
136
137
out:
138
acpi_unmap_table(madt);
139
}
140
141
static int
142
arm_spe_acpi_probe(device_t dev)
143
{
144
device_set_desc(dev, "ARM Statistical Profiling Extension");
145
return (BUS_PROBE_NOWILDCARD);
146
}
147
148