1 /* $NetBSD: rk_platform.c,v 1.18 2025/09/06 21:02:40 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2018,2021 Jared McNeill <jmcneill (at) 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_soc.h" 30 #include "opt_multiprocessor.h" 31 #include "opt_console.h" 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: rk_platform.c,v 1.18 2025/09/06 21:02:40 thorpej Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/bus.h> 38 #include <sys/cpu.h> 39 #include <sys/device.h> 40 #include <sys/termios.h> 41 42 #include <dev/fdt/fdtvar.h> 43 #include <dev/fdt/fdt_platform.h> 44 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 52 #include <arm/cortex/gtmr_var.h> 53 54 #include <dev/ic/ns16550reg.h> 55 #include <dev/ic/comreg.h> 56 57 #include <arm/arm/psci.h> 58 #include <arm/fdt/psci_fdtvar.h> 59 60 #include <libfdt.h> 61 62 extern struct arm32_bus_dma_tag arm_generic_dma_tag; 63 extern struct bus_space arm_generic_bs_tag; 64 65 static void 66 rk_platform_init_attach_args(struct fdt_attach_args *faa) 67 { 68 faa->faa_bst = &arm_generic_bs_tag; 69 faa->faa_dmat = &arm_generic_dma_tag; 70 } 71 72 static void 73 rk_platform_device_register(device_t self, void *aux) 74 { 75 } 76 77 static void 78 rk_platform_bootstrap(void) 79 { 80 void *fdt_data = __UNCONST(fdtbus_get_data()); 81 82 arm_fdt_cpu_bootstrap(); 83 84 const int chosen_off = fdt_path_offset(fdt_data, "/chosen"); 85 if (chosen_off < 0) 86 return; 87 88 if (match_bootconf_option(boot_args, "console", "fb")) { 89 const int framebuffer_off = 90 fdt_path_offset(fdt_data, "/chosen/framebuffer"); 91 if (framebuffer_off >= 0) { 92 const char *status = fdt_getprop(fdt_data, 93 framebuffer_off, "status", NULL); 94 if (status == NULL || strncmp(status, "ok", 2) == 0) { 95 fdt_setprop_string(fdt_data, chosen_off, 96 "stdout-path", "/chosen/framebuffer"); 97 } 98 } 99 } else if (match_bootconf_option(boot_args, "console", "serial")) { 100 fdt_setprop_string(fdt_data, chosen_off, 101 "stdout-path", "serial0:115200n8"); 102 } 103 } 104 105 #ifdef SOC_RK3288 106 107 #define RK3288_WDT_BASE 0xff800000 108 #define RK3288_WDT_SIZE 0x10000 109 110 #define RK3288_WDT_CR 0x0000 111 #define RK3288_WDT_CR_WDT_EN __BIT(0) 112 #define RK3288_WDT_TORR 0x0004 113 #define RK3288_WDT_CRR 0x000c 114 #define RK3288_WDT_MAGIC 0x76 115 116 static bus_space_handle_t rk3288_wdt_bsh; 117 118 #include <arm/rockchip/rk3288_platform.h> 119 120 static const struct pmap_devmap * 121 rk3288_platform_devmap(void) 122 { 123 static const struct pmap_devmap devmap[] = { 124 DEVMAP_ENTRY(RK3288_CORE_VBASE, 125 RK3288_CORE_PBASE, 126 RK3288_CORE_SIZE), 127 DEVMAP_ENTRY_END 128 }; 129 130 return devmap; 131 } 132 133 void rk3288_platform_early_putchar(char); 134 135 void __noasan 136 rk3288_platform_early_putchar(char c) 137 { 138 #ifdef CONSADDR 139 #define CONSADDR_VA ((CONSADDR - RK3288_CORE_PBASE) + RK3288_CORE_VBASE) 140 volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ? 141 (volatile uint32_t *)CONSADDR_VA : 142 (volatile uint32_t *)CONSADDR; 143 144 while ((le32toh(uartaddr[com_lsr]) & LSR_TXRDY) == 0) 145 ; 146 147 uartaddr[com_data] = htole32(c); 148 #undef CONSADDR_VA 149 #endif 150 } 151 152 static void 153 rk3288_platform_bootstrap(void) 154 { 155 bus_space_tag_t bst = &arm_generic_bs_tag; 156 157 rk_platform_bootstrap(); 158 bus_space_map(bst, RK3288_WDT_BASE, RK3288_WDT_SIZE, 0, &rk3288_wdt_bsh); 159 } 160 161 static void 162 rk3288_platform_reset(void) 163 { 164 bus_space_tag_t bst = &arm_generic_bs_tag; 165 166 bus_space_write_4(bst, rk3288_wdt_bsh, RK3288_WDT_TORR, 0); 167 bus_space_write_4(bst, rk3288_wdt_bsh, RK3288_WDT_CRR, RK3288_WDT_MAGIC); 168 for (;;) { 169 bus_space_write_4(bst, rk3288_wdt_bsh, RK3288_WDT_CR, RK3288_WDT_CR_WDT_EN); 170 } 171 } 172 173 static u_int 174 rk3288_platform_uart_freq(void) 175 { 176 return RK3288_UART_FREQ; 177 } 178 179 static const struct fdt_platform rk3288_platform = { 180 .fp_devmap = rk3288_platform_devmap, 181 .fp_bootstrap = rk3288_platform_bootstrap, 182 .fp_init_attach_args = rk_platform_init_attach_args, 183 .fp_device_register = rk_platform_device_register, 184 .fp_reset = rk3288_platform_reset, 185 .fp_delay = gtmr_delay, 186 .fp_uart_freq = rk3288_platform_uart_freq, 187 .fp_mpstart = arm_fdt_cpu_mpstart, 188 }; 189 190 FDT_PLATFORM(rk3288, "rockchip,rk3288", &rk3288_platform); 191 #endif /* SOC_RK3288 */ 192 193 194 #ifdef SOC_RK3328 195 196 #include <arm/rockchip/rk3328_platform.h> 197 198 static const struct pmap_devmap * 199 rk3328_platform_devmap(void) 200 { 201 static const struct pmap_devmap devmap[] = { 202 DEVMAP_ENTRY(RK3328_CORE_VBASE, 203 RK3328_CORE_PBASE, 204 RK3328_CORE_SIZE), 205 DEVMAP_ENTRY_END 206 }; 207 208 return devmap; 209 } 210 211 void rk3328_platform_early_putchar(char); 212 213 void __noasan 214 rk3328_platform_early_putchar(char c) 215 { 216 #ifdef CONSADDR 217 #define CONSADDR_VA ((CONSADDR - RK3328_CORE_PBASE) + RK3328_CORE_VBASE) 218 volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ? 219 (volatile uint32_t *)CONSADDR_VA : 220 (volatile uint32_t *)CONSADDR; 221 222 while ((le32toh(uartaddr[com_lsr]) & LSR_TXRDY) == 0) 223 ; 224 225 uartaddr[com_data] = htole32(c); 226 #undef CONSADDR_VA 227 #endif 228 } 229 230 static u_int 231 rk3328_platform_uart_freq(void) 232 { 233 return RK3328_UART_FREQ; 234 } 235 236 static const struct fdt_platform rk3328_platform = { 237 .fp_devmap = rk3328_platform_devmap, 238 .fp_bootstrap = rk_platform_bootstrap, 239 .fp_init_attach_args = rk_platform_init_attach_args, 240 .fp_device_register = rk_platform_device_register, 241 .fp_reset = psci_fdt_reset, 242 .fp_delay = gtmr_delay, 243 .fp_uart_freq = rk3328_platform_uart_freq, 244 .fp_mpstart = arm_fdt_cpu_mpstart, 245 }; 246 247 FDT_PLATFORM(rk3328, "rockchip,rk3328", &rk3328_platform); 248 249 #endif /* SOC_RK3328 */ 250 251 252 #ifdef SOC_RK3399 253 254 #include <arm/rockchip/rk3399_platform.h> 255 256 static const struct pmap_devmap * 257 rk3399_platform_devmap(void) 258 { 259 static const struct pmap_devmap devmap[] = { 260 DEVMAP_ENTRY(RK3399_CORE_VBASE, 261 RK3399_CORE_PBASE, 262 RK3399_CORE_SIZE), 263 DEVMAP_ENTRY_END 264 }; 265 266 return devmap; 267 } 268 269 void rk3399_platform_early_putchar(char); 270 271 void 272 rk3399_platform_early_putchar(char c) 273 { 274 #ifdef CONSADDR 275 #define CONSADDR_VA ((CONSADDR - RK3399_CORE_PBASE) + RK3399_CORE_VBASE) 276 volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ? 277 (volatile uint32_t *)CONSADDR_VA : 278 (volatile uint32_t *)CONSADDR; 279 280 while ((le32toh(uartaddr[com_lsr]) & LSR_TXRDY) == 0) 281 ; 282 283 uartaddr[com_data] = htole32(c); 284 #undef CONSADDR_VA 285 #endif 286 } 287 288 static u_int 289 rk3399_platform_uart_freq(void) 290 { 291 return RK3399_UART_FREQ; 292 } 293 294 static const struct fdt_platform rk3399_platform = { 295 .fp_devmap = rk3399_platform_devmap, 296 .fp_bootstrap = rk_platform_bootstrap, 297 .fp_init_attach_args = rk_platform_init_attach_args, 298 .fp_device_register = rk_platform_device_register, 299 .fp_reset = psci_fdt_reset, 300 .fp_delay = gtmr_delay, 301 .fp_uart_freq = rk3399_platform_uart_freq, 302 .fp_mpstart = arm_fdt_cpu_mpstart, 303 }; 304 305 FDT_PLATFORM(rk3399, "rockchip,rk3399", &rk3399_platform); 306 307 #endif /* SOC_RK3399 */ 308 309 310 #ifdef SOC_RK3588 311 312 #include <arm/rockchip/rk3588_platform.h> 313 314 static const struct pmap_devmap * 315 rk3588_platform_devmap(void) 316 { 317 static const struct pmap_devmap devmap[] = { 318 DEVMAP_ENTRY( 319 RK3588_CORE_VBASE, 320 RK3588_CORE_PBASE, 321 RK3588_CORE_SIZE), 322 DEVMAP_ENTRY_END 323 }; 324 325 return devmap; 326 } 327 328 void rk3588_platform_early_putchar(char); 329 330 void 331 rk3588_platform_early_putchar(char c) 332 { 333 #ifdef CONSADDR 334 #define CONSADDR_VA ((CONSADDR - RK3588_CORE_PBASE) + RK3588_CORE_VBASE) 335 volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ? 336 (volatile uint32_t *)CONSADDR_VA : 337 (volatile uint32_t *)CONSADDR; 338 339 while ((le32toh(uartaddr[com_lsr]) & LSR_TXRDY) == 0) 340 ; 341 342 uartaddr[com_data] = htole32(c); 343 #undef CONSADDR_VA 344 #endif 345 } 346 347 static u_int 348 rk3588_platform_uart_freq(void) 349 { 350 return RK3588_UART_FREQ; 351 } 352 353 static const struct fdt_platform rk3588_platform = { 354 .fp_devmap = rk3588_platform_devmap, 355 .fp_bootstrap = rk_platform_bootstrap, 356 .fp_init_attach_args = rk_platform_init_attach_args, 357 .fp_device_register = rk_platform_device_register, 358 .fp_reset = psci_fdt_reset, 359 .fp_delay = gtmr_delay, 360 .fp_uart_freq = rk3588_platform_uart_freq, 361 .fp_mpstart = arm_fdt_cpu_mpstart, 362 }; 363 364 FDT_PLATFORM(rk3588, "rockchip,rk3588", &rk3588_platform); 365 366 #endif /* SOC_RK3588 */ 367 368