git: be9fefafc280 - main - imx_ccm: Rearrange clock control module driver

From: Tom Jones <thj_at_FreeBSD.org>
Date: Fri, 13 Sep 2024 08:20:17 UTC
The branch main has been updated by thj:

URL: https://cgit.FreeBSD.org/src/commit/?id=be9fefafc2801ef449a0f3205c9397ba35425323

commit be9fefafc2801ef449a0f3205c9397ba35425323
Author:     Tom Jones <thj@FreeBSD.org>
AuthorDate: 2024-09-11 12:51:10 +0000
Commit:     Tom Jones <thj@FreeBSD.org>
CommitDate: 2024-09-13 08:15:19 +0000

    imx_ccm: Rearrange clock control module driver
    
    Rearrange the IMX clock control module driver so it is more straight
    forward to support clock trees from other SOCs in the family.
    
    Move the existing imx8mq_ccm driver to a more generic imx_ccm (based on
    rk_cru) and update the previous driver to sub class imx_ccm.
    
    Reviewed by:    manu
    Sponsored by:   The FreeBSD Foundations
    Differential Revision: https://reviews.freebsd.org/D46641
---
 sys/arm64/freescale/imx/imx8mq_ccm.c               | 197 ++---------------
 sys/arm64/freescale/imx/imx_ccm.c                  | 237 +++++++++++++++++++++
 .../freescale/imx/{imx_ccm_clk.h => imx_ccm.h}     |  20 +-
 sys/conf/files.arm64                               |   1 +
 4 files changed, 272 insertions(+), 183 deletions(-)

diff --git a/sys/arm64/freescale/imx/imx8mq_ccm.c b/sys/arm64/freescale/imx/imx8mq_ccm.c
index e89300c19d51..17bea24e9b39 100644
--- a/sys/arm64/freescale/imx/imx8mq_ccm.c
+++ b/sys/arm64/freescale/imx/imx8mq_ccm.c
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>
 /*
- * Clocks driver for Freescale i.MX8MQ SoC
+ * Clocks driver for Freescale i.MX 8M Quad SoC.
  */
 
 #include <sys/param.h>
@@ -43,7 +43,7 @@
 
 #include <machine/bus.h>
 
-#include <arm64/freescale/imx/imx_ccm_clk.h>
+#include <arm64/freescale/imx/imx_ccm.h>
 #include <arm64/freescale/imx/imx8mq_ccm.h>
 #include <arm64/freescale/imx/clk/imx_clk_gate.h>
 #include <arm64/freescale/imx/clk/imx_clk_mux.h>
@@ -118,7 +118,7 @@ static const char *ahb_p[] = {
 	"sys3_pll_out", "audio_pll1_out", "video_pll1_out"
 };
 
