diff --git a/sys/arm/qualcomm/qcom_gcc_ipq4018_clock.c b/sys/arm/qualcomm/qcom_gcc_ipq4018_clock.c deleted file mode 100644 index f7f7a6c348ba..000000000000 --- a/sys/arm/qualcomm/qcom_gcc_ipq4018_clock.c +++ /dev/null @@ -1,82 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2021, 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. - */ - -/* Driver for Qualcomm IPQ4018 clock and reset device */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include - -#include - - -/* - * Fixed frequency clock sources: - * - * P_XO - 48MHz - * sleep-clk - is really 32KHz, although older DTS have it as 32.768KHz - */ - -/* - * PLL derived sources: - * - * P_FEPLL125 - 125MHz - * P_FEPLL125DLY - 125MHz - * P_FEPLL200 - 200MHz - * P_FEPLL500 - 500MHz - * P_FEPLLWCSS2G - TBD - * P_FEPLLWCSS5G - TBD - * - * Then there are two DDR PLLs which are treated/configured slightly - * differently: - * - * P_DDRPLLAPSS - TBD - * P_DDRPLLSDCC - TBD - */ - -/* - * Interesting stuff in Linux whilst I reverse engineer + figure it out: - * /sys/kernel/debug/clk - */ diff --git a/sys/arm/qualcomm/std.ipq4018 b/sys/arm/qualcomm/std.ipq4018 index 38e561f4079c..8a9dba579e48 100644 --- a/sys/arm/qualcomm/std.ipq4018 +++ b/sys/arm/qualcomm/std.ipq4018 @@ -1,23 +1,24 @@ arm/qualcomm/ipq4018_machdep.c standard arm/qualcomm/ipq4018_mp.c optional smp arm/qualcomm/qcom_scm_legacy.c standard arm/qualcomm/qcom_cpu_kpssv2.c optional smp dev/qcom_rnd/qcom_rnd.c optional qcom_rnd -arm/qualcomm/qcom_gcc_ipq4018.c optional qcom_gcc_ipq4018 -arm/qualcomm/qcom_gcc_ipq4018_reset.c optional qcom_gcc_ipq4018 -arm/qualcomm/qcom_gcc_ipq4018_clock.c optional qcom_gcc_ipq4018 + +dev/qcom_gcc/qcom_gcc_ipq4018.c optional qcom_gcc_ipq4018 +dev/qcom_gcc/qcom_gcc_ipq4018_reset.c optional qcom_gcc_ipq4018 +dev/qcom_gcc/qcom_gcc_ipq4018_clock.c optional qcom_gcc_ipq4018 dev/qcom_clk/qcom_clk_fepll.c optional qcom_gcc_ipq4018 dev/qcom_clk/qcom_clk_fdiv.c optional qcom_gcc_ipq4018 dev/qcom_clk/qcom_clk_apssdiv.c optional qcom_gcc_ipq4018 dev/qcom_clk/qcom_clk_freqtbl.c optional qcom_gcc_ipq4018 dev/qcom_clk/qcom_clk_rcg2.c optional qcom_gcc_ipq4018 dev/qcom_clk/qcom_clk_branch2.c optional qcom_gcc_ipq4018 dev/qcom_clk/qcom_clk_ro_div.c optional qcom_gcc_ipq4018 dev/qcom_tlmm/qcom_tlmm_debug.c optional qcom_tlmm_ipq4018 dev/qcom_tlmm/qcom_tlmm_ipq4018.c optional qcom_tlmm_ipq4018 dev/qcom_tlmm/qcom_tlmm_ipq4018_hw.c optional qcom_tlmm_ipq4018 dev/qcom_tlmm/qcom_tlmm_pin.c optional qcom_tlmm_ipq4018 dev/qcom_tlmm/qcom_tlmm_pinmux.c optional qcom_tlmm_ipq4018 diff --git a/sys/arm/qualcomm/qcom_gcc_ipq4018.c b/sys/dev/qcom_gcc/qcom_gcc_ipq4018.c similarity index 87% rename from sys/arm/qualcomm/qcom_gcc_ipq4018.c rename to sys/dev/qcom_gcc/qcom_gcc_ipq4018.c index 3002ae32a597..12bd721c1e29 100644 --- a/sys/arm/qualcomm/qcom_gcc_ipq4018.c +++ b/sys/dev/qcom_gcc/qcom_gcc_ipq4018.c @@ -1,167 +1,184 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2021, 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. */ /* Driver for Qualcomm IPQ4018 clock and reset device */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include "clkdev_if.h" #include "hwreset_if.h" #include -#include +#include "qcom_gcc_ipq4018_var.h" static int qcom_gcc_ipq4018_modevent(module_t, int, void *); static int qcom_gcc_ipq4018_probe(device_t); static int qcom_gcc_ipq4018_attach(device_t); static int qcom_gcc_ipq4018_detach(device_t); static int qcom_gcc_ipq4018_modevent(module_t mod, int type, void *unused) { int error; switch (type) { case MOD_LOAD: case MOD_QUIESCE: case MOD_UNLOAD: case MOD_SHUTDOWN: error = 0; break; default: error = EOPNOTSUPP; break; } return (error); } static int qcom_gcc_ipq4018_probe(device_t dev) { if (! ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_is_compatible(dev, "qcom,gcc-ipq4019") == 0) return (ENXIO); return (0); } static int qcom_gcc_ipq4018_attach(device_t dev) { struct qcom_gcc_ipq4018_softc *sc; sc = device_get_softc(dev); /* Found a compatible device! */ sc->dev = dev; sc->reg_rid = 0; sc->reg = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY, &sc->reg_rid, 0x60000, RF_ACTIVE); if (sc->reg == NULL) { device_printf(dev, "Couldn't allocate memory resource!\n"); return (ENXIO); } device_set_desc(dev, "Qualcomm IPQ4018 Clock/Reset Controller"); mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); /* * Register as a reset provider. */ hwreset_register_ofw_provider(dev); + /* + * Setup and register as a clock provider. + */ + qcom_gcc_ipq4018_clock_setup(sc); + return (0); } static int qcom_gcc_ipq4018_detach(device_t dev) { struct qcom_gcc_ipq4018_softc *sc; sc = device_get_softc(dev); + /* + * TBD - deregistering reset/clock resources. + */ + if (sc->reg != NULL) { bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->reg_rid, sc->reg); } return (0); } static device_method_t qcom_gcc_ipq4018_methods[] = { /* Device methods. */ DEVMETHOD(device_probe, qcom_gcc_ipq4018_probe), DEVMETHOD(device_attach, qcom_gcc_ipq4018_attach), DEVMETHOD(device_detach, qcom_gcc_ipq4018_detach), /* Reset interface */ DEVMETHOD(hwreset_assert, qcom_gcc_ipq4018_hwreset_assert), DEVMETHOD(hwreset_is_asserted, qcom_gcc_ipq4018_hwreset_is_asserted), + /* Clock interface */ + DEVMETHOD(clkdev_read_4, qcom_gcc_ipq4018_clock_read), + DEVMETHOD(clkdev_write_4, qcom_gcc_ipq4018_clock_write), + DEVMETHOD(clkdev_modify_4, qcom_gcc_ipq4018_clock_modify), + DEVMETHOD(clkdev_device_lock, qcom_gcc_ipq4018_clock_lock), + DEVMETHOD(clkdev_device_unlock, qcom_gcc_ipq4018_clock_unlock), + DEVMETHOD_END }; static driver_t qcom_gcc_ipq4018_driver = { "qcom_gcc", qcom_gcc_ipq4018_methods, sizeof(struct qcom_gcc_ipq4018_softc) }; static devclass_t qcom_gcc_ipq4018_devclass; EARLY_DRIVER_MODULE(qcom_gcc_ipq4018, simplebus, qcom_gcc_ipq4018_driver, qcom_gcc_ipq4018_devclass, qcom_gcc_ipq4018_modevent, 0, - BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE); + BUS_PASS_CPU + BUS_PASS_ORDER_EARLY); EARLY_DRIVER_MODULE(qcom_gcc_ipq4018, ofwbus, qcom_gcc_ipq4018_driver, qcom_gcc_ipq4018_devclass, qcom_gcc_ipq4018_modevent, 0, - BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE); -MODULE_VERSION(qcom_gcc_ipq4018_random, 1); + BUS_PASS_CPU + BUS_PASS_ORDER_EARLY); +MODULE_VERSION(qcom_gcc_ipq4018, 1); diff --git a/sys/dev/qcom_gcc/qcom_gcc_ipq4018_clock.c b/sys/dev/qcom_gcc/qcom_gcc_ipq4018_clock.c new file mode 100644 index 000000000000..9f3261b3db8c --- /dev/null +++ b/sys/dev/qcom_gcc/qcom_gcc_ipq4018_clock.c @@ -0,0 +1,770 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021, 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. + */ + +/* Driver for Qualcomm IPQ4018 clock and reset device */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "qcom_gcc_ipq4018_var.h" + + +/* Fixed rate clock. */ +#define F_RATE(_id, cname, _freq) \ +{ \ + .clkdef.id = _id, \ + .clkdef.name = cname, \ + .clkdef.parent_names = NULL, \ + .clkdef.parent_cnt = 0, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .freq = _freq, \ +} + +/* Linked clock. */ +#define F_LINK(_id, _cname) \ +{ \ + .clkdef.id = _id, \ + .clkdef.name = _cname, \ + .clkdef.parent_names = NULL, \ + .clkdef.parent_cnt = 0, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ +} + + +/* FEPLL clock */ +#define F_FEPLL(_id, _cname, _parent, _reg, _fs, _fw, _rs, _rw) \ +{ \ + .clkdef.id = _id, \ + .clkdef.name = _cname, \ + .clkdef.parent_names = (const char *[]){_parent}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .offset = _reg, \ + .fdbkdiv_shift = _fs, \ + .fdbkdiv_width = _fw, \ + .refclkdiv_shift = _rs, \ + .refclkdiv_width = _rw, \ +} + +/* Fixed divisor clock */ +#define F_FDIV(_id, _cname, _parent, _divisor) \ +{ \ + .clkdef.id = _id, \ + .clkdef.name = _cname, \ + .clkdef.parent_names = (const char *[]){_parent}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .divisor = _divisor, \ +} + +/* APSS DIV clock */ +#define F_APSSDIV(_id, _cname, _parent, _doffset, _dshift, _dwidth, \ + _eoffset, _eshift, _freqtbl) \ +{ \ + .clkdef.id = _id, \ + .clkdef.name = _cname, \ + .clkdef.parent_names = (const char *[]){_parent}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .div_offset = _doffset, \ + .div_width = _dwidth, \ + .div_shift = _dshift, \ + .enable_offset = _eoffset, \ + .enable_shift = _eshift, \ + .freq_tbl = _freqtbl, \ +} + +/* read-only div table */ +#define F_RO_DIV(_id, _cname, _parent, _offset, _shift, _width, _tbl) \ +{ \ + .clkdef.id = _id, \ + .clkdef.name = _cname, \ + .clkdef.parent_names = (const char *[]){_parent}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .offset = _offset, \ + .width = _width, \ + .shift = _shift, \ + .div_tbl = _tbl, \ +} + +/* RCG2 clock */ +#define F_RCG2(_id, _cname, _parents, _rcgr, _hid_width, _mnd_width, \ + _safe_src_idx, _safe_pre_parent_idx, _cfg_offset, _flags, \ + _freq_tbl) \ +{ \ + .clkdef.id = _id, \ + .clkdef.name = _cname, \ + .clkdef.parent_names = _parents, \ + .clkdef.parent_cnt = nitems(_parents), \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .cmd_rcgr = _rcgr, \ + .hid_width = _hid_width, \ + .mnd_width = _mnd_width, \ + .safe_src_idx = _safe_src_idx, \ + .flags= _flags, \ + .safe_pre_parent_idx = _safe_pre_parent_idx, \ + .freq_tbl = _freq_tbl, \ +} + +/* branch2 gate nodes */ +#define F_BRANCH2(_id, _cname, _parent, _eo, _es, _hr, _hs, _haltreg, \ + _type, _voted, _flags) \ +{ \ + .clkdef.id = _id, \ + .clkdef.name = _cname, \ + .clkdef.parent_names = (const char *[]){_parent}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .enable_offset = _eo, \ + .enable_shift = _es, \ + .hwcg_reg = _hr, \ + .hwcg_bit = _hs, \ + .halt_reg = _haltreg, \ + .halt_check_type = _type, \ + .halt_check_voted = _voted, \ + .flags = _flags, \ +} + +/* + * Fixed "gcc_fepll_vco" PLL derived sources: + * + * P_FEPLL125 - 125MHz + * P_FEPLL125DLY - 125MHz + * P_FEPLL200 - 200MHz + * "fepll500" - 500MHz + * + * Fixed "gcc_apps_ddrpll_vco" PLL derived sources: + * + * P_DDRPLL - 192MHz + */ +static struct qcom_clk_fdiv_def fdiv_tbl[] = { + F_FDIV(GCC_FEPLL125_CLK, "fepll125", "gcc_fepll_vco", 32), + F_FDIV(GCC_FEPLL125DLY_CLK, "fepll125dly", "gcc_fepll_vco", 32), + F_FDIV(GCC_FEPLL200_CLK, "fepll200", "gcc_fepll_vco", 20), + F_FDIV(GCC_FEPLL500_CLK, "fepll500", "gcc_fepll_vco", 8), + F_FDIV(GCC_SDCC_PLLDIV_CLK, "ddrpllsdcc", "gcc_apps_ddrpll_vco", 28), +}; + +/* + * FEPLL - 48MHz (xo) input, 4GHz output + * DDRPLL - 48MHz (xo) input, 5.376GHz output + */ +static struct qcom_clk_fepll_def fepll_tbl[] = { + F_FEPLL(GCC_FEPLL_VCO, "gcc_fepll_vco", "xo", 0x2f020, 16, 8, 24, 5), + F_FEPLL(GCC_APSS_DDRPLL_VCO, "gcc_apps_ddrpll_vco", "xo", 0x2e020, + 16, 8, 24, 5), +}; + +/* + * Frequency table for the APSS PLL/DIV path for the CPU frequency. + * + * Note - the APSS DIV code only needs the frequency and pre-divisor, + * not the other fields. + */ +static struct qcom_clk_freq_tbl apss_freq_tbl[] = { + { 384000000, "gcc_apps_ddrpll_vco", 0xd, 0, 0 }, + { 413000000, "gcc_apps_ddrpll_vco", 0xc, 0, 0 }, + { 448000000, "gcc_apps_ddrpll_vco", 0xb, 0, 0 }, + { 488000000, "gcc_apps_ddrpll_vco", 0xa, 0, 0 }, + { 512000000, "gcc_apps_ddrpll_vco", 0x9, 0, 0 }, + { 537000000, "gcc_apps_ddrpll_vco", 0x8, 0, 0 }, + { 565000000, "gcc_apps_ddrpll_vco", 0x7, 0, 0 }, + { 597000000, "gcc_apps_ddrpll_vco", 0x6, 0, 0 }, + { 632000000, "gcc_apps_ddrpll_vco", 0x5, 0, 0 }, + { 672000000, "gcc_apps_ddrpll_vco", 0x4, 0, 0 }, + { 716000000, "gcc_apps_ddrpll_vco", 0x3, 0, 0 }, + { 768000000, "gcc_apps_ddrpll_vco", 0x2, 0, 0 }, + { 823000000, "gcc_apps_ddrpll_vco", 0x1, 0, 0 }, + { 896000000, "gcc_apps_ddrpll_vco", 0x0, 0, 0 }, + { 0, } +}; + +/* + * APSS div/gate + */ +static struct qcom_clk_apssdiv_def apssdiv_tbl[] = { + F_APSSDIV(GCC_APSS_CPU_PLLDIV_CLK, "ddrpllapss", + "gcc_apps_ddrpll_vco", 0x2e020, + 4, 4, 0x2e000, 0, &apss_freq_tbl[0]), +}; + +/* + * Parent clocks for the apps_clk_src clock. + */ +static const char * apps_clk_src_parents[] = { + "xo", "ddrpllapss", "fepll500", "fepll200" +}; + +/* + * Parents lists for a variety of blocks. + */ +static const char * gcc_xo_200_parents[] = { + "xo", "fepll200" +}; +static const char * gcc_xo_200_500_parents[] = { + "xo", "fepll200", "fepll500" +}; +static const char * gcc_xo_200_spi_parents[] = { + "xo", NULL, "fepll200" +}; +static const char * gcc_xo_sdcc1_500_parents[] = { + "xo", "ddrpllsdcc", "fepll500" +}; + +static const char * gcc_xo_125_dly_parents[] = { + "xo", "fepll125dly" +}; + +static const char * gcc_xo_wcss2g_parents[] = { + "xo", "fepllwcss2g" +}; + +static const char * gcc_xo_wcss5g_parents[] = { + "xo", "fepllwcss5g" +}; + +static struct qcom_clk_freq_tbl apps_clk_src_freq_tbl[] = { + { 48000000, "xo", 1, 0, 0 }, + { 200000000, "fepll200", 1, 0, 0 }, + { 384000000, "ddrpllapss", 1, 0, 0 }, + { 413000000, "ddrpllapss", 1, 0, 0 }, + { 448000000, "ddrpllapss", 1, 0, 0 }, + { 488000000, "ddrpllapss", 1, 0, 0 }, + { 500000000, "fepll500", 1, 0, 0 }, + { 512000000, "ddrpllapss", 1, 0, 0 }, + { 537000000, "ddrpllapss", 1, 0, 0 }, + { 565000000, "ddrpllapss", 1, 0, 0 }, + { 597000000, "ddrpllapss", 1, 0, 0 }, + { 632000000, "ddrpllapss", 1, 0, 0 }, + { 672000000, "ddrpllapss", 1, 0, 0 }, + { 716000000, "ddrpllapss", 1, 0, 0 }, + { 0,} + +}; + +static struct qcom_clk_freq_tbl audio_clk_src_freq_tbl[] = { + { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 200000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 0,} +}; + +static struct qcom_clk_freq_tbl blsp1_qup1_i2c_apps_clk_src_freq_tbl[] = { + { 19050000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(10.5), 1, 1 }, + { 0,} +}; + +static struct qcom_clk_freq_tbl blsp1_qup1_spi_apps_clk_src_freq_tbl[] = { + { 960000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(12), 1, 4 }, + { 4800000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 10 }, + { 9600000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 5 }, + { 15000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 3 }, + { 19200000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 2, 5 }, + { 24000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 2 }, + { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 0,} +}; + +static struct qcom_clk_freq_tbl gcc_pcnoc_ahb_clk_src_freq_tbl[] = { + { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 100000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(2), 0, 0 }, + { 0, } +}; + +static struct qcom_clk_freq_tbl blsp1_uart1_apps_clk_src_freq_tbl[] = { + { 1843200, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 144, 15625 }, + { 3686400, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 288, 15625 }, + { 7372800, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 576, 15625 }, + { 14745600, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1152, 15625 }, + { 16000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 2, 25 }, + { 24000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 2 }, + { 32000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 4, 25 }, + { 40000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 5 }, + { 46400000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 29, 125 }, + { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 0, } +}; + +static struct qcom_clk_freq_tbl gp1_clk_src_freq_tbl[] = { + { 1250000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 16, 0 }, + { 2500000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 8, 0 }, + { 5000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 4, 0 }, + { 0, } +}; + +static struct qcom_clk_freq_tbl sdcc1_apps_clk_src_freq_tbl[] = { + { 144000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 3, 240 }, + { 400000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 0 }, + { 20000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 25 }, + { 25000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 20 }, + { 50000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 10 }, + { 100000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 5 }, + { 192000000, "ddrpllsdcc", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 0, } +}; + +static struct qcom_clk_freq_tbl apps_ahb_clk_src_freq_tbl[] = { + { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 100000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(2), 0, 0 }, + { 0, } +}; + +static struct qcom_clk_freq_tbl usb30_mock_utmi_clk_src_freq_tbl[] = { + { 2000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(10), 0, 0 }, + { 0, } +}; + +static struct qcom_clk_freq_tbl fephy_125m_dly_clk_src_freq_tbl[] = { + { 125000000, "fepll125dly", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 0, } +}; + +static struct qcom_clk_freq_tbl wcss2g_clk_src_freq_tbl[] = { + { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 250000000, "fepllwcss2g", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 0, } +}; + +static struct qcom_clk_freq_tbl wcss5g_clk_src_freq_tbl[] = { + { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 250000000, "fepllwcss5g", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, + { 0, } +}; + +/* + * Divisor table for the 2g/5g wifi clock divisors. + */ +static struct qcom_clk_ro_div_tbl fepllwcss_clk_div_tbl[] = { + { 0, 15 }, + { 1, 16 }, + { 2, 18 }, + { 3, 20 }, + { 0, 0 } +}; + +/* + * Read-only divisor table clocks. + */ +static struct qcom_clk_ro_div_def ro_div_tbl[] = { + F_RO_DIV(GCC_FEPLL_WCSS2G_CLK, "fepllwcss2g", "gcc_fepll_vco", + 0x2f020, 8, 2, &fepllwcss_clk_div_tbl[0]), + F_RO_DIV(GCC_FEPLL_WCSS5G_CLK, "fepllwcss5g", "gcc_fepll_vco", + 0x2f020, 12, 2, &fepllwcss_clk_div_tbl[0]), +}; + +/* + * RCG2 clocks + */ +static struct qcom_clk_rcg2_def rcg2_tbl[] = { + F_RCG2(AUDIO_CLK_SRC, "audio_clk_src", gcc_xo_200_parents, + 0x1b000, 5, 0, -1, -1, 0, 0, &audio_clk_src_freq_tbl[0]), + F_RCG2(BLSP1_QUP1_I2C_APPS_CLK_SRC, "blsp1_qup1_i2c_apps_clk_src", + gcc_xo_200_parents, 0x200c, 5, 0, -1, -1, 0, 0, + &blsp1_qup1_i2c_apps_clk_src_freq_tbl[0]), + F_RCG2(BLSP1_QUP2_I2C_APPS_CLK_SRC, "blsp1_qup2_i2c_apps_clk_src", + gcc_xo_200_parents, 0x3000, 5, 0, -1, -1, 0, 0, + &blsp1_qup1_i2c_apps_clk_src_freq_tbl[0]), + F_RCG2(BLSP1_QUP1_SPI_APPS_CLK_SRC, "blsp1_qup1_spi_apps_clk_src", + gcc_xo_200_spi_parents, 0x2024, 5, 8, -1, -1, 0, 0, + &blsp1_qup1_spi_apps_clk_src_freq_tbl[0]), + F_RCG2(BLSP1_QUP2_SPI_APPS_CLK_SRC, "blsp1_qup2_spi_apps_clk_src", + gcc_xo_200_spi_parents, 0x3014, 5, 8, -1, -1, 0, 0, + &blsp1_qup1_spi_apps_clk_src_freq_tbl[0]), + F_RCG2(BLSP1_UART1_APPS_CLK_SRC, "blsp1_uart1_apps_clk_src", + gcc_xo_200_spi_parents, 0x2044, 5, 16, -1, -1, 0, 0, + &blsp1_uart1_apps_clk_src_freq_tbl[0]), + F_RCG2(BLSP1_UART2_APPS_CLK_SRC, "blsp1_uart2_apps_clk_src", + gcc_xo_200_spi_parents, 0x3034, 5, 16, -1, -1, 0, 0, + &blsp1_uart1_apps_clk_src_freq_tbl[0]), + F_RCG2(GP1_CLK_SRC, "gp1_clk_src", gcc_xo_200_parents, 0x8004, + 5, 8, -1, -1, 0, 0, + &gp1_clk_src_freq_tbl[0]), + F_RCG2(GP2_CLK_SRC, "gp2_clk_src", gcc_xo_200_parents, 0x9004, + 5, 8, -1, -1, 0, 0, + &gp1_clk_src_freq_tbl[0]), + F_RCG2(GP3_CLK_SRC, "gp3_clk_src", gcc_xo_200_parents, 0xa004, + 5, 8, -1, -1, 0, 0, + &gp1_clk_src_freq_tbl[0]), + F_RCG2(SDCC1_APPS_CLK_SRC, "sdcc1_apps_clk_src", + gcc_xo_sdcc1_500_parents, 0x18004, 5, 0, -1, -1, 0, 0, + &sdcc1_apps_clk_src_freq_tbl[0]), + F_RCG2(GCC_APPS_CLK_SRC, "apps_clk_src", apps_clk_src_parents, + 0x1900c, 5, 0, -1, 2, 0, + QCOM_CLK_RCG2_FLAGS_SET_RATE_PARENT, + &apps_clk_src_freq_tbl[0]), + F_RCG2(GCC_APPS_AHB_CLK_SRC, "apps_ahb_clk_src", + gcc_xo_200_500_parents, 0x19014, 5, 0, -1, -1, 0, + 0, &apps_ahb_clk_src_freq_tbl[0]), + F_RCG2(GCC_USB3_MOCK_UTMI_CLK_SRC, "usb30_mock_utmi_clk_src", + gcc_xo_200_parents, 0x1e000, 5, 0, -1, -1, 0, 0, + &usb30_mock_utmi_clk_src_freq_tbl[0]), + F_RCG2(FEPHY_125M_DLY_CLK_SRC, "fephy_125m_dly_clk_src", + gcc_xo_125_dly_parents, 0x12000, 5, 0, -1, -1, 0, 0, + &fephy_125m_dly_clk_src_freq_tbl[0]), + F_RCG2(WCSS2G_CLK_SRC, "wcss2g_clk_src", gcc_xo_wcss2g_parents, + 0x1f000, 5, 0, -1, -1, 0, 0, + &wcss2g_clk_src_freq_tbl[0]), + F_RCG2(WCSS5G_CLK_SRC, "wcss5g_clk_src", gcc_xo_wcss5g_parents, + 0x20000, 5, 0, -1, -1, 0, 0, + &wcss5g_clk_src_freq_tbl[0]), + F_RCG2(GCC_PCNOC_AHB_CLK_SRC, "gcc_pcnoc_ahb_clk_src", + gcc_xo_200_500_parents, 0x21024, 5, 0, -1, -1, 0, 0, + &gcc_pcnoc_ahb_clk_src_freq_tbl[0]), +}; + +/* + * branch2 clocks + */ +static struct qcom_clk_branch2_def branch2_tbl[] = { + F_BRANCH2(GCC_AUDIO_AHB_CLK, "gcc_audio_ahb_clk", "pcnoc_clk_src", + 0x1b010, 0, 0, 0, 0x1b010, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_AUDIO_PWM_CLK, "gcc_audio_pwm_clk", "audio_clk_src", + 0x1b00c, 0, 0, 0, 0x1b00c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_BLSP1_QUP1_I2C_APPS_CLK, "gcc_blsp1_qup1_i2c_apps_clk", + "blsp1_qup1_i2c_apps_clk_src", + 0x2008, 0, 0, 0, 0x2008, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_BLSP1_QUP2_I2C_APPS_CLK, "gcc_blsp1_qup2_i2c_apps_clk", + "blsp1_qup2_i2c_apps_clk_src", + 0x3010, 0, 0, 0, 0x3010, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_BLSP1_QUP1_SPI_APPS_CLK, "gcc_blsp1_qup1_spi_apps_clk", + "blsp1_qup1_spi_apps_clk_src", + 0x2004, 0, 0, 0, 0x2004, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_BLSP1_QUP2_SPI_APPS_CLK, "gcc_blsp1_qup2_spi_apps_clk", + "blsp1_qup2_spi_apps_clk_src", + 0x300c, 0, 0, 0, 0x300c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_BLSP1_UART1_APPS_CLK, "gcc_blsp1_uart1_apps_clk", + "blsp1_uart1_apps_clk_src", + 0x203c, 0, 0, 0, 0x203c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_BLSP1_UART2_APPS_CLK, "gcc_blsp1_uart2_apps_clk", + "blsp1_uart2_apps_clk_src", + 0x302c, 0, 0, 0, 0x302c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_GP1_CLK, "gcc_gp1_clk", "gp1_clk_src", + 0x8000, 0, 0, 0, 0x8000, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_GP2_CLK, "gcc_gp2_clk", "gp2_clk_src", + 0x9000, 0, 0, 0, 0x9000, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_GP3_CLK, "gcc_gp3_clk", "gp3_clk_src", + 0xa000, 0, 0, 0, 0xa000, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + /* BRANCH_HALT_VOTED; note the different enable/halt */ + F_BRANCH2(GCC_APPS_AHB_CLK_SRC, "gcc_apss_ahb_clk", + "apps_ahb_clk_src", + 0x6000, 14, 0, 0, 0x19004, QCOM_CLK_BRANCH2_BRANCH_HALT, + true, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_BLSP1_AHB_CLK, "gcc_blsp1_ahb_clk", + "pcnoc_clk_src", + 0x6000, 10, 0, 0, 0x1008, QCOM_CLK_BRANCH2_BRANCH_HALT, + true, 0), /* BRANCH_HALT_VOTED */ + F_BRANCH2(GCC_DCD_XO_CLK, "gcc_dcd_xo_clk", "xo", + 0x2103c, 0, 0, 0, 0x2103c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_BOOT_ROM_AHB_CLK, "gcc_boot_rom_ahb_clk", + "pcnoc_clk_src", 0x1300c, 0, 0, 0, 0x1300c, + QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_CRYPTO_AHB_CLK, "gcc_crypto_ahb_clk", + "pcnoc_clk_src", 0x6000, 0, 0, 0, 0x16024, + QCOM_CLK_BRANCH2_BRANCH_HALT, + true, 0), /* BRANCH_HALT_VOTED */ + F_BRANCH2(GCC_CRYPTO_AXI_CLK, "gcc_crypto_axi_clk", + "fepll125", 0x6000, 1, 0, 0, 0x16020, + QCOM_CLK_BRANCH2_BRANCH_HALT, + true, 0), /* BRANCH_HALT_VOTED */ + F_BRANCH2(GCC_CRYPTO_CLK, "gcc_crypto_clk", "fepll125", + 0x6000, 2, 0, 0, 0x1601c, QCOM_CLK_BRANCH2_BRANCH_HALT, + true, 0), /* BRANCH_HALT_VOTED */ + F_BRANCH2(GCC_ESS_CLK, "gcc_ess_clk", "fephy_125m_dly_clk_src", + 0x12010, 0, 0, 0, 0x12010, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + /* BRANCH_HALT_VOTED */ + F_BRANCH2(GCC_IMEM_AXI_CLK, "gcc_imem_axi_clk", "fepll200", + 0x6000, 17, 0, 0, 0xe004, QCOM_CLK_BRANCH2_BRANCH_HALT, + true, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_IMEM_CFG_AHB_CLK, "gcc_imem_cfg_ahb_clk", + "pcnoc_clk_src", + 0xe008, 0, 0, 0, 0xe008, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_PCIE_AHB_CLK, "gcc_pcie_ahb_clk", "pcnoc_clk_src", + 0x1d00c, 0, 0, 0, 0x1d00c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_PCIE_AXI_M_CLK, "gcc_pcie_axi_m_clk", "fepll200", + 0x1d004, 0, 0, 0, 0x1d004, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_PCIE_AXI_S_CLK, "gcc_pcie_axi_s_clk", "fepll200", + 0x1d008, 0, 0, 0, 0x1d008, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_PRNG_AHB_CLK, "gcc_prng_ahb_clk", "pcnoc_clk_src", + 0x6000, 8, 0, 0, 0x13004, QCOM_CLK_BRANCH2_BRANCH_HALT, + true, 0), /* BRANCH_HALT_VOTED */ + F_BRANCH2(GCC_QPIC_AHB_CLK, "gcc_qpic_ahb_clk", "pcnoc_clk_src", + 0x1c008, 0, 0, 0, 0x1c008, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_QPIC_CLK, "gcc_qpic_clk", "pcnoc_clk_src", + 0x1c004, 0, 0, 0, 0x1c004, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_SDCC1_AHB_CLK, "gcc_sdcc1_ahb_clk", "pcnoc_clk_src", + 0x18010, 0, 0, 0, 0x18010, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_SDCC1_APPS_CLK, "gcc_sdcc1_apps_clk", + "sdcc1_apps_clk_src", 0x1800c, 0, 0, 0, 0x1800c, + QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_TLMM_AHB_CLK, "gcc_tlmm_ahb_clk", "pcnoc_clk_src", + 0x6000, 5, 0, 0, 0x5004, QCOM_CLK_BRANCH2_BRANCH_HALT, + true, 0), /* BRANCH_HALT_VOTED */ + F_BRANCH2(GCC_USB2_MASTER_CLK, "gcc_usb2_master_clk", "pcnoc_clk_src", + 0x1e00c, 0, 0, 0, 0x1e00c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_USB2_SLEEP_CLK, "gcc_usb2_sleep_clk", + "sleep_clk", 0x1e010, 0, 0, 0, 0x1e010, + QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_USB2_MOCK_UTMI_CLK, "gcc_usb2_mock_utmi_clk", + "usb30_mock_utmi_clk_src", 0x1e014, 0, 0, 0, 0x1e014, + QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_USB3_MASTER_CLK, "gcc_usb3_master_clk", "fepll125", + 0x1e028, 0, 0, 0, 0x1e028, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_USB3_SLEEP_CLK, "gcc_usb3_sleep_clk", "sleep_clk", + 0x1e02c, 0, 0, 0, 0x1e02c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + F_BRANCH2(GCC_USB3_MOCK_UTMI_CLK, "gcc_usb3_mock_utmi_clk", + "usb30_mock_utmi_clk_src", + 0x1e030, 0, 0, 0, 0x1e030, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + /* Note - yes, these two have the same registers in linux */ + F_BRANCH2(GCC_WCSS2G_CLK, "gcc_wcss2g_clk", "wcss2g_clk_src", + 0x1f00c, 0, 0, 0, 0x1f00c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_WCSS2G_REF_CLK, "gcc_wcss2g_ref_clk", "xo", + 0x1f00c, 0, 0, 0, 0x1f00c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_WCSS2G_RTC_CLK, "gcc_wcss2g_rtc_clk", "sleep_clk", + 0x1f010, 0, 0, 0, 0x1f010, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + + /* Note - yes, these two have the same registers in linux */ + F_BRANCH2(GCC_WCSS5G_CLK, "gcc_wcss5g_clk", "wcss5g_clk_src", + 0x1f00c, 0, 0, 0, 0x2000c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_WCSS5G_REF_CLK, "gcc_wcss5g_ref_clk", "xo", + 0x1f00c, 0, 0, 0, 0x2000c, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), + F_BRANCH2(GCC_WCSS5G_RTC_CLK, "gcc_wcss5g_rtc_clk", "sleep_clk", + 0x1f010, 0, 0, 0, 0x20010, QCOM_CLK_BRANCH2_BRANCH_HALT, + false, 0), + + F_BRANCH2(GCC_PCNOC_AHB_CLK, "pcnoc_clk_src", "gcc_pcnoc_ahb_clk_src", + 0x21030, 0, 0, 0, 0x21030, QCOM_CLK_BRANCH2_BRANCH_HALT, false, + QCOM_CLK_BRANCH2_FLAGS_CRITICAL | + QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), +}; + +static void +qcom_gcc_ipq4018_clock_init_fepll(struct qcom_gcc_ipq4018_softc *sc) +{ + int i, rv; + + for (i = 0; i < nitems(fepll_tbl); i++) { + rv = qcom_clk_fepll_register(sc->clkdom, fepll_tbl + i); + if (rv != 0) + panic("qcom_clk_fepll_register failed"); + } +} + +static void +qcom_gcc_ipq4018_clock_init_fdiv(struct qcom_gcc_ipq4018_softc *sc) +{ + int i, rv; + + for (i = 0; i < nitems(fdiv_tbl); i++) { + rv = qcom_clk_fdiv_register(sc->clkdom, fdiv_tbl + i); + if (rv != 0) + panic("qcom_clk_fdiv_register failed"); + } +} + +static void +qcom_gcc_ipq4018_clock_init_apssdiv(struct qcom_gcc_ipq4018_softc *sc) +{ + int i, rv; + + for (i = 0; i < nitems(apssdiv_tbl); i++) { + rv = qcom_clk_apssdiv_register(sc->clkdom, apssdiv_tbl + i); + if (rv != 0) + panic("qcom_clk_apssdiv_register failed"); + } +} + +static void +qcom_gcc_ipq4018_clock_init_rcg2(struct qcom_gcc_ipq4018_softc *sc) +{ + int i, rv; + + for (i = 0; i < nitems(rcg2_tbl); i++) { + rv = qcom_clk_rcg2_register(sc->clkdom, rcg2_tbl + i); + if (rv != 0) + panic("qcom_clk_rcg2_register failed"); + } +} + +static void +qcom_gcc_ipq4018_clock_init_branch2(struct qcom_gcc_ipq4018_softc *sc) +{ + int i, rv; + + for (i = 0; i < nitems(branch2_tbl); i++) { + rv = qcom_clk_branch2_register(sc->clkdom, branch2_tbl + i); + if (rv != 0) + panic("qcom_clk_branch2_register failed"); + } +} + +static void +qcom_gcc_ipq4018_clock_init_ro_div(struct qcom_gcc_ipq4018_softc *sc) +{ + int i, rv; + + for (i = 0; i < nitems(ro_div_tbl); i++) { + rv = qcom_clk_ro_div_register(sc->clkdom, ro_div_tbl + i); + if (rv != 0) + panic("qcom_clk_ro_div_register failed"); + } +} + +int +qcom_gcc_ipq4018_clock_read(device_t dev, bus_addr_t addr, uint32_t *val) +{ + struct qcom_gcc_ipq4018_softc *sc; + + sc = device_get_softc(dev); + *val = bus_read_4(sc->reg, addr); + return (0); +} + +int +qcom_gcc_ipq4018_clock_write(device_t dev, bus_addr_t addr, uint32_t val) +{ + struct qcom_gcc_ipq4018_softc *sc; + + sc = device_get_softc(dev); + bus_write_4(sc->reg, addr, val); + return (0); +} + +int +qcom_gcc_ipq4018_clock_modify(device_t dev, bus_addr_t addr, + uint32_t clear_mask, uint32_t set_mask) +{ + struct qcom_gcc_ipq4018_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + reg = bus_read_4(sc->reg, addr); + reg &= clear_mask; + reg |= set_mask; + bus_write_4(sc->reg, addr, reg); + return (0); +} + +void +qcom_gcc_ipq4018_clock_setup(struct qcom_gcc_ipq4018_softc *sc) +{ + + sc->clkdom = clkdom_create(sc->dev); + + /* Setup stuff */ + qcom_gcc_ipq4018_clock_init_fepll(sc); + qcom_gcc_ipq4018_clock_init_fdiv(sc); + qcom_gcc_ipq4018_clock_init_apssdiv(sc); + qcom_gcc_ipq4018_clock_init_rcg2(sc); + qcom_gcc_ipq4018_clock_init_branch2(sc); + qcom_gcc_ipq4018_clock_init_ro_div(sc); + + /* Finalise clock tree */ + clkdom_finit(sc->clkdom); +} + +void +qcom_gcc_ipq4018_clock_lock(device_t dev) +{ + struct qcom_gcc_ipq4018_softc *sc; + + sc = device_get_softc(dev); + mtx_lock(&sc->mtx); +} + +void +qcom_gcc_ipq4018_clock_unlock(device_t dev) +{ + struct qcom_gcc_ipq4018_softc *sc; + + sc = device_get_softc(dev); + mtx_unlock(&sc->mtx); +} diff --git a/sys/arm/qualcomm/qcom_gcc_ipq4018_reset.c b/sys/dev/qcom_gcc/qcom_gcc_ipq4018_reset.c similarity index 97% rename from sys/arm/qualcomm/qcom_gcc_ipq4018_reset.c rename to sys/dev/qcom_gcc/qcom_gcc_ipq4018_reset.c index 754e7636ff6e..c83a8cd1a2a0 100644 --- a/sys/arm/qualcomm/qcom_gcc_ipq4018_reset.c +++ b/sys/dev/qcom_gcc/qcom_gcc_ipq4018_reset.c @@ -1,181 +1,180 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2021, 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. */ /* Driver for Qualcomm IPQ4018 clock and reset device */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "hwreset_if.h" #include -#include +#include "qcom_gcc_ipq4018_var.h" static const struct qcom_gcc_ipq4018_reset_entry gcc_ipq4019_reset_list[] = { [WIFI0_CPU_INIT_RESET] = { 0x1f008, 5 }, [WIFI0_RADIO_SRIF_RESET] = { 0x1f008, 4 }, [WIFI0_RADIO_WARM_RESET] = { 0x1f008, 3 }, [WIFI0_RADIO_COLD_RESET] = { 0x1f008, 2 }, [WIFI0_CORE_WARM_RESET] = { 0x1f008, 1 }, [WIFI0_CORE_COLD_RESET] = { 0x1f008, 0 }, [WIFI1_CPU_INIT_RESET] = { 0x20008, 5 }, [WIFI1_RADIO_SRIF_RESET] = { 0x20008, 4 }, [WIFI1_RADIO_WARM_RESET] = { 0x20008, 3 }, [WIFI1_RADIO_COLD_RESET] = { 0x20008, 2 }, [WIFI1_CORE_WARM_RESET] = { 0x20008, 1 }, [WIFI1_CORE_COLD_RESET] = { 0x20008, 0 }, [USB3_UNIPHY_PHY_ARES] = { 0x1e038, 5 }, [USB3_HSPHY_POR_ARES] = { 0x1e038, 4 }, [USB3_HSPHY_S_ARES] = { 0x1e038, 2 }, [USB2_HSPHY_POR_ARES] = { 0x1e01c, 4 }, [USB2_HSPHY_S_ARES] = { 0x1e01c, 2 }, [PCIE_PHY_AHB_ARES] = { 0x1d010, 11 }, [PCIE_AHB_ARES] = { 0x1d010, 10 }, [PCIE_PWR_ARES] = { 0x1d010, 9 }, [PCIE_PIPE_STICKY_ARES] = { 0x1d010, 8 }, [PCIE_AXI_M_STICKY_ARES] = { 0x1d010, 7 }, [PCIE_PHY_ARES] = { 0x1d010, 6 }, [PCIE_PARF_XPU_ARES] = { 0x1d010, 5 }, [PCIE_AXI_S_XPU_ARES] = { 0x1d010, 4 }, [PCIE_AXI_M_VMIDMT_ARES] = { 0x1d010, 3 }, [PCIE_PIPE_ARES] = { 0x1d010, 2 }, [PCIE_AXI_S_ARES] = { 0x1d010, 1 }, [PCIE_AXI_M_ARES] = { 0x1d010, 0 }, [ESS_RESET] = { 0x12008, 0}, [GCC_BLSP1_BCR] = {0x01000, 0}, [GCC_BLSP1_QUP1_BCR] = {0x02000, 0}, [GCC_BLSP1_UART1_BCR] = {0x02038, 0}, [GCC_BLSP1_QUP2_BCR] = {0x03008, 0}, [GCC_BLSP1_UART2_BCR] = {0x03028, 0}, [GCC_BIMC_BCR] = {0x04000, 0}, [GCC_TLMM_BCR] = {0x05000, 0}, [GCC_IMEM_BCR] = {0x0E000, 0}, [GCC_ESS_BCR] = {0x12008, 0}, [GCC_PRNG_BCR] = {0x13000, 0}, [GCC_BOOT_ROM_BCR] = {0x13008, 0}, [GCC_CRYPTO_BCR] = {0x16000, 0}, [GCC_SDCC1_BCR] = {0x18000, 0}, [GCC_SEC_CTRL_BCR] = {0x1A000, 0}, [GCC_AUDIO_BCR] = {0x1B008, 0}, [GCC_QPIC_BCR] = {0x1C000, 0}, [GCC_PCIE_BCR] = {0x1D000, 0}, [GCC_USB2_BCR] = {0x1E008, 0}, [GCC_USB2_PHY_BCR] = {0x1E018, 0}, [GCC_USB3_BCR] = {0x1E024, 0}, [GCC_USB3_PHY_BCR] = {0x1E034, 0}, [GCC_SYSTEM_NOC_BCR] = {0x21000, 0}, [GCC_PCNOC_BCR] = {0x2102C, 0}, [GCC_DCD_BCR] = {0x21038, 0}, [GCC_SNOC_BUS_TIMEOUT0_BCR] = {0x21064, 0}, [GCC_SNOC_BUS_TIMEOUT1_BCR] = {0x2106C, 0}, [GCC_SNOC_BUS_TIMEOUT2_BCR] = {0x21074, 0}, [GCC_SNOC_BUS_TIMEOUT3_BCR] = {0x2107C, 0}, [GCC_PCNOC_BUS_TIMEOUT0_BCR] = {0x21084, 0}, [GCC_PCNOC_BUS_TIMEOUT1_BCR] = {0x2108C, 0}, [GCC_PCNOC_BUS_TIMEOUT2_BCR] = {0x21094, 0}, [GCC_PCNOC_BUS_TIMEOUT3_BCR] = {0x2109C, 0}, [GCC_PCNOC_BUS_TIMEOUT4_BCR] = {0x210A4, 0}, [GCC_PCNOC_BUS_TIMEOUT5_BCR] = {0x210AC, 0}, [GCC_PCNOC_BUS_TIMEOUT6_BCR] = {0x210B4, 0}, [GCC_PCNOC_BUS_TIMEOUT7_BCR] = {0x210BC, 0}, [GCC_PCNOC_BUS_TIMEOUT8_BCR] = {0x210C4, 0}, [GCC_PCNOC_BUS_TIMEOUT9_BCR] = {0x210CC, 0}, [GCC_TCSR_BCR] = {0x22000, 0}, [GCC_MPM_BCR] = {0x24000, 0}, [GCC_SPDM_BCR] = {0x25000, 0}, }; int qcom_gcc_ipq4018_hwreset_assert(device_t dev, intptr_t id, bool reset) { struct qcom_gcc_ipq4018_softc *sc; uint32_t reg; sc = device_get_softc(dev); if (id > nitems(gcc_ipq4019_reset_list)) { device_printf(dev, "%s: invalid id (%d)\n", __func__, id); return (EINVAL); } - device_printf(dev, "%s: called; id=%d, reset=%d\n", __func__, id, reset); mtx_lock(&sc->mtx); reg = bus_read_4(sc->reg, gcc_ipq4019_reset_list[id].reg); if (reset) reg |= (1U << gcc_ipq4019_reset_list[id].bit); else reg &= ~(1U << gcc_ipq4019_reset_list[id].bit); bus_write_4(sc->reg, gcc_ipq4019_reset_list[id].reg, reg); mtx_unlock(&sc->mtx); return (0); } int qcom_gcc_ipq4018_hwreset_is_asserted(device_t dev, intptr_t id, bool *reset) { struct qcom_gcc_ipq4018_softc *sc; uint32_t reg; sc = device_get_softc(dev); if (id > nitems(gcc_ipq4019_reset_list)) { device_printf(dev, "%s: invalid id (%d)\n", __func__, id); return (EINVAL); } mtx_lock(&sc->mtx); reg = bus_read_4(sc->reg, gcc_ipq4019_reset_list[id].reg); if (reg & ((1U << gcc_ipq4019_reset_list[id].bit))) *reset = true; else *reset = false; mtx_unlock(&sc->mtx); device_printf(dev, "called; id=%d\n", id); return (0); } diff --git a/sys/arm/qualcomm/qcom_gcc_ipq4018_var.h b/sys/dev/qcom_gcc/qcom_gcc_ipq4018_var.h similarity index 77% rename from sys/arm/qualcomm/qcom_gcc_ipq4018_var.h rename to sys/dev/qcom_gcc/qcom_gcc_ipq4018_var.h index 3997e1860e43..8f5783c5a800 100644 --- a/sys/arm/qualcomm/qcom_gcc_ipq4018_var.h +++ b/sys/dev/qcom_gcc/qcom_gcc_ipq4018_var.h @@ -1,50 +1,67 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2021 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, 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. * * $FreeBSD$ */ #ifndef __QCOM_GCC_IPQ4018_VAR_H__ #define __QCOM_GCC_IPQ4018_VAR_H__ struct qcom_gcc_ipq4018_reset_entry { uint32_t reg; uint32_t bit; }; struct qcom_gcc_ipq4018_softc { device_t dev; int reg_rid; struct resource *reg; struct mtx mtx; + struct clkdom *clkdom; }; +/* + * reset block + */ extern int qcom_gcc_ipq4018_hwreset_assert(device_t dev, intptr_t id, bool reset); extern int qcom_gcc_ipq4018_hwreset_is_asserted(device_t dev, intptr_t id, bool *reset); +/* + * clock block + */ +extern int qcom_gcc_ipq4018_clock_read(device_t dev, bus_addr_t addr, + uint32_t *val); +extern int qcom_gcc_ipq4018_clock_write(device_t dev, bus_addr_t addr, + uint32_t val); +extern int qcom_gcc_ipq4018_clock_modify(device_t dev, bus_addr_t addr, + uint32_t clear_mask, uint32_t set_mask); +extern void qcom_gcc_ipq4018_clock_setup(struct qcom_gcc_ipq4018_softc *sc); +extern void qcom_gcc_ipq4018_clock_lock(device_t dev); +extern void qcom_gcc_ipq4018_clock_unlock(device_t dev); + #endif /* __QCOM_GCC_IPQ4018_VAR_H__ */