mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-07-24 02:22:03 +08:00
linux/of_irq.h: Generalize of_irq_to_resource()
Determine interrupt cells via device tree. Update #3277.
This commit is contained in:
parent
e4923c85c9
commit
cfc149bff3
@ -362,32 +362,73 @@ of_address_to_resource(struct device_node *dn, int index,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_interrupt_cells(const void *fdt, int node)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
const fdt32_t *p;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
p = fdt_getprop(fdt, node, "interrupt-parent", &len);
|
||||||
|
if (p != NULL) {
|
||||||
|
if (len != sizeof(*p))
|
||||||
|
return (-EINVAL);
|
||||||
|
|
||||||
|
node = fdt_node_offset_by_phandle(fdt,
|
||||||
|
fdt32_to_cpu(*p));
|
||||||
|
} else {
|
||||||
|
node = fdt_parent_offset(fdt, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
p = fdt_getprop(fdt, node, "#interrupt-cells", &len);
|
||||||
|
if (p != NULL) {
|
||||||
|
if (len != sizeof(*p))
|
||||||
|
return (-EINVAL);
|
||||||
|
|
||||||
|
return ((int)fdt32_to_cpu(*p));
|
||||||
|
}
|
||||||
|
} while (node >= 0);
|
||||||
|
|
||||||
|
return (-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
of_irq_to_resource(struct device_node *dn, int index,
|
of_irq_to_resource(struct device_node *dn, int index,
|
||||||
struct resource *res)
|
struct resource *res)
|
||||||
{
|
{
|
||||||
const void *fdt = bsp_fdt_get();
|
const void *fdt = bsp_fdt_get();
|
||||||
int len;
|
int len;
|
||||||
const fdt32_t *p;
|
uint32_t spec_buf[8];
|
||||||
|
const fdt32_t *spec;
|
||||||
|
int node;
|
||||||
|
int ic;
|
||||||
int i;
|
int i;
|
||||||
|
int j;
|
||||||
|
int item_len;
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
if (res != NULL)
|
if (res != NULL)
|
||||||
memset(res, 0, sizeof(*res));
|
memset(res, 0, sizeof(*res));
|
||||||
|
|
||||||
p = fdt_getprop(fdt, dn->offset, "interrupts", &len);
|
node = dn->offset;
|
||||||
if (p == NULL)
|
|
||||||
|
spec = fdt_getprop(fdt, node, "interrupts", &len);
|
||||||
|
if (spec == NULL)
|
||||||
return (-EINVAL);
|
return (-EINVAL);
|
||||||
|
|
||||||
i = index * 16;
|
ic = get_interrupt_cells(fdt, node);
|
||||||
if (i + 16 > len)
|
if (ic < 0 || ic >= RTEMS_ARRAY_SIZE(spec_buf))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
item_len = ic * 4;
|
||||||
|
i = index * item_len;
|
||||||
|
if (i + item_len > len)
|
||||||
return (-EINVAL);
|
return (-EINVAL);
|
||||||
|
|
||||||
irq = (int)fdt32_to_cpu(p[i / sizeof(*p)]);
|
for (j = 0; j < ic; ++j)
|
||||||
#ifdef __PPC__
|
spec_buf[j] = fdt32_to_cpu(spec[i / sizeof(*spec)]);
|
||||||
/* FIXME */
|
|
||||||
irq -= 16;
|
irq = bsp_fdt_map_intr(spec_buf, (size_t)ic);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
res->start = irq;
|
res->start = irq;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user