Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libcpu][riscv]统一plic #9689

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions bsp/qemu-virt64-riscv/driver/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ void rt_hw_board_init(void)
rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
#endif

plic_init();

rt_hw_interrupt_init();

rt_hw_uart_init();
Expand Down
4 changes: 4 additions & 0 deletions libcpu/risc-v/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ if rtconfig.CPU in common64_arch :
else :
group += SConscript(os.path.join('common', 'SConscript'))

# FIXME: remove implementation of plic in BSP
if rtconfig.CPU in common64_arch:
group += SConscript(os.path.join('plic', 'SConscript'))

# cpu porting code files
if 'VENDOR' in vars(rtconfig) and rtconfig.VENDOR != '':
group = group + SConscript(os.path.join(rtconfig.VENDOR, rtconfig.CPU, 'SConscript'))
Expand Down
10 changes: 10 additions & 0 deletions libcpu/risc-v/plic/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# RT-Thread building script for component

from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]

group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH)

Return('group')
136 changes: 84 additions & 52 deletions libcpu/risc-v/t-head/c908/plic.c → libcpu/risc-v/plic/plic.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,44 @@
#include "encoding.h"
#include "ioremap.h"

static void *plic_regs = RT_NULL;
extern struct rt_irq_desc isr_table[];

struct plic_handler
{
rt_bool_t present;
void *hart_base;
void *enable_base;
void *hart_base;
void *enable_base;
};

struct plic
{
void *base_pa;
volatile rt_uint32_t *priority_base;

void (*irq_handler)(int irq);

struct plic_handler handlers[NR_CPUS];
};

static struct plic _plic = {};

rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable);
struct plic_handler plic_handlers[C908_NR_CPUS];
static void *plic_irq_priority[INTERRUPTS_MAX] = {RT_NULL};

rt_inline struct plic_handler *plic_get_handler(int cpu)
{
return &_plic.handlers[cpu];
}

rt_inline struct plic *plic_get(void)
{
return &_plic;
}

