Skip to content
Merged
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: 2 additions & 0 deletions include/sbi_utils/fdt/fdt_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ bool fdt_node_is_enabled(const void *fdt, int nodeoff);

int fdt_parse_hart_id(const void *fdt, int cpu_offset, u32 *hartid);

int fdt_parse_hart_id_by_phandle(const void *fdt, u32 phandle, u32 *hartid);

int fdt_parse_max_enabled_hart_id(const void *fdt, u32 *max_hartid);

int fdt_parse_cbom_block_size(const void *fdt, int cpu_offset, unsigned long *cbom_block_size);
Expand Down
127 changes: 86 additions & 41 deletions lib/utils/fdt/fdt_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,79 @@ int fdt_parse_hart_id(const void *fdt, int cpu_offset, u32 *hartid)
return 0;
}

struct fdt_cpu_intc_entry {
u32 phandle;
u32 hartid;
};

static struct {
const void *fdt;
unsigned int n_entries;
struct fdt_cpu_intc_entry entries[SBI_HARTMASK_MAX_BITS];
} fdt_cpu_intc_cache;

static void fdt_cpu_intc_cache_build(const void *fdt)
{
int cpus_offset, cpu_offset, intc_offset, len;
const fdt32_t *prop;
unsigned int n = 0;
u32 hartid;

if (!fdt || fdt_cpu_intc_cache.fdt == fdt)
return;

fdt_cpu_intc_cache.fdt = NULL;
fdt_cpu_intc_cache.n_entries = 0;

cpus_offset = fdt_path_offset(fdt, "/cpus");
if (cpus_offset < 0)
return;

fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) {
if (n >= SBI_HARTMASK_MAX_BITS)
break;
if (fdt_parse_hart_id(fdt, cpu_offset, &hartid))
continue;

fdt_for_each_subnode(intc_offset, fdt, cpu_offset) {
if (!fdt_getprop(fdt, intc_offset,
"interrupt-controller", NULL))
continue;
prop = fdt_getprop(fdt, intc_offset, "phandle", &len);
if (!prop || len < (int)sizeof(fdt32_t))
continue;
fdt_cpu_intc_cache.entries[n].phandle =
fdt32_to_cpu(*prop);
fdt_cpu_intc_cache.entries[n].hartid = hartid;
n++;
break;
}
}

fdt_cpu_intc_cache.fdt = fdt;
fdt_cpu_intc_cache.n_entries = n;
}

int fdt_parse_hart_id_by_phandle(const void *fdt, u32 phandle, u32 *hartid)
{
unsigned int i;

if (!fdt)
return SBI_EINVAL;

fdt_cpu_intc_cache_build(fdt);

for (i = 0; i < fdt_cpu_intc_cache.n_entries; i++) {
if (fdt_cpu_intc_cache.entries[i].phandle == phandle) {
if (hartid)
*hartid = fdt_cpu_intc_cache.entries[i].hartid;
return 0;
}
}

return SBI_ENODEV;
}

int fdt_parse_cbom_block_size(const void *fdt, int cpu_offset, unsigned long *cbom_block_size)
{
int len;
Expand Down Expand Up @@ -968,7 +1041,7 @@ int fdt_parse_aclint_node(const void *fdt, int nodeoffset,
u32 *out_first_hartid, u32 *out_hart_count)
{
const fdt32_t *val;
int i, rc, count, cpu_offset, cpu_intc_offset;
int i, rc, count;
u32 phandle, hwirq, hartid, first_hartid, last_hartid;
u32 match_hwirq = (for_timer) ? IRQ_M_TIMER : IRQ_M_SOFT;

Expand Down Expand Up @@ -1003,24 +1076,16 @@ int fdt_parse_aclint_node(const void *fdt, int nodeoffset,
phandle = fdt32_to_cpu(val[2 * i]);
hwirq = fdt32_to_cpu(val[(2 * i) + 1]);

cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
if (cpu_intc_offset < 0)
if (match_hwirq != hwirq)
continue;

cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset);
if (cpu_offset < 0)
if (fdt_parse_hart_id_by_phandle(fdt, phandle, &hartid))
continue;

rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
if (rc)
continue;

if (match_hwirq == hwirq) {
if (hartid < first_hartid)
first_hartid = hartid;
if (hartid > last_hartid)
last_hartid = hartid;
}
if (hartid < first_hartid)
first_hartid = hartid;
if (hartid > last_hartid)
last_hartid = hartid;
}

if ((last_hartid >= first_hartid) && first_hartid != -1U) {
Expand Down Expand Up @@ -1056,29 +1121,19 @@ int fdt_parse_plmt_node(const void *fdt, int nodeoffset, unsigned long *plmt_bas

hcount = 0;
for (i = 0; i < (count / 2); i++) {
int cpu_offset, cpu_intc_offset;

phandle = fdt32_to_cpu(val[2 * i]);
hwirq = fdt32_to_cpu(val[2 * i + 1]);

cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
if (cpu_intc_offset < 0)
if (hwirq != IRQ_M_TIMER)
continue;

cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset);
if (cpu_offset < 0)
continue;

rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid);

if (rc)
if (fdt_parse_hart_id_by_phandle(fdt, phandle, &hartid))
continue;

if (SBI_HARTMASK_MAX_BITS <= sbi_hartid_to_hartindex(hartid))
continue;

if (hwirq == IRQ_M_TIMER)
hcount++;
hcount++;
}

*hart_count = hcount;
Expand Down Expand Up @@ -1112,29 +1167,19 @@ int fdt_parse_plicsw_node(const void *fdt, int nodeoffset, unsigned long *plicsw

hcount = 0;
for (i = 0; i < (count / 2); i++) {
int cpu_offset, cpu_intc_offset;

phandle = fdt32_to_cpu(val[2 * i]);
hwirq = fdt32_to_cpu(val[2 * i + 1]);

cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
if (cpu_intc_offset < 0)
continue;

cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset);
if (cpu_offset < 0)
if (hwirq != IRQ_M_SOFT)
continue;

rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid);

if (rc)
if (fdt_parse_hart_id_by_phandle(fdt, phandle, &hartid))
continue;

if (SBI_HARTMASK_MAX_BITS <= sbi_hartid_to_hartindex(hartid))
continue;

if (hwirq == IRQ_M_SOFT)
hcount++;
hcount++;
}

*hart_count = hcount;
Expand Down
12 changes: 3 additions & 9 deletions lib/utils/irqchip/fdt_irqchip_plic.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ static int irqchip_plic_update_context_map(const void *fdt, int nodeoff,
{
const fdt32_t *val;
u32 phandle, hwirq, hartid, hartindex;
int i, err, count, cpu_offset, cpu_intc_offset;
int i, count;

val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &count);
if (!val || count < sizeof(fdt32_t))
Expand All @@ -33,16 +33,10 @@ static int irqchip_plic_update_context_map(const void *fdt, int nodeoff,
phandle = fdt32_to_cpu(val[i]);
hwirq = fdt32_to_cpu(val[i + 1]);

cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
if (cpu_intc_offset < 0)
if (hwirq != IRQ_M_EXT && hwirq != IRQ_S_EXT)
continue;

cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset);
if (cpu_offset < 0)
continue;

err = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
if (err)
if (fdt_parse_hart_id_by_phandle(fdt, phandle, &hartid))
continue;

hartindex = sbi_hartid_to_hartindex(hartid);
Expand Down
Loading