1/** 2 * \file 3 * \brief ARMv7 arch specfic code 4 */ 5 6/* 7 * Copyright (c) 2013, 2016 ETH Zurich. 8 * Copyright (c) 2015, Hewlett Packard Enterprise Development LP. 9 * All rights reserved. 10 * 11 * This file is distributed under the terms in the attached LICENSE file. 12 * If you do not find this file, copies can be found by writing to: 13 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 14 */ 15 16#include <hw_records_arch.h> 17#include <barrelfish/barrelfish.h> 18#include <barrelfish_kpi/platform.h> 19#include <if/monitor_blocking_defs.h> 20#include <maps/vexpress_map.h> 21#include <maps/omap44xx_map.h> 22#include <barrelfish/sys_debug.h> 23 24#include <skb/skb.h> 25#include <octopus/getset.h> 26 27#include "kaluga.h" 28#include <pci/pci.h> 29 30struct serial_conf { 31 char *name; 32 int irq; 33 lpaddr_t mem_base; 34 size_t mem_size; 35}; 36 37static struct serial_conf vexpress_uart_0 = { 38 .name = "serial_kernel", 39 //.name = "serial_pl011", 40 .irq = 37, 41 .mem_base = VEXPRESS_MAP_UART0, 42 .mem_size = VEXPRESS_MAP_UART0_SIZE 43}; 44 45static struct serial_conf omap44xx_uart_1 = { 46 .name = "serial_kernel", 47 //.name = "serial_omap44xx", 48 .irq = 106, 49 .mem_base = OMAP44XX_MAP_L4_PER_UART1, 50 .mem_size = OMAP44XX_MAP_L4_PER_UART1_SIZE 51}; 52 53static errval_t start_serial(struct serial_conf *c, coreid_t where){ 54 errval_t err; 55 56 /* Prepare module and cap */ 57 struct module_info *mi = find_module(c->name); 58 if (mi == NULL) { 59 debug_printf("Binary %s not found!\n", c->name); 60 return KALUGA_ERR_MODULE_NOT_FOUND; 61 } 62 63 struct driver_argument arg; 64 init_driver_argument(&arg); 65 arg.module_name = c->name; 66 67 // TODO Add caps for all cases 68 if(strcmp(c->name, "serial_kernel") == 0) { 69 // No caps needed 70 } else if (strcmp(c->name, "serial_pl011") == 0) { 71 struct capref mem_dst = { 72 .cnode = arg.argnode_ref, 73 .slot = PCIARG_SLOT_BAR0 74 }; 75 struct capref mem_src; 76 err = get_device_cap(c->mem_base, c->mem_size, &mem_src); 77 assert(err_is_ok(err)); 78 err = cap_copy(mem_dst, mem_src); 79 assert(err_is_ok(err)); 80 } else { 81 assert(!"NYI"); 82 } 83 84 struct capref irq_src; 85 err = slot_alloc(&irq_src); 86 assert(err_is_ok(err)); 87 88 err = sys_debug_create_irq_src_cap(irq_src, c->irq, c->irq); 89 assert(err_is_ok(err)); 90 91 struct capref irq_dst = { 92 .cnode = arg.argnode_ref, 93 .slot = PCIARG_SLOT_INT 94 }; 95 err = cap_copy(irq_dst, irq_src); 96 if(err_is_fail(err)){ 97 DEBUG_ERR(err, "cap_copy\n"); 98 return err; 99 } 100 101 err = mi->start_function(where, mi, "hw.arm.vexpress.uart", &arg); 102 if(err_is_fail(err)){ 103 DEBUG_ERR(err, "couldnt start gic dist on core=%d\n", where); 104 } 105 return err; 106} 107 108__attribute((__used__)) 109static void start_driverdomain(char* module_name, char* record) { 110 struct module_info* mi = find_module("driverdomain"); 111 struct driver_argument arg; 112 init_driver_argument(&arg); 113 arg.module_name = module_name; 114 if (mi != NULL) { 115 errval_t err = mi->start_function(0, mi, record, &arg); 116 assert(err_is_ok(err)); 117 } else { 118 debug_printf("driverdomain not found!\n"); 119 } 120} 121 122/** 123 * \brief Starts the gic distributor driver on every core 124 * 125 */ 126static errval_t start_gic_dist(lpaddr_t mem_base, coreid_t where){ 127 errval_t err; 128 129 /* Prepare module and cap */ 130 struct module_info *mi = find_module("driverdomain_pl390"); 131 if (mi == NULL) { 132 debug_printf("Binary driverdomain_pl390 not found!\n"); 133 return KALUGA_ERR_MODULE_NOT_FOUND; 134 } 135 struct capref dist_reg; 136 err = get_device_cap(mem_base, 0x1000, &dist_reg); 137 if(err_is_fail(err)){ 138 DEBUG_ERR(err, "Get gic_dist device cap\n"); 139 return err; 140 } 141 struct driver_argument arg; 142 init_driver_argument(&arg); 143 arg.module_name = "pl390_dist"; 144 struct capref dst = { 145 .cnode = arg.argnode_ref, 146 .slot = 0 147 }; 148 err = cap_copy(dst, dist_reg); 149 if(err_is_fail(err)){ 150 DEBUG_ERR(err, "cap_copy\n"); 151 return err; 152 } 153 154 /* Create Octopus records for the known cores. */ 155 char oct_key[128]; 156 snprintf(oct_key, sizeof(oct_key), "hw.arm.gic.dist.%d {}", where); 157 err = mi->start_function(where, mi, oct_key, &arg); 158 if(err_is_fail(err)){ 159 DEBUG_ERR(err, "couldnt start gic dist on core=%d\n", where); 160 } 161 return err; 162} 163 164static errval_t omap44xx_startup(void) 165{ 166 errval_t err; 167 168 169 err = init_device_caps_manager(); 170 assert(err_is_ok(err)); 171 172 err = start_gic_dist(OMAP44XX_MAP_CORTEXA9_GICDIST, 0); 173 assert(err_is_ok(err)); 174 debug_printf("Ignoring default drivers on OMAP44xx for now\n"); 175 //start_driverdomain("fdif", "fdif {}"); 176 //start_driverdomain("sdma", "sdma {}"); 177 //start_driverdomain("mmchs", "mmchs { dep1: 'cm2', dep2: 'twl6030' }"); 178 start_serial(&omap44xx_uart_1, 0); 179 180 181 struct module_info* mi = find_module("prcm"); 182 if (mi != NULL) { 183 err = mi->start_function(0, mi, "hw.arm.omap44xx.prcm {}", NULL); 184 assert(err_is_ok(err)); 185 } 186 187 mi = find_module("usb_manager"); 188 if (mi != NULL) { 189#define USB_ARM_EHCI_IRQ 109 190 char *buf = malloc(255); 191 uint8_t offset = 0; 192 mi->cmdargs = buf; 193 mi->argc = 3; 194 mi->argv[0] = mi->cmdargs + 0; 195 196 snprintf(buf + offset, 255 - offset, "ehci\0"); 197 offset += strlen(mi->argv[0]) + 1; 198 mi->argv[1] = mi->cmdargs + offset; 199 snprintf(buf + offset, 255 - offset, "%u\0", 0xC00); 200 offset += strlen(mi->argv[1]) + 1; 201 mi->argv[2] = mi->cmdargs + offset; 202 snprintf(buf+offset, 255-offset, "%u\0", USB_ARM_EHCI_IRQ); 203 204 // XXX Use customized start function or add to module info 205 err = mi->start_function(0, mi, "hw.arm.omap44xx.usb {}", NULL); 206 assert(err_is_ok(err)); 207 free(buf); 208 } 209 return SYS_ERR_OK; 210} 211 212static errval_t vexpress_startup(void) 213{ 214 errval_t err; 215 err = init_device_caps_manager(); 216 assert(err_is_ok(err)); 217 218 err = start_gic_dist(VEXPRESS_MAP_GIC_DIST, 0); 219 assert(err_is_ok(err)); 220 221 err = start_serial(&vexpress_uart_0, 0); 222 assert(err_is_ok(err)); 223 224 return SYS_ERR_OK; 225} 226 227static errval_t zynq7_startup(void) 228{ 229 errval_t err; 230 231 // Since we don't seem to be able to boot cores on the Zynq yet, 232 // we just set all_spawnds_up here. -SG,2016-11-10. 233 err = oct_set("all_spawnds_up { iref: 0 }"); 234 assert(err_is_ok(err)); 235 236 /* There's nothing special to do for Zynq (yet). */ 237 return SYS_ERR_OK; 238} 239 240errval_t arch_startup(char * add_device_db_file) 241{ 242 errval_t err = SYS_ERR_OK; 243 244 KALUGA_DEBUG("Kaluga running on ARMv7.\n"); 245 246 err = skb_client_connect(); 247 if (err_is_fail(err)) { 248 USER_PANIC_ERR(err, "Connect to SKB."); 249 } 250 251 // Make sure the driver db is loaded 252 err = skb_execute("[device_db]."); 253 if (err_is_fail(err)) { 254 USER_PANIC_SKB_ERR(err, "Device DB not loaded."); 255 } 256 if(add_device_db_file != NULL){ 257 err = skb_execute_query("[%s].", add_device_db_file); 258 if(err_is_fail(err)){ 259 USER_PANIC_SKB_ERR(err, "Additional device db file %s not loaded.", 260 add_device_db_file); 261 } 262 } 263 264 err = skb_execute_query("decoding_net(N),load_net(N)."); 265 if(err_is_fail(err)){ 266 debug_printf("############ No decoding net loaded, continue without. ############\n"); 267 //DEBUG_SKB_ERR(err, "No decoding netloaded."); 268 } else { 269 err = skb_execute_query("decoding_net_meta(M),load_net(M)."); 270 if(err_is_fail(err)){ 271 DEBUG_SKB_ERR(err, "No decoding net metadata loaded."); 272 } 273 274 err = skb_execute_query("decoding_net_irq(N),load_net(N)."); 275 if(err_is_fail(err)){ 276 DEBUG_SKB_ERR(err, "No irq decoding net loaded."); 277 } 278 printf("Decoding net irq successfully loaded!\n"); 279 280 err = skb_execute_query("decoding_net_irq_meta(M),load_net(M)."); 281 if(err_is_fail(err)){ 282 DEBUG_SKB_ERR(err, "No irq decoding net metadata loaded."); 283 } 284 } 285 286 287 struct monitor_blocking_binding *m = get_monitor_blocking_binding(); 288 assert(m != NULL); 289 290 uint32_t arch, platform; 291 err = m->rpc_tx_vtbl.get_platform(m, &arch, &platform); 292 assert(err_is_ok(err)); 293 assert(arch == PI_ARCH_ARMV7A); 294 295 uint8_t buf[PI_ARCH_INFO_SIZE]; 296 297 struct arch_info_armv7 *arch_info= (struct arch_info_armv7 *)buf; 298 size_t buflen; 299 err = m->rpc_tx_vtbl.get_platform_arch(m, buf, &buflen); 300 assert(buflen == sizeof(struct arch_info_armv7)); 301 302 /* Query the SKB for the available cores on this platform - we can't 303 * generally discover this on ARMv7. */ 304 err= skb_execute_query("arm_mpids(L),write(L)."); 305 if (err_is_fail(err)) { 306 USER_PANIC_SKB_ERR(err, "Finding cores."); 307 } 308 309 /* Create Octopus records for the known cores. */ 310 debug_printf("CPU driver reports %u core(s).\n", arch_info->ncores); 311 int mpidr_raw; 312 struct list_parser_status skb_list; 313 skb_read_list_init(&skb_list); 314 uint32_t bf_core_id= 0; 315 while(skb_read_list(&skb_list, "mpid(%d)", &mpidr_raw)) { 316 oct_set(HW_PROCESSOR_ARM_RECORD_FORMAT, 317 bf_core_id, 1, bf_core_id, (uint32_t)mpidr_raw, CPU_ARM7); 318 bf_core_id++; 319 } 320 321 KALUGA_DEBUG("Kaluga: watch_for_cores\n"); 322 323 err = watch_for_cores(); 324 if (err_is_fail(err)) { 325 USER_PANIC_ERR(err, "Watching cores."); 326 } 327 328 KALUGA_DEBUG("Kaluga: wait_for_all_spawnds\n"); 329 330 err = wait_for_all_spawnds(0); 331 if (err_is_fail(err)) { 332 USER_PANIC_ERR(err, "Unable to wait for spawnds failed."); 333 } 334 335 336 switch(platform) { 337 case PI_PLATFORM_OMAP44XX: 338 debug_printf("Kaluga running on Pandaboard\n"); 339 return omap44xx_startup(); 340 case PI_PLATFORM_VEXPRESS: 341 debug_printf("Kaluga running on VExpressEMM\n"); 342 return vexpress_startup(); 343 case PI_PLATFORM_ZYNQ7: 344 debug_printf("Kaluga running on a Zynq7000\n"); 345 return zynq7_startup(); 346 } 347 348 return KALUGA_ERR_UNKNOWN_PLATFORM; 349} 350