Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: qcom: Add Display Clock controller (DISPCC) driver for Milos

Add support for the display clock controller found on Milos (e.g.
SM7635) based devices.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
Link: https://lore.kernel.org/r/20250715-sm7635-clocks-v3-7-18f9faac4984@fairphone.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Luca Weiss and committed by
Bjorn Andersson
f40b5217 63edb206

+985
+10
drivers/clk/qcom/Kconfig
··· 1089 1089 Say Y if you want to support display devices and functionality such as 1090 1090 splash screen. 1091 1091 1092 + config SM_DISPCC_MILOS 1093 + tristate "Milos Display Clock Controller" 1094 + depends on ARM64 || COMPILE_TEST 1095 + depends on SM_GCC_MILOS 1096 + help 1097 + Support for the display clock controller on Qualcomm Technologies, Inc 1098 + Milos devices. 1099 + Say Y if you want to support display devices and functionality such as 1100 + splash screen. 1101 + 1092 1102 config SM_DISPCC_8450 1093 1103 tristate "SM8450 Display Clock Controller" 1094 1104 depends on ARM64 || COMPILE_TEST
+1
drivers/clk/qcom/Makefile
··· 142 142 obj-$(CONFIG_SM_DISPCC_8450) += dispcc-sm8450.o 143 143 obj-$(CONFIG_SM_DISPCC_8550) += dispcc-sm8550.o 144 144 obj-$(CONFIG_SM_DISPCC_8750) += dispcc-sm8750.o 145 + obj-$(CONFIG_SM_DISPCC_MILOS) += dispcc-milos.o 145 146 obj-$(CONFIG_SM_GCC_4450) += gcc-sm4450.o 146 147 obj-$(CONFIG_SM_GCC_6115) += gcc-sm6115.o 147 148 obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o
+974
drivers/clk/qcom/dispcc-milos.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. 4 + * Copyright (c) 2025, Luca Weiss <luca.weiss@fairphone.com> 5 + */ 6 + 7 + #include <linux/clk.h> 8 + #include <linux/clk-provider.h> 9 + #include <linux/err.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/of.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/regmap.h> 15 + 16 + #include <dt-bindings/clock/qcom,milos-dispcc.h> 17 + 18 + #include "common.h" 19 + #include "clk-alpha-pll.h" 20 + #include "clk-branch.h" 21 + #include "clk-pll.h" 22 + #include "clk-rcg.h" 23 + #include "clk-regmap.h" 24 + #include "clk-regmap-divider.h" 25 + #include "clk-regmap-mux.h" 26 + #include "reset.h" 27 + #include "gdsc.h" 28 + 29 + /* Need to match the order of clocks in DT binding */ 30 + enum { 31 + DT_BI_TCXO, 32 + DT_SLEEP_CLK, 33 + DT_AHB_CLK, 34 + DT_GCC_DISP_GPLL0_CLK, 35 + DT_DSI0_PHY_PLL_OUT_BYTECLK, 36 + DT_DSI0_PHY_PLL_OUT_DSICLK, 37 + DT_DP0_PHY_PLL_LINK_CLK, 38 + DT_DP0_PHY_PLL_VCO_DIV_CLK, 39 + }; 40 + 41 + #define DISP_CC_MISC_CMD 0xF000 42 + 43 + enum { 44 + P_BI_TCXO, 45 + P_DISP_CC_PLL0_OUT_EVEN, 46 + P_DISP_CC_PLL0_OUT_MAIN, 47 + P_DP0_PHY_PLL_LINK_CLK, 48 + P_DP0_PHY_PLL_VCO_DIV_CLK, 49 + P_DSI0_PHY_PLL_OUT_BYTECLK, 50 + P_DSI0_PHY_PLL_OUT_DSICLK, 51 + P_GCC_DISP_GPLL0_CLK, 52 + P_SLEEP_CLK, 53 + }; 54 + 55 + static const struct pll_vco lucid_ole_vco[] = { 56 + { 249600000, 2300000000, 0 }, 57 + }; 58 + 59 + /* 257.142858 MHz Configuration */ 60 + static const struct alpha_pll_config disp_cc_pll0_config = { 61 + .l = 0xd, 62 + .alpha = 0x6492, 63 + .config_ctl_val = 0x20485699, 64 + .config_ctl_hi_val = 0x00182261, 65 + .config_ctl_hi1_val = 0x82aa299c, 66 + .test_ctl_val = 0x00000000, 67 + .test_ctl_hi_val = 0x00000003, 68 + .test_ctl_hi1_val = 0x00009000, 69 + .test_ctl_hi2_val = 0x00000034, 70 + .user_ctl_val = 0x00000000, 71 + .user_ctl_hi_val = 0x00000005, 72 + }; 73 + 74 + static struct clk_alpha_pll disp_cc_pll0 = { 75 + .offset = 0x0, 76 + .config = &disp_cc_pll0_config, 77 + .vco_table = lucid_ole_vco, 78 + .num_vco = ARRAY_SIZE(lucid_ole_vco), 79 + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], 80 + .clkr = { 81 + .hw.init = &(const struct clk_init_data) { 82 + .name = "disp_cc_pll0", 83 + .parent_data = &(const struct clk_parent_data) { 84 + .index = DT_BI_TCXO, 85 + }, 86 + .num_parents = 1, 87 + .ops = &clk_alpha_pll_lucid_evo_ops, 88 + }, 89 + }, 90 + }; 91 + 92 + static const struct parent_map disp_cc_parent_map_0[] = { 93 + { P_BI_TCXO, 0 }, 94 + }; 95 + 96 + static const struct clk_parent_data disp_cc_parent_data_0[] = { 97 + { .index = DT_BI_TCXO }, 98 + }; 99 + 100 + static const struct parent_map disp_cc_parent_map_1[] = { 101 + { P_BI_TCXO, 0 }, 102 + { P_DSI0_PHY_PLL_OUT_DSICLK, 1 }, 103 + { P_DSI0_PHY_PLL_OUT_BYTECLK, 2 }, 104 + }; 105 + 106 + static const struct clk_parent_data disp_cc_parent_data_1[] = { 107 + { .index = DT_BI_TCXO }, 108 + { .index = DT_DSI0_PHY_PLL_OUT_DSICLK }, 109 + { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK }, 110 + }; 111 + 112 + static const struct parent_map disp_cc_parent_map_2[] = { 113 + { P_BI_TCXO, 0 }, 114 + { P_DP0_PHY_PLL_LINK_CLK, 1 }, 115 + { P_DP0_PHY_PLL_VCO_DIV_CLK, 2 }, 116 + }; 117 + 118 + static const struct clk_parent_data disp_cc_parent_data_2[] = { 119 + { .index = DT_BI_TCXO }, 120 + { .index = DT_DP0_PHY_PLL_LINK_CLK }, 121 + { .index = DT_DP0_PHY_PLL_VCO_DIV_CLK }, 122 + }; 123 + 124 + static const struct parent_map disp_cc_parent_map_3[] = { 125 + { P_BI_TCXO, 0 }, 126 + { P_GCC_DISP_GPLL0_CLK, 4 }, 127 + }; 128 + 129 + static const struct clk_parent_data disp_cc_parent_data_3[] = { 130 + { .index = DT_BI_TCXO }, 131 + { .index = DT_GCC_DISP_GPLL0_CLK }, 132 + }; 133 + 134 + static const struct parent_map disp_cc_parent_map_4[] = { 135 + { P_BI_TCXO, 0 }, 136 + { P_DP0_PHY_PLL_LINK_CLK, 1 }, 137 + }; 138 + 139 + static const struct clk_parent_data disp_cc_parent_data_4[] = { 140 + { .index = DT_BI_TCXO }, 141 + { .index = DT_DP0_PHY_PLL_LINK_CLK }, 142 + }; 143 + 144 + static const struct parent_map disp_cc_parent_map_5[] = { 145 + { P_BI_TCXO, 0 }, 146 + { P_DSI0_PHY_PLL_OUT_BYTECLK, 2 }, 147 + }; 148 + 149 + static const struct clk_parent_data disp_cc_parent_data_5[] = { 150 + { .index = DT_BI_TCXO }, 151 + { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK }, 152 + }; 153 + 154 + static const struct parent_map disp_cc_parent_map_6[] = { 155 + { P_BI_TCXO, 0 }, 156 + { P_DISP_CC_PLL0_OUT_MAIN, 1 }, 157 + { P_GCC_DISP_GPLL0_CLK, 4 }, 158 + { P_DISP_CC_PLL0_OUT_EVEN, 6 }, 159 + }; 160 + 161 + static const struct clk_parent_data disp_cc_parent_data_6[] = { 162 + { .index = DT_BI_TCXO }, 163 + { .hw = &disp_cc_pll0.clkr.hw }, 164 + { .index = DT_GCC_DISP_GPLL0_CLK }, 165 + { .hw = &disp_cc_pll0.clkr.hw }, 166 + }; 167 + 168 + static const struct parent_map disp_cc_parent_map_7[] = { 169 + { P_SLEEP_CLK, 0 }, 170 + }; 171 + 172 + static const struct clk_parent_data disp_cc_parent_data_7_ao[] = { 173 + { .index = DT_SLEEP_CLK }, 174 + }; 175 + 176 + static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = { 177 + F(19200000, P_BI_TCXO, 1, 0, 0), 178 + F(37500000, P_GCC_DISP_GPLL0_CLK, 8, 0, 0), 179 + F(75000000, P_GCC_DISP_GPLL0_CLK, 4, 0, 0), 180 + { } 181 + }; 182 + 183 + static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = { 184 + .cmd_rcgr = 0x8130, 185 + .mnd_width = 0, 186 + .hid_width = 5, 187 + .parent_map = disp_cc_parent_map_3, 188 + .freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src, 189 + .clkr.hw.init = &(const struct clk_init_data) { 190 + .name = "disp_cc_mdss_ahb_clk_src", 191 + .parent_data = disp_cc_parent_data_3, 192 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), 193 + .flags = CLK_SET_RATE_PARENT, 194 + .ops = &clk_rcg2_shared_ops, 195 + }, 196 + }; 197 + 198 + static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = { 199 + .cmd_rcgr = 0x8098, 200 + .mnd_width = 0, 201 + .hid_width = 5, 202 + .parent_map = disp_cc_parent_map_1, 203 + .clkr.hw.init = &(const struct clk_init_data) { 204 + .name = "disp_cc_mdss_byte0_clk_src", 205 + .parent_data = disp_cc_parent_data_1, 206 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), 207 + .flags = CLK_SET_RATE_PARENT, 208 + .ops = &clk_byte2_ops, 209 + }, 210 + }; 211 + 212 + static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_aux_clk_src[] = { 213 + F(19200000, P_BI_TCXO, 1, 0, 0), 214 + { } 215 + }; 216 + 217 + static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = { 218 + .cmd_rcgr = 0x8118, 219 + .mnd_width = 0, 220 + .hid_width = 5, 221 + .parent_map = disp_cc_parent_map_0, 222 + .freq_tbl = ftbl_disp_cc_mdss_dptx0_aux_clk_src, 223 + .clkr.hw.init = &(const struct clk_init_data) { 224 + .name = "disp_cc_mdss_dptx0_aux_clk_src", 225 + .parent_data = disp_cc_parent_data_0, 226 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), 227 + .flags = CLK_SET_RATE_PARENT, 228 + .ops = &clk_rcg2_ops, 229 + }, 230 + }; 231 + 232 + static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = { 233 + .cmd_rcgr = 0x80cc, 234 + .mnd_width = 0, 235 + .hid_width = 5, 236 + .parent_map = disp_cc_parent_map_4, 237 + .clkr.hw.init = &(const struct clk_init_data) { 238 + .name = "disp_cc_mdss_dptx0_link_clk_src", 239 + .parent_data = disp_cc_parent_data_4, 240 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_4), 241 + .flags = CLK_SET_RATE_PARENT, 242 + .ops = &clk_byte2_ops, 243 + }, 244 + }; 245 + 246 + static struct clk_rcg2 disp_cc_mdss_dptx0_pixel0_clk_src = { 247 + .cmd_rcgr = 0x80e8, 248 + .mnd_width = 16, 249 + .hid_width = 5, 250 + .parent_map = disp_cc_parent_map_2, 251 + .clkr.hw.init = &(const struct clk_init_data) { 252 + .name = "disp_cc_mdss_dptx0_pixel0_clk_src", 253 + .parent_data = disp_cc_parent_data_2, 254 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_2), 255 + .flags = CLK_SET_RATE_PARENT, 256 + .ops = &clk_dp_ops, 257 + }, 258 + }; 259 + 260 + static struct clk_rcg2 disp_cc_mdss_dptx0_pixel1_clk_src = { 261 + .cmd_rcgr = 0x8100, 262 + .mnd_width = 16, 263 + .hid_width = 5, 264 + .parent_map = disp_cc_parent_map_2, 265 + .clkr.hw.init = &(const struct clk_init_data) { 266 + .name = "disp_cc_mdss_dptx0_pixel1_clk_src", 267 + .parent_data = disp_cc_parent_data_2, 268 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_2), 269 + .flags = CLK_SET_RATE_PARENT, 270 + .ops = &clk_dp_ops, 271 + }, 272 + }; 273 + 274 + static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src[] = { 275 + F(9600000, P_BI_TCXO, 2, 0, 0), 276 + F(12800000, P_BI_TCXO, 1.5, 0, 0), 277 + F(19200000, P_BI_TCXO, 1, 0, 0), 278 + { } 279 + }; 280 + static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = { 281 + .cmd_rcgr = 0x80b4, 282 + .mnd_width = 0, 283 + .hid_width = 5, 284 + .parent_map = disp_cc_parent_map_5, 285 + .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src, 286 + .clkr.hw.init = &(const struct clk_init_data) { 287 + .name = "disp_cc_mdss_esc0_clk_src", 288 + .parent_data = disp_cc_parent_data_5, 289 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_5), 290 + .flags = CLK_SET_RATE_PARENT, 291 + .ops = &clk_rcg2_ops, 292 + }, 293 + }; 294 + 295 + static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = { 296 + F(19200000, P_BI_TCXO, 1, 0, 0), 297 + F(85714286, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), 298 + F(100000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), 299 + F(200000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), 300 + F(342000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), 301 + F(402000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), 302 + F(535000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), 303 + F(600000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), 304 + F(630000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), 305 + { } 306 + }; 307 + 308 + static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = { 309 + .cmd_rcgr = 0x8068, 310 + .mnd_width = 0, 311 + .hid_width = 5, 312 + .parent_map = disp_cc_parent_map_6, 313 + .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src, 314 + .clkr.hw.init = &(const struct clk_init_data) { 315 + .name = "disp_cc_mdss_mdp_clk_src", 316 + .parent_data = disp_cc_parent_data_6, 317 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_6), 318 + .flags = CLK_SET_RATE_PARENT, 319 + .ops = &clk_rcg2_shared_ops, 320 + }, 321 + }; 322 + 323 + static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = { 324 + .cmd_rcgr = 0x8050, 325 + .mnd_width = 8, 326 + .hid_width = 5, 327 + .parent_map = disp_cc_parent_map_1, 328 + .clkr.hw.init = &(const struct clk_init_data) { 329 + .name = "disp_cc_mdss_pclk0_clk_src", 330 + .parent_data = disp_cc_parent_data_1, 331 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), 332 + .flags = CLK_SET_RATE_PARENT, 333 + .ops = &clk_pixel_ops, 334 + }, 335 + }; 336 + 337 + static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = { 338 + .cmd_rcgr = 0x8080, 339 + .mnd_width = 0, 340 + .hid_width = 5, 341 + .parent_map = disp_cc_parent_map_0, 342 + .freq_tbl = ftbl_disp_cc_mdss_dptx0_aux_clk_src, 343 + .clkr.hw.init = &(const struct clk_init_data) { 344 + .name = "disp_cc_mdss_vsync_clk_src", 345 + .parent_data = disp_cc_parent_data_0, 346 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), 347 + .flags = CLK_SET_RATE_PARENT, 348 + .ops = &clk_rcg2_ops, 349 + }, 350 + }; 351 + 352 + static const struct freq_tbl ftbl_disp_cc_sleep_clk_src[] = { 353 + F(32000, P_SLEEP_CLK, 1, 0, 0), 354 + { } 355 + }; 356 + 357 + static struct clk_rcg2 disp_cc_sleep_clk_src = { 358 + .cmd_rcgr = 0xe054, 359 + .mnd_width = 0, 360 + .hid_width = 5, 361 + .parent_map = disp_cc_parent_map_7, 362 + .freq_tbl = ftbl_disp_cc_sleep_clk_src, 363 + .clkr.hw.init = &(const struct clk_init_data) { 364 + .name = "disp_cc_sleep_clk_src", 365 + .parent_data = disp_cc_parent_data_7_ao, 366 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_7_ao), 367 + .flags = CLK_SET_RATE_PARENT, 368 + .ops = &clk_rcg2_ops, 369 + }, 370 + }; 371 + 372 + static struct clk_rcg2 disp_cc_xo_clk_src = { 373 + .cmd_rcgr = 0xe034, 374 + .mnd_width = 0, 375 + .hid_width = 5, 376 + .parent_map = disp_cc_parent_map_0, 377 + .freq_tbl = ftbl_disp_cc_mdss_dptx0_aux_clk_src, 378 + .clkr.hw.init = &(const struct clk_init_data) { 379 + .name = "disp_cc_xo_clk_src", 380 + .parent_data = disp_cc_parent_data_0, 381 + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), 382 + .flags = CLK_SET_RATE_PARENT, 383 + .ops = &clk_rcg2_ops, 384 + }, 385 + }; 386 + 387 + static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = { 388 + .reg = 0x80b0, 389 + .shift = 0, 390 + .width = 4, 391 + .clkr.hw.init = &(const struct clk_init_data) { 392 + .name = "disp_cc_mdss_byte0_div_clk_src", 393 + .parent_hws = (const struct clk_hw*[]) { 394 + &disp_cc_mdss_byte0_clk_src.clkr.hw, 395 + }, 396 + .num_parents = 1, 397 + .flags = CLK_SET_RATE_PARENT, 398 + .ops = &clk_regmap_div_ops, 399 + }, 400 + }; 401 + 402 + static struct clk_regmap_div disp_cc_mdss_dptx0_link_div_clk_src = { 403 + .reg = 0x80e4, 404 + .shift = 0, 405 + .width = 4, 406 + .clkr.hw.init = &(const struct clk_init_data) { 407 + .name = "disp_cc_mdss_dptx0_link_div_clk_src", 408 + .parent_hws = (const struct clk_hw*[]) { 409 + &disp_cc_mdss_dptx0_link_clk_src.clkr.hw, 410 + }, 411 + .num_parents = 1, 412 + .flags = CLK_SET_RATE_PARENT, 413 + .ops = &clk_regmap_div_ro_ops, 414 + }, 415 + }; 416 + 417 + static struct clk_branch disp_cc_mdss_accu_clk = { 418 + .halt_reg = 0xe050, 419 + .halt_check = BRANCH_HALT_VOTED, 420 + .clkr = { 421 + .enable_reg = 0xe050, 422 + .enable_mask = BIT(0), 423 + .hw.init = &(const struct clk_init_data) { 424 + .name = "disp_cc_mdss_accu_clk", 425 + .parent_hws = (const struct clk_hw*[]) { 426 + &disp_cc_xo_clk_src.clkr.hw, 427 + }, 428 + .num_parents = 1, 429 + .flags = CLK_SET_RATE_PARENT, 430 + .ops = &clk_branch2_ops, 431 + }, 432 + }, 433 + }; 434 + 435 + static struct clk_branch disp_cc_mdss_ahb1_clk = { 436 + .halt_reg = 0xa020, 437 + .halt_check = BRANCH_HALT, 438 + .clkr = { 439 + .enable_reg = 0xa020, 440 + .enable_mask = BIT(0), 441 + .hw.init = &(const struct clk_init_data) { 442 + .name = "disp_cc_mdss_ahb1_clk", 443 + .parent_hws = (const struct clk_hw*[]) { 444 + &disp_cc_mdss_ahb_clk_src.clkr.hw, 445 + }, 446 + .num_parents = 1, 447 + .flags = CLK_SET_RATE_PARENT, 448 + .ops = &clk_branch2_ops, 449 + }, 450 + }, 451 + }; 452 + 453 + static struct clk_branch disp_cc_mdss_ahb_clk = { 454 + .halt_reg = 0x804c, 455 + .halt_check = BRANCH_HALT, 456 + .clkr = { 457 + .enable_reg = 0x804c, 458 + .enable_mask = BIT(0), 459 + .hw.init = &(const struct clk_init_data) { 460 + .name = "disp_cc_mdss_ahb_clk", 461 + .parent_hws = (const struct clk_hw*[]) { 462 + &disp_cc_mdss_ahb_clk_src.clkr.hw, 463 + }, 464 + .num_parents = 1, 465 + .flags = CLK_SET_RATE_PARENT, 466 + .ops = &clk_branch2_ops, 467 + }, 468 + }, 469 + }; 470 + 471 + static struct clk_branch disp_cc_mdss_byte0_clk = { 472 + .halt_reg = 0x8024, 473 + .halt_check = BRANCH_HALT, 474 + .clkr = { 475 + .enable_reg = 0x8024, 476 + .enable_mask = BIT(0), 477 + .hw.init = &(const struct clk_init_data) { 478 + .name = "disp_cc_mdss_byte0_clk", 479 + .parent_hws = (const struct clk_hw*[]) { 480 + &disp_cc_mdss_byte0_clk_src.clkr.hw, 481 + }, 482 + .num_parents = 1, 483 + .flags = CLK_SET_RATE_PARENT, 484 + .ops = &clk_branch2_ops, 485 + }, 486 + }, 487 + }; 488 + 489 + static struct clk_branch disp_cc_mdss_byte0_intf_clk = { 490 + .halt_reg = 0x8028, 491 + .halt_check = BRANCH_HALT, 492 + .clkr = { 493 + .enable_reg = 0x8028, 494 + .enable_mask = BIT(0), 495 + .hw.init = &(const struct clk_init_data) { 496 + .name = "disp_cc_mdss_byte0_intf_clk", 497 + .parent_hws = (const struct clk_hw*[]) { 498 + &disp_cc_mdss_byte0_div_clk_src.clkr.hw, 499 + }, 500 + .num_parents = 1, 501 + .flags = CLK_SET_RATE_PARENT, 502 + .ops = &clk_branch2_ops, 503 + }, 504 + }, 505 + }; 506 + 507 + static struct clk_branch disp_cc_mdss_dptx0_aux_clk = { 508 + .halt_reg = 0x8048, 509 + .halt_check = BRANCH_HALT, 510 + .clkr = { 511 + .enable_reg = 0x8048, 512 + .enable_mask = BIT(0), 513 + .hw.init = &(const struct clk_init_data) { 514 + .name = "disp_cc_mdss_dptx0_aux_clk", 515 + .parent_hws = (const struct clk_hw*[]) { 516 + &disp_cc_mdss_dptx0_aux_clk_src.clkr.hw, 517 + }, 518 + .num_parents = 1, 519 + .flags = CLK_SET_RATE_PARENT, 520 + .ops = &clk_branch2_ops, 521 + }, 522 + }, 523 + }; 524 + 525 + static struct clk_branch disp_cc_mdss_dptx0_crypto_clk = { 526 + .halt_reg = 0x803c, 527 + .halt_check = BRANCH_HALT, 528 + .clkr = { 529 + .enable_reg = 0x803c, 530 + .enable_mask = BIT(0), 531 + .hw.init = &(const struct clk_init_data) { 532 + .name = "disp_cc_mdss_dptx0_crypto_clk", 533 + .parent_hws = (const struct clk_hw*[]) { 534 + &disp_cc_mdss_dptx0_link_clk_src.clkr.hw, 535 + }, 536 + .num_parents = 1, 537 + .flags = CLK_SET_RATE_PARENT, 538 + .ops = &clk_branch2_ops, 539 + }, 540 + }, 541 + }; 542 + 543 + static struct clk_branch disp_cc_mdss_dptx0_link_clk = { 544 + .halt_reg = 0x8030, 545 + .halt_check = BRANCH_HALT, 546 + .clkr = { 547 + .enable_reg = 0x8030, 548 + .enable_mask = BIT(0), 549 + .hw.init = &(const struct clk_init_data) { 550 + .name = "disp_cc_mdss_dptx0_link_clk", 551 + .parent_hws = (const struct clk_hw*[]) { 552 + &disp_cc_mdss_dptx0_link_clk_src.clkr.hw, 553 + }, 554 + .num_parents = 1, 555 + .flags = CLK_SET_RATE_PARENT, 556 + .ops = &clk_branch2_ops, 557 + }, 558 + }, 559 + }; 560 + 561 + static struct clk_branch disp_cc_mdss_dptx0_link_intf_clk = { 562 + .halt_reg = 0x8038, 563 + .halt_check = BRANCH_HALT, 564 + .clkr = { 565 + .enable_reg = 0x8038, 566 + .enable_mask = BIT(0), 567 + .hw.init = &(const struct clk_init_data) { 568 + .name = "disp_cc_mdss_dptx0_link_intf_clk", 569 + .parent_hws = (const struct clk_hw*[]) { 570 + &disp_cc_mdss_dptx0_link_div_clk_src.clkr.hw, 571 + }, 572 + .num_parents = 1, 573 + .flags = CLK_SET_RATE_PARENT, 574 + .ops = &clk_branch2_ops, 575 + }, 576 + }, 577 + }; 578 + 579 + static struct clk_branch disp_cc_mdss_dptx0_pixel0_clk = { 580 + .halt_reg = 0x8040, 581 + .halt_check = BRANCH_HALT, 582 + .clkr = { 583 + .enable_reg = 0x8040, 584 + .enable_mask = BIT(0), 585 + .hw.init = &(const struct clk_init_data) { 586 + .name = "disp_cc_mdss_dptx0_pixel0_clk", 587 + .parent_hws = (const struct clk_hw*[]) { 588 + &disp_cc_mdss_dptx0_pixel0_clk_src.clkr.hw, 589 + }, 590 + .num_parents = 1, 591 + .flags = CLK_SET_RATE_PARENT, 592 + .ops = &clk_branch2_ops, 593 + }, 594 + }, 595 + }; 596 + 597 + static struct clk_branch disp_cc_mdss_dptx0_pixel1_clk = { 598 + .halt_reg = 0x8044, 599 + .halt_check = BRANCH_HALT, 600 + .clkr = { 601 + .enable_reg = 0x8044, 602 + .enable_mask = BIT(0), 603 + .hw.init = &(const struct clk_init_data) { 604 + .name = "disp_cc_mdss_dptx0_pixel1_clk", 605 + .parent_hws = (const struct clk_hw*[]) { 606 + &disp_cc_mdss_dptx0_pixel1_clk_src.clkr.hw, 607 + }, 608 + .num_parents = 1, 609 + .flags = CLK_SET_RATE_PARENT, 610 + .ops = &clk_branch2_ops, 611 + }, 612 + }, 613 + }; 614 + 615 + static struct clk_branch disp_cc_mdss_dptx0_usb_router_link_intf_clk = { 616 + .halt_reg = 0x8034, 617 + .halt_check = BRANCH_HALT, 618 + .clkr = { 619 + .enable_reg = 0x8034, 620 + .enable_mask = BIT(0), 621 + .hw.init = &(const struct clk_init_data) { 622 + .name = "disp_cc_mdss_dptx0_usb_router_link_intf_clk", 623 + .parent_hws = (const struct clk_hw*[]) { 624 + &disp_cc_mdss_dptx0_link_div_clk_src.clkr.hw, 625 + }, 626 + .num_parents = 1, 627 + .flags = CLK_SET_RATE_PARENT, 628 + .ops = &clk_branch2_ops, 629 + }, 630 + }, 631 + }; 632 + 633 + static struct clk_branch disp_cc_mdss_esc0_clk = { 634 + .halt_reg = 0x802c, 635 + .halt_check = BRANCH_HALT, 636 + .clkr = { 637 + .enable_reg = 0x802c, 638 + .enable_mask = BIT(0), 639 + .hw.init = &(const struct clk_init_data) { 640 + .name = "disp_cc_mdss_esc0_clk", 641 + .parent_hws = (const struct clk_hw*[]) { 642 + &disp_cc_mdss_esc0_clk_src.clkr.hw, 643 + }, 644 + .num_parents = 1, 645 + .flags = CLK_SET_RATE_PARENT, 646 + .ops = &clk_branch2_ops, 647 + }, 648 + }, 649 + }; 650 + 651 + static struct clk_branch disp_cc_mdss_mdp1_clk = { 652 + .halt_reg = 0xa004, 653 + .halt_check = BRANCH_HALT, 654 + .clkr = { 655 + .enable_reg = 0xa004, 656 + .enable_mask = BIT(0), 657 + .hw.init = &(const struct clk_init_data) { 658 + .name = "disp_cc_mdss_mdp1_clk", 659 + .parent_hws = (const struct clk_hw*[]) { 660 + &disp_cc_mdss_mdp_clk_src.clkr.hw, 661 + }, 662 + .num_parents = 1, 663 + .flags = CLK_SET_RATE_PARENT, 664 + .ops = &clk_branch2_ops, 665 + }, 666 + }, 667 + }; 668 + 669 + static struct clk_branch disp_cc_mdss_mdp_clk = { 670 + .halt_reg = 0x8008, 671 + .halt_check = BRANCH_HALT, 672 + .clkr = { 673 + .enable_reg = 0x8008, 674 + .enable_mask = BIT(0), 675 + .hw.init = &(const struct clk_init_data) { 676 + .name = "disp_cc_mdss_mdp_clk", 677 + .parent_hws = (const struct clk_hw*[]) { 678 + &disp_cc_mdss_mdp_clk_src.clkr.hw, 679 + }, 680 + .num_parents = 1, 681 + .flags = CLK_SET_RATE_PARENT, 682 + .ops = &clk_branch2_ops, 683 + }, 684 + }, 685 + }; 686 + 687 + static struct clk_branch disp_cc_mdss_mdp_lut1_clk = { 688 + .halt_reg = 0xa010, 689 + .halt_check = BRANCH_HALT, 690 + .clkr = { 691 + .enable_reg = 0xa010, 692 + .enable_mask = BIT(0), 693 + .hw.init = &(const struct clk_init_data) { 694 + .name = "disp_cc_mdss_mdp_lut1_clk", 695 + .parent_hws = (const struct clk_hw*[]) { 696 + &disp_cc_mdss_mdp_clk_src.clkr.hw, 697 + }, 698 + .num_parents = 1, 699 + .flags = CLK_SET_RATE_PARENT, 700 + .ops = &clk_branch2_ops, 701 + }, 702 + }, 703 + }; 704 + 705 + static struct clk_branch disp_cc_mdss_mdp_lut_clk = { 706 + .halt_reg = 0x8014, 707 + .halt_check = BRANCH_HALT_VOTED, 708 + .clkr = { 709 + .enable_reg = 0x8014, 710 + .enable_mask = BIT(0), 711 + .hw.init = &(const struct clk_init_data) { 712 + .name = "disp_cc_mdss_mdp_lut_clk", 713 + .parent_hws = (const struct clk_hw*[]) { 714 + &disp_cc_mdss_mdp_clk_src.clkr.hw, 715 + }, 716 + .num_parents = 1, 717 + .flags = CLK_SET_RATE_PARENT, 718 + .ops = &clk_branch2_ops, 719 + }, 720 + }, 721 + }; 722 + 723 + static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = { 724 + .halt_reg = 0xc004, 725 + .halt_check = BRANCH_HALT_VOTED, 726 + .clkr = { 727 + .enable_reg = 0xc004, 728 + .enable_mask = BIT(0), 729 + .hw.init = &(const struct clk_init_data) { 730 + .name = "disp_cc_mdss_non_gdsc_ahb_clk", 731 + .parent_hws = (const struct clk_hw*[]) { 732 + &disp_cc_mdss_ahb_clk_src.clkr.hw, 733 + }, 734 + .num_parents = 1, 735 + .flags = CLK_SET_RATE_PARENT, 736 + .ops = &clk_branch2_ops, 737 + }, 738 + }, 739 + }; 740 + 741 + static struct clk_branch disp_cc_mdss_pclk0_clk = { 742 + .halt_reg = 0x8004, 743 + .halt_check = BRANCH_HALT, 744 + .clkr = { 745 + .enable_reg = 0x8004, 746 + .enable_mask = BIT(0), 747 + .hw.init = &(const struct clk_init_data) { 748 + .name = "disp_cc_mdss_pclk0_clk", 749 + .parent_hws = (const struct clk_hw*[]) { 750 + &disp_cc_mdss_pclk0_clk_src.clkr.hw, 751 + }, 752 + .num_parents = 1, 753 + .flags = CLK_SET_RATE_PARENT, 754 + .ops = &clk_branch2_ops, 755 + }, 756 + }, 757 + }; 758 + 759 + static struct clk_branch disp_cc_mdss_rscc_ahb_clk = { 760 + .halt_reg = 0xc00c, 761 + .halt_check = BRANCH_HALT, 762 + .clkr = { 763 + .enable_reg = 0xc00c, 764 + .enable_mask = BIT(0), 765 + .hw.init = &(const struct clk_init_data) { 766 + .name = "disp_cc_mdss_rscc_ahb_clk", 767 + .parent_hws = (const struct clk_hw*[]) { 768 + &disp_cc_mdss_ahb_clk_src.clkr.hw, 769 + }, 770 + .num_parents = 1, 771 + .flags = CLK_SET_RATE_PARENT, 772 + .ops = &clk_branch2_ops, 773 + }, 774 + }, 775 + }; 776 + 777 + static struct clk_branch disp_cc_mdss_rscc_vsync_clk = { 778 + .halt_reg = 0xc008, 779 + .halt_check = BRANCH_HALT, 780 + .clkr = { 781 + .enable_reg = 0xc008, 782 + .enable_mask = BIT(0), 783 + .hw.init = &(const struct clk_init_data) { 784 + .name = "disp_cc_mdss_rscc_vsync_clk", 785 + .parent_hws = (const struct clk_hw*[]) { 786 + &disp_cc_mdss_vsync_clk_src.clkr.hw, 787 + }, 788 + .num_parents = 1, 789 + .flags = CLK_SET_RATE_PARENT, 790 + .ops = &clk_branch2_ops, 791 + }, 792 + }, 793 + }; 794 + 795 + static struct clk_branch disp_cc_mdss_vsync1_clk = { 796 + .halt_reg = 0xa01c, 797 + .halt_check = BRANCH_HALT, 798 + .clkr = { 799 + .enable_reg = 0xa01c, 800 + .enable_mask = BIT(0), 801 + .hw.init = &(const struct clk_init_data) { 802 + .name = "disp_cc_mdss_vsync1_clk", 803 + .parent_hws = (const struct clk_hw*[]) { 804 + &disp_cc_mdss_vsync_clk_src.clkr.hw, 805 + }, 806 + .num_parents = 1, 807 + .flags = CLK_SET_RATE_PARENT, 808 + .ops = &clk_branch2_ops, 809 + }, 810 + }, 811 + }; 812 + 813 + static struct clk_branch disp_cc_mdss_vsync_clk = { 814 + .halt_reg = 0x8020, 815 + .halt_check = BRANCH_HALT, 816 + .clkr = { 817 + .enable_reg = 0x8020, 818 + .enable_mask = BIT(0), 819 + .hw.init = &(const struct clk_init_data) { 820 + .name = "disp_cc_mdss_vsync_clk", 821 + .parent_hws = (const struct clk_hw*[]) { 822 + &disp_cc_mdss_vsync_clk_src.clkr.hw, 823 + }, 824 + .num_parents = 1, 825 + .flags = CLK_SET_RATE_PARENT, 826 + .ops = &clk_branch2_ops, 827 + }, 828 + }, 829 + }; 830 + 831 + static struct gdsc disp_cc_mdss_core_gdsc = { 832 + .gdscr = 0x9000, 833 + .en_rest_wait_val = 0x2, 834 + .en_few_wait_val = 0x2, 835 + .clk_dis_wait_val = 0xf, 836 + .pd = { 837 + .name = "disp_cc_mdss_core_gdsc", 838 + }, 839 + .pwrsts = PWRSTS_OFF_ON, 840 + .flags = POLL_CFG_GDSCR | HW_CTRL | RETAIN_FF_ENABLE, 841 + }; 842 + 843 + static struct gdsc disp_cc_mdss_core_int2_gdsc = { 844 + .gdscr = 0xb000, 845 + .en_rest_wait_val = 0x2, 846 + .en_few_wait_val = 0x2, 847 + .clk_dis_wait_val = 0xf, 848 + .pd = { 849 + .name = "disp_cc_mdss_core_int2_gdsc", 850 + }, 851 + .pwrsts = PWRSTS_OFF_ON, 852 + .flags = POLL_CFG_GDSCR | HW_CTRL | RETAIN_FF_ENABLE, 853 + }; 854 + 855 + static struct clk_regmap *disp_cc_milos_clocks[] = { 856 + [DISP_CC_MDSS_ACCU_CLK] = &disp_cc_mdss_accu_clk.clkr, 857 + [DISP_CC_MDSS_AHB1_CLK] = &disp_cc_mdss_ahb1_clk.clkr, 858 + [DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr, 859 + [DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr, 860 + [DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr, 861 + [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr, 862 + [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr, 863 + [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr, 864 + [DISP_CC_MDSS_DPTX0_AUX_CLK] = &disp_cc_mdss_dptx0_aux_clk.clkr, 865 + [DISP_CC_MDSS_DPTX0_AUX_CLK_SRC] = &disp_cc_mdss_dptx0_aux_clk_src.clkr, 866 + [DISP_CC_MDSS_DPTX0_CRYPTO_CLK] = &disp_cc_mdss_dptx0_crypto_clk.clkr, 867 + [DISP_CC_MDSS_DPTX0_LINK_CLK] = &disp_cc_mdss_dptx0_link_clk.clkr, 868 + [DISP_CC_MDSS_DPTX0_LINK_CLK_SRC] = &disp_cc_mdss_dptx0_link_clk_src.clkr, 869 + [DISP_CC_MDSS_DPTX0_LINK_DIV_CLK_SRC] = &disp_cc_mdss_dptx0_link_div_clk_src.clkr, 870 + [DISP_CC_MDSS_DPTX0_LINK_INTF_CLK] = &disp_cc_mdss_dptx0_link_intf_clk.clkr, 871 + [DISP_CC_MDSS_DPTX0_PIXEL0_CLK] = &disp_cc_mdss_dptx0_pixel0_clk.clkr, 872 + [DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC] = &disp_cc_mdss_dptx0_pixel0_clk_src.clkr, 873 + [DISP_CC_MDSS_DPTX0_PIXEL1_CLK] = &disp_cc_mdss_dptx0_pixel1_clk.clkr, 874 + [DISP_CC_MDSS_DPTX0_PIXEL1_CLK_SRC] = &disp_cc_mdss_dptx0_pixel1_clk_src.clkr, 875 + [DISP_CC_MDSS_DPTX0_USB_ROUTER_LINK_INTF_CLK] = 876 + &disp_cc_mdss_dptx0_usb_router_link_intf_clk.clkr, 877 + [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr, 878 + [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr, 879 + [DISP_CC_MDSS_MDP1_CLK] = &disp_cc_mdss_mdp1_clk.clkr, 880 + [DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr, 881 + [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr, 882 + [DISP_CC_MDSS_MDP_LUT1_CLK] = &disp_cc_mdss_mdp_lut1_clk.clkr, 883 + [DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr, 884 + [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr, 885 + [DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr, 886 + [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr, 887 + [DISP_CC_MDSS_RSCC_AHB_CLK] = &disp_cc_mdss_rscc_ahb_clk.clkr, 888 + [DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp_cc_mdss_rscc_vsync_clk.clkr, 889 + [DISP_CC_MDSS_VSYNC1_CLK] = &disp_cc_mdss_vsync1_clk.clkr, 890 + [DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr, 891 + [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr, 892 + [DISP_CC_PLL0] = &disp_cc_pll0.clkr, 893 + [DISP_CC_SLEEP_CLK_SRC] = &disp_cc_sleep_clk_src.clkr, 894 + [DISP_CC_XO_CLK_SRC] = &disp_cc_xo_clk_src.clkr, 895 + }; 896 + 897 + static const struct qcom_reset_map disp_cc_milos_resets[] = { 898 + [DISP_CC_MDSS_CORE_BCR] = { 0x8000 }, 899 + [DISP_CC_MDSS_CORE_INT2_BCR] = { 0xa000 }, 900 + [DISP_CC_MDSS_RSCC_BCR] = { 0xc000 }, 901 + }; 902 + 903 + static struct gdsc *disp_cc_milos_gdscs[] = { 904 + [DISP_CC_MDSS_CORE_GDSC] = &disp_cc_mdss_core_gdsc, 905 + [DISP_CC_MDSS_CORE_INT2_GDSC] = &disp_cc_mdss_core_int2_gdsc, 906 + }; 907 + 908 + static struct clk_alpha_pll *disp_cc_milos_plls[] = { 909 + &disp_cc_pll0, 910 + }; 911 + 912 + static u32 disp_cc_milos_critical_cbcrs[] = { 913 + 0xe06c, /* DISP_CC_SLEEP_CLK */ 914 + 0xe04c, /* DISP_CC_XO_CLK */ 915 + }; 916 + 917 + static const struct regmap_config disp_cc_milos_regmap_config = { 918 + .reg_bits = 32, 919 + .reg_stride = 4, 920 + .val_bits = 32, 921 + .max_register = 0x11008, 922 + .fast_io = true, 923 + }; 924 + 925 + static void disp_cc_milos_clk_regs_configure(struct device *dev, struct regmap *regmap) 926 + { 927 + /* Enable clock gating for MDP clocks */ 928 + regmap_update_bits(regmap, DISP_CC_MISC_CMD, 0x10, 0x10); 929 + } 930 + 931 + 932 + static struct qcom_cc_driver_data disp_cc_milos_driver_data = { 933 + .alpha_plls = disp_cc_milos_plls, 934 + .num_alpha_plls = ARRAY_SIZE(disp_cc_milos_plls), 935 + .clk_cbcrs = disp_cc_milos_critical_cbcrs, 936 + .num_clk_cbcrs = ARRAY_SIZE(disp_cc_milos_critical_cbcrs), 937 + .clk_regs_configure = disp_cc_milos_clk_regs_configure, 938 + }; 939 + 940 + static struct qcom_cc_desc disp_cc_milos_desc = { 941 + .config = &disp_cc_milos_regmap_config, 942 + .clks = disp_cc_milos_clocks, 943 + .num_clks = ARRAY_SIZE(disp_cc_milos_clocks), 944 + .resets = disp_cc_milos_resets, 945 + .num_resets = ARRAY_SIZE(disp_cc_milos_resets), 946 + .gdscs = disp_cc_milos_gdscs, 947 + .num_gdscs = ARRAY_SIZE(disp_cc_milos_gdscs), 948 + .use_rpm = true, 949 + .driver_data = &disp_cc_milos_driver_data, 950 + }; 951 + 952 + static const struct of_device_id disp_cc_milos_match_table[] = { 953 + { .compatible = "qcom,milos-dispcc" }, 954 + { } 955 + }; 956 + MODULE_DEVICE_TABLE(of, disp_cc_milos_match_table); 957 + 958 + static int disp_cc_milos_probe(struct platform_device *pdev) 959 + { 960 + return qcom_cc_probe(pdev, &disp_cc_milos_desc); 961 + } 962 + 963 + static struct platform_driver disp_cc_milos_driver = { 964 + .probe = disp_cc_milos_probe, 965 + .driver = { 966 + .name = "disp_cc-milos", 967 + .of_match_table = disp_cc_milos_match_table, 968 + }, 969 + }; 970 + 971 + module_platform_driver(disp_cc_milos_driver); 972 + 973 + MODULE_DESCRIPTION("QTI DISP_CC Milos Driver"); 974 + MODULE_LICENSE("GPL");