rt_inline void plic_irq_toggle(int hwirq, int enable)
{
int cpu = 0;
void *priority_addr;

/* set priority of interrupt, interrupt 0 is zero. */
priority_addr = (void *)((rt_size_t)plic_regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID);
#ifdef RT_USING_SMART
if (plic_irq_priority[hwirq] == RT_NULL)
{
plic_irq_priority[hwirq] = (void *)rt_ioremap(priority_addr, 0x1000);
}
priority_addr = plic_irq_priority[hwirq];
#endif
writel(enable, priority_addr);
struct plic_handler *handler = &plic_handlers[cpu];
struct plic_handler *handler = plic_get_handler(cpu);

if (handler->present)
{
Expand All @@ -59,25 +67,21 @@ rt_inline void plic_irq_toggle(int hwirq, int enable)

static void generic_handle_irq(int irq)
{
rt_isr_handler_t isr;
void *param;

if (irq < 0 || irq >= IRQ_MAX_NR)
{
LOG_E("bad irq number %d!\n", irq);
return;
}

if (!irq) // irq = 0 => no irq
if (!irq) // irq = 0 => no irq
{
LOG_W("no irq!\n");
return;
}
isr = isr_table[IRQ_OFFSET + irq].handler;
param = isr_table[IRQ_OFFSET + irq].param;
if (isr != RT_NULL)

if (plic_get()->irq_handler != RT_NULL)
{
isr(irq, param);
plic_get()->irq_handler(irq);
}
/* complete irq. */
plic_complete(irq);
Expand All @@ -86,7 +90,7 @@ static void generic_handle_irq(int irq)
void plic_complete(int irqno)
{
int cpu = 0;
struct plic_handler *handler = &plic_handlers[cpu];
struct plic_handler *handler = plic_get_handler(cpu);

writel(irqno, (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM));
}
Expand All @@ -109,13 +113,13 @@ void plic_enable_irq(int irqno)
*/
void plic_handle_irq(void)
{
int cpu = 0;
int cpu = 0;
unsigned int irq;

struct plic_handler *handler = &plic_handlers[cpu];
void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM);
struct plic_handler *handler = plic_get_handler(cpu);
void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM);

if (plic_regs == RT_NULL || !handler->present)
if (!handler->present)
{
LOG_E("plic state not initialized.");
return;
Expand All @@ -140,8 +144,8 @@ void plic_handle_irq(void)

rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable)
{
uint32_t *reg = (uint32_t *)((rt_size_t)handler->enable_base + (hwirq / 32) * sizeof(uint32_t));
uint32_t hwirq_mask = 1 << (hwirq % 32);
uint32_t *reg = (uint32_t *)((rt_size_t)handler->enable_base + (hwirq / 32) * sizeof(uint32_t));
uint32_t hwirq_mask = 1 << (hwirq % 32);

if (enable)
{
Expand All @@ -153,32 +157,33 @@ rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable)
}
}

void plic_init(void)
void plic_init(unsigned long base_pa, void (*irq_handler)(int irq))
{
int nr_irqs;
int nr_context;
int i;
int nr_irqs;
int nr_context;
int i;
unsigned long hwirq;
int cpu = 0;
int cpu = 0;
struct plic *plic = plic_get();

if (plic_regs)
if (plic->base_pa)
{
LOG_E("plic already initialized!");
return;
}

nr_context = C908_NR_CONTEXT;

plic_regs = (void *)C908_PLIC_PHY_ADDR;
if (!plic_regs)
if (!base_pa || !irq_handler)
{
LOG_E("fatal error, plic is reg space is null.");
LOG_E("fatal error, plic init params is null.");
return;
}
plic->base_pa = (void*)base_pa;
plic->irq_handler = irq_handler;

nr_irqs = C908_PLIC_NR_EXT_IRQS;
nr_context = PLIC_NR_CONTEXT;
nr_irqs = IRQ_MAX_NR;

for (i = 0; i < nr_context; i ++)
for (i = 0; i < nr_context; i++)
{
struct plic_handler *handler;
uint32_t threshold = 0;
Expand All @@ -192,21 +197,21 @@ void plic_init(void)
}

// we always use CPU0 M-mode target register.
handler = &plic_handlers[cpu];
handler = plic_get_handler(cpu);
if (handler->present)
{
threshold = 0xffffffff;
threshold = 0xffffffff;
goto done;
}

handler->present = RT_TRUE;
handler->hart_base = (void *)((rt_size_t)plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART);
handler->enable_base = (void *)((rt_size_t)plic_regs + ENABLE_BASE + i * ENABLE_PER_HART);
handler->present = RT_TRUE;
handler->hart_base = (void *)(plic->base_pa + CONTEXT_BASE + i * CONTEXT_PER_HART);
handler->enable_base = (void *)(plic->base_pa + ENABLE_BASE + i * ENABLE_PER_HART);
#ifdef RT_USING_SMART
handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000);
handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000);
handler->enable_base = (void *)rt_ioremap(handler->enable_base, 0x1000);
#endif
done:
done:
/* priority must be > threshold to trigger an interrupt */
writel(threshold, (void *)((rt_size_t)handler->hart_base + CONTEXT_THRESHOLD));
for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
Expand All @@ -218,3 +223,30 @@ void plic_init(void)
/* Enable supervisor external interrupts. */
set_csr(sie, SIE_SEIE);
}

void plic_set_threshold(int threshold)
{
int hart = 0;
struct plic_handler *handler;

handler = plic_get_handler(hart);

writel(threshold, (void *)((rt_size_t)handler->hart_base + CONTEXT_THRESHOLD));
}

