diff --git a/sys/dev/extres/syscon/syscon.c b/sys/dev/extres/syscon/syscon.c index d1f4fe0838b0..2ab1bec4f140 100644 --- a/sys/dev/extres/syscon/syscon.c +++ b/sys/dev/extres/syscon/syscon.c @@ -67,6 +67,12 @@ typedef TAILQ_HEAD(syscon_list, syscon) syscon_list_t; */ static int syscon_method_init(struct syscon *syscon); static int syscon_method_uninit(struct syscon *syscon); +static uint32_t syscon_method_read_4(struct syscon *syscon, bus_size_t offset); +static int syscon_method_write_4(struct syscon *syscon, bus_size_t offset, + uint32_t val); +static int syscon_method_modify_4(struct syscon *syscon, bus_size_t offset, + uint32_t clear_bits, uint32_t set_bits); + MALLOC_DEFINE(M_SYSCON, "syscon", "Syscon driver"); @@ -80,6 +86,9 @@ SX_SYSINIT(syscon_topology, &syscon_topo_lock, "Syscon topology lock"); static syscon_method_t syscon_methods[] = { SYSCONMETHOD(syscon_init, syscon_method_init), SYSCONMETHOD(syscon_uninit, syscon_method_uninit), + SYSCONMETHOD(syscon_read_4, syscon_method_read_4), + SYSCONMETHOD(syscon_write_4, syscon_method_write_4), + SYSCONMETHOD(syscon_modify_4, syscon_method_modify_4), SYSCONMETHOD_END }; @@ -115,6 +124,39 @@ syscon_get_softc(struct syscon *syscon) return (syscon->softc); }; +static uint32_t +syscon_method_read_4(struct syscon *syscon, bus_size_t offset) +{ + uint32_t val; + + SYSCON_DEVICE_LOCK(syscon->pdev); + val = SYSCON_UNLOCKED_READ_4(syscon, offset); + SYSCON_DEVICE_UNLOCK(syscon->pdev); + return(val); +} + +static int +syscon_method_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val) +{ + int rv; + + SYSCON_DEVICE_LOCK(syscon->pdev); + rv = SYSCON_UNLOCKED_WRITE_4(syscon, offset, val); + SYSCON_DEVICE_UNLOCK(syscon->pdev); + return(rv); +} + +static int +syscon_method_modify_4(struct syscon *syscon, bus_size_t offset, + uint32_t clear_bits, uint32_t set_bits) +{ + int rv; + + SYSCON_DEVICE_LOCK(syscon->pdev); + rv = SYSCON_UNLOCKED_MODIFY_4(syscon, offset, clear_bits, set_bits); + SYSCON_DEVICE_UNLOCK(syscon->pdev); + return(rv); +} /* * Create and initialize syscon object, but do not register it. */ @@ -254,14 +296,3 @@ syscon_get_by_ofw_property(device_t cdev, phandle_t cnode, char *name, return (0); } #endif - -int -syscon_get_handle_default(device_t dev, struct syscon **syscon) -{ - device_t parent; - - parent = device_get_parent(dev); - if (parent == NULL) - return (ENODEV); - return (SYSCON_GET_HANDLE(parent, syscon)); -} diff --git a/sys/dev/extres/syscon/syscon_generic.c b/sys/dev/extres/syscon/syscon_generic.c index b68d3cdf6786..7e6c040bfb86 100644 --- a/sys/dev/extres/syscon/syscon_generic.c +++ b/sys/dev/extres/syscon/syscon_generic.c @@ -55,11 +55,12 @@ __FBSDID("$FreeBSD$"); MALLOC_DECLARE(M_SYSCON); -static uint32_t syscon_generic_read_4(struct syscon *syscon, bus_size_t offset); -static int syscon_generic_write_4(struct syscon *syscon, bus_size_t offset, - uint32_t val); -static int syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset, - uint32_t clear_bits, uint32_t set_bits); +static uint32_t syscon_generic_unlocked_read_4(struct syscon *syscon, + bus_size_t offset); +static int syscon_generic_unlocked_write_4(struct syscon *syscon, + bus_size_t offset, uint32_t val); +static int syscon_generic_unlocked_modify_4(struct syscon *syscon, + bus_size_t offset, uint32_t clear_bits, uint32_t set_bits); static int syscon_generic_detach(device_t dev); /* * Generic syscon driver (FDT) @@ -78,9 +79,9 @@ static struct ofw_compat_data compat_data[] = { #define SYSCON_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED); static syscon_method_t syscon_generic_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(syscon_unlocked_read_4, syscon_generic_unlocked_read_4), + SYSCONMETHOD(syscon_unlocked_write_4, syscon_generic_unlocked_write_4), + SYSCONMETHOD(syscon_unlocked_modify_4, syscon_generic_unlocked_modify_4), SYSCONMETHOD_END }; @@ -88,50 +89,62 @@ DEFINE_CLASS_1(syscon_generic, syscon_generic_class, syscon_generic_methods, 0, syscon_class); static uint32_t -syscon_generic_read_4(struct syscon *syscon, bus_size_t offset) +syscon_generic_unlocked_read_4(struct syscon *syscon, bus_size_t offset) { struct syscon_generic_softc *sc; uint32_t val; sc = device_get_softc(syscon->pdev); - - SYSCON_LOCK(sc); + SYSCON_ASSERT_UNLOCKED(sc); val = bus_read_4(sc->mem_res, offset); - SYSCON_UNLOCK(sc); return (val); } static int -syscon_generic_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val) +syscon_generic_unlocked_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val) { struct syscon_generic_softc *sc; sc = device_get_softc(syscon->pdev); - - SYSCON_LOCK(sc); + SYSCON_ASSERT_UNLOCKED(sc); bus_write_4(sc->mem_res, offset, val); - SYSCON_UNLOCK(sc); return (0); } static int -syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset, +syscon_generic_unlocked_modify_4(struct syscon *syscon, bus_size_t offset, uint32_t clear_bits, uint32_t set_bits) { struct syscon_generic_softc *sc; uint32_t val; sc = device_get_softc(syscon->pdev); - - SYSCON_LOCK(sc); + SYSCON_ASSERT_UNLOCKED(sc); val = bus_read_4(sc->mem_res, offset); val &= ~clear_bits; val |= set_bits; bus_write_4(sc->mem_res, offset, val); - SYSCON_UNLOCK(sc); return (0); } +static void +syscon_generic_lock(device_t dev) +{ + struct syscon_generic_softc *sc; + + sc = device_get_softc(dev); + SYSCON_LOCK(sc); +} + +static void +syscon_generic_unlock(device_t dev) +{ + struct syscon_generic_softc *sc; + + sc = device_get_softc(dev); + SYSCON_UNLOCK(sc); +} + static int syscon_generic_probe(device_t dev) { @@ -211,6 +224,9 @@ static device_method_t syscon_generic_dmethods[] = { DEVMETHOD(device_attach, syscon_generic_attach), DEVMETHOD(device_detach, syscon_generic_detach), + DEVMETHOD(syscon_device_lock, syscon_generic_lock), + DEVMETHOD(syscon_device_unlock, syscon_generic_unlock), + DEVMETHOD_END }; diff --git a/sys/dev/extres/syscon/syscon_if.m b/sys/dev/extres/syscon/syscon_if.m index 98008340cc9d..d6b88d2c35dd 100644 --- a/sys/dev/extres/syscon/syscon_if.m +++ b/sys/dev/extres/syscon/syscon_if.m @@ -35,6 +35,36 @@ HEADER { int syscon_get_handle_default(device_t dev, struct syscon **syscon); } +CODE { + #include + #include + + int + syscon_get_handle_default(device_t dev, struct syscon **syscon) + { + device_t parent; + + parent = device_get_parent(dev); + if (parent == NULL) + return (ENODEV); + return (SYSCON_GET_HANDLE(parent, syscon)); + } + + static void + syscon_device_lock_default(device_t dev) + { + + panic("syscon_device_lock is not implemented"); + }; + + static void + syscon_device_unlock_default(device_t dev) + { + + panic("syscon_device_unlock is not implemented"); + }; +} + METHOD int init { struct syscon *syscon; }; @@ -64,6 +94,38 @@ METHOD int modify_4 { uint32_t set_bits; }; +/** + * Unlocked verion of access function + */ +METHOD uint32_t unlocked_read_4 { + struct syscon *syscon; + bus_size_t offset; +}; + +METHOD int unlocked_write_4 { + struct syscon *syscon; + bus_size_t offset; + uint32_t val; +}; + +METHOD int unlocked_modify_4 { + struct syscon *syscon; + bus_size_t offset; + uint32_t clear_bits; + uint32_t set_bits; +}; + +/** +* Locking for exclusive access to underlying device +*/ +METHOD void device_lock { + device_t dev; +} DEFAULT syscon_device_lock_default; + +METHOD void device_unlock { + device_t dev; +} DEFAULT syscon_device_unlock_default; + /** * Get syscon handle from parent driver */