xref: /netbsd-src/sys/arch/arm/vexpress/vexpress_platform.c (revision 42b9e898991e23b560315a9b1da6a36a39d4351b)
1 /* $NetBSD: vexpress_platform.c,v 1.17 2020/07/10 12:25:10 skrll Exp $ */
2 
3 /*-
4  * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include "opt_multiprocessor.h"
30 #include "opt_console.h"
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: vexpress_platform.c,v 1.17 2020/07/10 12:25:10 skrll Exp $");
34 
35 #include <sys/param.h>
36 #include <sys/bus.h>
37 #include <sys/cpu.h>
38 #include <sys/device.h>
39 #include <sys/termios.h>
40 
41 #include <dev/fdt/fdtvar.h>
42 
43 #include <uvm/uvm_extern.h>
44 
45 #include <machine/bootconfig.h>
46 #include <arm/cpufunc.h>
47 
48 #include <arm/fdt/arm_fdtvar.h>
49 
50 #include <arm/cortex/gtmr_var.h>
51 
52 #include <arm/cortex/gic_reg.h>
53 
54 #include <evbarm/dev/plcomreg.h>
55 #include <evbarm/fdt/machdep.h>
56 
57 #include <arm/vexpress/vexpress_platform.h>
58 
59 #include <libfdt.h>
60 
61 #define	VEXPRESS_REF_FREQ	24000000
62 
63 extern struct bus_space armv7_generic_bs_tag;
64 extern struct bus_space armv7_generic_a4x_bs_tag;
65 extern struct arm32_bus_dma_tag arm_generic_dma_tag;
66 
67 #define	SYSREG_BASE		0x1c010000
68 #define	SYSREG_SIZE		0x1000
69 
70 #define	SYS_FLAGS		0x0030
71 #define	SYS_FLAGSCLR		0x0034
72 #define	SYS_CFGDATA		0x00a0
73 #define	SYS_CFGCTRL		0x00a4
74 #define	 SYS_CFGCTRL_START	__BIT(31)
75 #define	 SYS_CFGCTRL_WRITE	__BIT(30)
76 #define	 SYS_CFGCTRL_DCC	__BITS(29,26)
77 #define	 SYS_CFGCTRL_FUNCTION	__BITS(25,20)
78 #define	  SYS_CFGCTRL_FUNCTION_SHUTDOWN	8
79 #define	  SYS_CFGCTRL_FUNCTION_REBOOT	9
80 #define	 SYS_CFGCTRL_SITE	__BITS(17,16)
81 #define	 SYS_CFGCTRL_POSITION	__BITS(15,12)
82 #define	 SYS_CFGCTRL_DEVICE	__BITS(11,0)
83 #define	SYS_CFGSTAT		0x00a8
84 #define	 SYS_CFGSTAT_ERROR	__BIT(1)
85 #define	 SYS_CFGSTAT_COMPLETE	__BIT(0)
86 
87 static bus_space_tag_t sysreg_bst = &armv7_generic_bs_tag;
88 static bus_space_handle_t sysreg_bsh;
89 
90 #define	SYSREG_WRITE(o, v)	\
91 	bus_space_write_4(sysreg_bst, sysreg_bsh, (o), (v))
92 
93 void vexpress_platform_early_putchar(char);
94 
95 void __noasan
96 vexpress_platform_early_putchar(char c)
97 {
98 #ifdef CONSADDR
99 #define CONSADDR_VA ((CONSADDR - VEXPRESS_CORE_PBASE) + VEXPRESS_CORE_VBASE)
100 	volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ?
101 	    (volatile uint32_t *)CONSADDR_VA :
102 	    (volatile uint32_t *)CONSADDR;
103 
104 	while ((le32toh(uartaddr[PL01XCOM_FR / 4]) & PL01X_FR_TXFF) != 0)
105 		continue;
106 
107 	uartaddr[PL01XCOM_DR / 4] = htole32(c);
108 	arm_dsb();
109 
110 	while ((le32toh(uartaddr[PL01XCOM_FR / 4]) & PL01X_FR_TXFE) == 0)
111 		continue;
112 #endif
113 }
114 
115 
116 static int
117 vexpress_a15_smp_init(void)
118 {
119 	int ret = 0;
120 #ifdef MULTIPROCESSOR
121 	bus_space_tag_t gicd_bst = &armv7_generic_bs_tag;
122 	bus_space_handle_t gicd_bsh;
123 
124 	/* Write init vec to SYS_FLAGS register */
125 	SYSREG_WRITE(SYS_FLAGSCLR, 0xffffffff);
126 	SYSREG_WRITE(SYS_FLAGS, KERN_VTOPHYS((vaddr_t)cpu_mpstart));
127 
128 	/* Map GIC distributor */
129 	bus_space_map(gicd_bst, VEXPRESS_GIC_PBASE + GICD_BASE,
130 	    0x1000, 0, &gicd_bsh);
131 
132 	/* Enable GIC distributor */
133 	bus_space_write_4(gicd_bst, gicd_bsh,
134 	    GICD_CTRL, GICD_CTRL_Enable);
135 
136 	/* Send sw interrupt to APs */
137 	const uint32_t sgir = GICD_SGIR_TargetListFilter_NotMe;
138 	bus_space_write_4(gicd_bst, gicd_bsh, GICD_SGIR, sgir);
139 
140 	/* Bitmask of CPUs (non-BSP) to start */
141 	for (u_int cpuindex = 1; cpuindex < arm_cpu_max; cpuindex++) {
142 		u_int i;
143 		for (i = 0x10000000; i > 0; i--) {
144 			if (cpu_hatched_p(cpuindex))
145 				break;
146 		}
147 
148 		if (i == 0) {
149 			ret++;
150 			aprint_error("cpu%d: WARNING: AP failed to start\n",
151 			    cpuindex);
152 		}
153 	}
154 
155 	/* Disable GIC distributor */
156 	bus_space_write_4(gicd_bst, gicd_bsh, GICD_CTRL, 0);
157 #endif
158 	return ret;
159 }
160 
161 
162 static const struct pmap_devmap *
163 vexpress_platform_devmap(void)
164 {
165 	static const struct pmap_devmap devmap[] = {
166 		DEVMAP_ENTRY(VEXPRESS_CORE_VBASE,
167 			     VEXPRESS_CORE_PBASE,
168 			     VEXPRESS_CORE_SIZE),
169 		DEVMAP_ENTRY(VEXPRESS_GIC_VBASE,
170 			     VEXPRESS_GIC_PBASE,
171 			     VEXPRESS_GIC_SIZE),
172 		DEVMAP_ENTRY_END
173 	};
174 
175 	return devmap;
176 }
177 
178 static void
179 vexpress_platform_bootstrap(void)
180 {
181 	bus_space_map(sysreg_bst, SYSREG_BASE, SYSREG_SIZE, 0,
182 	    &sysreg_bsh);
183 
184 #ifdef MULTIPROCESSOR
185 	arm_cpu_max = 1 + __SHIFTOUT(armreg_l2ctrl_read(), L2CTRL_NUMCPU);
186 #endif
187 }
188 
189 static void
190 vexpress_platform_init_attach_args(struct fdt_attach_args *faa)
191 {
192 	faa->faa_bst = &armv7_generic_bs_tag;
193 	faa->faa_a4x_bst = &armv7_generic_a4x_bs_tag;
194 	faa->faa_dmat = &arm_generic_dma_tag;
195 }
196 
197 static void
198 vexpress_platform_device_register(device_t self, void *aux)
199 {
200 }
201 
202 static void
203 vexpress_platform_reset(void)
204 {
205 	SYSREG_WRITE(SYS_CFGSTAT, 0);
206 	SYSREG_WRITE(SYS_CFGDATA, 0);
207 	SYSREG_WRITE(SYS_CFGCTRL,
208 	    SYS_CFGCTRL_START |
209 	    SYS_CFGCTRL_WRITE |
210 	    __SHIFTIN(SYS_CFGCTRL_FUNCTION_REBOOT,
211 		      SYS_CFGCTRL_FUNCTION));
212 }
213 
214 static u_int
215 vexpress_platform_uart_freq(void)
216 {
217 	return VEXPRESS_REF_FREQ;
218 }
219 
220 static const struct arm_platform vexpress_platform = {
221 	.ap_devmap = vexpress_platform_devmap,
222 	.ap_bootstrap = vexpress_platform_bootstrap,
223 	.ap_mpstart = vexpress_a15_smp_init,
224 	.ap_init_attach_args = vexpress_platform_init_attach_args,
225 	.ap_device_register = vexpress_platform_device_register,
226 	.ap_reset = vexpress_platform_reset,
227 	.ap_delay = gtmr_delay,
228 	.ap_uart_freq = vexpress_platform_uart_freq,
229 };
230 
231 ARM_PLATFORM(vexpress, "arm,vexpress", &vexpress_platform);
232