plic.c 3.0 KB
Newer Older
bigmagic123's avatar
bigmagic123 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-05-20     bigmagic     first version
 */
#include "rtthread.h"
#include "plic.h"
#include <riscv_io.h>
#include "encoding.h"

/*
B
bigmagic123 已提交
16
* Each PLIC interrupt source can be assigned a priority by writing
bigmagic123's avatar
bigmagic123 已提交
17
* to its 32-bit memory-mapped priority register.
B
bigmagic123 已提交
18 19 20 21 22 23
* The QEMU-virt (the same as FU540-C000) supports 7 levels of priority.
* A priority value of 0 is reserved to mean "never interrupt" and
* effectively disables the interrupt.
* Priority 1 is the lowest active priority, and priority 7 is the highest.
* Ties between global interrupts of the same priority are broken by
* the Interrupt ID; interrupts with the lowest ID have the highest
bigmagic123's avatar
bigmagic123 已提交
24 25 26 27 28 29 30 31
* effective priority.
*/
void plic_set_priority(int irq, int priority)
{
    *(uint32_t*)PLIC_PRIORITY(irq) = priority;
}

/*
B
bigmagic123 已提交
32
* Each global interrupt can be enabled by setting the corresponding
bigmagic123's avatar
bigmagic123 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
* bit in the enables registers.
*/
void plic_irq_enable(int irq)
{
    int hart = r_mhartid();
    *(uint32_t*)PLIC_ENABLE(hart) = ((*(uint32_t*)PLIC_ENABLE(hart)) | (1 << irq));
#ifdef  RISCV_S_MODE
    set_csr(sie, read_csr(sie) | MIP_SEIP);
#else
    set_csr(mie, read_csr(mie) | MIP_MEIP);
#endif
}

void plic_irq_disable(int irq)
{
    int hart = r_mhartid();
    *(uint32_t*)PLIC_ENABLE(hart) = (((*(uint32_t*)PLIC_ENABLE(hart)) & (~(1 << irq))));
}

B
bigmagic123 已提交
52
/*
bigmagic123's avatar
bigmagic123 已提交
53 54 55 56 57 58 59 60 61 62 63 64
* PLIC will mask all interrupts of a priority less than or equal to threshold.
* Maximum threshold is 7.
* For example, a threshold value of zero permits all interrupts with
* non-zero priority, whereas a value of 7 masks all interrupts.
* Notice, the threshold is global for PLIC, not for each interrupt source.
*/
void plic_set_threshold(int threshold)
{
    int hart = r_mhartid();
    *(uint32_t*)PLIC_THRESHOLD(hart) = threshold;
}

B
bigmagic123 已提交
65
/*
bigmagic123's avatar
bigmagic123 已提交
66 67 68
 * DESCRIPTION:
 *    Query the PLIC what interrupt we should serve.
 *    Perform an interrupt claim by reading the claim register, which
B
bigmagic123 已提交
69 70
 *    returns the ID of the highest-priority pending interrupt or zero if there
 *    is no pending interrupt.
bigmagic123's avatar
bigmagic123 已提交
71 72 73
 *    A successful claim also atomically clears the corresponding pending bit
 *    on the interrupt source.
 * RETURN VALUE:
B
bigmagic123 已提交
74
 *    the ID of the highest-priority pending interrupt or zero if there
bigmagic123's avatar
bigmagic123 已提交
75 76 77 78 79 80 81 82 83
 *    is no pending interrupt.
 */
int plic_claim(void)
{
    int hart = r_mhartid();
    int irq = *(uint32_t*)PLIC_CLAIM(hart);
    return irq;
}

B
bigmagic123 已提交
84
/*
bigmagic123's avatar
bigmagic123 已提交
85
 * DESCRIPTION:
B
bigmagic123 已提交
86 87 88 89
  *    Writing the interrupt ID it received from the claim (irq) to the
 *    complete register would signal the PLIC we've served this IRQ.
 *    The PLIC does not check whether the completion ID is the same as the
 *    last claim ID for that target. If the completion ID does not match an
bigmagic123's avatar
bigmagic123 已提交
90 91 92 93 94 95 96 97 98
 *    interrupt source that is currently enabled for the target, the completion
 *    is silently ignored.
 * RETURN VALUE: none
 */
void plic_complete(int irq)
{
    int hart = r_mhartid();
    *(uint32_t*)PLIC_COMPLETE(hart) = irq;
}