git: d09ec2eeb0d8 - stable/14 - armada38x: implement gateclk clkdev methods
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 04 Mar 2025 15:14:25 UTC
The branch stable/14 has been updated by mhorne:
URL: https://cgit.FreeBSD.org/src/commit/?id=d09ec2eeb0d81528066fdb05db8a121f0f1e0c01
commit d09ec2eeb0d81528066fdb05db8a121f0f1e0c01
Author: Mitchell Horne <mhorne@FreeBSD.org>
AuthorDate: 2024-04-15 20:18:25 +0000
Commit: Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2025-03-04 15:11:46 +0000
armada38x: implement gateclk clkdev methods
Implement basic clkdev methods required by the generic clk_gate device.
This should make it functional, and prevent panics when invoking the
clock's CLKNODE_GET_GATE method (e.g. with `sysctl -a`).
Additionally, we need to fill in other key fields of the clk_gate_def
structure before registering each clk.
PR: 278188
Reported by: solo_code@protonmail.com
Tested by: solo_code@protonmail.com
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D48419
(cherry picked from commit 6f2775548278c76e7c33b15aaaaa759270a8dcd5)
---
sys/arm/mv/clk/armada38x_gateclk.c | 99 ++++++++++++++++++++++++++++++++++++--
1 file changed, 94 insertions(+), 5 deletions(-)
diff --git a/sys/arm/mv/clk/armada38x_gateclk.c b/sys/arm/mv/clk/armada38x_gateclk.c
index d00a01b0da67..1be3830cf375 100644
--- a/sys/arm/mv/clk/armada38x_gateclk.c
+++ b/sys/arm/mv/clk/armada38x_gateclk.c
@@ -44,11 +44,22 @@
#include "clkdev_if.h"
+#define ARMADA38X_GATECLK_MAXREG 0
+
+static struct resource_spec armada38x_gateclk_specs[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+#define RD4(_sc, addr) bus_read_4(_sc->res, addr)
+#define WR4(_sc, addr, val) bus_write_4(_sc->res, addr, val)
+
struct armada38x_gateclk_softc
{
- struct clkdom *clkdom;
- struct mtx mtx;
- const char* parent;
+ struct resource *res;
+ struct clkdom *clkdom;
+ struct mtx mtx;
+ const char* parent;
};
static struct clk_gate_def gateclk_nodes[] =
@@ -220,10 +231,75 @@ static struct clk_gate_def gateclk_nodes[] =
static int armada38x_gateclk_probe(device_t dev);
static int armada38x_gateclk_attach(device_t dev);
+static int
+armada38x_gateclk_write_4(device_t dev, bus_addr_t addr, uint32_t val)
+{
+ struct armada38x_gateclk_softc *sc = device_get_softc(dev);
+
+ if (addr > ARMADA38X_GATECLK_MAXREG)
+ return (EINVAL);
+
+ WR4(sc, addr, val);
+ return (0);
+}
+
+static int
+armada38x_gateclk_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
+{
+ struct armada38x_gateclk_softc *sc = device_get_softc(dev);
+
+ if (addr > ARMADA38X_GATECLK_MAXREG)
+ return (EINVAL);
+
+ *val = RD4(sc, addr);
+ return (0);
+}
+
+static int
+armada38x_gateclk_modify_4(device_t dev, bus_addr_t addr, uint32_t clr,
+ uint32_t set)
+{
+ struct armada38x_gateclk_softc *sc = device_get_softc(dev);
+ uint32_t reg;
+
+ if (addr > ARMADA38X_GATECLK_MAXREG)
+ return (EINVAL);
+
+ reg = RD4(sc, addr);
+ reg &= ~clr;
+ reg |= set;
+ WR4(sc, addr, reg);
+
+ return (0);
+}
+
+static void
+armada38x_gateclk_device_lock(device_t dev)
+{
+ struct armada38x_gateclk_softc *sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mtx);
+}
+
+static void
+armada38x_gateclk_device_unlock(device_t dev)
+{
+ struct armada38x_gateclk_softc *sc = device_get_softc(dev);
+
+ mtx_unlock(&sc->mtx);
+}
+
static device_method_t armada38x_gateclk_methods[] = {
DEVMETHOD(device_probe, armada38x_gateclk_probe),
DEVMETHOD(device_attach, armada38x_gateclk_attach),
+ /* clkdev interface */
+ DEVMETHOD(clkdev_write_4, armada38x_gateclk_write_4),
+ DEVMETHOD(clkdev_read_4, armada38x_gateclk_read_4),
+ DEVMETHOD(clkdev_modify_4, armada38x_gateclk_modify_4),
+ DEVMETHOD(clkdev_device_lock, armada38x_gateclk_device_lock),
+ DEVMETHOD(clkdev_device_unlock, armada38x_gateclk_device_unlock),
+
DEVMETHOD_END
};
@@ -255,6 +331,7 @@ static int
armada38x_gateclk_attach(device_t dev)
{
struct armada38x_gateclk_softc *sc;
+ struct clk_gate_def *defp;
phandle_t node;
int i, error;
clk_t clock;
@@ -262,6 +339,11 @@ armada38x_gateclk_attach(device_t dev)
sc = device_get_softc(dev);
node = ofw_bus_get_node(dev);
+ if (bus_alloc_resources(dev, armada38x_gateclk_specs, &sc->res) != 0) {
+ device_printf(dev, "Cannot allocate resources.\n");
+ return (ENXIO);
+ }
+
mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
sc->clkdom = clkdom_create(dev);
@@ -277,8 +359,15 @@ armada38x_gateclk_attach(device_t dev)
sc->parent = clk_get_name(clock);
for (i = 0; i < nitems(gateclk_nodes); ++i) {
- gateclk_nodes[i].clkdef.parent_names = &sc->parent;
- error = clknode_gate_register(sc->clkdom, &gateclk_nodes[i]);
+ /* Fill clk_gate fields. */
+ defp = &gateclk_nodes[i];
+ defp->clkdef.parent_names = &sc->parent;
+ defp->offset = 0;
+ defp->mask = 0x1;
+ defp->on_value = 1;
+ defp->off_value = 0;
+
+ error = clknode_gate_register(sc->clkdom, defp);
if (error != 0) {
device_printf(dev, "Cannot create gate nodes\n");
return (error);