1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Sophgo SG2042 Clock Generator Driver 4 * 5 * Copyright (C) 2024 Sophgo Technology Inc. 6 * Copyright (C) 2024 Chen Wang <unicorn_wang@outlook.com> 7 */ 8 9 #include <linux/array_size.h> 10 #include <linux/bits.h> 11 #include <linux/clk.h> 12 #include <linux/clk-provider.h> 13 #include <linux/io.h> 14 #include <linux/platform_device.h> 15 #include <asm/div64.h> 16 17 #include <dt-bindings/clock/sophgo,sg2042-clkgen.h> 18 19 #include "clk-sg2042.h" 20 21 /* Registers defined in SYS_CTRL */ 22 #define R_PLL_BEGIN 0xC0 23 #define R_PLL_STAT (0xC0 - R_PLL_BEGIN) 24 #define R_PLL_CLKEN_CONTROL (0xC4 - R_PLL_BEGIN) 25 #define R_MPLL_CONTROL (0xE8 - R_PLL_BEGIN) 26 #define R_FPLL_CONTROL (0xF4 - R_PLL_BEGIN) 27 #define R_DPLL0_CONTROL (0xF8 - R_PLL_BEGIN) 28 #define R_DPLL1_CONTROL (0xFC - R_PLL_BEGIN) 29 30 /* Registers defined in CLOCK */ 31 #define R_CLKENREG0 0x00 32 #define R_CLKENREG1 0x04 33 #define R_CLKSELREG0 0x20 34 #define R_CLKDIVREG0 0x40 35 #define R_CLKDIVREG1 0x44 36 #define R_CLKDIVREG2 0x48 37 #define R_CLKDIVREG3 0x4C 38 #define R_CLKDIVREG4 0x50 39 #define R_CLKDIVREG5 0x54 40 #define R_CLKDIVREG6 0x58 41 #define R_CLKDIVREG7 0x5C 42 #define R_CLKDIVREG8 0x60 43 #define R_CLKDIVREG9 0x64 44 #define R_CLKDIVREG10 0x68 45 #define R_CLKDIVREG11 0x6C 46 #define R_CLKDIVREG12 0x70 47 #define R_CLKDIVREG13 0x74 48 #define R_CLKDIVREG14 0x78 49 #define R_CLKDIVREG15 0x7C 50 #define R_CLKDIVREG16 0x80 51 #define R_CLKDIVREG17 0x84 52 #define R_CLKDIVREG18 0x88 53 #define R_CLKDIVREG19 0x8C 54 #define R_CLKDIVREG20 0x90 55 #define R_CLKDIVREG21 0x94 56 #define R_CLKDIVREG22 0x98 57 #define R_CLKDIVREG23 0x9C 58 #define R_CLKDIVREG24 0xA0 59 #define R_CLKDIVREG25 0xA4 60 #define R_CLKDIVREG26 0xA8 61 #define R_CLKDIVREG27 0xAC 62 #define R_CLKDIVREG28 0xB0 63 #define R_CLKDIVREG29 0xB4 64 #define R_CLKDIVREG30 0xB8 65 66 /* All following shift value are the same for all DIV registers */ 67 #define SHIFT_DIV_RESET_CTRL 0 68 #define SHIFT_DIV_FACTOR_SEL 3 69 #define SHIFT_DIV_FACTOR 16 70 71 /** 72 * struct sg2042_divider_clock - Divider clock 73 * @hw: clk_hw for initialization 74 * @id: used to map clk_onecell_data 75 * @reg: used for readl/writel. 76 * **NOTE**: DIV registers are ALL in CLOCK! 77 * @lock: spinlock to protect register access, modification of 78 * frequency can only be served one at the time 79 * @offset_ctrl: offset of divider control registers 80 * @shift: shift of "Clock Divider Factor" in divider control register 81 * @width: width of "Clock Divider Factor" in divider control register 82 * @div_flags: private flags for this clock, not for framework-specific 83 * @initval: In the divider control register, we can configure whether 84 * to use the value of "Clock Divider Factor" or just use 85 * the initial value pre-configured by IC. BIT[3] controls 86 * this and by default (value is 0), means initial value 87 * is used. 88 * **NOTE** that we cannot read the initial value (default 89 * value when poweron) and default value of "Clock Divider 90 * Factor" is zero, which I think is a hardware design flaw 91 * and should be sync-ed with the initial value. So in 92 * software we have to add a configuration item (initval) 93 * to manually configure this value and use it when BIT[3] 94 * is zero. 95 */ 96 struct sg2042_divider_clock { 97 struct clk_hw hw; 98 99 unsigned int id; 100 101 void __iomem *reg; 102 /* protect register access */ 103 spinlock_t *lock; 104 105 u32 offset_ctrl; 106 u8 shift; 107 u8 width; 108 u8 div_flags; 109 u32 initval; 110 }; 111 112 #define to_sg2042_clk_divider(_hw) \ 113 container_of(_hw, struct sg2042_divider_clock, hw) 114 115 /** 116 * struct sg2042_gate_clock - Gate clock 117 * @hw: clk_hw for initialization 118 * @id: used to map clk_onecell_data 119 * @offset_enable: offset of gate enable registers 120 * @bit_idx: which bit in the register controls gating of this clock 121 */ 122 struct sg2042_gate_clock { 123 struct clk_hw hw; 124 125 unsigned int id; 126 127 u32 offset_enable; 128 u8 bit_idx; 129 }; 130 131 /** 132 * struct sg2042_mux_clock - Mux clock 133 * @hw: clk_hw for initialization 134 * @id: used to map clk_onecell_data 135 * @offset_select: offset of mux selection registers 136 * **NOTE**: MUX registers are ALL in CLOCK! 137 * @shift: shift of "Clock Select" in mux selection register 138 * @width: width of "Clock Select" in mux selection register 139 * @clk_nb: used for notification 140 * @original_index: set by notifier callback 141 */ 142 struct sg2042_mux_clock { 143 struct clk_hw hw; 144 145 unsigned int id; 146 147 u32 offset_select; 148 u8 shift; 149 u8 width; 150 151 struct notifier_block clk_nb; 152 u8 original_index; 153 }; 154 155 #define to_sg2042_mux_nb(_nb) container_of(_nb, struct sg2042_mux_clock, clk_nb) 156 157 static unsigned long sg2042_clk_divider_recalc_rate(struct clk_hw *hw, 158 unsigned long parent_rate) 159 { 160 struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw); 161 unsigned long ret_rate; 162 u32 val; 163 164 if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) { 165 val = divider->initval; 166 } else { 167 val = readl(divider->reg) >> divider->shift; 168 val &= clk_div_mask(divider->width); 169 } 170 171 ret_rate = divider_recalc_rate(hw, parent_rate, val, NULL, 172 divider->div_flags, divider->width); 173 174 pr_debug("--> %s: divider_recalc_rate: ret_rate = %ld\n", 175 clk_hw_get_name(hw), ret_rate); 176 return ret_rate; 177 } 178 179 static int sg2042_clk_divider_determine_rate(struct clk_hw *hw, 180 struct clk_rate_request *req) 181 { 182 struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw); 183 unsigned long ret_rate; 184 u32 bestdiv; 185 186 /* if read only, just return current value */ 187 if (divider->div_flags & CLK_DIVIDER_READ_ONLY) { 188 if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) { 189 bestdiv = divider->initval; 190 } else { 191 bestdiv = readl(divider->reg) >> divider->shift; 192 bestdiv &= clk_div_mask(divider->width); 193 } 194 ret_rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, bestdiv); 195 } else { 196 ret_rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, NULL, 197 divider->width, divider->div_flags); 198 } 199 200 pr_debug("--> %s: divider_round_rate: val = %ld\n", 201 clk_hw_get_name(hw), ret_rate); 202 req->rate = ret_rate; 203 204 return 0; 205 } 206 207 static int sg2042_clk_divider_set_rate(struct clk_hw *hw, 208 unsigned long rate, 209 unsigned long parent_rate) 210 { 211 struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw); 212 unsigned long flags = 0; 213 u32 val, val2, value; 214 215 value = divider_get_val(rate, parent_rate, NULL, 216 divider->width, divider->div_flags); 217 218 if (divider->lock) 219 spin_lock_irqsave(divider->lock, flags); 220 else 221 __acquire(divider->lock); 222 223 /* 224 * The sequence of clock frequency modification is: 225 * Assert to reset divider. 226 * Modify the value of Clock Divide Factor (and High Wide if needed). 227 * De-assert to restore divided clock with new frequency. 228 */ 229 val = readl(divider->reg); 230 231 /* assert */ 232 val &= ~BIT(SHIFT_DIV_RESET_CTRL); 233 writel(val, divider->reg); 234 235 if (divider->div_flags & CLK_DIVIDER_HIWORD_MASK) { 236 val = clk_div_mask(divider->width) << (divider->shift + 16); 237 } else { 238 val = readl(divider->reg); 239 val &= ~(clk_div_mask(divider->width) << divider->shift); 240 } 241 val |= value << divider->shift; 242 val |= BIT(SHIFT_DIV_FACTOR_SEL); 243 writel(val, divider->reg); 244 val2 = val; 245 246 /* de-assert */ 247 val |= BIT(SHIFT_DIV_RESET_CTRL); 248 writel(val, divider->reg); 249 250 if (divider->lock) 251 spin_unlock_irqrestore(divider->lock, flags); 252 else 253 __release(divider->lock); 254 255 pr_debug("--> %s: divider_set_rate: register val = 0x%x\n", 256 clk_hw_get_name(hw), val2); 257 return 0; 258 } 259 260 static const struct clk_ops sg2042_clk_divider_ops = { 261 .recalc_rate = sg2042_clk_divider_recalc_rate, 262 .determine_rate = sg2042_clk_divider_determine_rate, 263 .set_rate = sg2042_clk_divider_set_rate, 264 }; 265 266 static const struct clk_ops sg2042_clk_divider_ro_ops = { 267 .recalc_rate = sg2042_clk_divider_recalc_rate, 268 .determine_rate = sg2042_clk_divider_determine_rate, 269 }; 270 271 /* 272 * Clock initialization macro naming rules: 273 * FW: use CLK_HW_INIT_FW_NAME 274 * HW: use CLK_HW_INIT_HW 275 * HWS: use CLK_HW_INIT_HWS 276 * RO: means Read-Only 277 */ 278 #define SG2042_DIV_FW(_id, _name, _parent, \ 279 _r_ctrl, _shift, _width, \ 280 _div_flag, _initval) { \ 281 .id = _id, \ 282 .hw.init = CLK_HW_INIT_FW_NAME( \ 283 _name, \ 284 _parent, \ 285 &sg2042_clk_divider_ops, \ 286 0), \ 287 .offset_ctrl = _r_ctrl, \ 288 .shift = _shift, \ 289 .width = _width, \ 290 .div_flags = _div_flag, \ 291 .initval = _initval, \ 292 } 293 294 #define SG2042_DIV_FW_RO(_id, _name, _parent, \ 295 _r_ctrl, _shift, _width, \ 296 _div_flag, _initval) { \ 297 .id = _id, \ 298 .hw.init = CLK_HW_INIT_FW_NAME( \ 299 _name, \ 300 _parent, \ 301 &sg2042_clk_divider_ro_ops, \ 302 0), \ 303 .offset_ctrl = _r_ctrl, \ 304 .shift = _shift, \ 305 .width = _width, \ 306 .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \ 307 .initval = _initval, \ 308 } 309 310 #define SG2042_DIV_HW(_id, _name, _parent, \ 311 _r_ctrl, _shift, _width, \ 312 _div_flag, _initval) { \ 313 .id = _id, \ 314 .hw.init = CLK_HW_INIT_HW( \ 315 _name, \ 316 _parent, \ 317 &sg2042_clk_divider_ops, \ 318 0), \ 319 .offset_ctrl = _r_ctrl, \ 320 .shift = _shift, \ 321 .width = _width, \ 322 .div_flags = _div_flag, \ 323 .initval = _initval, \ 324 } 325 326 #define SG2042_DIV_HW_RO(_id, _name, _parent, \ 327 _r_ctrl, _shift, _width, \ 328 _div_flag, _initval) { \ 329 .id = _id, \ 330 .hw.init = CLK_HW_INIT_HW( \ 331 _name, \ 332 _parent, \ 333 &sg2042_clk_divider_ro_ops, \ 334 0), \ 335 .offset_ctrl = _r_ctrl, \ 336 .shift = _shift, \ 337 .width = _width, \ 338 .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \ 339 .initval = _initval, \ 340 } 341 342 #define SG2042_DIV_HWS(_id, _name, _parent, \ 343 _r_ctrl, _shift, _width, \ 344 _div_flag, _initval) { \ 345 .id = _id, \ 346 .hw.init = CLK_HW_INIT_HWS( \ 347 _name, \ 348 _parent, \ 349 &sg2042_clk_divider_ops, \ 350 0), \ 351 .offset_ctrl = _r_ctrl, \ 352 .shift = _shift, \ 353 .width = _width, \ 354 .div_flags = _div_flag, \ 355 .initval = _initval, \ 356 } 357 358 #define SG2042_DIV_HWS_RO(_id, _name, _parent, \ 359 _r_ctrl, _shift, _width, \ 360 _div_flag, _initval) { \ 361 .id = _id, \ 362 .hw.init = CLK_HW_INIT_HWS( \ 363 _name, \ 364 _parent, \ 365 &sg2042_clk_divider_ro_ops, \ 366 0), \ 367 .offset_ctrl = _r_ctrl, \ 368 .shift = _shift, \ 369 .width = _width, \ 370 .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \ 371 .initval = _initval, \ 372 } 373 374 #define SG2042_GATE_HWS(_id, _name, _parent, _flags, \ 375 _r_enable, _bit_idx) { \ 376 .id = _id, \ 377 .hw.init = CLK_HW_INIT_HWS( \ 378 _name, \ 379 _parent, \ 380 NULL, \ 381 _flags), \ 382 .offset_enable = _r_enable, \ 383 .bit_idx = _bit_idx, \ 384 } 385 386 #define SG2042_GATE_HW(_id, _name, _parent, _flags, \ 387 _r_enable, _bit_idx) { \ 388 .id = _id, \ 389 .hw.init = CLK_HW_INIT_HW( \ 390 _name, \ 391 _parent, \ 392 NULL, \ 393 _flags), \ 394 .offset_enable = _r_enable, \ 395 .bit_idx = _bit_idx, \ 396 } 397 398 #define SG2042_GATE_FW(_id, _name, _parent, _flags, \ 399 _r_enable, _bit_idx) { \ 400 .id = _id, \ 401 .hw.init = CLK_HW_INIT_FW_NAME( \ 402 _name, \ 403 _parent, \ 404 NULL, \ 405 _flags), \ 406 .offset_enable = _r_enable, \ 407 .bit_idx = _bit_idx, \ 408 } 409 410 #define SG2042_MUX(_id, _name, _parents, _flags, _r_select, _shift, _width) { \ 411 .id = _id, \ 412 .hw.init = CLK_HW_INIT_PARENTS_HW( \ 413 _name, \ 414 _parents, \ 415 NULL, \ 416 _flags), \ 417 .offset_select = _r_select, \ 418 .shift = _shift, \ 419 .width = _width, \ 420 } 421 422 /* 423 * Clock items in the array are sorted according to the clock-tree diagram, 424 * from top to bottom, from upstream to downstream. Read TRM for details. 425 */ 426 427 /* updated during probe/registration */ 428 static const struct clk_hw *clk_gate_ddr01_div0[] = { NULL }; 429 static const struct clk_hw *clk_gate_ddr01_div1[] = { NULL }; 430 static const struct clk_hw *clk_gate_ddr23_div0[] = { NULL }; 431 static const struct clk_hw *clk_gate_ddr23_div1[] = { NULL }; 432 static const struct clk_hw *clk_gate_rp_cpu_normal_div0[] = { NULL }; 433 static const struct clk_hw *clk_gate_rp_cpu_normal_div1[] = { NULL }; 434 static const struct clk_hw *clk_gate_axi_ddr_div0[] = { NULL }; 435 static const struct clk_hw *clk_gate_axi_ddr_div1[] = { NULL }; 436 437 static const struct sg2042_gate_clock sg2042_gate_clks_level_1[] = { 438 SG2042_GATE_FW(GATE_CLK_DDR01_DIV0, "clk_gate_ddr01_div0", "dpll0", 439 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 440 R_CLKDIVREG27, 4), 441 SG2042_GATE_FW(GATE_CLK_DDR01_DIV1, "clk_gate_ddr01_div1", "fpll", 442 CLK_IS_CRITICAL, 443 R_CLKDIVREG28, 4), 444 445 SG2042_GATE_FW(GATE_CLK_DDR23_DIV0, "clk_gate_ddr23_div0", "dpll1", 446 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 447 R_CLKDIVREG29, 4), 448 SG2042_GATE_FW(GATE_CLK_DDR23_DIV1, "clk_gate_ddr23_div1", "fpll", 449 CLK_IS_CRITICAL, 450 R_CLKDIVREG30, 4), 451 452 SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV0, 453 "clk_gate_rp_cpu_normal_div0", "mpll", 454 CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 455 R_CLKDIVREG0, 4), 456 SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV1, 457 "clk_gate_rp_cpu_normal_div1", "fpll", 458 CLK_IS_CRITICAL, 459 R_CLKDIVREG1, 4), 460 461 SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV0, "clk_gate_axi_ddr_div0", "mpll", 462 CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 463 R_CLKDIVREG25, 4), 464 SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV1, "clk_gate_axi_ddr_div1", "fpll", 465 CLK_IS_CRITICAL, 466 R_CLKDIVREG26, 4), 467 }; 468 469 #define DEF_DIVFLAG (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO) 470 471 static struct sg2042_divider_clock sg2042_div_clks_level_1[] = { 472 SG2042_DIV_HWS_RO(DIV_CLK_DPLL0_DDR01_0, 473 "clk_div_ddr01_0", clk_gate_ddr01_div0, 474 R_CLKDIVREG27, 16, 5, DEF_DIVFLAG, 1), 475 SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR01_1, 476 "clk_div_ddr01_1", clk_gate_ddr01_div1, 477 R_CLKDIVREG28, 16, 5, DEF_DIVFLAG, 1), 478 479 SG2042_DIV_HWS_RO(DIV_CLK_DPLL1_DDR23_0, 480 "clk_div_ddr23_0", clk_gate_ddr23_div0, 481 R_CLKDIVREG29, 16, 5, DEF_DIVFLAG, 1), 482 SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR23_1, 483 "clk_div_ddr23_1", clk_gate_ddr23_div1, 484 R_CLKDIVREG30, 16, 5, DEF_DIVFLAG, 1), 485 486 SG2042_DIV_HWS(DIV_CLK_MPLL_RP_CPU_NORMAL_0, 487 "clk_div_rp_cpu_normal_0", clk_gate_rp_cpu_normal_div0, 488 R_CLKDIVREG0, 16, 5, DEF_DIVFLAG, 1), 489 SG2042_DIV_HWS(DIV_CLK_FPLL_RP_CPU_NORMAL_1, 490 "clk_div_rp_cpu_normal_1", clk_gate_rp_cpu_normal_div1, 491 R_CLKDIVREG1, 16, 5, DEF_DIVFLAG, 1), 492 493 SG2042_DIV_HWS(DIV_CLK_MPLL_AXI_DDR_0, 494 "clk_div_axi_ddr_0", clk_gate_axi_ddr_div0, 495 R_CLKDIVREG25, 16, 5, DEF_DIVFLAG, 2), 496 SG2042_DIV_HWS(DIV_CLK_FPLL_AXI_DDR_1, 497 "clk_div_axi_ddr_1", clk_gate_axi_ddr_div1, 498 R_CLKDIVREG26, 16, 5, DEF_DIVFLAG, 1), 499 }; 500 501 /* 502 * Note: regarding names for mux clock, "0/1" or "div0/div1" means the 503 * first/second parent input source, not the register value. 504 * For example: 505 * "clk_div_ddr01_0" is the name of Clock divider 0 control of DDR01, and 506 * "clk_gate_ddr01_div0" is the gate clock in front of the "clk_div_ddr01_0", 507 * they are both controlled by register CLKDIVREG27; 508 * "clk_div_ddr01_1" is the name of Clock divider 1 control of DDR01, and 509 * "clk_gate_ddr01_div1" is the gate clock in front of the "clk_div_ddr01_1", 510 * they are both controlled by register CLKDIVREG28; 511 * While for register value of mux selection, use Clock Select for DDR01’s clock 512 * as example, see CLKSELREG0, bit[2]. 513 * 1: Select in_dpll0_clk as clock source, correspondng to the parent input 514 * source from "clk_div_ddr01_0". 515 * 0: Select in_fpll_clk as clock source, corresponding to the parent input 516 * source from "clk_div_ddr01_1". 517 * So we need a table to define the array of register values corresponding to 518 * the parent index and tell CCF about this when registering mux clock. 519 */ 520 static const u32 sg2042_mux_table[] = {1, 0}; 521 522 /* Aliases just for easy reading */ 523 #define clk_div_ddr01_0 (&sg2042_div_clks_level_1[0].hw) 524 #define clk_div_ddr01_1 (&sg2042_div_clks_level_1[1].hw) 525 #define clk_div_ddr23_0 (&sg2042_div_clks_level_1[2].hw) 526 #define clk_div_ddr23_1 (&sg2042_div_clks_level_1[3].hw) 527 #define clk_div_rp_cpu_normal_0 (&sg2042_div_clks_level_1[4].hw) 528 #define clk_div_rp_cpu_normal_1 (&sg2042_div_clks_level_1[5].hw) 529 #define clk_div_axi_ddr_0 (&sg2042_div_clks_level_1[6].hw) 530 #define clk_div_axi_ddr_1 (&sg2042_div_clks_level_1[7].hw) 531 532 static const struct clk_hw *clk_mux_ddr01_p[] = { 533 clk_div_ddr01_0, 534 clk_div_ddr01_1, 535 }; 536 537 static const struct clk_hw *clk_mux_ddr23_p[] = { 538 clk_div_ddr23_0, 539 clk_div_ddr23_1, 540 }; 541 542 static const struct clk_hw *clk_mux_rp_cpu_normal_p[] = { 543 clk_div_rp_cpu_normal_0, 544 clk_div_rp_cpu_normal_1, 545 }; 546 547 static const struct clk_hw *clk_mux_axi_ddr_p[] = { 548 clk_div_axi_ddr_0, 549 clk_div_axi_ddr_1, 550 }; 551 552 /* Mux clocks to be updated during probe/registration */ 553 static const struct clk_hw *clk_mux_ddr01[] = { NULL }; 554 static const struct clk_hw *clk_mux_ddr23[] = { NULL }; 555 static const struct clk_hw *clk_mux_rp_cpu_normal[] = { NULL }; 556 static const struct clk_hw *clk_mux_axi_ddr[] = { NULL }; 557 558 static struct sg2042_mux_clock sg2042_mux_clks[] = { 559 SG2042_MUX(MUX_CLK_DDR01, "clk_mux_ddr01", clk_mux_ddr01_p, 560 CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY, 561 R_CLKSELREG0, 2, 1), 562 SG2042_MUX(MUX_CLK_DDR23, "clk_mux_ddr23", clk_mux_ddr23_p, 563 CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY, 564 R_CLKSELREG0, 3, 1), 565 SG2042_MUX(MUX_CLK_RP_CPU_NORMAL, "clk_mux_rp_cpu_normal", clk_mux_rp_cpu_normal_p, 566 CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 567 R_CLKSELREG0, 0, 1), 568 SG2042_MUX(MUX_CLK_AXI_DDR, "clk_mux_axi_ddr", clk_mux_axi_ddr_p, 569 CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 570 R_CLKSELREG0, 1, 1), 571 }; 572 573 /* Aliases just for easy reading */ 574 #define clk_div_top_rp_cmn_div2 (&sg2042_div_clks_level_2[0].hw) 575 #define clk_div_50m_a53 (&sg2042_div_clks_level_2[1].hw) 576 #define clk_div_timer1 (&sg2042_div_clks_level_2[2].hw) 577 #define clk_div_timer2 (&sg2042_div_clks_level_2[3].hw) 578 #define clk_div_timer3 (&sg2042_div_clks_level_2[4].hw) 579 #define clk_div_timer4 (&sg2042_div_clks_level_2[5].hw) 580 #define clk_div_timer5 (&sg2042_div_clks_level_2[6].hw) 581 #define clk_div_timer6 (&sg2042_div_clks_level_2[7].hw) 582 #define clk_div_timer7 (&sg2042_div_clks_level_2[8].hw) 583 #define clk_div_timer8 (&sg2042_div_clks_level_2[9].hw) 584 #define clk_div_uart_500m (&sg2042_div_clks_level_2[10].hw) 585 #define clk_div_ahb_lpc (&sg2042_div_clks_level_2[11].hw) 586 #define clk_div_efuse (&sg2042_div_clks_level_2[12].hw) 587 #define clk_div_tx_eth0 (&sg2042_div_clks_level_2[13].hw) 588 #define clk_div_ptp_ref_i_eth0 (&sg2042_div_clks_level_2[14].hw) 589 #define clk_div_ref_eth0 (&sg2042_div_clks_level_2[15].hw) 590 #define clk_div_emmc (&sg2042_div_clks_level_2[16].hw) 591 #define clk_div_sd (&sg2042_div_clks_level_2[17].hw) 592 #define clk_div_top_axi0 (&sg2042_div_clks_level_2[18].hw) 593 #define clk_div_100k_emmc (&sg2042_div_clks_level_2[19].hw) 594 #define clk_div_100k_sd (&sg2042_div_clks_level_2[20].hw) 595 #define clk_div_gpio_db (&sg2042_div_clks_level_2[21].hw) 596 #define clk_div_top_axi_hsperi (&sg2042_div_clks_level_2[22].hw) 597 598 static struct sg2042_divider_clock sg2042_div_clks_level_2[] = { 599 SG2042_DIV_HWS(DIV_CLK_FPLL_TOP_RP_CMN_DIV2, 600 "clk_div_top_rp_cmn_div2", clk_mux_rp_cpu_normal, 601 R_CLKDIVREG3, 16, 16, DEF_DIVFLAG, 2), 602 603 SG2042_DIV_FW(DIV_CLK_FPLL_50M_A53, "clk_div_50m_a53", "fpll", 604 R_CLKDIVREG2, 16, 8, DEF_DIVFLAG, 20), 605 /* downstream of div_50m_a53 */ 606 SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER1, "clk_div_timer1", clk_div_50m_a53, 607 R_CLKDIVREG6, 16, 16, DEF_DIVFLAG, 1), 608 SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER2, "clk_div_timer2", clk_div_50m_a53, 609 R_CLKDIVREG7, 16, 16, DEF_DIVFLAG, 1), 610 SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER3, "clk_div_timer3", clk_div_50m_a53, 611 R_CLKDIVREG8, 16, 16, DEF_DIVFLAG, 1), 612 SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER4, "clk_div_timer4", clk_div_50m_a53, 613 R_CLKDIVREG9, 16, 16, DEF_DIVFLAG, 1), 614 SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER5, "clk_div_timer5", clk_div_50m_a53, 615 R_CLKDIVREG10, 16, 16, DEF_DIVFLAG, 1), 616 SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER6, "clk_div_timer6", clk_div_50m_a53, 617 R_CLKDIVREG11, 16, 16, DEF_DIVFLAG, 1), 618 SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER7, "clk_div_timer7", clk_div_50m_a53, 619 R_CLKDIVREG12, 16, 16, DEF_DIVFLAG, 1), 620 SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER8, "clk_div_timer8", clk_div_50m_a53, 621 R_CLKDIVREG13, 16, 16, DEF_DIVFLAG, 1), 622 623 /* 624 * Set clk_div_uart_500m as RO, because the width of CLKDIVREG4 is too 625 * narrow for us to produce 115200. Use UART internal divider directly. 626 */ 627 SG2042_DIV_FW_RO(DIV_CLK_FPLL_UART_500M, "clk_div_uart_500m", "fpll", 628 R_CLKDIVREG4, 16, 7, DEF_DIVFLAG, 2), 629 SG2042_DIV_FW(DIV_CLK_FPLL_AHB_LPC, "clk_div_ahb_lpc", "fpll", 630 R_CLKDIVREG5, 16, 16, DEF_DIVFLAG, 5), 631 SG2042_DIV_FW(DIV_CLK_FPLL_EFUSE, "clk_div_efuse", "fpll", 632 R_CLKDIVREG14, 16, 7, DEF_DIVFLAG, 40), 633 SG2042_DIV_FW(DIV_CLK_FPLL_TX_ETH0, "clk_div_tx_eth0", "fpll", 634 R_CLKDIVREG16, 16, 11, DEF_DIVFLAG, 8), 635 SG2042_DIV_FW(DIV_CLK_FPLL_PTP_REF_I_ETH0, 636 "clk_div_ptp_ref_i_eth0", "fpll", 637 R_CLKDIVREG17, 16, 8, DEF_DIVFLAG, 20), 638 SG2042_DIV_FW(DIV_CLK_FPLL_REF_ETH0, "clk_div_ref_eth0", "fpll", 639 R_CLKDIVREG18, 16, 8, DEF_DIVFLAG, 40), 640 SG2042_DIV_FW(DIV_CLK_FPLL_EMMC, "clk_div_emmc", "fpll", 641 R_CLKDIVREG19, 16, 5, DEF_DIVFLAG, 10), 642 SG2042_DIV_FW(DIV_CLK_FPLL_SD, "clk_div_sd", "fpll", 643 R_CLKDIVREG21, 16, 5, DEF_DIVFLAG, 10), 644 645 SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI0, "clk_div_top_axi0", "fpll", 646 R_CLKDIVREG23, 16, 5, DEF_DIVFLAG, 10), 647 /* downstream of div_top_axi0 */ 648 SG2042_DIV_HW(DIV_CLK_FPLL_100K_EMMC, "clk_div_100k_emmc", clk_div_top_axi0, 649 R_CLKDIVREG20, 16, 16, DEF_DIVFLAG, 1000), 650 SG2042_DIV_HW(DIV_CLK_FPLL_100K_SD, "clk_div_100k_sd", clk_div_top_axi0, 651 R_CLKDIVREG22, 16, 16, DEF_DIVFLAG, 1000), 652 SG2042_DIV_HW(DIV_CLK_FPLL_GPIO_DB, "clk_div_gpio_db", clk_div_top_axi0, 653 R_CLKDIVREG15, 16, 16, DEF_DIVFLAG, 1000), 654 655 SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI_HSPERI, 656 "clk_div_top_axi_hsperi", "fpll", 657 R_CLKDIVREG24, 16, 5, DEF_DIVFLAG, 4), 658 }; 659 660 /* Gate clocks to be updated during probe/registration */ 661 static const struct clk_hw *clk_gate_rp_cpu_normal[] = { NULL }; 662 static const struct clk_hw *clk_gate_top_rp_cmn_div2[] = { NULL }; 663 664 static const struct sg2042_gate_clock sg2042_gate_clks_level_2[] = { 665 SG2042_GATE_HWS(GATE_CLK_DDR01, "clk_gate_ddr01", clk_mux_ddr01, 666 CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 667 R_CLKENREG1, 14), 668 669 SG2042_GATE_HWS(GATE_CLK_DDR23, "clk_gate_ddr23", clk_mux_ddr23, 670 CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 671 R_CLKENREG1, 15), 672 673 SG2042_GATE_HWS(GATE_CLK_RP_CPU_NORMAL, 674 "clk_gate_rp_cpu_normal", clk_mux_rp_cpu_normal, 675 CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 676 R_CLKENREG0, 0), 677 678 SG2042_GATE_HWS(GATE_CLK_AXI_DDR, "clk_gate_axi_ddr", clk_mux_axi_ddr, 679 CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 680 R_CLKENREG1, 13), 681 682 /* upon are gate clocks directly downstream of muxes */ 683 684 /* downstream of clk_div_top_rp_cmn_div2 */ 685 SG2042_GATE_HW(GATE_CLK_TOP_RP_CMN_DIV2, 686 "clk_gate_top_rp_cmn_div2", clk_div_top_rp_cmn_div2, 687 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 2), 688 SG2042_GATE_HWS(GATE_CLK_HSDMA, "clk_gate_hsdma", clk_gate_top_rp_cmn_div2, 689 CLK_SET_RATE_PARENT, R_CLKENREG1, 10), 690 691 /* 692 * downstream of clk_gate_rp_cpu_normal 693 * 694 * FIXME: there should be one 1/2 DIV between clk_gate_rp_cpu_normal 695 * and clk_gate_axi_pcie0/clk_gate_axi_pcie1. 696 * But the 1/2 DIV is fixed and no configurable register exported, so 697 * when reading from these two clocks, the rate value are still the 698 * same as that of clk_gate_rp_cpu_normal, it's not correct. 699 * This just affects the value read. 700 */ 701 SG2042_GATE_HWS(GATE_CLK_AXI_PCIE0, 702 "clk_gate_axi_pcie0", clk_gate_rp_cpu_normal, 703 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 8), 704 SG2042_GATE_HWS(GATE_CLK_AXI_PCIE1, 705 "clk_gate_axi_pcie1", clk_gate_rp_cpu_normal, 706 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 9), 707 708 /* downstream of div_50m_a53 */ 709 SG2042_GATE_HW(GATE_CLK_A53_50M, "clk_gate_a53_50m", clk_div_50m_a53, 710 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 1), 711 SG2042_GATE_HW(GATE_CLK_TIMER1, "clk_gate_timer1", clk_div_timer1, 712 CLK_SET_RATE_PARENT, R_CLKENREG0, 12), 713 SG2042_GATE_HW(GATE_CLK_TIMER2, "clk_gate_timer2", clk_div_timer2, 714 CLK_SET_RATE_PARENT, R_CLKENREG0, 13), 715 SG2042_GATE_HW(GATE_CLK_TIMER3, "clk_gate_timer3", clk_div_timer3, 716 CLK_SET_RATE_PARENT, R_CLKENREG0, 14), 717 SG2042_GATE_HW(GATE_CLK_TIMER4, "clk_gate_timer4", clk_div_timer4, 718 CLK_SET_RATE_PARENT, R_CLKENREG0, 15), 719 SG2042_GATE_HW(GATE_CLK_TIMER5, "clk_gate_timer5", clk_div_timer5, 720 CLK_SET_RATE_PARENT, R_CLKENREG0, 16), 721 SG2042_GATE_HW(GATE_CLK_TIMER6, "clk_gate_timer6", clk_div_timer6, 722 CLK_SET_RATE_PARENT, R_CLKENREG0, 17), 723 SG2042_GATE_HW(GATE_CLK_TIMER7, "clk_gate_timer7", clk_div_timer7, 724 CLK_SET_RATE_PARENT, R_CLKENREG0, 18), 725 SG2042_GATE_HW(GATE_CLK_TIMER8, "clk_gate_timer8", clk_div_timer8, 726 CLK_SET_RATE_PARENT, R_CLKENREG0, 19), 727 728 /* gate clocks downstream from div clocks one-to-one */ 729 SG2042_GATE_HW(GATE_CLK_UART_500M, "clk_gate_uart_500m", clk_div_uart_500m, 730 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 4), 731 SG2042_GATE_HW(GATE_CLK_AHB_LPC, "clk_gate_ahb_lpc", clk_div_ahb_lpc, 732 CLK_SET_RATE_PARENT, R_CLKENREG0, 7), 733 SG2042_GATE_HW(GATE_CLK_EFUSE, "clk_gate_efuse", clk_div_efuse, 734 CLK_SET_RATE_PARENT, R_CLKENREG0, 20), 735 SG2042_GATE_HW(GATE_CLK_TX_ETH0, "clk_gate_tx_eth0", clk_div_tx_eth0, 736 CLK_SET_RATE_PARENT, R_CLKENREG0, 30), 737 SG2042_GATE_HW(GATE_CLK_PTP_REF_I_ETH0, 738 "clk_gate_ptp_ref_i_eth0", clk_div_ptp_ref_i_eth0, 739 CLK_SET_RATE_PARENT, R_CLKENREG1, 0), 740 SG2042_GATE_HW(GATE_CLK_REF_ETH0, "clk_gate_ref_eth0", clk_div_ref_eth0, 741 CLK_SET_RATE_PARENT, R_CLKENREG1, 1), 742 SG2042_GATE_HW(GATE_CLK_EMMC_100M, "clk_gate_emmc", clk_div_emmc, 743 CLK_SET_RATE_PARENT, R_CLKENREG1, 3), 744 SG2042_GATE_HW(GATE_CLK_SD_100M, "clk_gate_sd", clk_div_sd, 745 CLK_SET_RATE_PARENT, R_CLKENREG1, 6), 746 747 /* downstream of clk_div_top_axi0 */ 748 SG2042_GATE_HW(GATE_CLK_AHB_ROM, "clk_gate_ahb_rom", clk_div_top_axi0, 749 0, R_CLKENREG0, 8), 750 SG2042_GATE_HW(GATE_CLK_AHB_SF, "clk_gate_ahb_sf", clk_div_top_axi0, 751 0, R_CLKENREG0, 9), 752 SG2042_GATE_HW(GATE_CLK_AXI_SRAM, "clk_gate_axi_sram", clk_div_top_axi0, 753 CLK_IGNORE_UNUSED, R_CLKENREG0, 10), 754 SG2042_GATE_HW(GATE_CLK_APB_TIMER, "clk_gate_apb_timer", clk_div_top_axi0, 755 CLK_IGNORE_UNUSED, R_CLKENREG0, 11), 756 SG2042_GATE_HW(GATE_CLK_APB_EFUSE, "clk_gate_apb_efuse", clk_div_top_axi0, 757 0, R_CLKENREG0, 21), 758 SG2042_GATE_HW(GATE_CLK_APB_GPIO, "clk_gate_apb_gpio", clk_div_top_axi0, 759 0, R_CLKENREG0, 22), 760 SG2042_GATE_HW(GATE_CLK_APB_GPIO_INTR, 761 "clk_gate_apb_gpio_intr", clk_div_top_axi0, 762 CLK_IS_CRITICAL, R_CLKENREG0, 23), 763 SG2042_GATE_HW(GATE_CLK_APB_I2C, "clk_gate_apb_i2c", clk_div_top_axi0, 764 0, R_CLKENREG0, 26), 765 SG2042_GATE_HW(GATE_CLK_APB_WDT, "clk_gate_apb_wdt", clk_div_top_axi0, 766 0, R_CLKENREG0, 27), 767 SG2042_GATE_HW(GATE_CLK_APB_PWM, "clk_gate_apb_pwm", clk_div_top_axi0, 768 0, R_CLKENREG0, 28), 769 SG2042_GATE_HW(GATE_CLK_APB_RTC, "clk_gate_apb_rtc", clk_div_top_axi0, 770 0, R_CLKENREG0, 29), 771 SG2042_GATE_HW(GATE_CLK_TOP_AXI0, "clk_gate_top_axi0", clk_div_top_axi0, 772 CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 773 R_CLKENREG1, 11), 774 /* downstream of DIV clocks which are sourced from clk_div_top_axi0 */ 775 SG2042_GATE_HW(GATE_CLK_GPIO_DB, "clk_gate_gpio_db", clk_div_gpio_db, 776 CLK_SET_RATE_PARENT, R_CLKENREG0, 24), 777 SG2042_GATE_HW(GATE_CLK_100K_EMMC, "clk_gate_100k_emmc", clk_div_100k_emmc, 778 CLK_SET_RATE_PARENT, R_CLKENREG1, 4), 779 SG2042_GATE_HW(GATE_CLK_100K_SD, "clk_gate_100k_sd", clk_div_100k_sd, 780 CLK_SET_RATE_PARENT, R_CLKENREG1, 7), 781 782 /* downstream of clk_div_top_axi_hsperi */ 783 SG2042_GATE_HW(GATE_CLK_SYSDMA_AXI, 784 "clk_gate_sysdma_axi", clk_div_top_axi_hsperi, 785 CLK_SET_RATE_PARENT, R_CLKENREG0, 3), 786 SG2042_GATE_HW(GATE_CLK_APB_UART, 787 "clk_gate_apb_uart", clk_div_top_axi_hsperi, 788 CLK_SET_RATE_PARENT, R_CLKENREG0, 5), 789 SG2042_GATE_HW(GATE_CLK_AXI_DBG_I2C, 790 "clk_gate_axi_dbg_i2c", clk_div_top_axi_hsperi, 791 CLK_SET_RATE_PARENT, R_CLKENREG0, 6), 792 SG2042_GATE_HW(GATE_CLK_APB_SPI, 793 "clk_gate_apb_spi", clk_div_top_axi_hsperi, 794 CLK_SET_RATE_PARENT, R_CLKENREG0, 25), 795 SG2042_GATE_HW(GATE_CLK_AXI_ETH0, 796 "clk_gate_axi_eth0", clk_div_top_axi_hsperi, 797 CLK_SET_RATE_PARENT, R_CLKENREG0, 31), 798 SG2042_GATE_HW(GATE_CLK_AXI_EMMC, 799 "clk_gate_axi_emmc", clk_div_top_axi_hsperi, 800 CLK_SET_RATE_PARENT, R_CLKENREG1, 2), 801 SG2042_GATE_HW(GATE_CLK_AXI_SD, 802 "clk_gate_axi_sd", clk_div_top_axi_hsperi, 803 CLK_SET_RATE_PARENT, R_CLKENREG1, 5), 804 SG2042_GATE_HW(GATE_CLK_TOP_AXI_HSPERI, 805 "clk_gate_top_axi_hsperi", clk_div_top_axi_hsperi, 806 CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 807 R_CLKENREG1, 12), 808 }; 809 810 static DEFINE_SPINLOCK(sg2042_clk_lock); 811 812 static int sg2042_clk_register_divs(struct device *dev, 813 struct sg2042_clk_data *clk_data, 814 struct sg2042_divider_clock div_clks[], 815 int num_div_clks) 816 { 817 struct sg2042_divider_clock *div; 818 struct clk_hw *hw; 819 int i, ret = 0; 820 821 for (i = 0; i < num_div_clks; i++) { 822 div = &div_clks[i]; 823 824 if (div->div_flags & CLK_DIVIDER_HIWORD_MASK) { 825 if (div->width + div->shift > 16) { 826 pr_warn("divider value exceeds LOWORD field\n"); 827 ret = -EINVAL; 828 break; 829 } 830 } 831 832 div->reg = clk_data->iobase + div->offset_ctrl; 833 div->lock = &sg2042_clk_lock; 834 835 hw = &div->hw; 836 ret = devm_clk_hw_register(dev, hw); 837 if (ret) { 838 pr_err("failed to register clock %s\n", div->hw.init->name); 839 break; 840 } 841 842 clk_data->onecell_data.hws[div->id] = hw; 843 } 844 845 return ret; 846 } 847 848 static int sg2042_clk_register_gates(struct device *dev, 849 struct sg2042_clk_data *clk_data, 850 const struct sg2042_gate_clock gate_clks[], 851 int num_gate_clks) 852 { 853 const struct sg2042_gate_clock *gate; 854 struct clk_hw *hw; 855 int i, ret = 0; 856 857 for (i = 0; i < num_gate_clks; i++) { 858 gate = &gate_clks[i]; 859 hw = __devm_clk_hw_register_gate 860 (dev, 861 NULL, 862 gate->hw.init->name, 863 NULL, 864 gate->hw.init->parent_hws[0], 865 NULL, 866 gate->hw.init->flags, 867 clk_data->iobase + gate->offset_enable, 868 gate->bit_idx, 869 0, 870 &sg2042_clk_lock); 871 if (IS_ERR(hw)) { 872 pr_err("failed to register clock %s\n", gate->hw.init->name); 873 ret = PTR_ERR(hw); 874 break; 875 } 876 877 clk_data->onecell_data.hws[gate->id] = hw; 878 879 /* Updated some clocks which take the role of parent */ 880 switch (gate->id) { 881 case GATE_CLK_RP_CPU_NORMAL: 882 *clk_gate_rp_cpu_normal = hw; 883 break; 884 case GATE_CLK_TOP_RP_CMN_DIV2: 885 *clk_gate_top_rp_cmn_div2 = hw; 886 break; 887 } 888 } 889 890 return ret; 891 } 892 893 static int sg2042_clk_register_gates_fw(struct device *dev, 894 struct sg2042_clk_data *clk_data, 895 const struct sg2042_gate_clock gate_clks[], 896 int num_gate_clks) 897 { 898 const struct sg2042_gate_clock *gate; 899 struct clk_hw *hw; 900 int i, ret = 0; 901 902 for (i = 0; i < num_gate_clks; i++) { 903 gate = &gate_clks[i]; 904 hw = devm_clk_hw_register_gate_parent_data 905 (dev, 906 gate->hw.init->name, 907 gate->hw.init->parent_data, 908 gate->hw.init->flags, 909 clk_data->iobase + gate->offset_enable, 910 gate->bit_idx, 911 0, 912 &sg2042_clk_lock); 913 if (IS_ERR(hw)) { 914 pr_err("failed to register clock %s\n", gate->hw.init->name); 915 ret = PTR_ERR(hw); 916 break; 917 } 918 919 clk_data->onecell_data.hws[gate->id] = hw; 920 921 /* Updated some clocks which take the role of parent */ 922 switch (gate->id) { 923 case GATE_CLK_DDR01_DIV0: 924 *clk_gate_ddr01_div0 = hw; 925 break; 926 case GATE_CLK_DDR01_DIV1: 927 *clk_gate_ddr01_div1 = hw; 928 break; 929 case GATE_CLK_DDR23_DIV0: 930 *clk_gate_ddr23_div0 = hw; 931 break; 932 case GATE_CLK_DDR23_DIV1: 933 *clk_gate_ddr23_div1 = hw; 934 break; 935 case GATE_CLK_RP_CPU_NORMAL_DIV0: 936 *clk_gate_rp_cpu_normal_div0 = hw; 937 break; 938 case GATE_CLK_RP_CPU_NORMAL_DIV1: 939 *clk_gate_rp_cpu_normal_div1 = hw; 940 break; 941 case GATE_CLK_AXI_DDR_DIV0: 942 *clk_gate_axi_ddr_div0 = hw; 943 break; 944 case GATE_CLK_AXI_DDR_DIV1: 945 *clk_gate_axi_ddr_div1 = hw; 946 break; 947 } 948 } 949 950 return ret; 951 } 952 953 static int sg2042_mux_notifier_cb(struct notifier_block *nb, 954 unsigned long event, 955 void *data) 956 { 957 struct sg2042_mux_clock *mux = to_sg2042_mux_nb(nb); 958 const struct clk_ops *ops = &clk_mux_ops; 959 struct clk_notifier_data *ndata = data; 960 struct clk_hw *hw; 961 int ret = 0; 962 963 hw = __clk_get_hw(ndata->clk); 964 965 /* To switch to fpll before changing rate and restore after that */ 966 if (event == PRE_RATE_CHANGE) { 967 mux->original_index = ops->get_parent(hw); 968 969 /* 970 * "1" is the array index of the second parent input source of 971 * mux. For SG2042, it's fpll for all mux clocks. 972 * "0" is the array index of the first parent input source of 973 * mux, For SG2042, it's mpll. 974 * FIXME, any good idea to avoid magic number? 975 */ 976 if (mux->original_index == 0) 977 ret = ops->set_parent(hw, 1); 978 } else if (event == POST_RATE_CHANGE) { 979 ret = ops->set_parent(hw, mux->original_index); 980 } 981 982 return notifier_from_errno(ret); 983 } 984 985 static int sg2042_clk_register_muxs(struct device *dev, 986 struct sg2042_clk_data *clk_data, 987 struct sg2042_mux_clock mux_clks[], 988 int num_mux_clks) 989 { 990 struct sg2042_mux_clock *mux; 991 struct clk_hw *hw; 992 int i, ret = 0; 993 994 for (i = 0; i < num_mux_clks; i++) { 995 mux = &mux_clks[i]; 996 997 hw = __devm_clk_hw_register_mux 998 (dev, 999 NULL, 1000 mux->hw.init->name, 1001 mux->hw.init->num_parents, 1002 NULL, 1003 mux->hw.init->parent_hws, 1004 NULL, 1005 mux->hw.init->flags, 1006 clk_data->iobase + mux->offset_select, 1007 mux->shift, 1008 BIT(mux->width) - 1, 1009 0, 1010 sg2042_mux_table, 1011 &sg2042_clk_lock); 1012 if (IS_ERR(hw)) { 1013 pr_err("failed to register clock %s\n", mux->hw.init->name); 1014 ret = PTR_ERR(hw); 1015 break; 1016 } 1017 1018 clk_data->onecell_data.hws[mux->id] = hw; 1019 1020 /* Updated some clocks which takes the role of parent */ 1021 switch (mux->id) { 1022 case MUX_CLK_DDR01: 1023 *clk_mux_ddr01 = hw; 1024 break; 1025 case MUX_CLK_DDR23: 1026 *clk_mux_ddr23 = hw; 1027 break; 1028 case MUX_CLK_RP_CPU_NORMAL: 1029 *clk_mux_rp_cpu_normal = hw; 1030 break; 1031 case MUX_CLK_AXI_DDR: 1032 *clk_mux_axi_ddr = hw; 1033 break; 1034 } 1035 1036 /* 1037 * FIXME: Theoretically, we should set parent for the 1038 * mux, but seems hardware has done this for us with 1039 * default value, so we don't set parent again here. 1040 */ 1041 1042 if (!(mux->hw.init->flags & CLK_MUX_READ_ONLY)) { 1043 mux->clk_nb.notifier_call = sg2042_mux_notifier_cb; 1044 ret = devm_clk_notifier_register(dev, hw->clk, &mux->clk_nb); 1045 if (ret) { 1046 pr_err("failed to register clock notifier for %s\n", 1047 mux->hw.init->name); 1048 break; 1049 } 1050 } 1051 } 1052 1053 return ret; 1054 } 1055 1056 static int sg2042_init_clkdata(struct platform_device *pdev, 1057 int num_clks, 1058 struct sg2042_clk_data **pp_clk_data) 1059 { 1060 struct sg2042_clk_data *clk_data = NULL; 1061 1062 clk_data = devm_kzalloc(&pdev->dev, 1063 struct_size(clk_data, onecell_data.hws, num_clks), 1064 GFP_KERNEL); 1065 if (!clk_data) 1066 return -ENOMEM; 1067 1068 clk_data->iobase = devm_platform_ioremap_resource(pdev, 0); 1069 if (WARN_ON(IS_ERR(clk_data->iobase))) 1070 return PTR_ERR(clk_data->iobase); 1071 1072 clk_data->onecell_data.num = num_clks; 1073 1074 *pp_clk_data = clk_data; 1075 1076 return 0; 1077 } 1078 1079 static int sg2042_clkgen_probe(struct platform_device *pdev) 1080 { 1081 struct sg2042_clk_data *clk_data = NULL; 1082 int num_clks; 1083 int ret; 1084 1085 num_clks = ARRAY_SIZE(sg2042_div_clks_level_1) + 1086 ARRAY_SIZE(sg2042_div_clks_level_2) + 1087 ARRAY_SIZE(sg2042_gate_clks_level_1) + 1088 ARRAY_SIZE(sg2042_gate_clks_level_2) + 1089 ARRAY_SIZE(sg2042_mux_clks); 1090 1091 ret = sg2042_init_clkdata(pdev, num_clks, &clk_data); 1092 if (ret) 1093 goto error_out; 1094 1095 /* level-1 gates */ 1096 ret = sg2042_clk_register_gates_fw(&pdev->dev, clk_data, 1097 sg2042_gate_clks_level_1, 1098 ARRAY_SIZE(sg2042_gate_clks_level_1)); 1099 if (ret) 1100 goto error_out; 1101 1102 /* level-1 div */ 1103 ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_1, 1104 ARRAY_SIZE(sg2042_div_clks_level_1)); 1105 if (ret) 1106 goto error_out; 1107 1108 /* mux */ 1109 ret = sg2042_clk_register_muxs(&pdev->dev, clk_data, sg2042_mux_clks, 1110 ARRAY_SIZE(sg2042_mux_clks)); 1111 if (ret) 1112 goto error_out; 1113 1114 /* level 2 div */ 1115 ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_2, 1116 ARRAY_SIZE(sg2042_div_clks_level_2)); 1117 if (ret) 1118 goto error_out; 1119 1120 /* level 2 gate */ 1121 ret = sg2042_clk_register_gates(&pdev->dev, clk_data, sg2042_gate_clks_level_2, 1122 ARRAY_SIZE(sg2042_gate_clks_level_2)); 1123 if (ret) 1124 goto error_out; 1125 1126 return devm_of_clk_add_hw_provider(&pdev->dev, 1127 of_clk_hw_onecell_get, 1128 &clk_data->onecell_data); 1129 1130 error_out: 1131 pr_err("%s failed error number %d\n", __func__, ret); 1132 return ret; 1133 } 1134 1135 static const struct of_device_id sg2042_clkgen_match[] = { 1136 { .compatible = "sophgo,sg2042-clkgen" }, 1137 { /* sentinel */ } 1138 }; 1139 MODULE_DEVICE_TABLE(of, sg2042_clkgen_match); 1140 1141 static struct platform_driver sg2042_clkgen_driver = { 1142 .probe = sg2042_clkgen_probe, 1143 .driver = { 1144 .name = "clk-sophgo-sg2042-clkgen", 1145 .of_match_table = sg2042_clkgen_match, 1146 .suppress_bind_attrs = true, 1147 }, 1148 }; 1149 module_platform_driver(sg2042_clkgen_driver); 1150 1151 MODULE_AUTHOR("Chen Wang"); 1152 MODULE_DESCRIPTION("Sophgo SG2042 clock generator driver"); 1153 MODULE_LICENSE("GPL"); 1154