int_irqmp_init.c 3.78 KB
/*
 * Copyright (c) 2017, Cobham Gaisler AB
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE. 
 */

#include <bcc/bsp.h>
#include "bcc/ambapp.h"
#include "int_irqmp_priv.h"

static void findplic(void)
{
        if (__BSP_PLIC_HANDLE) {
                return;
        }
        if (__bcc_plic_handle) {
                return;
        }

        struct amba_ahb_info ahbi;
        uintptr_t regs;
        regs = ambapp_visit(
                __bcc_ioarea,
                VENDOR_GAISLER,
                GAISLER_GRPLIC,
                AMBAPP_VISIT_AHBSLAVE,
                4,
                ambapp_findfirst_fn,
                &ahbi
        );
        __bcc_plic_handle = regs;
}

static void findclint(void)
{
        if (__BSP_CLINT_HANDLE) {
                return;
        }
        if (__bcc_clint_handle) {
                return;
        }

        struct amba_ahb_info ahbi;
        uintptr_t regs;
        regs = ambapp_visit(
                __bcc_ioarea,
                VENDOR_GAISLER,
                GAISLER_CLINT,
                AMBAPP_VISIT_AHBSLAVE,
                4,
                ambapp_findfirst_fn,
                &ahbi
        );
        __bcc_clint_handle = regs;
}

#ifndef UNUSED
#define UNUSED(v) ((void) sizeof (v))
#endif

/* count number of NOEL-V processor by plug&play scanning */
static uint32_t fncpu(
        void *info,
        uint32_t vendor,
        uint32_t device,
        uint32_t type,
        uint32_t depth,
        void *arg
)
{
        UNUSED(vendor); UNUSED(device); UNUSED(type); UNUSED(depth);
        UNUSED(info); UNUSED(arg);
        __bcc_cpu_count++;

        return 0;
}

int __bcc_int_init(void)
{
        /* The CPU counting can be disabled by assigning in __bcc_init60() */
        if (__bcc_cpu_count == 0) {
                ambapp_visit(
                        __bcc_ioarea,
                        VENDOR_GAISLER,
                        GAISLER_RV64GC,
                        AMBAPP_VISIT_AHBMASTER,
                        4,
                        fncpu,
                        NULL
                );
                if (__bcc_cpu_count == 0) {
                        __bcc_cpu_count = 1;
                }
        }

        findplic();
        findclint();

        volatile struct plic_regs *plic = (void *) __bcc_plic_handle;
        plic->context[__bcc_cpuid * 4].priority_threshold = 0;
        for (int i = 1; i < 32; i++) {
                plic->priority[i] = 1;
        }
        __asm__ volatile ( "csrrs zero, mie, %0" : : "r" (1<<11) );
        bcc_int_enable(RISCV_MSTATUS_MIE);
        return BCC_OK;
}