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, Universitaetstr. 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 130static struct allowed_registers* omap44xx[] = { 131 &usb, 132 &fdif, 133 &twl6030, 134 &cm2, 135 &mmchs, 136 &prcm, 137 &omap_uart, 138 &sdma, 139 NULL, 140}; 141 142static struct allowed_registers vexpress_uart = { 143 .binary = "hw.arm.vexpress.uart", 144 .registers = 145 { 146 {VEXPRESS_MAP_UART0, VEXPRESS_MAP_UART0_SIZE}, 147 {VEXPRESS_MAP_UART1, VEXPRESS_MAP_UART1_SIZE}, 148 {VEXPRESS_MAP_UART2, VEXPRESS_MAP_UART2_SIZE}, 149 {VEXPRESS_MAP_UART3, VEXPRESS_MAP_UART3_SIZE}, 150 {0x0, 0x0} 151 } 152}; 153 154static struct allowed_registers* vexpress[] = { 155 &vexpress_uart, 156 NULL, 157}; 158 159/** 160 * \brief Startup function for ARMv7 drivers. 161 * 162 * Makes sure we get the device register capabilities. 163 */ 164errval_t 165default_start_function(coreid_t where, struct module_info* driver, 166 char* record, struct driver_argument* int_arg) 167{ 168 assert(driver != NULL); 169 assert(record != NULL); 170 171 errval_t err; 172 173 struct monitor_blocking_binding *m= 174 get_monitor_blocking_binding(); 175 assert(m != NULL); 176 177 uint32_t arch, platform; 178 err = m->rpc_tx_vtbl.get_platform(m, &arch, &platform); 179 assert(err_is_ok(err)); 180 assert(arch == PI_ARCH_ARMV7A); 181 182 struct allowed_registers **regs= NULL; 183 switch(platform) { 184 case PI_PLATFORM_OMAP44XX: 185 regs= omap44xx; 186 break; 187 case PI_PLATFORM_VEXPRESS: 188 regs= vexpress; 189 break; 190 default: 191 printf("Unrecognised ARMv7 platform\n"); 192 abort(); 193 } 194 195 // TODO Request the right set of caps and put in device_range_cap 196 struct cnoderef dev_cnode; 197 struct capref dev_cnode_cap; 198 err = cnode_create_l2(&dev_cnode_cap, &dev_cnode); 199 assert(err_is_ok(err)); 200 201 struct capref device_cap; 202 device_cap.cnode = dev_cnode; 203 device_cap.slot = 0; 204 205 char* name; 206 err = oct_read(record, "%s", &name); 207 assert(err_is_ok(err)); 208 KALUGA_DEBUG("%s:%d: Starting driver for %s\n", __FUNCTION__, __LINE__, name); 209 for (size_t i=0; regs[i] != NULL; i++) { 210 211 if(strcmp(name, regs[i]->binary) != 0) { 212 continue; 213 } 214 215 // Get the device cap from the managed capability tree 216 // put them all in a single cnode 217 for (size_t j=0; regs[i]->registers[j][0] != 0x0; j++) { 218 struct capref device_frame; 219 KALUGA_DEBUG("%s:%d: mapping 0x%"PRIxLPADDR" %"PRIuLPADDR"\n", __FUNCTION__, __LINE__, 220 regs[i]->registers[j][0], regs[i]->registers[j][1]); 221 222 lpaddr_t base = regs[i]->registers[j][0] & ~(BASE_PAGE_SIZE-1); 223 err = get_device_cap(base, 224 regs[i]->registers[j][1], 225 &device_frame); 226 assert(err_is_ok(err)); 227 228 KALUGA_DEBUG("get_device_cap worked\n"); 229 230 err = cap_copy(device_cap, device_frame); 231 assert(err_is_ok(err)); 232 device_cap.slot++; 233 } 234 } 235 free(name); 236 237 err = spawn_program_with_caps(0, driver->path, driver->argv, environ, 238 NULL_CAP, dev_cnode_cap, 0, driver->did); 239 if (err_is_fail(err)) { 240 DEBUG_ERR(err, "Spawning %s failed.", driver->path); 241 return err; 242 } 243 244 return SYS_ERR_OK; 245} 246 247static void provide_driver_with_caps(struct driver_instance* drv, char* name) { 248 errval_t err; 249 250 struct monitor_blocking_binding *m = get_monitor_blocking_binding(); 251 assert(m != NULL); 252 253 uint32_t arch, platform; 254 err = m->rpc_tx_vtbl.get_platform(m, &arch, &platform); 255 assert(err_is_ok(err)); 256 assert(arch == PI_ARCH_ARMV7A); 257 258 struct allowed_registers **regs= NULL; 259 switch(platform) { 260 case PI_PLATFORM_OMAP44XX: 261 regs= omap44xx; 262 break; 263 case PI_PLATFORM_VEXPRESS: 264 regs= vexpress; 265 break; 266 default: 267 printf("Unrecognised ARMv7 platform\n"); 268 abort(); 269 } 270 271 272 KALUGA_DEBUG("%s:%d: Finding caps for driver for %s\n", __FUNCTION__, __LINE__, name); 273 for (size_t i=0; regs[i] != NULL; i++) { 274 if(strcmp(name, regs[i]->binary) != 0) { 275 continue; 276 } 277 278 // Get the device cap from the managed capability tree 279 // put them all in a single cnode 280 for (size_t j=0; regs[i]->registers[j][0] != 0x0; j++) { 281 struct capref device_frame; 282 KALUGA_DEBUG("%s:%d: mapping 0x%"PRIxLPADDR" %"PRIuLPADDR"\n", __FUNCTION__, __LINE__, 283 regs[i]->registers[j][0], regs[i]->registers[j][1]); 284 285 lpaddr_t base = regs[i]->registers[j][0] & ~(BASE_PAGE_SIZE-1); 286 err = get_device_cap(base, regs[i]->registers[j][1], &device_frame); 287 assert(err_is_ok(err)); 288 289 KALUGA_DEBUG("get_device_cap worked\n"); 290 err = ddomain_driver_add_cap(drv, device_frame); 291 assert(err_is_ok(err)); 292 } 293 } 294} 295 296 297/** 298 * \brief Startup function for new-style ARMv7 drivers. 299 * 300 * Launches the driver instance in a driver domain instead. 301 */ 302errval_t 303newstyle_start_function(coreid_t where, struct module_info* driver, char* record, 304 struct driver_argument* int_arg) 305{ 306 assert(driver != NULL); 307 assert(record != NULL); 308 errval_t err; 309 310 struct domain_instance* inst = instantiate_driver_domain(driver->binary, where); 311 312 char* dep1; 313 err = oct_read(record, "_ { dep1: %s }", &dep1); 314 if (err_is_ok(err)) { 315 struct driver_instance* drv1 = ddomain_create_driver_instance(dep1, dep1); 316 provide_driver_with_caps(drv1, dep1); 317 free(dep1); 318 ddomain_instantiate_driver(inst, drv1); 319 } 320 321 char* dep2; 322 err = oct_read(record, "_ { dep2: %s }", &dep2); 323 if (err_is_ok(err)) { 324 struct driver_instance* drv2 = ddomain_create_driver_instance(dep2, dep2); 325 provide_driver_with_caps(drv2, dep2); 326 free(dep2); 327 ddomain_instantiate_driver(inst, drv2); 328 } 329 330 char* name; 331 err = oct_read(record, "%s", &name); 332 assert(err_is_ok(err)); 333 334 struct driver_instance* drv = ddomain_create_driver_instance(name, name); 335 provide_driver_with_caps(drv, name); 336 free(name); 337 338 ddomain_instantiate_driver(inst, drv); 339 return SYS_ERR_OK; 340} 341