diff --git a/sys/arm64/freescale/imx/imx8mq_ccm.c b/sys/arm64/freescale/imx/imx8mq_ccm.c --- a/sys/arm64/freescale/imx/imx8mq_ccm.c +++ b/sys/arm64/freescale/imx/imx8mq_ccm.c @@ -27,7 +27,7 @@ #include /* - * Clocks driver for Freescale i.MX8MQ SoC + * Clocks driver for Freescale i.MX 8M Quad SoC. */ #include @@ -43,7 +43,7 @@ #include -#include +#include #include #include #include @@ -118,7 +118,7 @@ "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 @@ 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 @@ 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_clk.h b/sys/arm64/freescale/imx/imx_ccm.h rename from sys/arm64/freescale/imx/imx_ccm_clk.h rename to sys/arm64/freescale/imx/imx_ccm.h --- 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 #include @@ -34,6 +34,20 @@ #include #include +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 @@ }, \ } -#endif +#endif /* IMX8_CCM_H */ diff --git a/sys/arm64/freescale/imx/imx_ccm.c b/sys/arm64/freescale/imx/imx_ccm.c new file mode 100644 --- /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 + * Copyright (c) 2024 The FreeBSD Foundation + * + * Portions of this software were developed by Tom Jones + * 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 + +/* + * Clock Control Module driver for Freescale i.MX 8M SoC family. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#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/conf/files.arm64 b/sys/conf/files.arm64 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -590,6 +590,7 @@ 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