12091650bSEmmanuel Vadot /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
32091650bSEmmanuel Vadot *
42091650bSEmmanuel Vadot * Copyright (c) 2018 Rubicon Communications, LLC (Netgate)
52091650bSEmmanuel Vadot *
62091650bSEmmanuel Vadot * Redistribution and use in source and binary forms, with or without
72091650bSEmmanuel Vadot * modification, are permitted provided that the following conditions
82091650bSEmmanuel Vadot * are met:
92091650bSEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright
102091650bSEmmanuel Vadot * notice, this list of conditions and the following disclaimer.
112091650bSEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright
122091650bSEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the
132091650bSEmmanuel Vadot * documentation and/or other materials provided with the distribution.
142091650bSEmmanuel Vadot *
152091650bSEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
162091650bSEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
172091650bSEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
182091650bSEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
192091650bSEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
202091650bSEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
212091650bSEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
222091650bSEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
232091650bSEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
242091650bSEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
252091650bSEmmanuel Vadot * SUCH DAMAGE.
262091650bSEmmanuel Vadot *
272091650bSEmmanuel Vadot */
282091650bSEmmanuel Vadot
292091650bSEmmanuel Vadot #include <sys/param.h>
302091650bSEmmanuel Vadot #include <sys/systm.h>
312091650bSEmmanuel Vadot #include <sys/bus.h>
322091650bSEmmanuel Vadot #include <sys/kernel.h>
3373155b43SGanbold Tsagaankhuu #include <sys/lock.h>
342091650bSEmmanuel Vadot #include <sys/module.h>
3573155b43SGanbold Tsagaankhuu #include <sys/mutex.h>
3673155b43SGanbold Tsagaankhuu #include <sys/rman.h>
372091650bSEmmanuel Vadot
382091650bSEmmanuel Vadot #include <machine/bus.h>
392091650bSEmmanuel Vadot
402091650bSEmmanuel Vadot #include <dev/fdt/simplebus.h>
412091650bSEmmanuel Vadot
422091650bSEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
432091650bSEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
442091650bSEmmanuel Vadot
4573155b43SGanbold Tsagaankhuu #include <dev/fdt/simple_mfd.h>
462091650bSEmmanuel Vadot
472091650bSEmmanuel Vadot device_t simple_mfd_add_device(device_t dev, phandle_t node, u_int order,
482091650bSEmmanuel Vadot const char *name, int unit, struct simplebus_devinfo *di);
497f8c4c78SMichal Meloun struct simplebus_devinfo *simple_mfd_setup_dinfo(device_t dev, phandle_t node,
507f8c4c78SMichal Meloun struct simplebus_devinfo *di);
512091650bSEmmanuel Vadot
5273155b43SGanbold Tsagaankhuu #include "syscon_if.h"
5362e8ccc3SEmmanuel Vadot #include <dev/syscon/syscon.h>
5473155b43SGanbold Tsagaankhuu
5573155b43SGanbold Tsagaankhuu MALLOC_DECLARE(M_SYSCON);
5673155b43SGanbold Tsagaankhuu
577f8c4c78SMichal Meloun static uint32_t simple_mfd_syscon_read_4(struct syscon *syscon,
587f8c4c78SMichal Meloun bus_size_t offset);
5973155b43SGanbold Tsagaankhuu static int simple_mfd_syscon_write_4(struct syscon *syscon, bus_size_t offset,
6073155b43SGanbold Tsagaankhuu uint32_t val);
6173155b43SGanbold Tsagaankhuu static int simple_mfd_syscon_modify_4(struct syscon *syscon, bus_size_t offset,
6273155b43SGanbold Tsagaankhuu uint32_t clear_bits, uint32_t set_bits);
6373155b43SGanbold Tsagaankhuu
6473155b43SGanbold Tsagaankhuu #define SYSCON_LOCK(_sc) mtx_lock_spin(&(_sc)->mtx)
6573155b43SGanbold Tsagaankhuu #define SYSCON_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->mtx)
6673155b43SGanbold Tsagaankhuu #define SYSCON_LOCK_INIT(_sc) mtx_init(&(_sc)->mtx, \
6773155b43SGanbold Tsagaankhuu device_get_nameunit((_sc)->dev), "syscon", MTX_SPIN)
6873155b43SGanbold Tsagaankhuu #define SYSCON_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx);
6973155b43SGanbold Tsagaankhuu #define SYSCON_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED);
7073155b43SGanbold Tsagaankhuu #define SYSCON_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED);
7173155b43SGanbold Tsagaankhuu
7273155b43SGanbold Tsagaankhuu static syscon_method_t simple_mfd_syscon_methods[] = {
73f97f57b5SMichal Meloun SYSCONMETHOD(syscon_unlocked_read_4, simple_mfd_syscon_read_4),
74f97f57b5SMichal Meloun SYSCONMETHOD(syscon_unlocked_write_4, simple_mfd_syscon_write_4),
75f97f57b5SMichal Meloun SYSCONMETHOD(syscon_unlocked_modify_4, simple_mfd_syscon_modify_4),
7673155b43SGanbold Tsagaankhuu
7773155b43SGanbold Tsagaankhuu SYSCONMETHOD_END
7873155b43SGanbold Tsagaankhuu };
7973155b43SGanbold Tsagaankhuu DEFINE_CLASS_1(simple_mfd_syscon, simple_mfd_syscon_class,
8073155b43SGanbold Tsagaankhuu simple_mfd_syscon_methods, 0, syscon_class);
8173155b43SGanbold Tsagaankhuu
8273155b43SGanbold Tsagaankhuu static uint32_t
simple_mfd_syscon_read_4(struct syscon * syscon,bus_size_t offset)8373155b43SGanbold Tsagaankhuu simple_mfd_syscon_read_4(struct syscon *syscon, bus_size_t offset)
8473155b43SGanbold Tsagaankhuu {
8573155b43SGanbold Tsagaankhuu struct simple_mfd_softc *sc;
8673155b43SGanbold Tsagaankhuu uint32_t val;
8773155b43SGanbold Tsagaankhuu
8873155b43SGanbold Tsagaankhuu sc = device_get_softc(syscon->pdev);
8921cc0918SElliott Mitchell SYSCON_ASSERT_LOCKED(sc);
9073155b43SGanbold Tsagaankhuu val = bus_read_4(sc->mem_res, offset);
9173155b43SGanbold Tsagaankhuu return (val);
9273155b43SGanbold Tsagaankhuu }
9373155b43SGanbold Tsagaankhuu
9473155b43SGanbold Tsagaankhuu static int
simple_mfd_syscon_write_4(struct syscon * syscon,bus_size_t offset,uint32_t val)9573155b43SGanbold Tsagaankhuu simple_mfd_syscon_write_4(struct syscon *syscon, bus_size_t offset,
9673155b43SGanbold Tsagaankhuu uint32_t val)
9773155b43SGanbold Tsagaankhuu {
9873155b43SGanbold Tsagaankhuu struct simple_mfd_softc *sc;
9973155b43SGanbold Tsagaankhuu
10073155b43SGanbold Tsagaankhuu sc = device_get_softc(syscon->pdev);
101f97f57b5SMichal Meloun SYSCON_ASSERT_LOCKED(sc);
10273155b43SGanbold Tsagaankhuu bus_write_4(sc->mem_res, offset, val);
10373155b43SGanbold Tsagaankhuu return (0);
10473155b43SGanbold Tsagaankhuu }
10573155b43SGanbold Tsagaankhuu
10673155b43SGanbold Tsagaankhuu static int
simple_mfd_syscon_modify_4(struct syscon * syscon,bus_size_t offset,uint32_t clear_bits,uint32_t set_bits)10773155b43SGanbold Tsagaankhuu simple_mfd_syscon_modify_4(struct syscon *syscon, bus_size_t offset,
10873155b43SGanbold Tsagaankhuu uint32_t clear_bits, uint32_t set_bits)
10973155b43SGanbold Tsagaankhuu {
11073155b43SGanbold Tsagaankhuu struct simple_mfd_softc *sc;
11173155b43SGanbold Tsagaankhuu uint32_t val;
11273155b43SGanbold Tsagaankhuu
11373155b43SGanbold Tsagaankhuu sc = device_get_softc(syscon->pdev);
114f97f57b5SMichal Meloun SYSCON_ASSERT_LOCKED(sc);
11573155b43SGanbold Tsagaankhuu val = bus_read_4(sc->mem_res, offset);
11673155b43SGanbold Tsagaankhuu val &= ~clear_bits;
11773155b43SGanbold Tsagaankhuu val |= set_bits;
11873155b43SGanbold Tsagaankhuu bus_write_4(sc->mem_res, offset, val);
11973155b43SGanbold Tsagaankhuu return (0);
12073155b43SGanbold Tsagaankhuu }
121f97f57b5SMichal Meloun
1227f8c4c78SMichal Meloun static int
simple_mfd_syscon_get_handle(device_t dev,struct syscon ** syscon)1237f8c4c78SMichal Meloun simple_mfd_syscon_get_handle(device_t dev, struct syscon **syscon)
1247f8c4c78SMichal Meloun {
1257f8c4c78SMichal Meloun struct simple_mfd_softc *sc;
1267f8c4c78SMichal Meloun
1277f8c4c78SMichal Meloun sc = device_get_softc(dev);
1287f8c4c78SMichal Meloun *syscon = sc->syscon;
12976eeda85SMichal Meloun if (*syscon == NULL)
1307f8c4c78SMichal Meloun return (ENODEV);
1317f8c4c78SMichal Meloun return (0);
1327f8c4c78SMichal Meloun }
13373155b43SGanbold Tsagaankhuu
134f97f57b5SMichal Meloun static void
simple_mfd_syscon_lock(device_t dev)135f97f57b5SMichal Meloun simple_mfd_syscon_lock(device_t dev)
136f97f57b5SMichal Meloun {
137f97f57b5SMichal Meloun struct simple_mfd_softc *sc;
138f97f57b5SMichal Meloun
139f97f57b5SMichal Meloun sc = device_get_softc(dev);
140f97f57b5SMichal Meloun SYSCON_LOCK(sc);
141f97f57b5SMichal Meloun }
142f97f57b5SMichal Meloun
143f97f57b5SMichal Meloun static void
simple_mfd_syscon_unlock(device_t dev)144f97f57b5SMichal Meloun simple_mfd_syscon_unlock(device_t dev)
145f97f57b5SMichal Meloun {
146f97f57b5SMichal Meloun struct simple_mfd_softc *sc;
147f97f57b5SMichal Meloun
148f97f57b5SMichal Meloun sc = device_get_softc(dev);
149f97f57b5SMichal Meloun SYSCON_UNLOCK(sc);
150f97f57b5SMichal Meloun }
151f97f57b5SMichal Meloun
1522091650bSEmmanuel Vadot static int
simple_mfd_probe(device_t dev)1532091650bSEmmanuel Vadot simple_mfd_probe(device_t dev)
1542091650bSEmmanuel Vadot {
1552091650bSEmmanuel Vadot
1562091650bSEmmanuel Vadot if (!ofw_bus_status_okay(dev))
1572091650bSEmmanuel Vadot return (ENXIO);
1582091650bSEmmanuel Vadot if (!ofw_bus_is_compatible(dev, "simple-mfd"))
1592091650bSEmmanuel Vadot return (ENXIO);
1602091650bSEmmanuel Vadot
1612091650bSEmmanuel Vadot device_set_desc(dev, "Simple MFD (Multi-Functions Device)");
1622091650bSEmmanuel Vadot
1632091650bSEmmanuel Vadot return (BUS_PROBE_GENERIC);
1642091650bSEmmanuel Vadot }
1652091650bSEmmanuel Vadot
1662091650bSEmmanuel Vadot static int
simple_mfd_attach(device_t dev)1672091650bSEmmanuel Vadot simple_mfd_attach(device_t dev)
1682091650bSEmmanuel Vadot {
1692091650bSEmmanuel Vadot struct simple_mfd_softc *sc;
1702091650bSEmmanuel Vadot phandle_t node, child;
17173155b43SGanbold Tsagaankhuu int rid;
1722091650bSEmmanuel Vadot
1732091650bSEmmanuel Vadot sc = device_get_softc(dev);
1742091650bSEmmanuel Vadot node = ofw_bus_get_node(dev);
1752091650bSEmmanuel Vadot
17673155b43SGanbold Tsagaankhuu sc->dev = dev;
17773155b43SGanbold Tsagaankhuu rid = 0;
17873155b43SGanbold Tsagaankhuu
1792091650bSEmmanuel Vadot /* Parse address-cells and size-cells from the parent node as a fallback */
1802091650bSEmmanuel Vadot if (OF_getencprop(node, "#address-cells", &sc->sc.acells,
1812091650bSEmmanuel Vadot sizeof(sc->sc.acells)) == -1) {
1822091650bSEmmanuel Vadot if (OF_getencprop(OF_parent(node), "#address-cells", &sc->sc.acells,
1832091650bSEmmanuel Vadot sizeof(sc->sc.acells)) == -1) {
1842091650bSEmmanuel Vadot sc->sc.acells = 2;
1852091650bSEmmanuel Vadot }
1862091650bSEmmanuel Vadot }
1872091650bSEmmanuel Vadot if (OF_getencprop(node, "#size-cells", &sc->sc.scells,
1882091650bSEmmanuel Vadot sizeof(sc->sc.scells)) == -1) {
1892091650bSEmmanuel Vadot if (OF_getencprop(OF_parent(node), "#size-cells", &sc->sc.scells,
1902091650bSEmmanuel Vadot sizeof(sc->sc.scells)) == -1) {
1912091650bSEmmanuel Vadot sc->sc.scells = 1;
1922091650bSEmmanuel Vadot }
1932091650bSEmmanuel Vadot }
1942091650bSEmmanuel Vadot
1952091650bSEmmanuel Vadot /* If the node has a ranges prop, parse it so children mapping will be done correctly */
1962091650bSEmmanuel Vadot if (OF_hasprop(node, "ranges")) {
1972091650bSEmmanuel Vadot if (simplebus_fill_ranges(node, &sc->sc) < 0) {
1982091650bSEmmanuel Vadot device_printf(dev, "could not get ranges\n");
1992091650bSEmmanuel Vadot return (ENXIO);
2002091650bSEmmanuel Vadot }
2012091650bSEmmanuel Vadot }
2022091650bSEmmanuel Vadot
2032091650bSEmmanuel Vadot /* Attach child devices */
2042091650bSEmmanuel Vadot for (child = OF_child(node); child > 0; child = OF_peer(child)) {
205accda781SMitchell Horne (void)simple_mfd_add_device(dev, child, 0, NULL, -1, NULL);
2062091650bSEmmanuel Vadot }
2072091650bSEmmanuel Vadot
20873155b43SGanbold Tsagaankhuu if (ofw_bus_is_compatible(dev, "syscon")) {
20973155b43SGanbold Tsagaankhuu sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
210b52d0dc4SEmmanuel Vadot RF_ACTIVE);
21173155b43SGanbold Tsagaankhuu if (sc->mem_res == NULL) {
21273155b43SGanbold Tsagaankhuu device_printf(dev,
21373155b43SGanbold Tsagaankhuu "Cannot allocate memory resource\n");
21473155b43SGanbold Tsagaankhuu return (ENXIO);
21573155b43SGanbold Tsagaankhuu }
21673155b43SGanbold Tsagaankhuu
21773155b43SGanbold Tsagaankhuu SYSCON_LOCK_INIT(sc);
21873155b43SGanbold Tsagaankhuu sc->syscon = syscon_create_ofw_node(dev,
21973155b43SGanbold Tsagaankhuu &simple_mfd_syscon_class, ofw_bus_get_node(dev));
22073155b43SGanbold Tsagaankhuu if (sc->syscon == NULL) {
22173155b43SGanbold Tsagaankhuu device_printf(dev,
22273155b43SGanbold Tsagaankhuu "Failed to create/register syscon\n");
22373155b43SGanbold Tsagaankhuu return (ENXIO);
22473155b43SGanbold Tsagaankhuu }
22573155b43SGanbold Tsagaankhuu }
226*18250ec6SJohn Baldwin bus_attach_children(dev);
227*18250ec6SJohn Baldwin return (0);
2282091650bSEmmanuel Vadot }
2292091650bSEmmanuel Vadot
23073155b43SGanbold Tsagaankhuu static int
simple_mfd_detach(device_t dev)23173155b43SGanbold Tsagaankhuu simple_mfd_detach(device_t dev)
23273155b43SGanbold Tsagaankhuu {
23373155b43SGanbold Tsagaankhuu struct simple_mfd_softc *sc;
23473155b43SGanbold Tsagaankhuu
23573155b43SGanbold Tsagaankhuu sc = device_get_softc(dev);
23673155b43SGanbold Tsagaankhuu if (ofw_bus_is_compatible(dev, "syscon")) {
23773155b43SGanbold Tsagaankhuu if (sc->syscon != NULL) {
23873155b43SGanbold Tsagaankhuu syscon_unregister(sc->syscon);
23973155b43SGanbold Tsagaankhuu free(sc->syscon, M_SYSCON);
24073155b43SGanbold Tsagaankhuu }
24173155b43SGanbold Tsagaankhuu
24273155b43SGanbold Tsagaankhuu SYSCON_LOCK_DESTROY(sc);
24373155b43SGanbold Tsagaankhuu
24473155b43SGanbold Tsagaankhuu if (sc->mem_res != NULL)
24573155b43SGanbold Tsagaankhuu bus_release_resource(dev, SYS_RES_MEMORY, 0,
24673155b43SGanbold Tsagaankhuu sc->mem_res);
24773155b43SGanbold Tsagaankhuu }
24873155b43SGanbold Tsagaankhuu return (0);
24973155b43SGanbold Tsagaankhuu }
25073155b43SGanbold Tsagaankhuu
2512091650bSEmmanuel Vadot struct simplebus_devinfo *
simple_mfd_setup_dinfo(device_t dev,phandle_t node,struct simplebus_devinfo * di)2522091650bSEmmanuel Vadot simple_mfd_setup_dinfo(device_t dev, phandle_t node,
2532091650bSEmmanuel Vadot struct simplebus_devinfo *di)
2542091650bSEmmanuel Vadot {
2552091650bSEmmanuel Vadot struct simplebus_softc *sc;
2562091650bSEmmanuel Vadot struct simplebus_devinfo *ndi;
2572091650bSEmmanuel Vadot
2582091650bSEmmanuel Vadot sc = device_get_softc(dev);
2592091650bSEmmanuel Vadot if (di == NULL)
2602091650bSEmmanuel Vadot ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
2612091650bSEmmanuel Vadot else
2622091650bSEmmanuel Vadot ndi = di;
2632091650bSEmmanuel Vadot if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) {
2642091650bSEmmanuel Vadot if (di == NULL)
2652091650bSEmmanuel Vadot free(ndi, M_DEVBUF);
2662091650bSEmmanuel Vadot return (NULL);
2672091650bSEmmanuel Vadot }
2682091650bSEmmanuel Vadot
2692091650bSEmmanuel Vadot /* reg resources is from the parent but interrupts is on the node itself */
2702091650bSEmmanuel Vadot resource_list_init(&ndi->rl);
2712091650bSEmmanuel Vadot ofw_bus_reg_to_rl(dev, OF_parent(node), sc->acells, sc->scells, &ndi->rl);
2722091650bSEmmanuel Vadot ofw_bus_intr_to_rl(dev, node, &ndi->rl, NULL);
2732091650bSEmmanuel Vadot
2742091650bSEmmanuel Vadot return (ndi);
2752091650bSEmmanuel Vadot }
2762091650bSEmmanuel Vadot
2772091650bSEmmanuel Vadot device_t
simple_mfd_add_device(device_t dev,phandle_t node,u_int order,const char * name,int unit,struct simplebus_devinfo * di)2782091650bSEmmanuel Vadot simple_mfd_add_device(device_t dev, phandle_t node, u_int order,
2792091650bSEmmanuel Vadot const char *name, int unit, struct simplebus_devinfo *di)
2802091650bSEmmanuel Vadot {
2812091650bSEmmanuel Vadot struct simplebus_devinfo *ndi;
2822091650bSEmmanuel Vadot device_t cdev;
2832091650bSEmmanuel Vadot
2842091650bSEmmanuel Vadot if ((ndi = simple_mfd_setup_dinfo(dev, node, di)) == NULL)
2852091650bSEmmanuel Vadot return (NULL);
2862091650bSEmmanuel Vadot cdev = device_add_child_ordered(dev, order, name, unit);
2872091650bSEmmanuel Vadot if (cdev == NULL) {
2882091650bSEmmanuel Vadot device_printf(dev, "<%s>: device_add_child failed\n",
2892091650bSEmmanuel Vadot ndi->obdinfo.obd_name);
2902091650bSEmmanuel Vadot resource_list_free(&ndi->rl);
2912091650bSEmmanuel Vadot ofw_bus_gen_destroy_devinfo(&ndi->obdinfo);
2922091650bSEmmanuel Vadot if (di == NULL)
2932091650bSEmmanuel Vadot free(ndi, M_DEVBUF);
2942091650bSEmmanuel Vadot return (NULL);
2952091650bSEmmanuel Vadot }
2962091650bSEmmanuel Vadot device_set_ivars(cdev, ndi);
2972091650bSEmmanuel Vadot
2982091650bSEmmanuel Vadot return(cdev);
2992091650bSEmmanuel Vadot }
3002091650bSEmmanuel Vadot
3012091650bSEmmanuel Vadot static device_method_t simple_mfd_methods[] = {
3027f8c4c78SMichal Meloun /* syscon interface */
3037f8c4c78SMichal Meloun DEVMETHOD(syscon_get_handle, simple_mfd_syscon_get_handle),
304f97f57b5SMichal Meloun DEVMETHOD(syscon_device_lock, simple_mfd_syscon_lock),
305f97f57b5SMichal Meloun DEVMETHOD(syscon_device_unlock, simple_mfd_syscon_unlock),
306f97f57b5SMichal Meloun
3072091650bSEmmanuel Vadot /* Device interface */
3082091650bSEmmanuel Vadot DEVMETHOD(device_probe, simple_mfd_probe),
3092091650bSEmmanuel Vadot DEVMETHOD(device_attach, simple_mfd_attach),
31073155b43SGanbold Tsagaankhuu DEVMETHOD(device_detach, simple_mfd_detach),
3112091650bSEmmanuel Vadot
3122091650bSEmmanuel Vadot DEVMETHOD_END
3132091650bSEmmanuel Vadot };
3142091650bSEmmanuel Vadot
3152091650bSEmmanuel Vadot DEFINE_CLASS_1(simple_mfd, simple_mfd_driver, simple_mfd_methods,
3162091650bSEmmanuel Vadot sizeof(struct simple_mfd_softc), simplebus_driver);
3172091650bSEmmanuel Vadot
3180a73fdb9SJohn Baldwin EARLY_DRIVER_MODULE(simple_mfd, simplebus, simple_mfd_driver, 0, 0,
3190a73fdb9SJohn Baldwin BUS_PASS_BUS + BUS_PASS_ORDER_LATE);
3202091650bSEmmanuel Vadot MODULE_VERSION(simple_mfd, 1);
321