void plic_set_priority(int irq, int priority)
{
struct plic *plic = plic_get();

/* set priority of interrupt, interrupt 0 is zero. */
if (plic->priority_base == RT_NULL)
{
#ifdef RT_USING_SMART
plic->priority_base = (rt_uint32_t *)rt_ioremap(plic->base_pa, 0x1000);
#else
plic->priority_base = (rt_uint32_t *)plic->base_pa;
#endif
}

plic->priority_base[irq] = priority;
}
12 changes: 4 additions & 8 deletions libcpu/risc-v/t-head/c908/plic.h → libcpu/risc-v/plic/plic.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,8 @@

#include <interrupt.h>

#ifndef C908_PLIC_PHY_ADDR
#define C908_PLIC_PHY_ADDR (0xF00000000UL)
#endif
#define C908_PLIC_NR_EXT_IRQS (IRQ_MAX_NR)
#define C908_NR_CPUS (NR_CPUS)

/* M and S mode context. */
#define C908_NR_CONTEXT (2)
#define PLIC_NR_CONTEXT (2)

#define MAX_DEVICES 1024
#define MAX_CONTEXTS 15872
Expand Down Expand Up @@ -50,11 +44,13 @@
#define CONTEXT_THRESHOLD 0x00
#define CONTEXT_CLAIM 0x04

void plic_init(void);
void plic_init(unsigned long base_pa, void (*irq_handler)(int irq));
void plic_enable_irq(int irqno);
void plic_disable_irq(int irqno);
// tell PLIC that we've served this IRQ
void plic_complete(int irq);
void plic_handle_irq(void);
void plic_set_threshold(int mthreshold);
void plic_set_priority(int irq, int priority);

#endif
21 changes: 19 additions & 2 deletions libcpu/risc-v/t-head/c906/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#include "riscv.h"
#include "plic.h"

#ifndef C906_PLIC_PHY_ADDR
#define C906_PLIC_PHY_ADDR (0x10000000)
#endif

extern rt_atomic_t rt_interrupt_nest;
extern rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
extern rt_uint32_t rt_thread_switch_interrupt_flag;
Expand All @@ -26,13 +30,26 @@ static void rt_hw_interrupt_handler(int vector, void *param)
rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
}

static void __isr(int irq)
{
rt_isr_handler_t isr;
void *param;

isr = isr_table[IRQ_OFFSET + irq].handler;
param = isr_table[IRQ_OFFSET + irq].param;
if (isr != RT_NULL)
{
isr(irq, param);
}
}

/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
/* init interrupt controller */
plic_init();
plic_init(C906_PLIC_PHY_ADDR, __isr);

rt_int32_t idx;

Expand Down Expand Up @@ -88,7 +105,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if ((vector < 0) || (vector > IRQ_MAX_NR))
if ((vector < 0) || (vector >= IRQ_MAX_NR))
{
return old_handler;
}
Expand Down
21 changes: 19 additions & 2 deletions libcpu/risc-v/t-head/c908/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#include "riscv.h"
#include "plic.h"

#ifndef C908_PLIC_PHY_ADDR
#define C908_PLIC_PHY_ADDR (0xF00000000UL)
#endif

extern rt_atomic_t rt_interrupt_nest;
extern rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
extern rt_uint32_t rt_thread_switch_interrupt_flag;
Expand All @@ -26,13 +30,26 @@ static void rt_hw_interrupt_handler(int vector, void *param)
rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
}

static void __isr(int irq)
{
rt_isr_handler_t isr;
void *param;

isr = isr_table[IRQ_OFFSET + irq].handler;
param = isr_table[IRQ_OFFSET + irq].param;
if (isr != RT_NULL)
{
isr(irq, param);
}
}

/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
/* init interrupt controller */
plic_init();
plic_init(C908_PLIC_PHY_ADDR, __isr);

rt_int32_t idx;

Expand Down Expand Up @@ -88,7 +105,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if ((vector < 0) || (vector > IRQ_MAX_NR))
if ((vector < 0) || (vector >= IRQ_MAX_NR))
{
return old_handler;
}
Expand Down
Loading
Loading