diff options
author | Anup Patel <anup.patel@wdc.com> | 2020-05-12 10:27:52 +0300 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2020-05-23 08:06:29 +0300 |
commit | 446a9c6d1eb97fcedd6a94ac76d15e941a6087a8 (patch) | |
tree | b8b8d6e8fec3fb2caf01913b0f2139c4f8695846 /lib | |
parent | 73d6ef3b2933ccf0b3a8a0ba110bf53ad9720b51 (diff) | |
download | opensbi-446a9c6d1eb97fcedd6a94ac76d15e941a6087a8.tar.xz |
lib: utils: Allow PLIC functions to be used for multiple PLICs
We extend all PLIC functions to have a "struct plic_data *"
parameter pointing to PLIC details. This allows platforms to
use these functions for multiple PLIC instances.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/utils/fdt/fdt_helper.c | 11 | ||||
-rw-r--r-- | lib/utils/irqchip/fdt_irqchip_plic.c | 6 | ||||
-rw-r--r-- | lib/utils/irqchip/plic.c | 60 |
3 files changed, 45 insertions, 32 deletions
diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c index ee733e7..61d70d9 100644 --- a/lib/utils/fdt/fdt_helper.c +++ b/lib/utils/fdt/fdt_helper.c @@ -12,6 +12,7 @@ #include <sbi/sbi_platform.h> #include <sbi/sbi_scratch.h> #include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/irqchip/plic.h> #define DEFAULT_UART_FREQ 0 #define DEFAULT_UART_BAUD 115200 @@ -259,8 +260,7 @@ int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart, return fdt_parse_uart8250_node(fdt, nodeoffset, uart); } -int fdt_parse_plic_node(void *fdt, int nodeoffset, - struct platform_plic_data *plic) +int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic) { int len, rc; const fdt32_t *val; @@ -281,15 +281,14 @@ int fdt_parse_plic_node(void *fdt, int nodeoffset, return 0; } -int fdt_parse_plic(void *fdt, struct platform_plic_data *plic, - const char *compatible) +int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat) { int nodeoffset; - if (!compatible || !plic || !fdt) + if (!compat || !plic || !fdt) return SBI_ENODEV; - nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compatible); + nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compat); if (nodeoffset < 0) return nodeoffset; diff --git a/lib/utils/irqchip/fdt_irqchip_plic.c b/lib/utils/irqchip/fdt_irqchip_plic.c index 11ed300..e0ad3e2 100644 --- a/lib/utils/irqchip/fdt_irqchip_plic.c +++ b/lib/utils/irqchip/fdt_irqchip_plic.c @@ -15,13 +15,14 @@ #include <sbi_utils/irqchip/fdt_irqchip.h> #include <sbi_utils/irqchip/plic.h> +static struct plic_data plic; static int plic_hartid2context[SBI_HARTMASK_MAX_BITS][2]; static int irqchip_plic_warm_init(void) { u32 hartid = current_hartid(); - return plic_warm_irqchip_init(plic_hartid2context[hartid][0], + return plic_warm_irqchip_init(&plic, plic_hartid2context[hartid][0], plic_hartid2context[hartid][1]); } @@ -77,13 +78,12 @@ static int irqchip_plic_cold_init(void *fdt, int nodeoff, const struct fdt_match *match) { int rc; - struct platform_plic_data plic; rc = fdt_parse_plic_node(fdt, nodeoff, &plic); if (rc) return rc; - rc = plic_cold_irqchip_init(plic.addr, plic.num_src); + rc = plic_cold_irqchip_init(&plic); if (rc) return rc; diff --git a/lib/utils/irqchip/plic.c b/lib/utils/irqchip/plic.c index 8975729..7665c62 100644 --- a/lib/utils/irqchip/plic.c +++ b/lib/utils/irqchip/plic.c @@ -10,6 +10,7 @@ #include <sbi/riscv_io.h> #include <sbi/riscv_encoding.h> #include <sbi/sbi_console.h> +#include <sbi/sbi_error.h> #include <sbi/sbi_string.h> #include <sbi_utils/irqchip/plic.h> @@ -20,67 +21,80 @@ #define PLIC_CONTEXT_BASE 0x200000 #define PLIC_CONTEXT_STRIDE 0x1000 -static u32 plic_num_sources; -static volatile void *plic_base; - -static void plic_set_priority(u32 source, u32 val) +static void plic_set_priority(struct plic_data *plic, u32 source, u32 val) { - volatile void *plic_priority = - plic_base + PLIC_PRIORITY_BASE + 4 * source; + volatile void *plic_priority = (void *)plic->addr + + PLIC_PRIORITY_BASE + 4 * source; writel(val, plic_priority); } -void plic_set_thresh(u32 cntxid, u32 val) +void plic_set_thresh(struct plic_data *plic, u32 cntxid, u32 val) { - volatile void *plic_thresh = - plic_base + PLIC_CONTEXT_BASE + PLIC_CONTEXT_STRIDE * cntxid; + volatile void *plic_thresh; + + if (!plic) + return; + + plic_thresh = (void *)plic->addr + + PLIC_CONTEXT_BASE + PLIC_CONTEXT_STRIDE * cntxid; writel(val, plic_thresh); } -void plic_set_ie(u32 cntxid, u32 word_index, u32 val) +void plic_set_ie(struct plic_data *plic, u32 cntxid, u32 word_index, u32 val) { - volatile void *plic_ie = - plic_base + PLIC_ENABLE_BASE + PLIC_ENABLE_STRIDE * cntxid; + volatile void *plic_ie; + + if (!plic) + return; + + plic_ie = (void *)plic->addr + + PLIC_ENABLE_BASE + PLIC_ENABLE_STRIDE * cntxid; writel(val, plic_ie + word_index * 4); } -int plic_warm_irqchip_init(int m_cntx_id, int s_cntx_id) +int plic_warm_irqchip_init(struct plic_data *plic, + int m_cntx_id, int s_cntx_id) { - size_t i, ie_words = plic_num_sources / 32 + 1; + size_t i, ie_words; + + if (!plic) + return SBI_EINVAL; + + ie_words = plic->num_src / 32 + 1; /* By default, disable all IRQs for M-mode of target HART */ if (m_cntx_id > -1) { for (i = 0; i < ie_words; i++) - plic_set_ie(m_cntx_id, i, 0); + plic_set_ie(plic, m_cntx_id, i, 0); } /* By default, disable all IRQs for S-mode of target HART */ if (s_cntx_id > -1) { for (i = 0; i < ie_words; i++) - plic_set_ie(s_cntx_id, i, 0); + plic_set_ie(plic, s_cntx_id, i, 0); } /* By default, disable M-mode threshold */ if (m_cntx_id > -1) - plic_set_thresh(m_cntx_id, 0x7); + plic_set_thresh(plic, m_cntx_id, 0x7); /* By default, disable S-mode threshold */ if (s_cntx_id > -1) - plic_set_thresh(s_cntx_id, 0x7); + plic_set_thresh(plic, s_cntx_id, 0x7); return 0; } -int plic_cold_irqchip_init(unsigned long base, u32 num_sources) +int plic_cold_irqchip_init(struct plic_data *plic) { int i; - plic_num_sources = num_sources; - plic_base = (void *)base; + if (!plic) + return SBI_EINVAL; /* Configure default priorities of all IRQs */ - for (i = 1; i <= plic_num_sources; i++) - plic_set_priority(i, 0); + for (i = 1; i <= plic->num_src; i++) + plic_set_priority(plic, i, 0); return 0; } |