From 5b0333eb177ac3945d3516e391274ca1ac2f6af4 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Sat, 30 Jun 2018 12:35:18 +0000 Subject: [PATCH] Add support for system controller nodes. --- sys/dev/fdt/fdt_syscon.c | 98 +++++++++++++++++++++++++++ sys/dev/fdt/fdtvar.h | 6 +- sys/dev/fdt/files.fdt | 7 +- sys/dev/fdt/syscon.c | 138 +++++++++++++++++++++++++++++++++++++++ sys/dev/fdt/syscon.h | 54 +++++++++++++++ 5 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 sys/dev/fdt/fdt_syscon.c create mode 100644 sys/dev/fdt/syscon.c create mode 100644 sys/dev/fdt/syscon.h diff --git a/sys/dev/fdt/fdt_syscon.c b/sys/dev/fdt/fdt_syscon.c new file mode 100644 index 000000000000..8b14f6e2da51 --- /dev/null +++ b/sys/dev/fdt/fdt_syscon.c @@ -0,0 +1,98 @@ +/* $NetBSD: fdt_syscon.c,v 1.1 2018/06/30 12:35:18 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 Jared McNeill + * All rights reserved. + * + * 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 AUTHOR ``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 AUTHOR 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_syscon.c,v 1.1 2018/06/30 12:35:18 jmcneill Exp $"); + +#include +#include +#include +#include + +#include +#include + +struct syscon; + +struct fdtbus_syscon { + device_t sc_dev; + int sc_phandle; + struct syscon *sc_syscon; + + LIST_ENTRY(fdtbus_syscon) sc_next; +}; + +LIST_HEAD(fdtbus_syscon_h, fdtbus_syscon); +static struct fdtbus_syscon_h fdtbus_syscons = + LIST_HEAD_INITIALIZER(fdtbus_syscons); + +int +fdtbus_register_syscon(device_t dev, int phandle, + struct syscon *syscon) +{ + struct fdtbus_syscon *sc; + + sc = kmem_alloc(sizeof(*sc), KM_SLEEP); + sc->sc_dev = dev; + sc->sc_phandle = phandle; + sc->sc_syscon = syscon; + + LIST_INSERT_HEAD(&fdtbus_syscons, sc, sc_next); + + return 0; +} + +static struct fdtbus_syscon * +fdtbus_get_syscon(int phandle) +{ + struct fdtbus_syscon *sc; + + LIST_FOREACH(sc, &fdtbus_syscons, sc_next) { + if (sc->sc_phandle == phandle) + return sc; + } + + return NULL; +} + +struct syscon * +fdtbus_syscon_acquire(int phandle, const char *prop) +{ + struct fdtbus_syscon *sc; + int sc_phandle; + + sc_phandle = fdtbus_get_phandle(phandle, prop); + if (sc_phandle < 0) + return NULL; + + sc = fdtbus_get_syscon(sc_phandle); + if (sc == NULL) + return NULL; + + return sc->sc_syscon; +} diff --git a/sys/dev/fdt/fdtvar.h b/sys/dev/fdt/fdtvar.h index 34ff98eaf5f4..502195114b48 100644 --- a/sys/dev/fdt/fdtvar.h +++ b/sys/dev/fdt/fdtvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: fdtvar.h,v 1.34 2018/06/12 10:28:55 jmcneill Exp $ */ +/* $NetBSD: fdtvar.h,v 1.35 2018/06/30 12:35:18 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill @@ -210,6 +210,8 @@ struct fdtbus_mmc_pwrseq_func { void (*reset)(device_t); }; +struct syscon; + struct fdt_console { int (*match)(int); void (*consinit)(struct fdt_attach_args *, u_int); @@ -256,6 +258,7 @@ int fdtbus_register_pwm_controller(device_t, int, const struct fdtbus_pwm_controller_func *); int fdtbus_register_mmc_pwrseq(device_t, int, const struct fdtbus_mmc_pwrseq_func *); +int fdtbus_register_syscon(device_t, int, struct syscon *); void fdtbus_set_decoderegprop(bool); @@ -292,6 +295,7 @@ int fdtbus_regulator_set_voltage(struct fdtbus_regulator *, u_int, u_int); int fdtbus_regulator_get_voltage(struct fdtbus_regulator *, u_int *); +struct syscon * fdtbus_syscon_acquire(int, const char *); struct fdtbus_dma *fdtbus_dma_get(int, const char *, void (*)(void *), void *); struct fdtbus_dma *fdtbus_dma_get_index(int, u_int, void (*)(void *), diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt index b17b74056bb0..9116555977a8 100644 --- a/sys/dev/fdt/files.fdt +++ b/sys/dev/fdt/files.fdt @@ -1,4 +1,4 @@ -# $NetBSD: files.fdt,v 1.33 2018/06/30 10:50:30 jmcneill Exp $ +# $NetBSD: files.fdt,v 1.34 2018/06/30 12:35:18 jmcneill Exp $ include "external/bsd/libfdt/conf/files.libfdt" @@ -59,6 +59,7 @@ file dev/fdt/fdt_pwm.c fdtbus file dev/fdt/fdt_regulator.c fdtbus file dev/fdt/fdt_reset.c fdtbus file dev/fdt/fdt_rtc.c fdtbus +file dev/fdt/fdt_syscon.c fdtbus file dev/fdt/fdt_pinctrl.c fdtbus device cpus { } : fdtbus @@ -69,6 +70,10 @@ device mmcpwrseq attach mmcpwrseq at fdt file dev/fdt/mmc_pwrseq_simple.c mmcpwrseq +device syscon +attach syscon at fdt +file dev/fdt/syscon.c syscon + device pwmbacklight attach pwmbacklight at fdt file dev/fdt/pwm_backlight.c pwmbacklight diff --git a/sys/dev/fdt/syscon.c b/sys/dev/fdt/syscon.c new file mode 100644 index 000000000000..e902cc872372 --- /dev/null +++ b/sys/dev/fdt/syscon.c @@ -0,0 +1,138 @@ +/* $NetBSD: syscon.c,v 1.1 2018/06/30 12:35:18 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 Jared McNeill + * All rights reserved. + * + * 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 AUTHOR ``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 AUTHOR 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: syscon.c,v 1.1 2018/06/30 12:35:18 jmcneill Exp $"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct syscon_softc { + device_t sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + kmutex_t sc_lock; + + struct syscon sc_syscon; +}; + +static int syscon_match(device_t, cfdata_t, void *); +static void syscon_attach(device_t, device_t, void *); + +static const char *compatible[] = { + "syscon", + NULL +}; + +CFATTACH_DECL_NEW(syscon, sizeof(struct syscon_softc), + syscon_match, syscon_attach, NULL, NULL); + +static void +syscon_generic_lock(void *priv) +{ + struct syscon_softc * const sc = priv; + + mutex_enter(&sc->sc_lock); +} + +static void +syscon_generic_unlock(void *priv) +{ + struct syscon_softc * const sc = priv; + + mutex_exit(&sc->sc_lock); +} + +static uint32_t +syscon_generic_read_4(void *priv, bus_size_t reg) +{ + struct syscon_softc * const sc = priv; + + KASSERT(mutex_owned(&sc->sc_lock)); + + return bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg); +} + +static void +syscon_generic_write_4(void *priv, bus_size_t reg, uint32_t val) +{ + struct syscon_softc * const sc = priv; + + KASSERT(mutex_owned(&sc->sc_lock)); + + bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val); +} + +static int +syscon_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_match_compatible(faa->faa_phandle, compatible); +} + +static void +syscon_attach(device_t parent, device_t self, void *aux) +{ + struct syscon_softc * const sc = device_private(self); + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + bus_addr_t addr; + bus_size_t size; + + if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { + aprint_error(": couldn't get registers\n"); + return; + } + + sc->sc_dev = self; + sc->sc_bst = faa->faa_bst; + if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { + aprint_error(": couldn't map registers\n"); + return; + } + mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); + sc->sc_syscon.priv = sc; + sc->sc_syscon.lock = syscon_generic_lock; + sc->sc_syscon.unlock = syscon_generic_unlock; + sc->sc_syscon.read_4 = syscon_generic_read_4; + sc->sc_syscon.write_4 = syscon_generic_write_4; + + aprint_naive("\n"); + aprint_normal(": System Controller Registers\n"); + + fdtbus_register_syscon(self, phandle, &sc->sc_syscon); +} diff --git a/sys/dev/fdt/syscon.h b/sys/dev/fdt/syscon.h new file mode 100644 index 000000000000..ce8b3c32173b --- /dev/null +++ b/sys/dev/fdt/syscon.h @@ -0,0 +1,54 @@ +/* $NetBSD: syscon.h,v 1.1 2018/06/30 12:35:18 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 Jared McNeill + * All rights reserved. + * + * 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 AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _FDT_SYSCON_H +#define _FDT_SYSCON_H + +struct syscon { + void *priv; + + void (*lock)(void *); + void (*unlock)(void *); + uint32_t (*read_4)(void *, bus_size_t); + void (*write_4)(void *, bus_size_t, uint32_t); +}; + +#define syscon_lock(_syscon) \ + (_syscon)->lock((_syscon)->priv) + +#define syscon_unlock(_syscon) \ + (_syscon)->unlock((_syscon)->priv) + +#define syscon_read_4(_syscon, _reg) \ + (_syscon)->read_4((_syscon)->priv, (_reg)) + +#define syscon_write_4(_syscon, _reg, _val) \ + (_syscon)->write_4((_syscon)->priv, (_reg), (_val)) + + +#endif /* !_FDT_SYSCON_H */