aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/extres
diff options
context:
space:
mode:
authorMichal Meloun <mmel@FreeBSD.org>2020-09-25 16:44:01 +0000
committerMichal Meloun <mmel@FreeBSD.org>2020-09-25 16:44:01 +0000
commit01d0f9c0e40a44cff5e25842b72075cbaf0864de (patch)
treee8d3a1a3326ec1ff3c8526d3d5493e1ac22cebd3 /sys/dev/extres
parent0d46edd0bb21e872a2ed42db10b6f1138f64dbe8 (diff)
Notes
Diffstat (limited to 'sys/dev/extres')
-rw-r--r--sys/dev/extres/syscon/syscon.c53
-rw-r--r--sys/dev/extres/syscon/syscon_generic.c56
-rw-r--r--sys/dev/extres/syscon/syscon_if.m62
3 files changed, 140 insertions, 31 deletions
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 <sys/systm.h>
+ #include <sys/bus.h>
+
+ 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;
};
@@ -65,6 +95,38 @@ METHOD int modify_4 {
};
/**
+ * 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
*/
METHOD int get_handle {