Index: sys/arm/allwinner/aw_syscon.c =================================================================== --- sys/arm/allwinner/aw_syscon.c +++ sys/arm/allwinner/aw_syscon.c @@ -40,6 +40,8 @@ #include #include +#include + #include #include #include Index: sys/dev/extres/syscon/syscon_generic.h =================================================================== --- sys/dev/extres/syscon/syscon_generic.h +++ sys/dev/extres/syscon/syscon_generic.h @@ -30,6 +30,7 @@ #define DEV_SYSCON_GENERIC_H struct syscon_generic_softc { + struct simplebus_softc sc_simplebus; device_t dev; struct syscon *syscon; struct resource *mem_res; Index: sys/dev/extres/syscon/syscon_generic.c =================================================================== --- sys/dev/extres/syscon/syscon_generic.c +++ sys/dev/extres/syscon/syscon_generic.c @@ -46,12 +46,15 @@ #include +#include + #include #include #include "syscon_if.h" #include "syscon.h" #include "syscon_generic.h" +#include "clkdev_if.h" MALLOC_DECLARE(M_SYSCON); @@ -77,14 +80,14 @@ #define SYSCON_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED); #define SYSCON_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED); -static syscon_method_t syscon_generic_methods[] = { +static syscon_method_t syscon_generic_syscon_methods[] = { SYSCONMETHOD(syscon_read_4, syscon_generic_read_4), SYSCONMETHOD(syscon_write_4, syscon_generic_write_4), SYSCONMETHOD(syscon_modify_4, syscon_generic_modify_4), SYSCONMETHOD_END }; -DEFINE_CLASS_1(syscon_generic, syscon_generic_class, syscon_generic_methods, +DEFINE_CLASS_1(syscon_generic_syscon, syscon_generic_syscon_class, syscon_generic_syscon_methods, 0, syscon_class); static uint32_t @@ -145,6 +148,8 @@ if (!bootverbose) device_quiet(dev); + if (ofw_bus_is_compatible(dev, "simple-bus")) + return (BUS_PROBE_DEFAULT); return (BUS_PROBE_GENERIC); } @@ -153,6 +158,8 @@ { struct syscon_generic_softc *sc; int rid; + phandle_t node, child; + device_t cdev; sc = device_get_softc(dev); sc->dev = dev; @@ -166,12 +173,24 @@ } SYSCON_LOCK_INIT(sc); - sc->syscon = syscon_create_ofw_node(dev, &syscon_generic_class, - ofw_bus_get_node(dev)); + node = ofw_bus_get_node(sc->dev); + sc->syscon = syscon_create_ofw_node(dev, &syscon_generic_syscon_class, + node); if (sc->syscon == NULL) { device_printf(dev, "Failed to create/register syscon\n"); return (ENXIO); } + + if (ofw_bus_is_compatible(dev, "simple-bus")) { + simplebus_init(sc->dev, node); + + for (child = OF_child(node); child != 0; child = OF_peer(child)) { + cdev = simplebus_add_device(sc->dev, child, 0, NULL, -1, NULL); + if (cdev != NULL) + device_probe_and_attach(cdev); + } + } + return (0); } @@ -186,6 +205,10 @@ free(sc->syscon, M_SYSCON); } + /* Memory allocated in simplebus_init */ + if (sc->sc_simplebus.ranges != NULL) + free(sc->sc_simplebus.ranges, M_DEVBUF); + SYSCON_LOCK_DESTROY(sc); if (sc->mem_res != NULL) @@ -193,19 +216,83 @@ return (0); } +/* clkdev interface */ +static int +syscon_generic_clk_write_4(device_t dev, bus_addr_t offset, uint32_t val) +{ + struct syscon_generic_softc *sc; + + sc = device_get_softc(dev); + bus_write_4(sc->mem_res, offset, val); + return (0); +} + +static int +syscon_generic_clk_read_4(device_t dev, bus_addr_t offset, uint32_t *val) +{ + struct syscon_generic_softc *sc; + + sc = device_get_softc(dev); + + *val = bus_read_4(sc->mem_res, offset); + return (0); +} + +static int +syscon_generic_clk_modify_4(device_t dev, bus_addr_t offset, uint32_t clear_bits, uint32_t set_bits) +{ + struct syscon_generic_softc *sc; + uint32_t val; + + sc = device_get_softc(dev); + + val = bus_read_4(sc->mem_res, offset); + val &= ~clear_bits; + val |= set_bits; + bus_write_4(sc->mem_res, offset, val); + + return (0); +} + +static void +syscon_generic_clk_device_lock(device_t dev) +{ + struct syscon_generic_softc *sc; + + sc = device_get_softc(dev); + SYSCON_LOCK(sc); +} + +static void +syscon_generic_clk_device_unlock(device_t dev) +{ + struct syscon_generic_softc *sc; + + sc = device_get_softc(dev); + SYSCON_UNLOCK(sc); +} + static device_method_t syscon_generic_dmethods[] = { /* Device interface */ DEVMETHOD(device_probe, syscon_generic_probe), DEVMETHOD(device_attach, syscon_generic_attach), DEVMETHOD(device_detach, syscon_generic_detach), + /* clkdev interface */ + DEVMETHOD(clkdev_write_4, syscon_generic_clk_write_4), + DEVMETHOD(clkdev_read_4, syscon_generic_clk_read_4), + DEVMETHOD(clkdev_modify_4, syscon_generic_clk_modify_4), + DEVMETHOD(clkdev_device_lock, syscon_generic_clk_device_lock), + DEVMETHOD(clkdev_device_unlock, syscon_generic_clk_device_unlock), + DEVMETHOD_END }; -DEFINE_CLASS_0(syscon_generic, syscon_generic_driver, syscon_generic_dmethods, - sizeof(struct syscon_generic_softc)); +DEFINE_CLASS_1(syscon_generic, syscon_generic_driver, syscon_generic_dmethods, + sizeof(struct syscon_generic_softc), simplebus_driver); static devclass_t syscon_generic_devclass; EARLY_DRIVER_MODULE(syscon_generic, simplebus, syscon_generic_driver, - syscon_generic_devclass, 0, 0, BUS_PASS_DEFAULT); + syscon_generic_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); MODULE_VERSION(syscon_generic, 1); +