acpi_platform.c revision 1.4 1 /* $NetBSD: acpi_platform.c,v 1.4 2018/10/19 15:29:00 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jared McNeill <jmcneill (at) invisible.ca>.
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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "com.h"
33 #include "plcom.h"
34
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: acpi_platform.c,v 1.4 2018/10/19 15:29:00 jmcneill Exp $");
37
38 #include <sys/param.h>
39 #include <sys/bus.h>
40 #include <sys/cpu.h>
41 #include <sys/device.h>
42 #include <sys/termios.h>
43
44 #include <dev/fdt/fdtvar.h>
45 #include <arm/fdt/arm_fdtvar.h>
46
47 #include <uvm/uvm_extern.h>
48
49 #include <machine/bootconfig.h>
50 #include <arm/cpufunc.h>
51 #include <arm/locore.h>
52
53 #include <arm/cortex/gtmr_var.h>
54
55 #include <arm/arm/psci.h>
56 #include <arm/fdt/psci_fdtvar.h>
57
58 #include <evbarm/fdt/platform.h>
59
60 #include <evbarm/dev/plcomreg.h>
61 #include <evbarm/dev/plcomvar.h>
62 #include <dev/ic/ns16550reg.h>
63 #include <dev/ic/comreg.h>
64 #include <dev/ic/comvar.h>
65
66 #include <dev/acpi/acpireg.h>
67 #include <dev/acpi/acpivar.h>
68 #include <arch/arm/acpi/acpi_table.h>
69
70 #define SPCR_INTERFACE_TYPE_PL011 0x0003
71 #define SPCR_INTERFACE_TYPE_SBSA_32BIT 0x000d
72 #define SPCR_INTERFACE_TYPE_SBSA_GENERIC 0x000e
73 #define SPCR_INTERFACE_TYPE_BCM2835 0x0010
74
75 #define SPCR_BAUD_UNKNOWN 0
76 #define SPCR_BAUD_9600 3
77 #define SPCR_BAUD_19200 4
78 #define SPCR_BAUD_57600 6
79 #define SPCR_BAUD_115200 7
80
81 extern struct bus_space arm_generic_bs_tag;
82 extern struct bus_space arm_generic_a4x_bs_tag;
83
84 static struct plcom_instance plcom_console;
85
86 static const struct pmap_devmap *
87 acpi_platform_devmap(void)
88 {
89 static const struct pmap_devmap devmap[] = {
90 DEVMAP_ENTRY_END
91 };
92
93 return devmap;
94 }
95
96 static void
97 acpi_platform_bootstrap(void)
98 {
99 }
100
101 static void
102 acpi_platform_startup(void)
103 {
104 ACPI_TABLE_SPCR *spcr;
105 ACPI_TABLE_FADT *fadt;
106 ACPI_TABLE_MADT *madt;
107 int baud_rate;
108
109 /*
110 * Setup serial console device
111 */
112 if (ACPI_SUCCESS(acpi_table_find(ACPI_SIG_SPCR, (void **)&spcr))) {
113
114 switch (spcr->BaudRate) {
115 case SPCR_BAUD_9600:
116 baud_rate = 9600;
117 break;
118 case SPCR_BAUD_19200:
119 baud_rate = 19200;
120 break;
121 case SPCR_BAUD_57600:
122 baud_rate = 57600;
123 break;
124 case SPCR_BAUD_115200:
125 case SPCR_BAUD_UNKNOWN:
126 default:
127 baud_rate = 115200;
128 break;
129 }
130
131 if (spcr->SerialPort.SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY &&
132 spcr->SerialPort.Address != 0) {
133 switch (spcr->InterfaceType) {
134 #if NPLCOM > 0
135 case SPCR_INTERFACE_TYPE_PL011:
136 case SPCR_INTERFACE_TYPE_SBSA_32BIT:
137 case SPCR_INTERFACE_TYPE_SBSA_GENERIC:
138 plcom_console.pi_type = PLCOM_TYPE_PL011;
139 plcom_console.pi_iot = &arm_generic_bs_tag;
140 plcom_console.pi_iobase = spcr->SerialPort.Address;
141 plcom_console.pi_size = PL011COM_UART_SIZE;
142 if (spcr->InterfaceType == SPCR_INTERFACE_TYPE_SBSA_32BIT) {
143 plcom_console.pi_flags = PLC_FLAG_32BIT_ACCESS;
144 } else {
145 plcom_console.pi_flags = ACPI_ACCESS_BIT_WIDTH(spcr->SerialPort.AccessWidth) == 8 ?
146 0 : PLC_FLAG_32BIT_ACCESS;
147 }
148
149 plcomcnattach(&plcom_console, baud_rate, 0, TTYDEF_CFLAG, -1);
150 break;
151 #endif
152 #if NCOM > 0
153 case SPCR_INTERFACE_TYPE_BCM2835:
154 comcnattach(&arm_generic_a4x_bs_tag, spcr->SerialPort.Address + 0x40, baud_rate, -1,
155 COM_TYPE_BCMAUXUART, TTYDEF_CFLAG);
156 cn_set_magic("+++++");
157 break;
158 #endif
159 default:
160 printf("SPCR: kernel does not support interface type %#x\n", spcr->InterfaceType);
161 break;
162 }
163 }
164 acpi_table_unmap((ACPI_TABLE_HEADER *)spcr);
165 }
166
167 /*
168 * Initialize PSCI 0.2+ if implemented
169 */
170 if (ACPI_SUCCESS(acpi_table_find(ACPI_SIG_FADT, (void **)&fadt))) {
171 if (fadt->ArmBootFlags & ACPI_FADT_PSCI_COMPLIANT) {
172 if (fadt->ArmBootFlags & ACPI_FADT_PSCI_USE_HVC) {
173 psci_init(psci_call_hvc);
174 } else {
175 psci_init(psci_call_smc);
176 }
177 }
178 acpi_table_unmap((ACPI_TABLE_HEADER *)fadt);
179 }
180
181 /*
182 * Count CPUs
183 */
184 if (ACPI_SUCCESS(acpi_table_find(ACPI_SIG_MADT, (void **)&madt))) {
185 char *end = (char *)madt + madt->Header.Length;
186 char *where = (char *)madt + sizeof(ACPI_TABLE_MADT);
187 while (where < end) {
188 ACPI_SUBTABLE_HEADER *subtable = (ACPI_SUBTABLE_HEADER *)where;
189 if (subtable->Type == ACPI_MADT_TYPE_GENERIC_INTERRUPT)
190 arm_cpu_max++;
191 where += subtable->Length;
192 }
193 acpi_table_unmap((ACPI_TABLE_HEADER *)madt);
194 }
195 }
196
197 static void
198 acpi_platform_init_attach_args(struct fdt_attach_args *faa)
199 {
200 extern struct arm32_bus_dma_tag arm_generic_dma_tag;
201 extern struct bus_space arm_generic_bs_tag;
202 extern struct bus_space arm_generic_a4x_bs_tag;
203
204 faa->faa_bst = &arm_generic_bs_tag;
205 faa->faa_a4x_bst = &arm_generic_a4x_bs_tag;
206 faa->faa_dmat = &arm_generic_dma_tag;
207 }
208
209 static void
210 acpi_platform_early_putchar(char c)
211 {
212 }
213
214 static void
215 acpi_platform_device_register(device_t self, void *aux)
216 {
217 }
218
219 static void
220 acpi_platform_reset(void)
221 {
222 if (psci_available())
223 psci_system_reset();
224 }
225
226 static u_int
227 acpi_platform_uart_freq(void)
228 {
229 return 0;
230 }
231
232 static const struct arm_platform acpi_platform = {
233 .ap_devmap = acpi_platform_devmap,
234 .ap_bootstrap = acpi_platform_bootstrap,
235 .ap_startup = acpi_platform_startup,
236 .ap_init_attach_args = acpi_platform_init_attach_args,
237 .ap_early_putchar = acpi_platform_early_putchar,
238 .ap_device_register = acpi_platform_device_register,
239 .ap_reset = acpi_platform_reset,
240 .ap_delay = gtmr_delay,
241 .ap_uart_freq = acpi_platform_uart_freq,
242 };
243
244 ARM_PLATFORM(virt, "netbsd,generic-acpi", &acpi_platform);
245