diff --git a/sys/arm/qualcomm/std.ipq4018 b/sys/arm/qualcomm/std.ipq4018 --- a/sys/arm/qualcomm/std.ipq4018 +++ b/sys/arm/qualcomm/std.ipq4018 @@ -39,6 +39,8 @@ dev/qcom_gcc/qcom_gcc_reset.c optional qcom_gcc dev/qcom_gcc/qcom_gcc_ipq4018_reset.c optional qcom_gcc dev/qcom_gcc/qcom_gcc_ipq4018_clock.c optional qcom_gcc +dev/qcom_gcc/qcom_gcc_msm8916_reset.c optional qcom_gcc +dev/qcom_gcc/qcom_gcc_msm8916_clock.c optional qcom_gcc dev/qcom_clk/qcom_clk_fepll.c optional qcom_gcc dev/qcom_clk/qcom_clk_fdiv.c optional qcom_gcc diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -717,7 +717,20 @@ dev/flash/flexspi/flex_spi.c optional clk flex_spi soc_nxp_ls fdt # Qualcomm -arm64/qualcomm/qcom_gcc.c optional qcom_gcc fdt +dev/qcom_gcc/qcom_gcc_main.c optional qcom_gcc +dev/qcom_gcc/qcom_gcc_clock.c optional qcom_gcc +dev/qcom_gcc/qcom_gcc_reset.c optional qcom_gcc +dev/qcom_gcc/qcom_gcc_ipq4018_reset.c optional qcom_gcc +dev/qcom_gcc/qcom_gcc_ipq4018_clock.c optional qcom_gcc +dev/qcom_gcc/qcom_gcc_msm8916_reset.c optional qcom_gcc +dev/qcom_gcc/qcom_gcc_msm8916_clock.c optional qcom_gcc +dev/qcom_clk/qcom_clk_fepll.c optional qcom_gcc +dev/qcom_clk/qcom_clk_fdiv.c optional qcom_gcc +dev/qcom_clk/qcom_clk_apssdiv.c optional qcom_gcc +dev/qcom_clk/qcom_clk_freqtbl.c optional qcom_gcc +dev/qcom_clk/qcom_clk_rcg2.c optional qcom_gcc +dev/qcom_clk/qcom_clk_branch2.c optional qcom_gcc +dev/qcom_clk/qcom_clk_ro_div.c optional qcom_gcc dev/qcom_mdio/qcom_mdio_ipq4018.c optional qcom_mdio fdt mdio mii # RockChip Drivers diff --git a/sys/dev/qcom_gcc/qcom_gcc_main.c b/sys/dev/qcom_gcc/qcom_gcc_main.c --- a/sys/dev/qcom_gcc/qcom_gcc_main.c +++ b/sys/dev/qcom_gcc/qcom_gcc_main.c @@ -51,6 +51,7 @@ #include "qcom_gcc_var.h" #include "qcom_gcc_ipq4018.h" +#include "qcom_gcc_msm8916.h" static int qcom_gcc_modevent(module_t, int, void *); @@ -67,6 +68,8 @@ static struct qcom_gcc_chipset_list_entry qcom_gcc_chipset_list[] = { { "qcom,gcc-ipq4019", "Qualcomm IPQ4018 Clock/Reset Controller", QCOM_GCC_CHIPSET_IPQ4018 }, + { "qcom,gcc-msm8916", "Qualcomm MSM8916 Clock/Reset Controller", + QCOM_GCC_CHIPSET_MSM8916 }, { NULL, NULL, 0 }, }; @@ -135,6 +138,10 @@ qcom_gcc_ipq4018_hwreset_init(sc); mem_sz = 0x60000; break; + case QCOM_GCC_CHIPSET_MSM8916: + qcom_gcc_msm8916_hwreset_init(sc); + mem_sz = 0x0; + break; case QCOM_GCC_CHIPSET_NONE: device_printf(dev, "Invalid chipset (%d)\n", sc->sc_chipset); return (ENXIO); @@ -142,8 +149,13 @@ sc->reg_rid = 0; - sc->reg = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY, - &sc->reg_rid, mem_sz, RF_ACTIVE); + if (mem_sz != 0) + sc->reg = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY, + &sc->reg_rid, mem_sz, RF_ACTIVE); + else + sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->reg_rid, RF_ACTIVE); + if (sc->reg == NULL) { device_printf(dev, "Couldn't allocate memory resource!\n"); return (ENXIO); @@ -163,6 +175,9 @@ case QCOM_GCC_CHIPSET_IPQ4018: qcom_gcc_ipq4018_clock_setup(sc); break; + case QCOM_GCC_CHIPSET_MSM8916: + qcom_gcc_msm8916_clock_setup(sc); + break; case QCOM_GCC_CHIPSET_NONE: device_printf(dev, "Invalid chipset (%d)\n", sc->sc_chipset); return (ENXIO); diff --git a/sys/dev/qcom_gcc/qcom_gcc_var.h b/sys/dev/qcom_gcc/qcom_gcc_msm8916.h copy from sys/dev/qcom_gcc/qcom_gcc_var.h copy to sys/dev/qcom_gcc/qcom_gcc_msm8916.h --- a/sys/dev/qcom_gcc/qcom_gcc_var.h +++ b/sys/dev/qcom_gcc/qcom_gcc_msm8916.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Adrian Chadd + * Copyright (c) 2025 Adrian Chadd * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,56 +25,17 @@ * SUCH DAMAGE. */ -#ifndef __QCOM_GCC_VAR_H__ -#define __QCOM_GCC_VAR_H__ - -typedef enum { - QCOM_GCC_CHIPSET_NONE = 0, - QCOM_GCC_CHIPSET_IPQ4018 = 1, -} qcom_gcc_chipset_t; - -struct qcom_gcc_reset_entry { - uint32_t reg; - uint32_t bit; -}; - -struct qcom_gcc_hw_callbacks { - /* Reset block */ - int (*hw_reset_assert)(device_t, intptr_t, bool); - int (*hw_reset_is_asserted)(device_t, intptr_t, bool *); - - /* Clock block */ -}; - -struct qcom_gcc_softc { - device_t dev; - int reg_rid; - struct resource *reg; - struct mtx mtx; - struct clkdom *clkdom; - qcom_gcc_chipset_t sc_chipset; - struct qcom_gcc_hw_callbacks sc_cb; -}; +#ifndef __QCOM_GCC_MSM8916_H__ +#define __QCOM_GCC_MSM8916_H__ /* * reset block */ -extern int qcom_gcc_hwreset_assert(device_t dev, intptr_t id, - bool reset); -extern int qcom_gcc_hwreset_is_asserted(device_t dev, intptr_t id, - bool *reset); +extern void qcom_gcc_msm8916_hwreset_init(struct qcom_gcc_softc *); /* * clock block */ -extern int qcom_gcc_clock_read(device_t dev, bus_addr_t addr, - uint32_t *val); -extern int qcom_gcc_clock_write(device_t dev, bus_addr_t addr, - uint32_t val); -extern int qcom_gcc_clock_modify(device_t dev, bus_addr_t addr, - uint32_t clear_mask, uint32_t set_mask); -extern void qcom_gcc_clock_setup(struct qcom_gcc_softc *sc); -extern void qcom_gcc_clock_lock(device_t dev); -extern void qcom_gcc_clock_unlock(device_t dev); +extern void qcom_gcc_msm8916_clock_setup(struct qcom_gcc_softc *); -#endif /* __QCOM_GCC_VAR_H__ */ +#endif /* __QCOM_GCC_MSM8916_H__ */ diff --git a/sys/arm64/qualcomm/qcom_gcc.c b/sys/dev/qcom_gcc/qcom_gcc_msm8916_clock.c rename from sys/arm64/qualcomm/qcom_gcc.c rename to sys/dev/qcom_gcc/qcom_gcc_msm8916_clock.c --- a/sys/arm64/qualcomm/qcom_gcc.c +++ b/sys/dev/qcom_gcc/qcom_gcc_msm8916_clock.c @@ -41,6 +41,9 @@ #include #include +#include "qcom_gcc_var.h" +#include "qcom_gcc_msm8916.h" + #define GCC_QDSS_BCR 0x29000 #define GCC_QDSS_BCR_BLK_ARES (1 << 0) /* Async software reset. */ #define GCC_QDSS_CFG_AHB_CBCR 0x29008 @@ -50,94 +53,32 @@ #define GCC_QDSS_DAP_CBCR 0x29084 #define DAP_CBCR_CLK_ENABLE (1 << 0) /* DAP clk branch ctrl */ -static struct ofw_compat_data compat_data[] = { - { "qcom,gcc-msm8916", 1 }, - { NULL, 0 } -}; - -struct qcom_gcc_softc { - struct resource *res; -}; - -static struct resource_spec qcom_gcc_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, 0 } -}; - /* * Qualcomm Debug Subsystem (QDSS) * block enabling routine. */ static void -qcom_qdss_enable(struct qcom_gcc_softc *sc) +qcom_msm8916_qdss_enable(struct qcom_gcc_softc *sc) { /* Put QDSS block to reset */ - bus_write_4(sc->res, GCC_QDSS_BCR, GCC_QDSS_BCR_BLK_ARES); + bus_write_4(sc->reg, GCC_QDSS_BCR, GCC_QDSS_BCR_BLK_ARES); /* Enable AHB clock branch */ - bus_write_4(sc->res, GCC_QDSS_CFG_AHB_CBCR, AHB_CBCR_CLK_ENABLE); + bus_write_4(sc->reg, GCC_QDSS_CFG_AHB_CBCR, AHB_CBCR_CLK_ENABLE); /* Enable DAP clock branch */ - bus_write_4(sc->res, GCC_QDSS_DAP_CBCR, DAP_CBCR_CLK_ENABLE); + bus_write_4(sc->reg, GCC_QDSS_DAP_CBCR, DAP_CBCR_CLK_ENABLE); /* Enable ETR USB clock branch */ - bus_write_4(sc->res, GCC_QDSS_ETR_USB_CBCR, ETR_USB_CBCR_CLK_ENABLE); + bus_write_4(sc->reg, GCC_QDSS_ETR_USB_CBCR, ETR_USB_CBCR_CLK_ENABLE); /* Out of reset */ - bus_write_4(sc->res, GCC_QDSS_BCR, 0); -} - -static int -qcom_gcc_probe(device_t dev) -{ - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) - return (ENXIO); - - device_set_desc(dev, "Qualcomm Global Clock Controller"); - - return (BUS_PROBE_DEFAULT); + bus_write_4(sc->reg, GCC_QDSS_BCR, 0); } -static int -qcom_gcc_attach(device_t dev) +void +qcom_gcc_msm8916_clock_setup(struct qcom_gcc_softc *sc) { - struct qcom_gcc_softc *sc; - - sc = device_get_softc(dev); - - if (bus_alloc_resources(dev, qcom_gcc_spec, &sc->res) != 0) { - device_printf(dev, "cannot allocate resources for device\n"); - return (ENXIO); - } - - /* - * Enable debug unit. - * This is required for Coresight operation. - * This also enables USB clock branch. - */ - qcom_qdss_enable(sc); - - return (0); + qcom_msm8916_qdss_enable(sc); } - -static device_method_t qcom_gcc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, qcom_gcc_probe), - DEVMETHOD(device_attach, qcom_gcc_attach), - - DEVMETHOD_END -}; - -static driver_t qcom_gcc_driver = { - "qcom_gcc", - qcom_gcc_methods, - sizeof(struct qcom_gcc_softc), -}; - -EARLY_DRIVER_MODULE(qcom_gcc, simplebus, qcom_gcc_driver, 0, 0, - BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); -MODULE_VERSION(qcom_gcc, 1); diff --git a/sys/dev/qcom_gcc/qcom_gcc_msm8916_reset.c b/sys/dev/qcom_gcc/qcom_gcc_msm8916_reset.c new file mode 100644 --- /dev/null +++ b/sys/dev/qcom_gcc/qcom_gcc_msm8916_reset.c @@ -0,0 +1,71 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025, Adrian Chadd + * + * 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 unmodified, 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 ``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 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "hwreset_if.h" + +#include "qcom_gcc_var.h" +#include "qcom_gcc_msm8916.h" + +static int +qcom_gcc_msm8916_hwreset_assert(device_t dev, intptr_t id, bool reset) +{ + device_printf(dev, "%s: invalid id (%d)\n", __func__, id); + return (EINVAL); +} + +static int +qcom_gcc_msm8916_hwreset_is_asserted(device_t dev, intptr_t id, bool *reset) +{ + device_printf(dev, "%s: invalid id (%d)\n", __func__, id); + return (EINVAL); +} + +void +qcom_gcc_msm8916_hwreset_init(struct qcom_gcc_softc *sc) +{ + sc->sc_cb.hw_reset_assert = qcom_gcc_msm8916_hwreset_assert; + sc->sc_cb.hw_reset_is_asserted = qcom_gcc_msm8916_hwreset_is_asserted; +} diff --git a/sys/dev/qcom_gcc/qcom_gcc_var.h b/sys/dev/qcom_gcc/qcom_gcc_var.h --- a/sys/dev/qcom_gcc/qcom_gcc_var.h +++ b/sys/dev/qcom_gcc/qcom_gcc_var.h @@ -31,6 +31,7 @@ typedef enum { QCOM_GCC_CHIPSET_NONE = 0, QCOM_GCC_CHIPSET_IPQ4018 = 1, + QCOM_GCC_CHIPSET_MSM8916 = 2, } qcom_gcc_chipset_t; struct qcom_gcc_reset_entry {