diff --git a/sys/dev/fdt/fdt_intr.c b/sys/dev/fdt/fdt_intr.c index 50e11f1a7701..1ad8a08bd1a2 100644 --- a/sys/dev/fdt/fdt_intr.c +++ b/sys/dev/fdt/fdt_intr.c @@ -1,4 +1,4 @@ -/* $NetBSD: fdt_intr.c,v 1.21 2019/02/27 17:01:57 jakllsch Exp $ */ +/* $NetBSD: fdt_intr.c,v 1.22 2019/06/14 11:08:18 hkenken Exp $ */ /*- * Copyright (c) 2015-2018 Jared McNeill @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: fdt_intr.c,v 1.21 2019/02/27 17:01:57 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdt_intr.c,v 1.22 2019/06/14 11:08:18 hkenken Exp $"); #include #include @@ -322,12 +322,31 @@ done: return result; } + +static const u_int * +get_specifier_from_extended(int phandle, int pindex, int *piphandle) +{ + const u_int *result = NULL; + struct fdt_phandle_data data; + + if (fdtbus_get_phandle_with_data(phandle, "interrupts-extended", + "#interrupt-cells", pindex, &data) == 0) { + *piphandle = data.phandle; + result = data.values; + } + + return result; +} + static const u_int * get_specifier_by_index(int phandle, int pindex, int *piphandle) { const u_int *node_specifier; int interrupt_parent, interrupt_cells, len; + if (of_hasprop(phandle, "interrupts-extended")) + return get_specifier_from_extended(phandle, pindex, piphandle); + interrupt_parent = fdtbus_get_interrupt_parent(phandle); if (interrupt_parent <= 0) return NULL; diff --git a/sys/dev/fdt/fdt_subr.c b/sys/dev/fdt/fdt_subr.c index 443ef0a19a24..8ca7c8f81840 100644 --- a/sys/dev/fdt/fdt_subr.c +++ b/sys/dev/fdt/fdt_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: fdt_subr.c,v 1.29 2019/02/27 16:56:00 jakllsch Exp $ */ +/* $NetBSD: fdt_subr.c,v 1.30 2019/06/14 11:08:18 hkenken Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.29 2019/02/27 16:56:00 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.30 2019/06/14 11:08:18 hkenken Exp $"); #include "opt_fdt.h" @@ -129,6 +129,42 @@ fdtbus_get_phandle(int phandle, const char *prop) return fdtbus_get_phandle_from_native(phandle_ref); } +int +fdtbus_get_phandle_with_data(int phandle, const char *prop, const char *cells, + int index, struct fdt_phandle_data *data) +{ + int len; + const int offset = 1; + + const u_int *p = fdtbus_get_prop(phandle, prop, &len); + if (p == NULL || len <= 0) + return EINVAL; + + for (int i = 0; len > 0; i++) { + u_int phandle_ref = be32toh(*p); + const u_int iparent = fdtbus_get_phandle_from_native(phandle_ref); + uint32_t cells_num; + of_getprop_uint32(iparent, cells, &cells_num); + + if (index == i) { + if (data != NULL) { + data->phandle = iparent; + data->count = cells_num; + data->values = p + offset; + } + goto done; + } + + const u_int reclen = offset + cells_num; + len -= reclen * sizeof(u_int); + p += reclen; + } + return EINVAL; + +done: + return 0; +} + int fdtbus_get_phandle_from_native(int phandle) { diff --git a/sys/dev/fdt/fdtvar.h b/sys/dev/fdt/fdtvar.h index 1279fde3f07e..976db090a500 100644 --- a/sys/dev/fdt/fdtvar.h +++ b/sys/dev/fdt/fdtvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: fdtvar.h,v 1.51 2019/05/08 13:40:18 isaki Exp $ */ +/* $NetBSD: fdtvar.h,v 1.52 2019/06/14 11:08:18 hkenken Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill @@ -232,6 +232,12 @@ struct fdt_console_info { const struct fdt_console *ops; }; +struct fdt_phandle_data { + int phandle; + int count; + const u_int *values; +}; + #define _FDT_CONSOLE_REGISTER(name) \ __link_set_add_rodata(fdt_consoles, __CONCAT(name,_consinfo)); @@ -278,6 +284,8 @@ int fdtbus_get_reg_byname(int, const char *, bus_addr_t *, bus_size_t *); int fdtbus_get_reg64(int, u_int, uint64_t *, uint64_t *); int fdtbus_get_phandle(int, const char *); +int fdtbus_get_phandle_with_data(int, const char *, const char *, + int, struct fdt_phandle_data *); int fdtbus_get_phandle_from_native(int); i2c_tag_t fdtbus_get_i2c_tag(int); i2c_tag_t fdtbus_i2c_acquire(int, const char *);