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