1/** 2 * \file 3 * \brief Provides a generic startup function for the ARM OMAP platform 4 */ 5/* 6 * Copyright (c) 2013, ETH Zurich. 7 * Copyright (c) 2015, Hewlett Packard Enterprise Development LP. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdlib.h> 16#include <stdio.h> 17#include <string.h> 18#include <assert.h> 19 20#include <barrelfish/barrelfish.h> 21#include <barrelfish/spawn_client.h> 22#include <barrelfish_kpi/platform.h> 23#include <if/monitor_blocking_defs.h> 24 25#include <arch/arm/omap44xx/device_registers.h> 26#include <maps/omap44xx_map.h> 27#include <maps/vexpress_map.h> 28 29#include "kaluga.h" 30 31struct allowed_registers 32{ 33 char* binary; 34 lpaddr_t registers[][2]; 35}; 36 37static struct allowed_registers usb = { 38 .binary = "hw.arm.omap44xx.usb", 39 .registers = 40 { 41 {OMAP44XX_MAP_L4_CFG_HSUSBHOST, OMAP44XX_MAP_L4_CFG_HSUSBHOST_SIZE}, 42 {OMAP44XX_MAP_L4_CFG_HSUSBTLL, OMAP44XX_MAP_L4_CFG_HSUSBTLL_SIZE}, 43 {OMAP44XX_MAP_L4_WKUP_SRCM, OMAP44XX_MAP_L4_WKUP_SRCM_SIZE}, 44 {OMAP44XX_MAP_L4_WKUP_SYSCTRL_PADCONF_WKUP, OMAP44XX_MAP_L4_WKUP_SYSCTRL_PADCONF_WKUP_SIZE}, 45 {OMAP44XX_MAP_L4_CFG_SYSCTRL_PADCONF_CORE, OMAP44XX_MAP_L4_CFG_SYSCTRL_PADCONF_CORE_SIZE}, 46 {OMAP44XX_MAP_L4_CFG_CM2, OMAP44XX_MAP_L4_CFG_CM2_SIZE}, 47 {OMAP44XX_MAP_L4_WKUP_GPIO1, OMAP44XX_MAP_L4_WKUP_GPIO1_SIZE}, 48 {OMAP44XX_MAP_L4_PER_GPIO2, OMAP44XX_MAP_L4_PER_GPIO2_SIZE}, 49 {OMAP44XX_MAP_L4_WKUP_PRM, OMAP44XX_MAP_L4_WKUP_PRM_SIZE}, 50 {0x0, 0x0} 51 } 52}; 53 54static struct allowed_registers fdif = { 55 .binary = "fdif", 56 .registers = 57 { 58 {OMAP44XX_CAM_CM2, 0x1000}, 59 {OMAP44XX_DEVICE_PRM, 0x1000}, 60 {OMAP44XX_CAM_PRM, 0x1000}, 61 {OMAP44XX_MAP_L4_CFG_FACE_DETECT,OMAP44XX_MAP_L4_CFG_FACE_DETECT_SIZE}, 62 {0x0, 0x0} 63 } 64}; 65 66static struct allowed_registers twl6030 = { 67 .binary = "twl6030", 68 .registers = 69 { 70 {OMAP44XX_MAP_L4_PER_I2C1, OMAP44XX_MAP_L4_PER_I2C1_SIZE}, 71 {0x0, 0x0} 72 } 73}; 74 75static struct allowed_registers cm2 = { 76 .binary = "cm2", 77 .registers = 78 { 79 {OMAP44XX_CM2, 0x1000}, 80 {0x0, 0x0} 81 } 82}; 83 84 85static struct allowed_registers mmchs = { 86 .binary = "mmchs", 87 .registers = 88 { 89 {OMAP44XX_MAP_L4_CFG_SYSCTRL_PADCONF_CORE, OMAP44XX_MAP_L4_CFG_SYSCTRL_PADCONF_CORE_SIZE}, 90 {OMAP44XX_MAP_L4_PER_HSMMC1, OMAP44XX_MAP_L4_PER_HSMMC1_SIZE}, 91 {0x0, 0x0} 92 } 93}; 94 95static struct allowed_registers prcm = { 96 .binary = "hw.arm.omap44xx.prcm", 97 .registers = 98 { 99 {OMAP44XX_MAP_L4_WKUP_PRM, OMAP44XX_MAP_L4_WKUP_PRM_SIZE}, 100 {OMAP44XX_DEVICE_PRM, 0x1000}, 101 {OMAP44XX_MAP_L4_PER_I2C1, OMAP44XX_MAP_L4_PER_I2C1_SIZE}, 102 {OMAP44XX_MAP_L4_PER_I2C2, OMAP44XX_MAP_L4_PER_I2C2_SIZE}, 103 {OMAP44XX_MAP_L4_PER_I2C3, OMAP44XX_MAP_L4_PER_I2C3_SIZE}, 104 {OMAP44XX_MAP_L4_PER_I2C4, OMAP44XX_MAP_L4_PER_I2C4_SIZE}, 105 {0x0, 0x0} 106 } 107}; 108 109static struct allowed_registers omap_uart = { 110 .binary = "hw.arm.omap44xx.uart", 111 .registers = 112 { 113 {OMAP44XX_MAP_L4_PER_UART1,OMAP44XX_MAP_L4_PER_UART1_SIZE}, 114 {OMAP44XX_MAP_L4_PER_UART2,OMAP44XX_MAP_L4_PER_UART2_SIZE}, 115 {OMAP44XX_MAP_L4_PER_UART3,OMAP44XX_MAP_L4_PER_UART3_SIZE}, 116 {OMAP44XX_MAP_L4_PER_UART4,OMAP44XX_MAP_L4_PER_UART4_SIZE}, 117 {0x0, 0x0} 118 } 119}; 120 121static struct allowed_registers sdma = { 122 .binary = "sdma", 123 .registers = 124 { 125 {OMAP44XX_MAP_L4_CFG_SDMA, OMAP44XX_MAP_L4_CFG_SDMA_SIZE}, 126 {0x0, 0x0} 127 } 128}; 129 130 131static struct allowed_registers* omap44xx[] = { 132 &usb, 133 &fdif, 134 &twl6030, 135 &cm2, 136 &mmchs, 137 &prcm, 138 &omap_uart, 139 &sdma, 140 NULL, 141}; 142 143static struct allowed_registers vexpress_pl390_dist = { 144 .binary = "pl390_dist", 145 .registers = 146 { 147 {VEXPRESS_MAP_GIC_DIST, VEXPRESS_MAP_GIC_DIST_SIZE}, 148 {0x0, 0x0} 149 } 150}; 151 152static struct allowed_registers vexpress_uart = { 153 .binary = "hw.arm.vexpress.uart", 154 .registers = 155 { 156 {VEXPRESS_MAP_UART0, VEXPRESS_MAP_UART0_SIZE}, 157 {VEXPRESS_MAP_UART1, VEXPRESS_MAP_UART1_SIZE}, 158 {VEXPRESS_MAP_UART2, VEXPRESS_MAP_UART2_SIZE}, 159 {VEXPRESS_MAP_UART3, VEXPRESS_MAP_UART3_SIZE}, 160 {0x0, 0x0} 161 } 162}; 163 164static struct allowed_registers* vexpress[] = { 165 &vexpress_uart, 166 &vexpress_pl390_dist, 167 NULL, 168}; 169 170/** 171 * \brief Startup function for ARMv7 drivers. 172 * 173 * Makes sure we get the device register capabilities. 174 */ 175errval_t 176default_start_function(coreid_t where, struct module_info* driver, 177 char* record, struct driver_argument* int_arg) 178{ 179 assert(driver != NULL); 180 assert(record != NULL); 181 182 errval_t err; 183 184 struct monitor_blocking_binding *m= 185 get_monitor_blocking_binding(); 186 assert(m != NULL); 187 188 uint32_t arch, platform; 189 err = m->rpc_tx_vtbl.get_platform(m, &arch, &platform); 190 assert(err_is_ok(err)); 191 assert(arch == PI_ARCH_ARMV7A); 192 193 struct allowed_registers **regs= NULL; 194 switch(platform) { 195 case PI_PLATFORM_OMAP44XX: 196 regs= omap44xx; 197 break; 198 case PI_PLATFORM_VEXPRESS: 199 regs= vexpress; 200 break; 201 default: 202 printf("Unrecognised ARMv7 platform\n"); 203 abort(); 204 } 205 206 // TODO Request the right set of caps and put in device_range_cap 207 struct cnoderef dev_cnode; 208 struct capref dev_cnode_cap; 209 err = cnode_create_l2(&dev_cnode_cap, &dev_cnode); 210 assert(err_is_ok(err)); 211 212 struct capref device_cap; 213 device_cap.cnode = dev_cnode; 214 device_cap.slot = 0; 215 216 char* name; 217 err = oct_read(record, "%s", &name); 218 assert(err_is_ok(err)); 219 KALUGA_DEBUG("%s:%d: Starting driver for %s\n", __FUNCTION__, __LINE__, name); 220 for (size_t i=0; regs[i] != NULL; i++) { 221 222 if(strcmp(name, regs[i]->binary) != 0) { 223 continue; 224 } 225 226 // Get the device cap from the managed capability tree 227 // put them all in a single cnode 228 for (size_t j=0; regs[i]->registers[j][0] != 0x0; j++) { 229 struct capref device_frame; 230 KALUGA_DEBUG("%s:%d: mapping 0x%"PRIxLPADDR" %"PRIuLPADDR"\n", __FUNCTION__, __LINE__, 231 regs[i]->registers[j][0], regs[i]->registers[j][1]); 232 233 lpaddr_t base = regs[i]->registers[j][0] & ~(BASE_PAGE_SIZE-1); 234 err = get_device_cap(base, 235 regs[i]->registers[j][1], 236 &device_frame); 237 assert(err_is_ok(err)); 238 239 KALUGA_DEBUG("get_device_cap worked\n"); 240 241 err = cap_copy(device_cap, device_frame); 242 assert(err_is_ok(err)); 243 device_cap.slot++; 244 } 245 } 246 free(name); 247 248 err = spawn_program_with_caps(0, driver->path, driver->argv, environ, 249 NULL_CAP, dev_cnode_cap, 0, driver->did); 250 if (err_is_fail(err)) { 251 DEBUG_ERR(err, "Spawning %s failed.", driver->path); 252 return err; 253 } 254 255 return SYS_ERR_OK; 256} 257 258static void provide_driver_with_caps(struct driver_instance* drv, char* name) { 259 errval_t err; 260 261 struct monitor_blocking_binding *m = get_monitor_blocking_binding(); 262 assert(m != NULL); 263 264 uint32_t arch, platform; 265 err = m->rpc_tx_vtbl.get_platform(m, &arch, &platform); 266 assert(err_is_ok(err)); 267 assert(arch == PI_ARCH_ARMV7A); 268 269 struct allowed_registers **regs= NULL; 270 switch(platform) { 271 case PI_PLATFORM_OMAP44XX: 272 regs= omap44xx; 273 break; 274 case PI_PLATFORM_VEXPRESS: 275 regs= vexpress; 276 break; 277 default: 278 printf("Unrecognised ARMv7 platform\n"); 279 abort(); 280 } 281 282 283 KALUGA_DEBUG("%s:%d: Finding caps for driver for %s\n", __FUNCTION__, __LINE__, name); 284 for (size_t i=0; regs[i] != NULL; i++) { 285 if(strcmp(name, regs[i]->binary) != 0) { 286 continue; 287 } 288 289 // Get the device cap from the managed capability tree 290 // put them all in a single cnode 291 for (size_t j=0; regs[i]->registers[j][0] != 0x0; j++) { 292 struct capref device_frame; 293 KALUGA_DEBUG("%s:%d: mapping 0x%"PRIxLPADDR" %"PRIuLPADDR"\n", __FUNCTION__, __LINE__, 294 regs[i]->registers[j][0], regs[i]->registers[j][1]); 295 296 lpaddr_t base = regs[i]->registers[j][0] & ~(BASE_PAGE_SIZE-1); 297 err = get_device_cap(base, regs[i]->registers[j][1], &device_frame); 298 assert(err_is_ok(err)); 299 300 KALUGA_DEBUG("get_device_cap worked\n"); 301 err = ddomain_driver_add_cap(drv, device_frame); 302 assert(err_is_ok(err)); 303 } 304 } 305} 306 307 308/** 309 * \brief Startup function for new-style ARMv7 drivers. 310 * 311 * Launches the driver instance in a driver domain instead. 312 */ 313errval_t 314newstyle_start_function(coreid_t where, struct module_info* driver, char* record, 315 struct driver_argument* int_arg) 316{ 317 assert(driver != NULL); 318 assert(record != NULL); 319 errval_t err; 320 321 struct domain_instance* inst = instantiate_driver_domain(driver->binary, where); 322 323 char* dep1; 324 err = oct_read(record, "_ { dep1: %s }", &dep1); 325 if (err_is_ok(err)) { 326 struct driver_instance* drv1 = ddomain_create_driver_instance(dep1, dep1); 327 provide_driver_with_caps(drv1, dep1); 328 free(dep1); 329 ddomain_instantiate_driver(inst, drv1); 330 } 331 332 char* dep2; 333 err = oct_read(record, "_ { dep2: %s }", &dep2); 334 if (err_is_ok(err)) { 335 struct driver_instance* drv2 = ddomain_create_driver_instance(dep2, dep2); 336 provide_driver_with_caps(drv2, dep2); 337 free(dep2); 338 ddomain_instantiate_driver(inst, drv2); 339 } 340 341 char* name; 342 err = oct_read(record, "%s", &name); 343 assert(err_is_ok(err)); 344 345 struct driver_instance* drv = ddomain_create_driver_instance(name, name); 346 provide_driver_with_caps(drv, name); 347 free(name); 348 349 ddomain_instantiate_driver(inst, drv); 350 return SYS_ERR_OK; 351} 352