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