-static struct imx_clk imx_clks[] = {
+static struct imx_clk imx8mq_clks[] = {
 	FIXED(IMX8MQ_CLK_DUMMY, "dummy", 0),
 
 	LINK(IMX8MQ_CLK_32K, "ckil"),
@@ -275,119 +275,22 @@ struct ccm_softc {
 	int			nclks;
 };
 
-static inline uint32_t
-CCU_READ4(struct ccm_softc *sc, bus_size_t off)
-{
-
-	return (bus_read_4(sc->mem_res, off));
-}
-
-static inline void
-CCU_WRITE4(struct ccm_softc *sc, bus_size_t off, uint32_t val)
-{
-
-	bus_write_4(sc->mem_res, off, val);
-}
-
 static int
-ccm_detach(device_t dev)
+imx8mq_ccm_attach(device_t dev)
 {
-	struct ccm_softc *sc;
+	struct imx_ccm_softc *sc;
 
 	sc = device_get_softc(dev);
+	sc->dev = dev;
 
-	if (sc->mem_res != NULL)
-		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
-
-	return (0);
-}
-
-static int
-ccm_attach(device_t dev)
-{
-	struct ccm_softc *sc;
-	int err, rid;
-	phandle_t node;
-	int i;
+	sc->clks = imx8mq_clks;
+	sc->nclks = nitems(imx8mq_clks);
 
-	sc = device_get_softc(dev);
-	err = 0;
-
-	/* Allocate bus_space resources. */
-	rid = 0;
-	sc->clks = imx_clks;
-	sc->nclks = nitems(imx_clks);
-	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
-	    RF_ACTIVE);
-	if (sc->mem_res == NULL) {
-		device_printf(dev, "Cannot allocate memory resources\n");
-		err = ENXIO;
-		goto out;
-	}
-
-	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
-
-	sc->clkdom = clkdom_create(dev);
-	if (sc->clkdom == NULL)
-		panic("Cannot create clkdom\n");
-
-	for (i = 0; i < sc->nclks; i++) {
-		switch (sc->clks[i].type) {
-		case IMX_CLK_UNDEFINED:
-			break;
-		case IMX_CLK_LINK:
-			clknode_link_register(sc->clkdom,
-			    sc->clks[i].clk.link);
-			break;
-		case IMX_CLK_FIXED:
-			clknode_fixed_register(sc->clkdom,
-			    sc->clks[i].clk.fixed);
-			break;
-		case IMX_CLK_MUX:
-			imx_clk_mux_register(sc->clkdom, sc->clks[i].clk.mux);
-			break;
-		case IMX_CLK_GATE:
-			imx_clk_gate_register(sc->clkdom, sc->clks[i].clk.gate);
-			break;
-		case IMX_CLK_COMPOSITE:
-			imx_clk_composite_register(sc->clkdom, sc->clks[i].clk.composite);
-			break;
-		case IMX_CLK_SSCG_PLL:
-			imx_clk_sscg_pll_register(sc->clkdom, sc->clks[i].clk.sscg_pll);
-			break;
-		case IMX_CLK_FRAC_PLL:
-			imx_clk_frac_pll_register(sc->clkdom, sc->clks[i].clk.frac_pll);
-			break;
-		case IMX_CLK_DIV:
-			clknode_div_register(sc->clkdom, sc->clks[i].clk.div);
-			break;
-		default:
-			device_printf(dev, "Unknown clock type %d\n", sc->clks[i].type);
-			return (ENXIO);
-		}
-	}
-
-	if (clkdom_finit(sc->clkdom) != 0)
-		panic("cannot finalize clkdom initialization\n");
-
-	if (bootverbose)
-		clkdom_dump(sc->clkdom);
-
-	node = ofw_bus_get_node(dev);
-	clk_set_assigned(dev, node);
-
-	err = 0;
-
-out:
-
-	if (err != 0)
-		ccm_detach(dev);
-
-	return (err);
+	return (imx_ccm_attach(dev));
 }
 
 static int
-ccm_probe(device_t dev)
+imx8mq_ccm_probe(device_t dev)
 {
 
 	if (!ofw_bus_status_okay(dev))
@@ -396,87 +299,21 @@ ccm_probe(device_t dev)
 	if (ofw_bus_is_compatible(dev, "fsl,imx8mq-ccm") == 0)
 		return (ENXIO);
 
-	device_set_desc(dev, "Freescale i.MX8 Clock Control Module");
+	device_set_desc(dev, "Freescale i.MX 8M Quad Clock Control Module");
 
 	return (BUS_PROBE_DEFAULT);
 }
 
-static int
-imx_ccm_write_4(device_t dev, bus_addr_t addr, uint32_t val)
-{
-	struct ccm_softc *sc;
-
-	sc = device_get_softc(dev);
-	CCU_WRITE4(sc, addr, val);
-	return (0);
-}
-
-static int
-imx_ccm_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
-{
-	struct ccm_softc *sc;
-
-	sc = device_get_softc(dev);
-
-	*val = CCU_READ4(sc, addr);
-	return (0);
-}
-
-static int
-imx_ccm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
-{
-	struct ccm_softc *sc;
-	uint32_t reg;
-
-	sc = device_get_softc(dev);
-
-	reg = CCU_READ4(sc, addr);
-	reg &= ~clr;
-	reg |= set;
-	CCU_WRITE4(sc, addr, reg);
-
-	return (0);
-}
-
-static void
-imx_ccm_device_lock(device_t dev)
-{
-	struct ccm_softc *sc;
-
-	sc = device_get_softc(dev);
-	mtx_lock(&sc->mtx);
-}
-
-static void
-imx_ccm_device_unlock(device_t dev)
-{
-	struct ccm_softc *sc;
-
-	sc = device_get_softc(dev);
-	mtx_unlock(&sc->mtx);
-}
-
-static device_method_t ccm_methods[] = {
+static device_method_t imx8mq_ccm_methods[] = {
 	/* Device interface */
-	DEVMETHOD(device_probe,  ccm_probe),
-	DEVMETHOD(device_attach, ccm_attach),
-	DEVMETHOD(device_detach, ccm_detach),
-
-	/* clkdev interface */
-	DEVMETHOD(clkdev_write_4,	imx_ccm_write_4),
-	DEVMETHOD(clkdev_read_4,	imx_ccm_read_4),
-	DEVMETHOD(clkdev_modify_4,	imx_ccm_modify_4),
-	DEVMETHOD(clkdev_device_lock,	imx_ccm_device_lock),
-	DEVMETHOD(clkdev_device_unlock,	imx_ccm_device_unlock),
+	DEVMETHOD(device_probe,  imx8mq_ccm_probe),
+	DEVMETHOD(device_attach, imx8mq_ccm_attach),
 
 	DEVMETHOD_END
 };
 
-static driver_t ccm_driver = {
-	"ccm",
-	ccm_methods,
-	sizeof(struct ccm_softc)
-};
+DEFINE_CLASS_1(imx8mq_ccm, imx8mq_ccm_driver, imx8mq_ccm_methods,
+    sizeof(struct imx_ccm_softc), imx_ccm_driver);
 
-EARLY_DRIVER_MODULE(ccm, simplebus, ccm_driver, 0, 0, 
+EARLY_DRIVER_MODULE(imx8mq_ccm, simplebus, imx8mq_ccm_driver, 0, 0,
     BUS_PASS_CPU + BUS_PASS_ORDER_EARLY);
diff --git a/sys/arm64/freescale/imx/imx_ccm.c b/sys/arm64/freescale/imx/imx_ccm.c
new file mode 100644
index 000000000000..a5660c5d0a5d
--- /dev/null
+++ b/sys/arm64/freescale/imx/imx_ccm.c
@@ -0,0 +1,237 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ * Copyright (c) 2024 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Tom Jones <thj@freebsd.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+/*
+ * Clock Control Module driver for Freescale i.MX 8M SoC family.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+
+#include <arm64/freescale/imx/imx_ccm.h>
+#include <arm64/freescale/imx/clk/imx_clk_gate.h>
+#include <arm64/freescale/imx/clk/imx_clk_mux.h>
+#include <arm64/freescale/imx/clk/imx_clk_composite.h>
+#include <arm64/freescale/imx/clk/imx_clk_sscg_pll.h>
+#include <arm64/freescale/imx/clk/imx_clk_frac_pll.h>
+
+#include "clkdev_if.h"
+
+static inline uint32_t
+CCU_READ4(struct imx_ccm_softc *sc, bus_size_t off)
+{
+
+	return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+CCU_WRITE4(struct imx_ccm_softc *sc, bus_size_t off, uint32_t val)
+{
+
+	bus_write_4(sc->mem_res, off, val);
+}
+
+int
+imx_ccm_detach(device_t dev)
+{
+	struct imx_ccm_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	if (sc->mem_res != NULL)
+		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+	return (0);
+}
+
+int
+imx_ccm_attach(device_t dev)
+{
+	struct imx_ccm_softc *sc;
+	int err, rid;
+	phandle_t node;
+	int i;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+	err = 0;
+
+	/* Allocate bus_space resources. */
+	rid = 0;
+	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE);
+	if (sc->mem_res == NULL) {
+		device_printf(dev, "Cannot allocate memory resources\n");
+		err = ENXIO;
+		goto out;
+	}
+
+	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+	sc->clkdom = clkdom_create(dev);
+	if (sc->clkdom == NULL)
+		panic("Cannot create clkdom\n");
+
+	for (i = 0; i < sc->nclks; i++) {
+		switch (sc->clks[i].type) {
+		case IMX_CLK_UNDEFINED:
+			break;
+		case IMX_CLK_LINK:
+			clknode_link_register(sc->clkdom,
+			    sc->clks[i].clk.link);
+			break;
+		case IMX_CLK_FIXED:
+			clknode_fixed_register(sc->clkdom,
+			    sc->clks[i].clk.fixed);
+			break;
+		case IMX_CLK_MUX:
+			imx_clk_mux_register(sc->clkdom, sc->clks[i].clk.mux);
+			break;
+		case IMX_CLK_GATE:
+			imx_clk_gate_register(sc->clkdom, sc->clks[i].clk.gate);
+			break;
+		case IMX_CLK_COMPOSITE:
+			imx_clk_composite_register(sc->clkdom, sc->clks[i].clk.composite);
+			break;
+		case IMX_CLK_SSCG_PLL:
+			imx_clk_sscg_pll_register(sc->clkdom, sc->clks[i].clk.sscg_pll);
+			break;
+		case IMX_CLK_FRAC_PLL:
+			imx_clk_frac_pll_register(sc->clkdom, sc->clks[i].clk.frac_pll);
+			break;
+		case IMX_CLK_DIV:
+			clknode_div_register(sc->clkdom, sc->clks[i].clk.div);
+			break;
+		default:
+			device_printf(dev, "Unknown clock type %d\n", sc->clks[i].type);
+			return (ENXIO);
+		}
+	}
+
+	if (clkdom_finit(sc->clkdom) != 0)
+		panic("cannot finalize clkdom initialization\n");
+
+	if (bootverbose)
+		clkdom_dump(sc->clkdom);
+
+	node = ofw_bus_get_node(dev);
+	clk_set_assigned(dev, node);
+
+	err = 0;
+
+out:
+
+	if (err != 0)
+		imx_ccm_detach(dev);
+
+	return (err);
+}
+
+static int
+imx_ccm_write_4(device_t dev, bus_addr_t addr, uint32_t val)
+{
+	struct imx_ccm_softc *sc;
+
+	sc = device_get_softc(dev);
+	CCU_WRITE4(sc, addr, val);
+	return (0);
+}
+
+static int
+imx_ccm_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
+{
+	struct imx_ccm_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	*val = CCU_READ4(sc, addr);
+	return (0);
+}
+
+static int
+imx_ccm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
+{
+	struct imx_ccm_softc *sc;
+	uint32_t reg;
+
+	sc = device_get_softc(dev);
+
+	reg = CCU_READ4(sc, addr);
+	reg &= ~clr;
+	reg |= set;
+	CCU_WRITE4(sc, addr, reg);
+
+	return (0);
+}
+
+static void
+imx_ccm_device_lock(device_t dev)
+{
+	struct imx_ccm_softc *sc;
+
+	sc = device_get_softc(dev);
+	mtx_lock(&sc->mtx);
+}
+
+static void
+imx_ccm_device_unlock(device_t dev)
+{
+	struct imx_ccm_softc *sc;
+
+	sc = device_get_softc(dev);
+	mtx_unlock(&sc->mtx);
+}
+
+static device_method_t imx_ccm_methods[] = {
+	/* clkdev interface */
+	DEVMETHOD(clkdev_write_4,	imx_ccm_write_4),
+	DEVMETHOD(clkdev_read_4,	imx_ccm_read_4),
+	DEVMETHOD(clkdev_modify_4,	imx_ccm_modify_4),
+	DEVMETHOD(clkdev_device_lock,	imx_ccm_device_lock),
+	DEVMETHOD(clkdev_device_unlock,	imx_ccm_device_unlock),
+
+	DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(imx_ccm, imx_ccm_driver, imx_ccm_methods,
+    sizeof(struct imx_ccm_softc));
diff --git a/sys/arm64/freescale/imx/imx_ccm_clk.h b/sys/arm64/freescale/imx/imx_ccm.h
similarity index 95%
rename from sys/arm64/freescale/imx/imx_ccm_clk.h
rename to sys/arm64/freescale/imx/imx_ccm.h
index 4c16fa00fe6b..9c34789a648e 100644
--- a/sys/arm64/freescale/imx/imx_ccm_clk.h
+++ b/sys/arm64/freescale/imx/imx_ccm.h
@@ -25,8 +25,8 @@
  * SUCH DAMAGE.
  */
 
-#ifndef	IMX6_CCM_CLK_H
-#define	IMX6_CCM_CLK_H
+#ifndef	IMX8_CCM_H
+#define	IMX8_CCM_H
 
 #include <dev/clk/clk.h>
 #include <dev/clk/clk_div.h>
@@ -34,6 +34,20 @@
 #include <dev/clk/clk_gate.h>
 #include <dev/clk/clk_link.h>
 
+int imx_ccm_attach(device_t);
+int imx_ccm_detach(device_t);
+
+struct imx_ccm_softc {
+	device_t		dev;
+	struct resource		*mem_res;
+	struct clkdom		*clkdom;
+	struct mtx		mtx;
+	struct imx_clk		*clks;
+	int			nclks;
+};
+
+DECLARE_CLASS(imx_ccm_driver);
+
 enum imx_clk_type {
 	IMX_CLK_UNDEFINED = 0,
 	IMX_CLK_FIXED,
@@ -207,4 +221,4 @@ struct imx_clk {
 	},								\
 }
 
-#endif
+#endif	/* IMX8_CCM_H */
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index cd161a18500f..fe1259669059 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -590,6 +590,7 @@ arm64/cavium/thunder_pcie_pem_fdt.c		optional soc_cavm_thunderx pci fdt
 arm64/cavium/thunder_pcie_common.c		optional soc_cavm_thunderx pci
 
 # i.MX8 Clock support
+arm64/freescale/imx/imx_ccm.c			optional fdt soc_freescale_imx8
 arm64/freescale/imx/imx8mq_ccm.c		optional fdt soc_freescale_imx8
 arm64/freescale/imx/clk/imx_clk_gate.c		optional fdt soc_freescale_imx8
 arm64/freescale/imx/clk/imx_clk_mux.c		optional fdt soc_freescale_imx8