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