1#include <armv8_imx8x.h> 2#include <barrelfish/barrelfish.h> 3#include <barrelfish/nameservice_client.h> 4#include <barrelfish/spawn_client.h> 5#include <skb/skb.h> 6#include <barrelfish_kpi/platform.h> 7#include <if/monitor_blocking_defs.h> 8#include "kaluga.h" 9#include <pci/pci.h> 10 11// For booting cores 12#include <hw_records_arch.h> 13#include <barrelfish/cpu_arch.h> 14 15static errval_t armv8_startup_common_noacpi(void) 16{ 17 errval_t err = SYS_ERR_OK; 18 19 // We need to run on core 0 20 // (we are responsible for booting all the other cores) 21 assert(my_core_id == BSP_CORE_ID); 22 23 err = skb_client_connect(); 24 if (err_is_fail(err)) { 25 USER_PANIC_ERR(err, "Connect to SKB."); 26 } 27 28 // Make sure the driver db is loaded 29 err = skb_execute("[device_db]."); 30 if (err_is_fail(err)) { 31 USER_PANIC_ERR(err, "Device DB not loaded."); 32 } 33 34 err = skb_execute("[plat_imx8x]."); 35 if (err_is_fail(err)) { 36 USER_PANIC_ERR(err, "Plat imx8x not loaded."); 37 } 38 39 KALUGA_DEBUG("Kaluga: pci_root_bridge\n"); 40 41 err = watch_for_pci_root_bridge(); 42 if (err_is_fail(err)) { 43 USER_PANIC_ERR(err, "Watching PCI root bridges."); 44 } 45 46 KALUGA_DEBUG("Kaluga: pci_devices\n"); 47 48 err = watch_for_pci_devices(); 49 if (err_is_fail(err)) { 50 USER_PANIC_ERR(err, "Watching PCI devices."); 51 } 52 53 return SYS_ERR_OK; 54} 55 56static inline errval_t 57invoke_monitor_create_cap(uint64_t *raw, capaddr_t caddr, int level, capaddr_t slot, coreid_t owner) 58{ 59 struct capref my_cap_kernel = { 60 .cnode = cnode_task, 61 .slot = TASKCN_SLOT_KERNELCAP 62 }; 63 return cap_invoke6(my_cap_kernel, KernelCmd_Create_cap, caddr, level, slot, 64 owner, (uintptr_t)raw).error; 65} 66 67static errval_t imx8x_get_device_cap(lpaddr_t address, size_t size, struct capref *devframe) { 68 KALUGA_DEBUG("HACK: Forging cap directly in kaluga....\n"); 69 errval_t err; 70 err = slot_alloc(devframe); 71 assert(err_is_ok(err)); 72 capaddr_t caddr = get_cnode_addr(*devframe); 73 uint8_t level = get_cnode_level(*devframe); 74 size_t slot = devframe->slot; 75 76 assert(address % 4096 == 0); 77 assert(size % 4096 == 0); 78 79 struct capability the_cap = { 80 .type = ObjType_DevFrame, 81 .rights = CAPRIGHTS_ALLRIGHTS, 82 .u.devframe.base = address, 83 .u.devframe.bytes = size 84 }; 85 86 return invoke_monitor_create_cap((uint64_t*)&the_cap, caddr, level, slot, disp_get_core_id()); 87} 88__attribute__((used)) 89static errval_t start_gpio(char*name, lpaddr_t address) 90 91{ 92 errval_t err; 93 struct module_info *mi; 94 mi = find_module("imx8x_gpio"); 95 if(mi == NULL){ 96 KALUGA_DEBUG("imx8x_gpio not found, not starting\n"); 97 return KALUGA_ERR_MODULE_NOT_FOUND; 98 } 99 struct driver_argument arg; 100 init_driver_argument(&arg); 101 arg.module_name = "imx8x_gpio_module"; 102 struct capref device_frame; 103 err = imx8x_get_device_cap(address, 0x1000, &device_frame); 104 if(err_is_fail(err)){ 105 USER_PANIC_ERR(err, "get_device_cap"); 106 } 107 KALUGA_DEBUG("get_device_cap worked\n"); 108 //transfer destination 109 struct capref cap = { 110 .cnode = (&arg)->argnode_ref, 111 .slot = DRIVERKIT_ARGCN_SLOT_BAR0 112 }; 113 err = cap_copy(cap, device_frame); 114 if(err_is_fail(err)){ 115 USER_PANIC_ERR(err, "get_device_cap"); 116 } 117 err = default_start_function_pure(0, mi, name, &arg); 118 if(err_is_fail(err)){ 119 USER_PANIC_ERR(err, "get_device_cap"); 120 } 121 return err; 122} 123 124__attribute__((used)) 125static errval_t imx8x_serial_kernel(void) 126 127{ errval_t err; 128 struct module_info *mi; 129 mi = find_module("serial_kernel"); 130 struct driver_argument arg; 131 init_driver_argument(&arg); 132 arg.flags = 1; // disable interrupt 133 arg.module_name = "serial_kernel"; 134 err = default_start_function_pure(0, mi,"serial_kernel {}", &arg); 135 return err; 136} 137 138/* IMX8X Reference Manual page 65 */ 139#define UART0_INT 257 140#define UART1_INT 258 141#define UART2_INT 259 142#define UART3_INT 260 143#define DIST_OFFSET 1000 /* First interrupt index on the distributor */ 144 145__attribute__((used)) 146static errval_t start_serial_lpuart(lpaddr_t address, uint32_t irq) 147 148{ errval_t err; 149 struct module_info *mi; 150 151 // get module 152 mi = find_module("serial_lpuart"); 153 if(mi == NULL){ 154 KALUGA_DEBUG("serial_lpuart not found, not starting"); 155 return KALUGA_ERR_MODULE_NOT_FOUND; 156 } 157 struct driver_argument arg; 158 init_driver_argument(&arg); 159 arg.module_name = "serial_lpuart"; 160 161 // get device frame 162 struct capref device_frame; 163 err = imx8x_get_device_cap(address, 0x00010000, &device_frame); 164 if(err_is_fail(err)){ 165 USER_PANIC_ERR(err, "get_device_cap"); 166 } 167 KALUGA_DEBUG("got device frame for lpuart\n"); 168 169 170 struct capref cap = { 171 .cnode = arg.argnode_ref, 172 .slot = DRIVERKIT_ARGCN_SLOT_BAR0 173 }; 174 err = cap_copy(cap, device_frame); 175 if(err_is_fail(err)){ 176 USER_PANIC_ERR(err, "get_device_cap"); 177 } 178 179 // get irq src for lpuart 180 struct capref irq_src; 181 err = slot_alloc(&irq_src); 182 assert(err_is_ok(err)); 183 184 err = sys_debug_create_irq_src_cap(irq_src, irq + DIST_OFFSET, irq + DIST_OFFSET); 185 assert(err_is_ok(err)); 186 187 struct capref irq_dst = { 188 .cnode = arg.argnode_ref, 189 .slot = PCIARG_SLOT_INT 190 }; 191 err = cap_copy(irq_dst, irq_src); 192 if(err_is_fail(err)){ 193 DEBUG_ERR(err, "cap_copy\n"); 194 return err; 195 } 196 KALUGA_DEBUG("got irq src cap frame for lpuart\n"); 197 198 err = default_start_function_pure(0, mi, "serial_lpuart {}", &arg); 199 if(err_is_fail(err)){ 200 USER_PANIC_ERR(err, "get_device_cap"); 201 } 202 return err; 203} 204 205 206#define USDHC1_BASE 0x5B010000 207#define USDHC2_BASE 0x5B020000 208#define USDHC0_INT 264 209#define USDHC1_INT 265 210#define USDHC2_INT 266 211 212__attribute__((used)) 213static errval_t start_sdhc(lpaddr_t address, uint32_t irq) 214 215{ errval_t err; 216 struct module_info *mi; 217 218 // get module 219 mi = find_module("imx8x_sdhc"); 220 if(mi == NULL){ 221 KALUGA_DEBUG("imx8x_sdhc not found, not starting"); 222 return KALUGA_ERR_MODULE_NOT_FOUND; 223 } 224 struct driver_argument arg; 225 init_driver_argument(&arg); 226 arg.module_name = "sdhc"; 227 228 // get device frame 229 struct capref device_frame; 230 err = imx8x_get_device_cap(address, 0x00010000, &device_frame); 231 if(err_is_fail(err)){ 232 USER_PANIC_ERR(err, "get_device_cap"); 233 } 234 KALUGA_DEBUG("got device frame for sdhc\n"); 235 236 237 struct capref cap = { 238 .cnode = arg.argnode_ref, 239 .slot = DRIVERKIT_ARGCN_SLOT_BAR0 240 }; 241 err = cap_copy(cap, device_frame); 242 if(err_is_fail(err)){ 243 USER_PANIC_ERR(err, "get_device_cap"); 244 } 245 246 // get irq src for lpuart 247 struct capref irq_src; 248 err = slot_alloc(&irq_src); 249 assert(err_is_ok(err)); 250 251 err = sys_debug_create_irq_src_cap(irq_src, irq + DIST_OFFSET, irq + DIST_OFFSET); 252 assert(err_is_ok(err)); 253 254 struct capref irq_dst = { 255 .cnode = arg.argnode_ref, 256 .slot = PCIARG_SLOT_INT 257 }; 258 err = cap_copy(irq_dst, irq_src); 259 if(err_is_fail(err)){ 260 DEBUG_ERR(err, "cap_copy\n"); 261 return err; 262 } 263 KALUGA_DEBUG("got irq src cap frame for lpuart\n"); 264 265 err = default_start_function_pure(0, mi, "sdhc {}", &arg); 266 if(err_is_fail(err)){ 267 USER_PANIC_ERR(err, "get_device_cap"); 268 } 269 return err; 270} 271 272static lpaddr_t platform_gic_distributor_base = 0x51a00000; 273//static lpaddr_t platform_gic_redistributor_base = 0x51b00000; 274 275static errval_t 276start_int_route_domains(void) 277{ 278 errval_t err; 279 // Int route server 280 char *argv[] = {NULL}; 281 err = spawn_program(0, "int_route", argv, NULL, 0, NULL); 282 if(err_is_fail(err)){ 283 DEBUG_ERR(err,"int_route start"); 284 return err; 285 } 286 287 //Distributor driver 288 struct module_info *mi; 289 mi = find_module("pl390_dist"); 290 if(mi == NULL){ 291 KALUGA_DEBUG("pl390_dist not found, not starting\n"); 292 return KALUGA_ERR_MODULE_NOT_FOUND; 293 } 294 struct driver_argument arg; 295 init_driver_argument(&arg); 296 arg.module_name = "pl390_dist"; 297 struct capref device_frame; 298 299 err = imx8x_get_device_cap(platform_gic_distributor_base, 0x1000, &device_frame); 300 if(err_is_fail(err)){ 301 USER_PANIC_ERR(err, "get_device_cap"); 302 } 303 KALUGA_DEBUG("get_device_cap worked\n"); 304 //transfer destination 305 struct capref cap = { 306 .cnode = arg.argnode_ref, 307 .slot = 0 308 }; 309 err = cap_copy(cap, device_frame); 310 if(err_is_fail(err)){ 311 USER_PANIC_ERR(err, "get_device_cap"); 312 } 313 err = default_start_function_pure(0, mi, "gic.dist {}", &arg); 314 if(err_is_fail(err)){ 315 USER_PANIC_ERR(err, "get_device_cap"); 316 } 317 return err; 318 319 320} 321 322extern size_t cpu_count; 323 324static errval_t start_cores(void){ 325 /* We can't discover cores an ARMv8 embedded platforms. This 326 * works similar to armv7 startup. */ 327 errval_t err; 328 KALUGA_DEBUG("Kaluga: start_cores\n"); 329 330 err = skb_execute_query("findall(mpid(X), arm_mpid(X), Li), write(Li)."); 331 if (err_is_fail(err)) { 332 USER_PANIC_SKB_ERR(err, "Finding cores."); 333 } 334 int id; 335 struct list_parser_status skb_list; 336 skb_read_list_init(&skb_list); 337 size_t skb_cpus = 0; 338 while(skb_read_list(&skb_list, "mpid(%d)", &id)) { 339 skb_cpus++; 340 err = oct_set(HW_PROCESSOR_ARMV8_RECORD_FORMAT, id, 1 /*enabled*/, 341 id, id, CURRENT_CPU_TYPE, id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342 0, id); 343 if(err_is_fail(err)){ 344 USER_PANIC_ERR(err, "oct_set core"); 345 } 346 } 347 cpu_count = skb_cpus; 348 349 err = watch_for_cores(); 350 if (err_is_fail(err)) { 351 USER_PANIC_ERR(err, "Watching cores."); 352 } 353 354 err = wait_for_all_spawnds(0); 355 if (err_is_fail(err)) { 356 USER_PANIC_ERR(err, "Unable to wait for spawnds failed."); 357 } 358 return err; 359} 360 361__attribute__((used)) 362static errval_t start_network(lpaddr_t address) 363 364{ errval_t err; 365 struct module_info *mi; 366 mi = find_module("enet"); 367 if(mi == NULL){ 368 KALUGA_DEBUG("enet not found, not starting"); 369 return KALUGA_ERR_MODULE_NOT_FOUND; 370 } 371 struct driver_argument arg; 372 init_driver_argument(&arg); 373 arg.module_name = "enet_module"; 374 struct capref device_frame; 375 err = imx8x_get_device_cap(address, 0x00010000, &device_frame); 376 if(err_is_fail(err)){ 377 USER_PANIC_ERR(err, "get_device_cap"); 378 } 379 KALUGA_DEBUG("get_device_cap worked\n"); 380 //transfer destination 381 struct capref cap = { 382 .cnode = (&arg)->argnode_ref, 383 .slot = DRIVERKIT_ARGCN_SLOT_BAR0 384 }; 385 err = cap_copy(cap, device_frame); 386 if(err_is_fail(err)){ 387 USER_PANIC_ERR(err, "get_device_cap"); 388 } 389 390 err = default_start_function_pure(0, mi, "enet {}", &arg); 391 if(err_is_fail(err)){ 392 USER_PANIC_ERR(err, "get_device_cap"); 393 } 394 return err; 395} 396 397errval_t imx8x_startup(void) 398{ 399 errval_t err; 400 err = armv8_startup_common_noacpi(); 401 if(err_is_fail(err)){ 402 USER_PANIC_ERR(err, "startup common"); 403 } 404 405 err = start_cores(); 406 if(err_is_fail(err)) { 407 USER_PANIC_ERR(err, "start cores"); 408 } 409 410 err = start_int_route_domains(); 411 if(err_is_fail(err)) { 412 USER_PANIC_ERR(err, "start int_route"); 413 } 414 415 err = start_gpio("imx8x.gpio1 {}", 0x5D090000); 416 if(err_is_fail(err) && err_no(err) != KALUGA_ERR_MODULE_NOT_FOUND) { 417 USER_PANIC_ERR(err, "gpio1 start"); 418 } 419 err = start_gpio("imx8x.gpio2 {}", 0x5D0B0000); 420 if(err_is_fail(err) && err_no(err) != KALUGA_ERR_MODULE_NOT_FOUND) { 421 USER_PANIC_ERR(err, "gpio2 start"); 422 } 423 424 err = start_serial_lpuart(0x5A090000, UART3_INT); 425 if(err_is_fail(err) && err_no(err) != KALUGA_ERR_MODULE_NOT_FOUND) { 426 USER_PANIC_ERR(err, "imx8x serial lpuart"); 427 } 428 429 // SDHC2 is the one that is broken out on the carrier board. 430 err = start_sdhc(USDHC2_BASE, USDHC2_INT); 431 if(err_is_fail(err) && err_no(err) != KALUGA_ERR_MODULE_NOT_FOUND) { 432 USER_PANIC_ERR(err, "imx8x sdhc"); 433 } 434 435 err = start_network(0x5B040000); 436 if(err_is_fail(err) && err_no(err) != KALUGA_ERR_MODULE_NOT_FOUND) { 437 USER_PANIC_ERR(err, "imx8x network"); 438 } 439 440 return SYS_ERR_OK; 441} 442