1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2021, Adrian Chadd <adrian@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice unmodified, this list of conditions, and the following 11 * disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* Driver for Qualcomm IPQ4018 clock and reset device */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/kernel.h> 35 #include <sys/malloc.h> 36 #include <sys/module.h> 37 #include <sys/sglist.h> 38 #include <sys/random.h> 39 #include <sys/stdatomic.h> 40 #include <sys/mutex.h> 41 42 #include <machine/bus.h> 43 #include <machine/resource.h> 44 #include <sys/bus.h> 45 46 #include <dev/fdt/fdt_common.h> 47 #include <dev/ofw/ofw_bus.h> 48 #include <dev/ofw/ofw_bus_subr.h> 49 50 #include <dev/extres/clk/clk_div.h> 51 #include <dev/extres/clk/clk_fixed.h> 52 #include <dev/extres/clk/clk_mux.h> 53 #include <dev/extres/clk/clk_link.h> 54 55 #include <dt-bindings/clock/qcom,gcc-ipq4019.h> 56 57 #include <dev/qcom_clk/qcom_clk_freqtbl.h> 58 #include <dev/qcom_clk/qcom_clk_fepll.h> 59 #include <dev/qcom_clk/qcom_clk_fdiv.h> 60 #include <dev/qcom_clk/qcom_clk_apssdiv.h> 61 #include <dev/qcom_clk/qcom_clk_rcg2.h> 62 #include <dev/qcom_clk/qcom_clk_branch2.h> 63 #include <dev/qcom_clk/qcom_clk_ro_div.h> 64 65 #include "qcom_gcc_ipq4018_var.h" 66 67 68 /* Fixed rate clock. */ 69 #define F_RATE(_id, cname, _freq) \ 70 { \ 71 .clkdef.id = _id, \ 72 .clkdef.name = cname, \ 73 .clkdef.parent_names = NULL, \ 74 .clkdef.parent_cnt = 0, \ 75 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 76 .freq = _freq, \ 77 } 78 79 /* Linked clock. */ 80 #define F_LINK(_id, _cname) \ 81 { \ 82 .clkdef.id = _id, \ 83 .clkdef.name = _cname, \ 84 .clkdef.parent_names = NULL, \ 85 .clkdef.parent_cnt = 0, \ 86 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 87 } 88 89 90 /* FEPLL clock */ 91 #define F_FEPLL(_id, _cname, _parent, _reg, _fs, _fw, _rs, _rw) \ 92 { \ 93 .clkdef.id = _id, \ 94 .clkdef.name = _cname, \ 95 .clkdef.parent_names = (const char *[]){_parent}, \ 96 .clkdef.parent_cnt = 1, \ 97 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 98 .offset = _reg, \ 99 .fdbkdiv_shift = _fs, \ 100 .fdbkdiv_width = _fw, \ 101 .refclkdiv_shift = _rs, \ 102 .refclkdiv_width = _rw, \ 103 } 104 105 /* Fixed divisor clock */ 106 #define F_FDIV(_id, _cname, _parent, _divisor) \ 107 { \ 108 .clkdef.id = _id, \ 109 .clkdef.name = _cname, \ 110 .clkdef.parent_names = (const char *[]){_parent}, \ 111 .clkdef.parent_cnt = 1, \ 112 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 113 .divisor = _divisor, \ 114 } 115 116 /* APSS DIV clock */ 117 #define F_APSSDIV(_id, _cname, _parent, _doffset, _dshift, _dwidth, \ 118 _eoffset, _eshift, _freqtbl) \ 119 { \ 120 .clkdef.id = _id, \ 121 .clkdef.name = _cname, \ 122 .clkdef.parent_names = (const char *[]){_parent}, \ 123 .clkdef.parent_cnt = 1, \ 124 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 125 .div_offset = _doffset, \ 126 .div_width = _dwidth, \ 127 .div_shift = _dshift, \ 128 .enable_offset = _eoffset, \ 129 .enable_shift = _eshift, \ 130 .freq_tbl = _freqtbl, \ 131 } 132 133 /* read-only div table */ 134 #define F_RO_DIV(_id, _cname, _parent, _offset, _shift, _width, _tbl) \ 135 { \ 136 .clkdef.id = _id, \ 137 .clkdef.name = _cname, \ 138 .clkdef.parent_names = (const char *[]){_parent}, \ 139 .clkdef.parent_cnt = 1, \ 140 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 141 .offset = _offset, \ 142 .width = _width, \ 143 .shift = _shift, \ 144 .div_tbl = _tbl, \ 145 } 146 147 /* RCG2 clock */ 148 #define F_RCG2(_id, _cname, _parents, _rcgr, _hid_width, _mnd_width, \ 149 _safe_src_idx, _safe_pre_parent_idx, _cfg_offset, _flags, \ 150 _freq_tbl) \ 151 { \ 152 .clkdef.id = _id, \ 153 .clkdef.name = _cname, \ 154 .clkdef.parent_names = _parents, \ 155 .clkdef.parent_cnt = nitems(_parents), \ 156 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 157 .cmd_rcgr = _rcgr, \ 158 .hid_width = _hid_width, \ 159 .mnd_width = _mnd_width, \ 160 .safe_src_idx = _safe_src_idx, \ 161 .flags= _flags, \ 162 .safe_pre_parent_idx = _safe_pre_parent_idx, \ 163 .freq_tbl = _freq_tbl, \ 164 } 165 166 /* branch2 gate nodes */ 167 #define F_BRANCH2(_id, _cname, _parent, _eo, _es, _hr, _hs, _haltreg, \ 168 _type, _voted, _flags) \ 169 { \ 170 .clkdef.id = _id, \ 171 .clkdef.name = _cname, \ 172 .clkdef.parent_names = (const char *[]){_parent}, \ 173 .clkdef.parent_cnt = 1, \ 174 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 175 .enable_offset = _eo, \ 176 .enable_shift = _es, \ 177 .hwcg_reg = _hr, \ 178 .hwcg_bit = _hs, \ 179 .halt_reg = _haltreg, \ 180 .halt_check_type = _type, \ 181 .halt_check_voted = _voted, \ 182 .flags = _flags, \ 183 } 184 185 /* 186 * Fixed "gcc_fepll_vco" PLL derived sources: 187 * 188 * P_FEPLL125 - 125MHz 189 * P_FEPLL125DLY - 125MHz 190 * P_FEPLL200 - 200MHz 191 * "fepll500" - 500MHz 192 * 193 * Fixed "gcc_apps_ddrpll_vco" PLL derived sources: 194 * 195 * P_DDRPLL - 192MHz 196 */ 197 static struct qcom_clk_fdiv_def fdiv_tbl[] = { 198 F_FDIV(GCC_FEPLL125_CLK, "fepll125", "gcc_fepll_vco", 32), 199 F_FDIV(GCC_FEPLL125DLY_CLK, "fepll125dly", "gcc_fepll_vco", 32), 200 F_FDIV(GCC_FEPLL200_CLK, "fepll200", "gcc_fepll_vco", 20), 201 F_FDIV(GCC_FEPLL500_CLK, "fepll500", "gcc_fepll_vco", 8), 202 F_FDIV(GCC_SDCC_PLLDIV_CLK, "ddrpllsdcc", "gcc_apps_ddrpll_vco", 28), 203 }; 204 205 /* 206 * FEPLL - 48MHz (xo) input, 4GHz output 207 * DDRPLL - 48MHz (xo) input, 5.376GHz output 208 */ 209 static struct qcom_clk_fepll_def fepll_tbl[] = { 210 F_FEPLL(GCC_FEPLL_VCO, "gcc_fepll_vco", "xo", 0x2f020, 16, 8, 24, 5), 211 F_FEPLL(GCC_APSS_DDRPLL_VCO, "gcc_apps_ddrpll_vco", "xo", 0x2e020, 212 16, 8, 24, 5), 213 }; 214 215 /* 216 * Frequency table for the APSS PLL/DIV path for the CPU frequency. 217 * 218 * Note - the APSS DIV code only needs the frequency and pre-divisor, 219 * not the other fields. 220 */ 221 static struct qcom_clk_freq_tbl apss_freq_tbl[] = { 222 { 384000000, "gcc_apps_ddrpll_vco", 0xd, 0, 0 }, 223 { 413000000, "gcc_apps_ddrpll_vco", 0xc, 0, 0 }, 224 { 448000000, "gcc_apps_ddrpll_vco", 0xb, 0, 0 }, 225 { 488000000, "gcc_apps_ddrpll_vco", 0xa, 0, 0 }, 226 { 512000000, "gcc_apps_ddrpll_vco", 0x9, 0, 0 }, 227 { 537000000, "gcc_apps_ddrpll_vco", 0x8, 0, 0 }, 228 { 565000000, "gcc_apps_ddrpll_vco", 0x7, 0, 0 }, 229 { 597000000, "gcc_apps_ddrpll_vco", 0x6, 0, 0 }, 230 { 632000000, "gcc_apps_ddrpll_vco", 0x5, 0, 0 }, 231 { 672000000, "gcc_apps_ddrpll_vco", 0x4, 0, 0 }, 232 { 716000000, "gcc_apps_ddrpll_vco", 0x3, 0, 0 }, 233 { 768000000, "gcc_apps_ddrpll_vco", 0x2, 0, 0 }, 234 { 823000000, "gcc_apps_ddrpll_vco", 0x1, 0, 0 }, 235 { 896000000, "gcc_apps_ddrpll_vco", 0x0, 0, 0 }, 236 { 0, } 237 }; 238 239 /* 240 * APSS div/gate 241 */ 242 static struct qcom_clk_apssdiv_def apssdiv_tbl[] = { 243 F_APSSDIV(GCC_APSS_CPU_PLLDIV_CLK, "ddrpllapss", 244 "gcc_apps_ddrpll_vco", 0x2e020, 245 4, 4, 0x2e000, 0, &apss_freq_tbl[0]), 246 }; 247 248 /* 249 * Parent clocks for the apps_clk_src clock. 250 */ 251 static const char * apps_clk_src_parents[] = { 252 "xo", "ddrpllapss", "fepll500", "fepll200" 253 }; 254 255 /* 256 * Parents lists for a variety of blocks. 257 */ 258 static const char * gcc_xo_200_parents[] = { 259 "xo", "fepll200" 260 }; 261 static const char * gcc_xo_200_500_parents[] = { 262 "xo", "fepll200", "fepll500" 263 }; 264 static const char * gcc_xo_200_spi_parents[] = { 265 "xo", NULL, "fepll200" 266 }; 267 static const char * gcc_xo_sdcc1_500_parents[] = { 268 "xo", "ddrpllsdcc", "fepll500" 269 }; 270 271 static const char * gcc_xo_125_dly_parents[] = { 272 "xo", "fepll125dly" 273 }; 274 275 static const char * gcc_xo_wcss2g_parents[] = { 276 "xo", "fepllwcss2g" 277 }; 278 279 static const char * gcc_xo_wcss5g_parents[] = { 280 "xo", "fepllwcss5g" 281 }; 282 283 static struct qcom_clk_freq_tbl apps_clk_src_freq_tbl[] = { 284 { 48000000, "xo", 1, 0, 0 }, 285 { 200000000, "fepll200", 1, 0, 0 }, 286 { 384000000, "ddrpllapss", 1, 0, 0 }, 287 { 413000000, "ddrpllapss", 1, 0, 0 }, 288 { 448000000, "ddrpllapss", 1, 0, 0 }, 289 { 488000000, "ddrpllapss", 1, 0, 0 }, 290 { 500000000, "fepll500", 1, 0, 0 }, 291 { 512000000, "ddrpllapss", 1, 0, 0 }, 292 { 537000000, "ddrpllapss", 1, 0, 0 }, 293 { 565000000, "ddrpllapss", 1, 0, 0 }, 294 { 597000000, "ddrpllapss", 1, 0, 0 }, 295 { 632000000, "ddrpllapss", 1, 0, 0 }, 296 { 672000000, "ddrpllapss", 1, 0, 0 }, 297 { 716000000, "ddrpllapss", 1, 0, 0 }, 298 { 0,} 299 300 }; 301 302 static struct qcom_clk_freq_tbl audio_clk_src_freq_tbl[] = { 303 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 304 { 200000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 305 { 0,} 306 }; 307 308 static struct qcom_clk_freq_tbl blsp1_qup1_i2c_apps_clk_src_freq_tbl[] = { 309 { 19050000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(10.5), 1, 1 }, 310 { 0,} 311 }; 312 313 static struct qcom_clk_freq_tbl blsp1_qup1_spi_apps_clk_src_freq_tbl[] = { 314 { 960000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(12), 1, 4 }, 315 { 4800000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 10 }, 316 { 9600000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 5 }, 317 { 15000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 3 }, 318 { 19200000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 2, 5 }, 319 { 24000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 2 }, 320 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 321 { 0,} 322 }; 323 324 static struct qcom_clk_freq_tbl gcc_pcnoc_ahb_clk_src_freq_tbl[] = { 325 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 326 { 100000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(2), 0, 0 }, 327 { 0, } 328 }; 329 330 static struct qcom_clk_freq_tbl blsp1_uart1_apps_clk_src_freq_tbl[] = { 331 { 1843200, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 144, 15625 }, 332 { 3686400, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 288, 15625 }, 333 { 7372800, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 576, 15625 }, 334 { 14745600, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1152, 15625 }, 335 { 16000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 2, 25 }, 336 { 24000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 2 }, 337 { 32000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 4, 25 }, 338 { 40000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 5 }, 339 { 46400000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 29, 125 }, 340 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 341 { 0, } 342 }; 343 344 static struct qcom_clk_freq_tbl gp1_clk_src_freq_tbl[] = { 345 { 1250000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 16, 0 }, 346 { 2500000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 8, 0 }, 347 { 5000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 4, 0 }, 348 { 0, } 349 }; 350 351 static struct qcom_clk_freq_tbl sdcc1_apps_clk_src_freq_tbl[] = { 352 { 144000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 3, 240 }, 353 { 400000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 0 }, 354 { 20000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 25 }, 355 { 25000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 20 }, 356 { 50000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 10 }, 357 { 100000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 5 }, 358 { 192000000, "ddrpllsdcc", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 359 { 0, } 360 }; 361 362 static struct qcom_clk_freq_tbl apps_ahb_clk_src_freq_tbl[] = { 363 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 364 { 100000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(2), 0, 0 }, 365 { 0, } 366 }; 367 368 static struct qcom_clk_freq_tbl usb30_mock_utmi_clk_src_freq_tbl[] = { 369 { 2000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(10), 0, 0 }, 370 { 0, } 371 }; 372 373 static struct qcom_clk_freq_tbl fephy_125m_dly_clk_src_freq_tbl[] = { 374 { 125000000, "fepll125dly", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 375 { 0, } 376 }; 377 378 static struct qcom_clk_freq_tbl wcss2g_clk_src_freq_tbl[] = { 379 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 380 { 250000000, "fepllwcss2g", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 381 { 0, } 382 }; 383 384 static struct qcom_clk_freq_tbl wcss5g_clk_src_freq_tbl[] = { 385 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 386 { 250000000, "fepllwcss5g", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 }, 387 { 0, } 388 }; 389 390 /* 391 * Divisor table for the 2g/5g wifi clock divisors. 392 */ 393 static struct qcom_clk_ro_div_tbl fepllwcss_clk_div_tbl[] = { 394 { 0, 15 }, 395 { 1, 16 }, 396 { 2, 18 }, 397 { 3, 20 }, 398 { 0, 0 } 399 }; 400 401 /* 402 * Read-only divisor table clocks. 403 */ 404 static struct qcom_clk_ro_div_def ro_div_tbl[] = { 405 F_RO_DIV(GCC_FEPLL_WCSS2G_CLK, "fepllwcss2g", "gcc_fepll_vco", 406 0x2f020, 8, 2, &fepllwcss_clk_div_tbl[0]), 407 F_RO_DIV(GCC_FEPLL_WCSS5G_CLK, "fepllwcss5g", "gcc_fepll_vco", 408 0x2f020, 12, 2, &fepllwcss_clk_div_tbl[0]), 409 }; 410 411 /* 412 * RCG2 clocks 413 */ 414 static struct qcom_clk_rcg2_def rcg2_tbl[] = { 415 F_RCG2(AUDIO_CLK_SRC, "audio_clk_src", gcc_xo_200_parents, 416 0x1b000, 5, 0, -1, -1, 0, 0, &audio_clk_src_freq_tbl[0]), 417 F_RCG2(BLSP1_QUP1_I2C_APPS_CLK_SRC, "blsp1_qup1_i2c_apps_clk_src", 418 gcc_xo_200_parents, 0x200c, 5, 0, -1, -1, 0, 0, 419 &blsp1_qup1_i2c_apps_clk_src_freq_tbl[0]), 420 F_RCG2(BLSP1_QUP2_I2C_APPS_CLK_SRC, "blsp1_qup2_i2c_apps_clk_src", 421 gcc_xo_200_parents, 0x3000, 5, 0, -1, -1, 0, 0, 422 &blsp1_qup1_i2c_apps_clk_src_freq_tbl[0]), 423 F_RCG2(BLSP1_QUP1_SPI_APPS_CLK_SRC, "blsp1_qup1_spi_apps_clk_src", 424 gcc_xo_200_spi_parents, 0x2024, 5, 8, -1, -1, 0, 0, 425 &blsp1_qup1_spi_apps_clk_src_freq_tbl[0]), 426 F_RCG2(BLSP1_QUP2_SPI_APPS_CLK_SRC, "blsp1_qup2_spi_apps_clk_src", 427 gcc_xo_200_spi_parents, 0x3014, 5, 8, -1, -1, 0, 0, 428 &blsp1_qup1_spi_apps_clk_src_freq_tbl[0]), 429 F_RCG2(BLSP1_UART1_APPS_CLK_SRC, "blsp1_uart1_apps_clk_src", 430 gcc_xo_200_spi_parents, 0x2044, 5, 16, -1, -1, 0, 0, 431 &blsp1_uart1_apps_clk_src_freq_tbl[0]), 432 F_RCG2(BLSP1_UART2_APPS_CLK_SRC, "blsp1_uart2_apps_clk_src", 433 gcc_xo_200_spi_parents, 0x3034, 5, 16, -1, -1, 0, 0, 434 &blsp1_uart1_apps_clk_src_freq_tbl[0]), 435 F_RCG2(GP1_CLK_SRC, "gp1_clk_src", gcc_xo_200_parents, 0x8004, 436 5, 8, -1, -1, 0, 0, 437 &gp1_clk_src_freq_tbl[0]), 438 F_RCG2(GP2_CLK_SRC, "gp2_clk_src", gcc_xo_200_parents, 0x9004, 439 5, 8, -1, -1, 0, 0, 440 &gp1_clk_src_freq_tbl[0]), 441 F_RCG2(GP3_CLK_SRC, "gp3_clk_src", gcc_xo_200_parents, 0xa004, 442 5, 8, -1, -1, 0, 0, 443 &gp1_clk_src_freq_tbl[0]), 444 F_RCG2(SDCC1_APPS_CLK_SRC, "sdcc1_apps_clk_src", 445 gcc_xo_sdcc1_500_parents, 0x18004, 5, 0, -1, -1, 0, 0, 446 &sdcc1_apps_clk_src_freq_tbl[0]), 447 F_RCG2(GCC_APPS_CLK_SRC, "apps_clk_src", apps_clk_src_parents, 448 0x1900c, 5, 0, -1, 2, 0, 449 QCOM_CLK_RCG2_FLAGS_SET_RATE_PARENT, 450 &apps_clk_src_freq_tbl[0]), 451 F_RCG2(GCC_APPS_AHB_CLK_SRC, "apps_ahb_clk_src", 452 gcc_xo_200_500_parents, 0x19014, 5, 0, -1, -1, 0, 453 0, &apps_ahb_clk_src_freq_tbl[0]), 454 F_RCG2(GCC_USB3_MOCK_UTMI_CLK_SRC, "usb30_mock_utmi_clk_src", 455 gcc_xo_200_parents, 0x1e000, 5, 0, -1, -1, 0, 0, 456 &usb30_mock_utmi_clk_src_freq_tbl[0]), 457 F_RCG2(FEPHY_125M_DLY_CLK_SRC, "fephy_125m_dly_clk_src", 458 gcc_xo_125_dly_parents, 0x12000, 5, 0, -1, -1, 0, 0, 459 &fephy_125m_dly_clk_src_freq_tbl[0]), 460 F_RCG2(WCSS2G_CLK_SRC, "wcss2g_clk_src", gcc_xo_wcss2g_parents, 461 0x1f000, 5, 0, -1, -1, 0, 0, 462 &wcss2g_clk_src_freq_tbl[0]), 463 F_RCG2(WCSS5G_CLK_SRC, "wcss5g_clk_src", gcc_xo_wcss5g_parents, 464 0x20000, 5, 0, -1, -1, 0, 0, 465 &wcss5g_clk_src_freq_tbl[0]), 466 F_RCG2(GCC_PCNOC_AHB_CLK_SRC, "gcc_pcnoc_ahb_clk_src", 467 gcc_xo_200_500_parents, 0x21024, 5, 0, -1, -1, 0, 0, 468 &gcc_pcnoc_ahb_clk_src_freq_tbl[0]), 469 }; 470 471 /* 472 * branch2 clocks 473 */ 474 static struct qcom_clk_branch2_def branch2_tbl[] = { 475 F_BRANCH2(GCC_AUDIO_AHB_CLK, "gcc_audio_ahb_clk", "pcnoc_clk_src", 476 0x1b010, 0, 0, 0, 0x1b010, QCOM_CLK_BRANCH2_BRANCH_HALT, 477 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 478 F_BRANCH2(GCC_AUDIO_PWM_CLK, "gcc_audio_pwm_clk", "audio_clk_src", 479 0x1b00c, 0, 0, 0, 0x1b00c, QCOM_CLK_BRANCH2_BRANCH_HALT, 480 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 481 F_BRANCH2(GCC_BLSP1_QUP1_I2C_APPS_CLK, "gcc_blsp1_qup1_i2c_apps_clk", 482 "blsp1_qup1_i2c_apps_clk_src", 483 0x2008, 0, 0, 0, 0x2008, QCOM_CLK_BRANCH2_BRANCH_HALT, 484 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 485 F_BRANCH2(GCC_BLSP1_QUP2_I2C_APPS_CLK, "gcc_blsp1_qup2_i2c_apps_clk", 486 "blsp1_qup2_i2c_apps_clk_src", 487 0x3010, 0, 0, 0, 0x3010, QCOM_CLK_BRANCH2_BRANCH_HALT, 488 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 489 F_BRANCH2(GCC_BLSP1_QUP1_SPI_APPS_CLK, "gcc_blsp1_qup1_spi_apps_clk", 490 "blsp1_qup1_spi_apps_clk_src", 491 0x2004, 0, 0, 0, 0x2004, QCOM_CLK_BRANCH2_BRANCH_HALT, 492 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 493 F_BRANCH2(GCC_BLSP1_QUP2_SPI_APPS_CLK, "gcc_blsp1_qup2_spi_apps_clk", 494 "blsp1_qup2_spi_apps_clk_src", 495 0x300c, 0, 0, 0, 0x300c, QCOM_CLK_BRANCH2_BRANCH_HALT, 496 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 497 F_BRANCH2(GCC_BLSP1_UART1_APPS_CLK, "gcc_blsp1_uart1_apps_clk", 498 "blsp1_uart1_apps_clk_src", 499 0x203c, 0, 0, 0, 0x203c, QCOM_CLK_BRANCH2_BRANCH_HALT, 500 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 501 F_BRANCH2(GCC_BLSP1_UART2_APPS_CLK, "gcc_blsp1_uart2_apps_clk", 502 "blsp1_uart2_apps_clk_src", 503 0x302c, 0, 0, 0, 0x302c, QCOM_CLK_BRANCH2_BRANCH_HALT, 504 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 505 F_BRANCH2(GCC_GP1_CLK, "gcc_gp1_clk", "gp1_clk_src", 506 0x8000, 0, 0, 0, 0x8000, QCOM_CLK_BRANCH2_BRANCH_HALT, 507 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 508 F_BRANCH2(GCC_GP2_CLK, "gcc_gp2_clk", "gp2_clk_src", 509 0x9000, 0, 0, 0, 0x9000, QCOM_CLK_BRANCH2_BRANCH_HALT, 510 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 511 F_BRANCH2(GCC_GP3_CLK, "gcc_gp3_clk", "gp3_clk_src", 512 0xa000, 0, 0, 0, 0xa000, QCOM_CLK_BRANCH2_BRANCH_HALT, 513 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 514 /* BRANCH_HALT_VOTED; note the different enable/halt */ 515 F_BRANCH2(GCC_APPS_AHB_CLK_SRC, "gcc_apss_ahb_clk", 516 "apps_ahb_clk_src", 517 0x6000, 14, 0, 0, 0x19004, QCOM_CLK_BRANCH2_BRANCH_HALT, 518 true, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 519 F_BRANCH2(GCC_BLSP1_AHB_CLK, "gcc_blsp1_ahb_clk", 520 "pcnoc_clk_src", 521 0x6000, 10, 0, 0, 0x1008, QCOM_CLK_BRANCH2_BRANCH_HALT, 522 true, 0), /* BRANCH_HALT_VOTED */ 523 F_BRANCH2(GCC_DCD_XO_CLK, "gcc_dcd_xo_clk", "xo", 524 0x2103c, 0, 0, 0, 0x2103c, QCOM_CLK_BRANCH2_BRANCH_HALT, 525 false, 0), 526 F_BRANCH2(GCC_BOOT_ROM_AHB_CLK, "gcc_boot_rom_ahb_clk", 527 "pcnoc_clk_src", 0x1300c, 0, 0, 0, 0x1300c, 528 QCOM_CLK_BRANCH2_BRANCH_HALT, 529 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 530 F_BRANCH2(GCC_CRYPTO_AHB_CLK, "gcc_crypto_ahb_clk", 531 "pcnoc_clk_src", 0x6000, 0, 0, 0, 0x16024, 532 QCOM_CLK_BRANCH2_BRANCH_HALT, 533 true, 0), /* BRANCH_HALT_VOTED */ 534 F_BRANCH2(GCC_CRYPTO_AXI_CLK, "gcc_crypto_axi_clk", 535 "fepll125", 0x6000, 1, 0, 0, 0x16020, 536 QCOM_CLK_BRANCH2_BRANCH_HALT, 537 true, 0), /* BRANCH_HALT_VOTED */ 538 F_BRANCH2(GCC_CRYPTO_CLK, "gcc_crypto_clk", "fepll125", 539 0x6000, 2, 0, 0, 0x1601c, QCOM_CLK_BRANCH2_BRANCH_HALT, 540 true, 0), /* BRANCH_HALT_VOTED */ 541 F_BRANCH2(GCC_ESS_CLK, "gcc_ess_clk", "fephy_125m_dly_clk_src", 542 0x12010, 0, 0, 0, 0x12010, QCOM_CLK_BRANCH2_BRANCH_HALT, 543 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 544 /* BRANCH_HALT_VOTED */ 545 F_BRANCH2(GCC_IMEM_AXI_CLK, "gcc_imem_axi_clk", "fepll200", 546 0x6000, 17, 0, 0, 0xe004, QCOM_CLK_BRANCH2_BRANCH_HALT, 547 true, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 548 F_BRANCH2(GCC_IMEM_CFG_AHB_CLK, "gcc_imem_cfg_ahb_clk", 549 "pcnoc_clk_src", 550 0xe008, 0, 0, 0, 0xe008, QCOM_CLK_BRANCH2_BRANCH_HALT, 551 false, 0), 552 F_BRANCH2(GCC_PCIE_AHB_CLK, "gcc_pcie_ahb_clk", "pcnoc_clk_src", 553 0x1d00c, 0, 0, 0, 0x1d00c, QCOM_CLK_BRANCH2_BRANCH_HALT, 554 false, 0), 555 F_BRANCH2(GCC_PCIE_AXI_M_CLK, "gcc_pcie_axi_m_clk", "fepll200", 556 0x1d004, 0, 0, 0, 0x1d004, QCOM_CLK_BRANCH2_BRANCH_HALT, 557 false, 0), 558 F_BRANCH2(GCC_PCIE_AXI_S_CLK, "gcc_pcie_axi_s_clk", "fepll200", 559 0x1d008, 0, 0, 0, 0x1d008, QCOM_CLK_BRANCH2_BRANCH_HALT, 560 false, 0), 561 F_BRANCH2(GCC_PRNG_AHB_CLK, "gcc_prng_ahb_clk", "pcnoc_clk_src", 562 0x6000, 8, 0, 0, 0x13004, QCOM_CLK_BRANCH2_BRANCH_HALT, 563 true, 0), /* BRANCH_HALT_VOTED */ 564 F_BRANCH2(GCC_QPIC_AHB_CLK, "gcc_qpic_ahb_clk", "pcnoc_clk_src", 565 0x1c008, 0, 0, 0, 0x1c008, QCOM_CLK_BRANCH2_BRANCH_HALT, 566 false, 0), 567 F_BRANCH2(GCC_QPIC_CLK, "gcc_qpic_clk", "pcnoc_clk_src", 568 0x1c004, 0, 0, 0, 0x1c004, QCOM_CLK_BRANCH2_BRANCH_HALT, 569 false, 0), 570 F_BRANCH2(GCC_SDCC1_AHB_CLK, "gcc_sdcc1_ahb_clk", "pcnoc_clk_src", 571 0x18010, 0, 0, 0, 0x18010, QCOM_CLK_BRANCH2_BRANCH_HALT, 572 false, 0), 573 F_BRANCH2(GCC_SDCC1_APPS_CLK, "gcc_sdcc1_apps_clk", 574 "sdcc1_apps_clk_src", 0x1800c, 0, 0, 0, 0x1800c, 575 QCOM_CLK_BRANCH2_BRANCH_HALT, 576 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 577 F_BRANCH2(GCC_TLMM_AHB_CLK, "gcc_tlmm_ahb_clk", "pcnoc_clk_src", 578 0x6000, 5, 0, 0, 0x5004, QCOM_CLK_BRANCH2_BRANCH_HALT, 579 true, 0), /* BRANCH_HALT_VOTED */ 580 F_BRANCH2(GCC_USB2_MASTER_CLK, "gcc_usb2_master_clk", "pcnoc_clk_src", 581 0x1e00c, 0, 0, 0, 0x1e00c, QCOM_CLK_BRANCH2_BRANCH_HALT, 582 false, 0), 583 F_BRANCH2(GCC_USB2_SLEEP_CLK, "gcc_usb2_sleep_clk", 584 "gcc_sleep_clk_src", 0x1e010, 0, 0, 0, 0x1e010, 585 QCOM_CLK_BRANCH2_BRANCH_HALT, 586 false, 0), 587 F_BRANCH2(GCC_USB2_MOCK_UTMI_CLK, "gcc_usb2_mock_utmi_clk", 588 "usb30_mock_utmi_clk_src", 0x1e014, 0, 0, 0, 0x1e014, 589 QCOM_CLK_BRANCH2_BRANCH_HALT, 590 false, 0), 591 F_BRANCH2(GCC_USB3_MASTER_CLK, "gcc_usb3_master_clk", "fepll125", 592 0x1e028, 0, 0, 0, 0x1e028, QCOM_CLK_BRANCH2_BRANCH_HALT, 593 false, 0), 594 F_BRANCH2(GCC_USB3_SLEEP_CLK, "gcc_usb3_sleep_clk", "gcc_sleep_clk_src", 595 0x1e02c, 0, 0, 0, 0x1e02c, QCOM_CLK_BRANCH2_BRANCH_HALT, 596 false, 0), 597 F_BRANCH2(GCC_USB3_MOCK_UTMI_CLK, "gcc_usb3_mock_utmi_clk", 598 "usb30_mock_utmi_clk_src", 599 0x1e030, 0, 0, 0, 0x1e030, QCOM_CLK_BRANCH2_BRANCH_HALT, 600 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 601 /* Note - yes, these two have the same registers in linux */ 602 F_BRANCH2(GCC_WCSS2G_CLK, "gcc_wcss2g_clk", "wcss2g_clk_src", 603 0x1f00c, 0, 0, 0, 0x1f00c, QCOM_CLK_BRANCH2_BRANCH_HALT, 604 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 605 F_BRANCH2(GCC_WCSS2G_REF_CLK, "gcc_wcss2g_ref_clk", "xo", 606 0x1f00c, 0, 0, 0, 0x1f00c, QCOM_CLK_BRANCH2_BRANCH_HALT, 607 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 608 F_BRANCH2(GCC_WCSS2G_RTC_CLK, "gcc_wcss2g_rtc_clk", "gcc_sleep_clk_src", 609 0x1f010, 0, 0, 0, 0x1f010, QCOM_CLK_BRANCH2_BRANCH_HALT, 610 false, 0), 611 612 /* Note - yes, these two have the same registers in linux */ 613 F_BRANCH2(GCC_WCSS5G_CLK, "gcc_wcss5g_clk", "wcss5g_clk_src", 614 0x1f00c, 0, 0, 0, 0x2000c, QCOM_CLK_BRANCH2_BRANCH_HALT, 615 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 616 F_BRANCH2(GCC_WCSS5G_REF_CLK, "gcc_wcss5g_ref_clk", "xo", 617 0x1f00c, 0, 0, 0, 0x2000c, QCOM_CLK_BRANCH2_BRANCH_HALT, 618 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 619 F_BRANCH2(GCC_WCSS5G_RTC_CLK, "gcc_wcss5g_rtc_clk", "gcc_sleep_clk_src", 620 0x1f010, 0, 0, 0, 0x20010, QCOM_CLK_BRANCH2_BRANCH_HALT, 621 false, 0), 622 623 F_BRANCH2(GCC_PCNOC_AHB_CLK, "pcnoc_clk_src", "gcc_pcnoc_ahb_clk_src", 624 0x21030, 0, 0, 0, 0x21030, QCOM_CLK_BRANCH2_BRANCH_HALT, false, 625 QCOM_CLK_BRANCH2_FLAGS_CRITICAL | 626 QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT), 627 }; 628 629 static void 630 qcom_gcc_ipq4018_clock_init_fepll(struct qcom_gcc_ipq4018_softc *sc) 631 { 632 int i, rv; 633 634 for (i = 0; i < nitems(fepll_tbl); i++) { 635 rv = qcom_clk_fepll_register(sc->clkdom, fepll_tbl + i); 636 if (rv != 0) 637 panic("qcom_clk_fepll_register failed"); 638 } 639 } 640 641 static void 642 qcom_gcc_ipq4018_clock_init_fdiv(struct qcom_gcc_ipq4018_softc *sc) 643 { 644 int i, rv; 645 646 for (i = 0; i < nitems(fdiv_tbl); i++) { 647 rv = qcom_clk_fdiv_register(sc->clkdom, fdiv_tbl + i); 648 if (rv != 0) 649 panic("qcom_clk_fdiv_register failed"); 650 } 651 } 652 653 static void 654 qcom_gcc_ipq4018_clock_init_apssdiv(struct qcom_gcc_ipq4018_softc *sc) 655 { 656 int i, rv; 657 658 for (i = 0; i < nitems(apssdiv_tbl); i++) { 659 rv = qcom_clk_apssdiv_register(sc->clkdom, apssdiv_tbl + i); 660 if (rv != 0) 661 panic("qcom_clk_apssdiv_register failed"); 662 } 663 } 664 665 static void 666 qcom_gcc_ipq4018_clock_init_rcg2(struct qcom_gcc_ipq4018_softc *sc) 667 { 668 int i, rv; 669 670 for (i = 0; i < nitems(rcg2_tbl); i++) { 671 rv = qcom_clk_rcg2_register(sc->clkdom, rcg2_tbl + i); 672 if (rv != 0) 673 panic("qcom_clk_rcg2_register failed"); 674 } 675 } 676 677 static void 678 qcom_gcc_ipq4018_clock_init_branch2(struct qcom_gcc_ipq4018_softc *sc) 679 { 680 int i, rv; 681 682 for (i = 0; i < nitems(branch2_tbl); i++) { 683 rv = qcom_clk_branch2_register(sc->clkdom, branch2_tbl + i); 684 if (rv != 0) 685 panic("qcom_clk_branch2_register failed"); 686 } 687 } 688 689 static void 690 qcom_gcc_ipq4018_clock_init_ro_div(struct qcom_gcc_ipq4018_softc *sc) 691 { 692 int i, rv; 693 694 for (i = 0; i < nitems(ro_div_tbl); i++) { 695 rv = qcom_clk_ro_div_register(sc->clkdom, ro_div_tbl + i); 696 if (rv != 0) 697 panic("qcom_clk_ro_div_register failed"); 698 } 699 } 700 701 int 702 qcom_gcc_ipq4018_clock_read(device_t dev, bus_addr_t addr, uint32_t *val) 703 { 704 struct qcom_gcc_ipq4018_softc *sc; 705 706 sc = device_get_softc(dev); 707 *val = bus_read_4(sc->reg, addr); 708 return (0); 709 } 710 711 int 712 qcom_gcc_ipq4018_clock_write(device_t dev, bus_addr_t addr, uint32_t val) 713 { 714 struct qcom_gcc_ipq4018_softc *sc; 715 716 sc = device_get_softc(dev); 717 bus_write_4(sc->reg, addr, val); 718 return (0); 719 } 720 721 int 722 qcom_gcc_ipq4018_clock_modify(device_t dev, bus_addr_t addr, 723 uint32_t clear_mask, uint32_t set_mask) 724 { 725 struct qcom_gcc_ipq4018_softc *sc; 726 uint32_t reg; 727 728 sc = device_get_softc(dev); 729 reg = bus_read_4(sc->reg, addr); 730 reg &= clear_mask; 731 reg |= set_mask; 732 bus_write_4(sc->reg, addr, reg); 733 return (0); 734 } 735 736 void 737 qcom_gcc_ipq4018_clock_setup(struct qcom_gcc_ipq4018_softc *sc) 738 { 739 740 sc->clkdom = clkdom_create(sc->dev); 741 742 /* Setup stuff */ 743 qcom_gcc_ipq4018_clock_init_fepll(sc); 744 qcom_gcc_ipq4018_clock_init_fdiv(sc); 745 qcom_gcc_ipq4018_clock_init_apssdiv(sc); 746 qcom_gcc_ipq4018_clock_init_rcg2(sc); 747 qcom_gcc_ipq4018_clock_init_branch2(sc); 748 qcom_gcc_ipq4018_clock_init_ro_div(sc); 749 750 /* Finalise clock tree */ 751 clkdom_finit(sc->clkdom); 752 } 753 754 void 755 qcom_gcc_ipq4018_clock_lock(device_t dev) 756 { 757 struct qcom_gcc_ipq4018_softc *sc; 758 759 sc = device_get_softc(dev); 760 mtx_lock(&sc->mtx); 761 } 762 763 void 764 qcom_gcc_ipq4018_clock_unlock(device_t dev) 765 { 766 struct qcom_gcc_ipq4018_softc *sc; 767 768 sc = device_get_softc(dev); 769 mtx_unlock(&sc->mtx); 770 } 771