diff --git a/sys/dev/fdt/fdt_mbox.c b/sys/dev/fdt/fdt_mbox.c new file mode 100644 index 000000000000..7121c9e1bd52 --- /dev/null +++ b/sys/dev/fdt/fdt_mbox.c @@ -0,0 +1,183 @@ +/* $NetBSD: fdt_mbox.c,v 1.1 2022/03/04 08:19:06 skrll Exp $ */ + +/*- + * Copyright (c) 2022 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: fdt_mbox.c,v 1.1 2022/03/04 08:19:06 skrll Exp $"); + +#include + +#include +#include +#include + +#include +#include + + +struct fdtbus_mbox_controller { + device_t mc_dev; + int mc_phandle; + + int mc_cells; + + const struct fdtbus_mbox_controller_func *mc_funcs; + + LIST_ENTRY(fdtbus_mbox_controller) mc_next; +}; + +static LIST_HEAD(, fdtbus_mbox_controller) fdtbus_mbox_controllers = + LIST_HEAD_INITIALIZER(fdtbus_mbox_controllers); + +int +fdtbus_register_mbox_controller(device_t dev, int phandle, + const struct fdtbus_mbox_controller_func *funcs) +{ + struct fdtbus_mbox_controller *mc; + + uint32_t cells; + if (of_getprop_uint32(phandle, "#mbox-cells", &cells) != 0) { + aprint_debug_dev(dev, "missing #mbox-cells"); + return EINVAL; + } + + mc = kmem_alloc(sizeof(*mc), KM_SLEEP); + mc->mc_dev = dev; + mc->mc_phandle = phandle; + mc->mc_funcs = funcs; + mc->mc_cells = cells; + + LIST_INSERT_HEAD(&fdtbus_mbox_controllers, mc, mc_next); + + return 0; +} + +static struct fdtbus_mbox_controller * +fdtbus_mbox_lookup(int phandle) +{ + struct fdtbus_mbox_controller *mc; + + LIST_FOREACH(mc, &fdtbus_mbox_controllers, mc_next) { + if (mc->mc_phandle == phandle) + return mc; + } + + return NULL; +} + +struct fdtbus_mbox_channel * +fdtbus_mbox_get_index(int phandle, u_int index, void (*cb)(void *), void *cbarg) +{ + struct fdtbus_mbox_controller *mc; + struct fdtbus_mbox_channel *mbox = NULL; + void *mbox_priv = NULL; + uint32_t *mboxes = NULL; + uint32_t *p; + u_int n; + int len, resid; + + len = OF_getproplen(phandle, "mboxes"); + if (len <= 0) + return NULL; + + mboxes = kmem_alloc(len, KM_SLEEP); + if (OF_getprop(phandle, "mboxes", mboxes, len) != len) { + kmem_free(mboxes, len); + return NULL; + } + + p = mboxes; + for (n = 0, resid = len; resid > 0; n++) { + const int mc_phandle = + fdtbus_get_phandle_from_native(be32toh(p[0])); + + mc = fdtbus_mbox_lookup(mc_phandle); + if (mc == NULL) + break; + + u_int mbox_cells = mc->mc_cells; + if (n == index) { + mbox_priv = mc->mc_funcs->mc_acquire(mc->mc_dev, + mbox_cells > 0 ? &p[1] : NULL, mbox_cells * 4, + cb, cbarg); + if (mbox_priv) { + mbox = kmem_alloc(sizeof(*mbox), KM_SLEEP); + mbox->mb_ctlr = mc; + mbox->mb_priv = mbox_priv; + } + break; + } + resid -= (mbox_cells + 1) * 4; + p += mbox_cells + 1; + } + + if (mboxes) + kmem_free(mboxes, len); + + return mbox; +} + +struct fdtbus_mbox_channel * +fdtbus_mbox_get(int phandle, const char *name, void (*cb)(void *), void *cbarg) +{ + u_int index; + int err; + + err = fdtbus_get_index(phandle, "mbox-names", name, &index); + if (err != 0) + return NULL; + + return fdtbus_mbox_get_index(phandle, index, cb, cbarg); +} + +void +fdtbus_mbox_put(struct fdtbus_mbox_channel *mbox) +{ + struct fdtbus_mbox_controller *mc = mbox->mb_ctlr; + + mc->mc_funcs->mc_release(mc->mc_dev, mbox->mb_priv); + kmem_free(mbox, sizeof(*mbox)); +} + +int +fdtbus_mbox_send(struct fdtbus_mbox_channel *mbox, const void *data, size_t len) +{ + struct fdtbus_mbox_controller * const mc = mbox->mb_ctlr; + + return mc->mc_funcs->mc_send(mc->mc_dev, mbox->mb_priv, data, len); +} + +int +fdtbus_mbox_recv(struct fdtbus_mbox_channel *mbox, void *data, size_t len) +{ + struct fdtbus_mbox_controller * const mc = mbox->mb_ctlr; + + return mc->mc_funcs->mc_recv(mc->mc_dev, mbox->mb_priv, data, len); +} diff --git a/sys/dev/fdt/fdt_powerdomain.c b/sys/dev/fdt/fdt_powerdomain.c new file mode 100644 index 000000000000..2db92884201e --- /dev/null +++ b/sys/dev/fdt/fdt_powerdomain.c @@ -0,0 +1,148 @@ +/* $NetBSD: fdt_powerdomain.c,v 1.1 2022/03/04 08:19:06 skrll Exp $ */ + +/*- + * Copyright (c) 2022 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: fdt_powerdomain.c,v 1.1 2022/03/04 08:19:06 skrll Exp $"); + +#include + +#include +#include +#include + +#include +#include + + +struct fdtbus_powerdomain_controller { + device_t pdc_dev; + int pdc_phandle; + + void *pdc_cookie; + + int pdc_cells; + + const struct fdtbus_powerdomain_controller_func *pdc_funcs; + + LIST_ENTRY(fdtbus_powerdomain_controller) pdc_next; +}; + +static LIST_HEAD(, fdtbus_powerdomain_controller) fdtbus_powerdomain_controllers = + LIST_HEAD_INITIALIZER(fdtbus_powerdomain_controllers); + +int +fdtbus_register_powerdomain_controller(device_t dev, int phandle, + const struct fdtbus_powerdomain_controller_func *funcs) +{ + struct fdtbus_powerdomain_controller *pdc; + + uint32_t cells; + if (of_getprop_uint32(phandle, "#power-domain-cells", &cells) != 0) { + aprint_debug_dev(dev, "missing #power-domain-cells"); + return EINVAL; + } + + pdc = kmem_alloc(sizeof(*pdc), KM_SLEEP); + pdc->pdc_dev = dev; + pdc->pdc_phandle = phandle; + pdc->pdc_funcs = funcs; + pdc->pdc_cells = cells; + + LIST_INSERT_HEAD(&fdtbus_powerdomain_controllers, pdc, pdc_next); + + return 0; +} + +static struct fdtbus_powerdomain_controller * +fdtbus_powerdomain_lookup(int phandle) +{ + struct fdtbus_powerdomain_controller *pdc; + + LIST_FOREACH(pdc, &fdtbus_powerdomain_controllers, pdc_next) { + if (pdc->pdc_phandle == phandle) + return pdc; + } + + return NULL; +} + +static int +fdtbus_powerdomain_enable_internal(int phandle, int index, bool enable) +{ + int len; + const uint32_t *pds = fdtbus_get_prop(phandle, "power-domains", &len); + + if (pds == NULL) + return EINVAL; + + for (const uint32_t *pd = pds; pd < pds + len; index--) { + uint32_t pd_node = + fdtbus_get_phandle_from_native(be32toh(pd[0])); + struct fdtbus_powerdomain_controller *pdc = + fdtbus_powerdomain_lookup(pd_node); + + if (pdc == NULL) + return ENXIO; + + if (index < 0 || index == 0) + pdc->pdc_funcs->pdc_enable(pdc->pdc_dev, pd, enable); + if (index == 0) + break; + + pd += pdc->pdc_cells + 1; + } + + return 0; +} + +int +fdtbus_powerdomain_enable_index(int phandle, int index) +{ + return fdtbus_powerdomain_enable_internal(phandle, index, true); +} + +int +fdtbus_powerdomain_disable_index(int phandle, int index) +{ + return fdtbus_powerdomain_enable_internal(phandle, index, false); +} + +int +fdtbus_powerdomain_enable(int node) +{ + return fdtbus_powerdomain_enable_index(node, -1); +} + +int +fdtbus_powerdomain_disable(int node) +{ + return fdtbus_powerdomain_disable_index(node, -1); +} diff --git a/sys/dev/fdt/fdtbus.c b/sys/dev/fdt/fdtbus.c index 86879f63c140..b956318f203a 100644 --- a/sys/dev/fdt/fdtbus.c +++ b/sys/dev/fdt/fdtbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: fdtbus.c,v 1.45 2022/01/22 11:49:17 thorpej Exp $ */ +/* $NetBSD: fdtbus.c,v 1.46 2022/03/04 08:19:06 skrll Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.45 2022/01/22 11:49:17 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.46 2022/03/04 08:19:06 skrll Exp $"); #include #include @@ -468,6 +468,8 @@ fdt_pre_attach(struct fdt_node *node) aprint_debug_dev(node->n_bus, "failed to set %s config on %s: %d\n", cfgname, node->n_name, error); + + fdtbus_powerdomain_enable(node->n_phandle); } static void diff --git a/sys/dev/fdt/fdtvar.h b/sys/dev/fdt/fdtvar.h index 579087cbbc1b..d9a1395d31c1 100644 --- a/sys/dev/fdt/fdtvar.h +++ b/sys/dev/fdt/fdtvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: fdtvar.h,v 1.76 2022/02/23 08:56:11 skrll Exp $ */ +/* $NetBSD: fdtvar.h,v 1.77 2022/03/04 08:19:06 skrll Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill @@ -157,6 +157,20 @@ struct fdtbus_iommu_func { }; +struct fdtbus_mbox_channel { + struct fdtbus_mbox_controller *mb_ctlr; + void *mb_priv; +}; + +struct fdtbus_mbox_controller_func { + void * (*mc_acquire)(device_t, const void *, size_t, void (*)(void *), + void *); + void (*mc_release)(device_t, void *); + int (*mc_recv)(device_t, void *, void *, size_t); + int (*mc_send)(device_t, void *, const void *, size_t); +}; + + struct fdtbus_mmc_pwrseq; struct fdtbus_mmc_pwrseq_func { @@ -201,6 +215,13 @@ struct fdtbus_power_controller_func { }; +struct fdtbus_powerdomain_controller; + +struct fdtbus_powerdomain_controller_func { + void (*pdc_enable)(device_t, const uint32_t *, bool); +}; + + struct fdtbus_pwm_controller_func { pwm_tag_t (*get_tag)(device_t, const void *, size_t); }; @@ -306,12 +327,16 @@ int fdtbus_register_interrupt_controller(device_t, int, const struct fdtbus_interrupt_controller_func *); int fdtbus_register_iommu(device_t, int, const struct fdtbus_iommu_func *); +int fdtbus_register_mbox_controller(device_t, int, + const struct fdtbus_mbox_controller_func *); int fdtbus_register_mmc_pwrseq(device_t, int, const struct fdtbus_mmc_pwrseq_func *); int fdtbus_register_pinctrl_config(device_t, int, const struct fdtbus_pinctrl_controller_func *); int fdtbus_register_power_controller(device_t, int, const struct fdtbus_power_controller_func *); +int fdtbus_register_powerdomain_controller(device_t, int, + const struct fdtbus_powerdomain_controller_func *); int fdtbus_register_phy_controller(device_t, int, const struct fdtbus_phy_controller_func *); int fdtbus_register_pwm_controller(device_t, int, @@ -392,6 +417,15 @@ int fdtbus_intr_parent(int); bus_dma_tag_t fdtbus_iommu_map(int, u_int, bus_dma_tag_t); bus_dma_tag_t fdtbus_iommu_map_pci(int, uint32_t, bus_dma_tag_t); +struct fdtbus_mbox_channel * + fdtbus_mbox_get(int, const char *, void (*)(void *), void *); +struct fdtbus_mbox_channel * + fdtbus_mbox_get_index(int, u_int, void (*)(void *), + void *); +int fdtbus_mbox_send(struct fdtbus_mbox_channel *, const void *, size_t); +int fdtbus_mbox_recv(struct fdtbus_mbox_channel *, void *, size_t); +void fdtbus_mbox_put(struct fdtbus_mbox_channel *); + struct fdtbus_mmc_pwrseq * fdtbus_mmc_pwrseq_get(int); void fdtbus_mmc_pwrseq_pre_power_on(struct fdtbus_mmc_pwrseq *); @@ -447,6 +481,11 @@ int fdtbus_todr_attach(device_t, int, todr_chip_handle_t); void fdtbus_power_reset(void); void fdtbus_power_poweroff(void); +int fdtbus_powerdomain_enable(int); +int fdtbus_powerdomain_enable_index(int, int); +int fdtbus_powerdomain_disable(int); +int fdtbus_powerdomain_disable_index(int, int); + struct syscon * fdtbus_syscon_acquire(int, const char *); struct syscon * fdtbus_syscon_lookup(int); diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt index 8464a0e8f2fe..7d3cb21e152c 100644 --- a/sys/dev/fdt/files.fdt +++ b/sys/dev/fdt/files.fdt @@ -1,4 +1,4 @@ -# $NetBSD: files.fdt,v 1.62 2021/09/04 12:34:39 jmcneill Exp $ +# $NetBSD: files.fdt,v 1.63 2022/03/04 08:19:06 skrll Exp $ include "external/bsd/libfdt/conf/files.libfdt" @@ -74,9 +74,11 @@ file dev/fdt/fdt_gpio.c fdt file dev/fdt/fdt_i2c.c fdt file dev/fdt/fdt_iommu.c fdt file dev/fdt/fdt_intr.c fdt +file dev/fdt/fdt_mbox.c fdt file dev/fdt/fdt_mmc_pwrseq.c fdt file dev/fdt/fdt_phy.c fdt file dev/fdt/fdt_power.c fdt +file dev/fdt/fdt_powerdomain.c fdt file dev/fdt/fdt_pwm.c fdt file dev/fdt/fdt_regulator.c fdt file dev/fdt/fdt_reset.c fdt