| 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* |
| 3 | * Copyright (C) 2013 DENX Software Engineering |
| 4 | * |
| 5 | * Gerhard Sittig, <gsi@denx.de> |
| 6 | * |
| 7 | * common clock driver support for the MPC512x platform |
| 8 | */ |
| 9 | |
| 10 | #include <linux/bitops.h> |
| 11 | #include <linux/clk.h> |
| 12 | #include <linux/clk-provider.h> |
| 13 | #include <linux/clkdev.h> |
| 14 | #include <linux/device.h> |
| 15 | #include <linux/errno.h> |
| 16 | #include <linux/io.h> |
| 17 | #include <linux/of.h> |
| 18 | #include <linux/of_address.h> |
| 19 | |
| 20 | #include <asm/mpc5121.h> |
| 21 | #include <dt-bindings/clock/mpc512x-clock.h> |
| 22 | |
| 23 | #include "mpc512x.h" /* our public mpc5121_clk_init() API */ |
| 24 | |
| 25 | /* helpers to keep the MCLK intermediates "somewhere" in our table */ |
| 26 | enum { |
| 27 | MCLK_IDX_MUX0, |
| 28 | MCLK_IDX_EN0, |
| 29 | MCLK_IDX_DIV0, |
| 30 | MCLK_MAX_IDX, |
| 31 | }; |
| 32 | |
| 33 | #define NR_PSCS 12 |
| 34 | #define NR_MSCANS 4 |
| 35 | #define NR_SPDIFS 1 |
| 36 | #define NR_OUTCLK 4 |
| 37 | #define NR_MCLKS (NR_PSCS + NR_MSCANS + NR_SPDIFS + NR_OUTCLK) |
| 38 | |
| 39 | /* extend the public set of clocks by adding internal slots for management */ |
| 40 | enum { |
| 41 | /* arrange for adjacent numbers after the public set */ |
| 42 | MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC, |
| 43 | /* clocks which aren't announced to the public */ |
| 44 | MPC512x_CLK_DDR, |
| 45 | MPC512x_CLK_MEM, |
| 46 | MPC512x_CLK_IIM, |
| 47 | /* intermediates in div+gate combos or fractional dividers */ |
| 48 | MPC512x_CLK_DDR_UG, |
| 49 | MPC512x_CLK_SDHC_x4, |
| 50 | MPC512x_CLK_SDHC_UG, |
| 51 | MPC512x_CLK_SDHC2_UG, |
| 52 | MPC512x_CLK_DIU_x4, |
| 53 | MPC512x_CLK_DIU_UG, |
| 54 | MPC512x_CLK_MBX_BUS_UG, |
| 55 | MPC512x_CLK_MBX_UG, |
| 56 | MPC512x_CLK_MBX_3D_UG, |
| 57 | MPC512x_CLK_PCI_UG, |
| 58 | MPC512x_CLK_NFC_UG, |
| 59 | MPC512x_CLK_LPC_UG, |
| 60 | MPC512x_CLK_SPDIF_TX_IN, |
| 61 | /* intermediates for the mux+gate+div+mux MCLK generation */ |
| 62 | MPC512x_CLK_MCLKS_FIRST, |
| 63 | MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST |
| 64 | + NR_MCLKS * MCLK_MAX_IDX, |
| 65 | /* internal, symbolic spec for the number of slots */ |
| 66 | MPC512x_CLK_LAST_PRIVATE, |
| 67 | }; |
| 68 | |
| 69 | /* data required for the OF clock provider registration */ |
| 70 | static struct clk *clks[MPC512x_CLK_LAST_PRIVATE]; |
| 71 | static struct clk_onecell_data clk_data; |
| 72 | |
| 73 | /* CCM register access */ |
| 74 | static struct mpc512x_ccm __iomem *clkregs; |
| 75 | static DEFINE_SPINLOCK(clklock); |
| 76 | |
| 77 | /* SoC variants {{{ */ |
| 78 | |
| 79 | /* |
| 80 | * tell SoC variants apart as they are rather similar yet not identical, |
| 81 | * cache the result in an enum to not repeatedly run the expensive OF test |
| 82 | * |
| 83 | * MPC5123 is an MPC5121 without the MBX graphics accelerator |
| 84 | * |
| 85 | * MPC5125 has many more differences: no MBX, no AXE, no VIU, no SPDIF, |
| 86 | * no PATA, no SATA, no PCI, two FECs (of different compatibility name), |
| 87 | * only 10 PSCs (of different compatibility name), two SDHCs, different |
| 88 | * NFC IP block, output clocks, system PLL status query, different CPMF |
| 89 | * interpretation, no CFM, different fourth PSC/CAN mux0 input -- yet |
| 90 | * those differences can get folded into this clock provider support |
| 91 | * code and don't warrant a separate highly redundant implementation |
| 92 | */ |
| 93 | |
| 94 | static enum soc_type { |
| 95 | MPC512x_SOC_MPC5121, |
| 96 | MPC512x_SOC_MPC5123, |
| 97 | MPC512x_SOC_MPC5125, |
| 98 | } soc; |
| 99 | |
| 100 | static void __init mpc512x_clk_determine_soc(void) |
| 101 | { |
| 102 | if (of_machine_is_compatible(compat: "fsl,mpc5121" )) { |
| 103 | soc = MPC512x_SOC_MPC5121; |
| 104 | return; |
| 105 | } |
| 106 | if (of_machine_is_compatible(compat: "fsl,mpc5123" )) { |
| 107 | soc = MPC512x_SOC_MPC5123; |
| 108 | return; |
| 109 | } |
| 110 | if (of_machine_is_compatible(compat: "fsl,mpc5125" )) { |
| 111 | soc = MPC512x_SOC_MPC5125; |
| 112 | return; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | static bool __init soc_has_mbx(void) |
| 117 | { |
| 118 | if (soc == MPC512x_SOC_MPC5121) |
| 119 | return true; |
| 120 | return false; |
| 121 | } |
| 122 | |
| 123 | static bool __init soc_has_axe(void) |
| 124 | { |
| 125 | if (soc == MPC512x_SOC_MPC5125) |
| 126 | return false; |
| 127 | return true; |
| 128 | } |
| 129 | |
| 130 | static bool __init soc_has_viu(void) |
| 131 | { |
| 132 | if (soc == MPC512x_SOC_MPC5125) |
| 133 | return false; |
| 134 | return true; |
| 135 | } |
| 136 | |
| 137 | static bool __init soc_has_spdif(void) |
| 138 | { |
| 139 | if (soc == MPC512x_SOC_MPC5125) |
| 140 | return false; |
| 141 | return true; |
| 142 | } |
| 143 | |
| 144 | static bool __init soc_has_pata(void) |
| 145 | { |
| 146 | if (soc == MPC512x_SOC_MPC5125) |
| 147 | return false; |
| 148 | return true; |
| 149 | } |
| 150 | |
| 151 | static bool __init soc_has_sata(void) |
| 152 | { |
| 153 | if (soc == MPC512x_SOC_MPC5125) |
| 154 | return false; |
| 155 | return true; |
| 156 | } |
| 157 | |
| 158 | static bool __init soc_has_pci(void) |
| 159 | { |
| 160 | if (soc == MPC512x_SOC_MPC5125) |
| 161 | return false; |
| 162 | return true; |
| 163 | } |
| 164 | |
| 165 | static bool __init soc_has_fec2(void) |
| 166 | { |
| 167 | if (soc == MPC512x_SOC_MPC5125) |
| 168 | return true; |
| 169 | return false; |
| 170 | } |
| 171 | |
| 172 | static int __init soc_max_pscnum(void) |
| 173 | { |
| 174 | if (soc == MPC512x_SOC_MPC5125) |
| 175 | return 10; |
| 176 | return 12; |
| 177 | } |
| 178 | |
| 179 | static bool __init soc_has_sdhc2(void) |
| 180 | { |
| 181 | if (soc == MPC512x_SOC_MPC5125) |
| 182 | return true; |
| 183 | return false; |
| 184 | } |
| 185 | |
| 186 | static bool __init soc_has_nfc_5125(void) |
| 187 | { |
| 188 | if (soc == MPC512x_SOC_MPC5125) |
| 189 | return true; |
| 190 | return false; |
| 191 | } |
| 192 | |
| 193 | static bool __init soc_has_outclk(void) |
| 194 | { |
| 195 | if (soc == MPC512x_SOC_MPC5125) |
| 196 | return true; |
| 197 | return false; |
| 198 | } |
| 199 | |
| 200 | static bool __init soc_has_cpmf_0_bypass(void) |
| 201 | { |
| 202 | if (soc == MPC512x_SOC_MPC5125) |
| 203 | return true; |
| 204 | return false; |
| 205 | } |
| 206 | |
| 207 | static bool __init soc_has_mclk_mux0_canin(void) |
| 208 | { |
| 209 | if (soc == MPC512x_SOC_MPC5125) |
| 210 | return true; |
| 211 | return false; |
| 212 | } |
| 213 | |
| 214 | /* }}} SoC variants */ |
| 215 | /* common clk API wrappers {{{ */ |
| 216 | |
| 217 | /* convenience wrappers around the common clk API */ |
| 218 | static inline struct clk *mpc512x_clk_fixed(const char *name, int rate) |
| 219 | { |
| 220 | return clk_register_fixed_rate(NULL, name, NULL, flags: 0, fixed_rate: rate); |
| 221 | } |
| 222 | |
| 223 | static inline struct clk *mpc512x_clk_factor( |
| 224 | const char *name, const char *parent_name, |
| 225 | int mul, int div) |
| 226 | { |
| 227 | int clkflags; |
| 228 | |
| 229 | clkflags = CLK_SET_RATE_PARENT; |
| 230 | return clk_register_fixed_factor(NULL, name, parent_name, flags: clkflags, |
| 231 | mult: mul, div); |
| 232 | } |
| 233 | |
| 234 | static inline struct clk *mpc512x_clk_divider( |
| 235 | const char *name, const char *parent_name, u8 clkflags, |
| 236 | u32 __iomem *reg, u8 pos, u8 len, int divflags) |
| 237 | { |
| 238 | divflags |= CLK_DIVIDER_BIG_ENDIAN; |
| 239 | return clk_register_divider(NULL, name, parent_name, clkflags, |
| 240 | reg, pos, len, divflags, &clklock); |
| 241 | } |
| 242 | |
| 243 | static inline struct clk *mpc512x_clk_divtable( |
| 244 | const char *name, const char *parent_name, |
| 245 | u32 __iomem *reg, u8 pos, u8 len, |
| 246 | const struct clk_div_table *divtab) |
| 247 | { |
| 248 | u8 divflags; |
| 249 | |
| 250 | divflags = CLK_DIVIDER_BIG_ENDIAN; |
| 251 | return clk_register_divider_table(NULL, name, parent_name, flags: 0, |
| 252 | reg, shift: pos, width: len, clk_divider_flags: divflags, |
| 253 | table: divtab, lock: &clklock); |
| 254 | } |
| 255 | |
| 256 | static inline struct clk *mpc512x_clk_gated( |
| 257 | const char *name, const char *parent_name, |
| 258 | u32 __iomem *reg, u8 pos) |
| 259 | { |
| 260 | int clkflags; |
| 261 | u8 gateflags; |
| 262 | |
| 263 | clkflags = CLK_SET_RATE_PARENT; |
| 264 | gateflags = CLK_GATE_BIG_ENDIAN; |
| 265 | return clk_register_gate(NULL, name, parent_name, flags: clkflags, |
| 266 | reg, bit_idx: pos, clk_gate_flags: gateflags, lock: &clklock); |
| 267 | } |
| 268 | |
| 269 | static inline struct clk *mpc512x_clk_muxed(const char *name, |
| 270 | const char **parent_names, int parent_count, |
| 271 | u32 __iomem *reg, u8 pos, u8 len) |
| 272 | { |
| 273 | int clkflags; |
| 274 | u8 muxflags; |
| 275 | |
| 276 | clkflags = CLK_SET_RATE_PARENT; |
| 277 | muxflags = CLK_MUX_BIG_ENDIAN; |
| 278 | return clk_register_mux(NULL, name, |
| 279 | parent_names, parent_count, clkflags, |
| 280 | reg, pos, len, muxflags, &clklock); |
| 281 | } |
| 282 | |
| 283 | /* }}} common clk API wrappers */ |
| 284 | |
| 285 | /* helper to isolate a bit field from a register */ |
| 286 | static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len) |
| 287 | { |
| 288 | uint32_t val; |
| 289 | |
| 290 | val = in_be32(reg); |
| 291 | val >>= pos; |
| 292 | val &= (1 << len) - 1; |
| 293 | return val; |
| 294 | } |
| 295 | |
| 296 | /* get the SPMF and translate it into the "sys pll" multiplier */ |
| 297 | static int __init get_spmf_mult(void) |
| 298 | { |
| 299 | static int spmf_to_mult[] = { |
| 300 | 68, 1, 12, 16, 20, 24, 28, 32, |
| 301 | 36, 40, 44, 48, 52, 56, 60, 64, |
| 302 | }; |
| 303 | int spmf; |
| 304 | |
| 305 | spmf = get_bit_field(reg: &clkregs->spmr, pos: 24, len: 4); |
| 306 | return spmf_to_mult[spmf]; |
| 307 | } |
| 308 | |
| 309 | /* |
| 310 | * get the SYS_DIV value and translate it into a divide factor |
| 311 | * |
| 312 | * values returned from here are a multiple of the real factor since the |
| 313 | * divide ratio is fractional |
| 314 | */ |
| 315 | static int __init get_sys_div_x2(void) |
| 316 | { |
| 317 | static int sysdiv_code_to_x2[] = { |
| 318 | 4, 5, 6, 7, 8, 9, 10, 14, |
| 319 | 12, 16, 18, 22, 20, 24, 26, 30, |
| 320 | 28, 32, 34, 38, 36, 40, 42, 46, |
| 321 | 44, 48, 50, 54, 52, 56, 58, 62, |
| 322 | 60, 64, 66, |
| 323 | }; |
| 324 | int divcode; |
| 325 | |
| 326 | divcode = get_bit_field(reg: &clkregs->scfr2, pos: 26, len: 6); |
| 327 | return sysdiv_code_to_x2[divcode]; |
| 328 | } |
| 329 | |
| 330 | /* |
| 331 | * get the CPMF value and translate it into a multiplier factor |
| 332 | * |
| 333 | * values returned from here are a multiple of the real factor since the |
| 334 | * multiplier ratio is fractional |
| 335 | */ |
| 336 | static int __init get_cpmf_mult_x2(void) |
| 337 | { |
| 338 | static int cpmf_to_mult_x36[] = { |
| 339 | /* 0b000 is "times 36" */ |
| 340 | 72, 2, 2, 3, 4, 5, 6, 7, |
| 341 | }; |
| 342 | static int cpmf_to_mult_0by[] = { |
| 343 | /* 0b000 is "bypass" */ |
| 344 | 2, 2, 2, 3, 4, 5, 6, 7, |
| 345 | }; |
| 346 | |
| 347 | int *cpmf_to_mult; |
| 348 | int cpmf; |
| 349 | |
| 350 | cpmf = get_bit_field(reg: &clkregs->spmr, pos: 16, len: 4); |
| 351 | if (soc_has_cpmf_0_bypass()) |
| 352 | cpmf_to_mult = cpmf_to_mult_0by; |
| 353 | else |
| 354 | cpmf_to_mult = cpmf_to_mult_x36; |
| 355 | return cpmf_to_mult[cpmf]; |
| 356 | } |
| 357 | |
| 358 | /* |
| 359 | * some of the clock dividers do scale in a linear way, yet not all of |
| 360 | * their bit combinations are legal; use a divider table to get a |
| 361 | * resulting set of applicable divider values |
| 362 | */ |
| 363 | |
| 364 | /* applies to the IPS_DIV, and PCI_DIV values */ |
| 365 | static const struct clk_div_table divtab_2346[] = { |
| 366 | { .val = 2, .div = 2, }, |
| 367 | { .val = 3, .div = 3, }, |
| 368 | { .val = 4, .div = 4, }, |
| 369 | { .val = 6, .div = 6, }, |
| 370 | { .div = 0, }, |
| 371 | }; |
| 372 | |
| 373 | /* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */ |
| 374 | static const struct clk_div_table divtab_1234[] = { |
| 375 | { .val = 1, .div = 1, }, |
| 376 | { .val = 2, .div = 2, }, |
| 377 | { .val = 3, .div = 3, }, |
| 378 | { .val = 4, .div = 4, }, |
| 379 | { .div = 0, }, |
| 380 | }; |
| 381 | |
| 382 | static int __init get_freq_from_dt(char *propname) |
| 383 | { |
| 384 | struct device_node *np; |
| 385 | const unsigned int *prop; |
| 386 | int val; |
| 387 | |
| 388 | val = 0; |
| 389 | np = of_find_compatible_node(NULL, NULL, compat: "fsl,mpc5121-immr" ); |
| 390 | if (np) { |
| 391 | prop = of_get_property(node: np, name: propname, NULL); |
| 392 | if (prop) |
| 393 | val = *prop; |
| 394 | of_node_put(node: np); |
| 395 | } |
| 396 | return val; |
| 397 | } |
| 398 | |
| 399 | static void __init mpc512x_clk_preset_data(void) |
| 400 | { |
| 401 | size_t i; |
| 402 | |
| 403 | for (i = 0; i < ARRAY_SIZE(clks); i++) |
| 404 | clks[i] = ERR_PTR(error: -ENODEV); |
| 405 | } |
| 406 | |
| 407 | /* |
| 408 | * - receives the "bus frequency" from the caller (that's the IPS clock |
| 409 | * rate, the historical source of clock information) |
| 410 | * - fetches the system PLL multiplier and divider values as well as the |
| 411 | * IPS divider value from hardware |
| 412 | * - determines the REF clock rate either from the XTAL/OSC spec (if |
| 413 | * there is a device tree node describing the oscillator) or from the |
| 414 | * IPS bus clock (supported for backwards compatibility, such that |
| 415 | * setups without XTAL/OSC specs keep working) |
| 416 | * - creates the "ref" clock item in the clock tree, such that |
| 417 | * subsequent code can create the remainder of the hierarchy (REF -> |
| 418 | * SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div |
| 419 | * values |
| 420 | */ |
| 421 | static void __init mpc512x_clk_setup_ref_clock(struct device_node *np, int bus_freq, |
| 422 | int *sys_mul, int *sys_div, |
| 423 | int *ips_div) |
| 424 | { |
| 425 | struct clk *osc_clk; |
| 426 | int calc_freq; |
| 427 | |
| 428 | /* fetch mul/div factors from the hardware */ |
| 429 | *sys_mul = get_spmf_mult(); |
| 430 | *sys_mul *= 2; /* compensate for the fractional divider */ |
| 431 | *sys_div = get_sys_div_x2(); |
| 432 | *ips_div = get_bit_field(reg: &clkregs->scfr1, pos: 23, len: 3); |
| 433 | |
| 434 | /* lookup the oscillator clock for its rate */ |
| 435 | osc_clk = of_clk_get_by_name(np, name: "osc" ); |
| 436 | |
| 437 | /* |
| 438 | * either descend from OSC to REF (and in bypassing verify the |
| 439 | * IPS rate), or backtrack from IPS and multiplier values that |
| 440 | * were fetched from hardware to REF and thus to the OSC value |
| 441 | * |
| 442 | * in either case the REF clock gets created here and the |
| 443 | * remainder of the clock tree can get spanned from there |
| 444 | */ |
| 445 | if (!IS_ERR(ptr: osc_clk)) { |
| 446 | clks[MPC512x_CLK_REF] = mpc512x_clk_factor(name: "ref" , parent_name: "osc" , mul: 1, div: 1); |
| 447 | calc_freq = clk_get_rate(clk: clks[MPC512x_CLK_REF]); |
| 448 | calc_freq *= *sys_mul; |
| 449 | calc_freq /= *sys_div; |
| 450 | calc_freq /= 2; |
| 451 | calc_freq /= *ips_div; |
| 452 | if (bus_freq && calc_freq != bus_freq) |
| 453 | pr_warn("calc rate %d != OF spec %d\n" , |
| 454 | calc_freq, bus_freq); |
| 455 | } else { |
| 456 | calc_freq = bus_freq; /* start with IPS */ |
| 457 | calc_freq *= *ips_div; /* IPS -> CSB */ |
| 458 | calc_freq *= 2; /* CSB -> SYS */ |
| 459 | calc_freq *= *sys_div; /* SYS -> PLL out */ |
| 460 | calc_freq /= *sys_mul; /* PLL out -> REF == OSC */ |
| 461 | clks[MPC512x_CLK_REF] = mpc512x_clk_fixed(name: "ref" , rate: calc_freq); |
| 462 | } |
| 463 | } |
| 464 | |
| 465 | /* MCLK helpers {{{ */ |
| 466 | |
| 467 | /* |
| 468 | * helper code for the MCLK subtree setup |
| 469 | * |
| 470 | * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4 |
| 471 | * suggests that all instances of the "PSC clock generation" are equal, |
| 472 | * and that one might re-use the PSC setup for MSCAN clock generation |
| 473 | * (section 5.2.5) as well, at least the logic if not the data for |
| 474 | * description |
| 475 | * |
| 476 | * the details (starting at page 5-20) show differences in the specific |
| 477 | * inputs of the first mux stage ("can clk in", "spdif tx"), and the |
| 478 | * factual non-availability of the second mux stage (it's present yet |
| 479 | * only one input is valid) |
| 480 | * |
| 481 | * the MSCAN clock related registers (starting at page 5-35) all |
| 482 | * reference "spdif clk" at the first mux stage and don't mention any |
| 483 | * "can clk" at all, which somehow is unexpected |
| 484 | * |
| 485 | * TODO re-check the document, and clarify whether the RM is correct in |
| 486 | * the overview or in the details, and whether the difference is a |
| 487 | * clipboard induced error or results from chip revisions |
| 488 | * |
| 489 | * it turns out that the RM rev4 as of 2012-06 talks about "can" for the |
| 490 | * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that |
| 491 | * first a doc update is required which better reflects reality in the |
| 492 | * SoC before the implementation should follow while no questions remain |
| 493 | */ |
| 494 | |
| 495 | /* |
| 496 | * note that this declaration raises a checkpatch warning, but |
| 497 | * it's the very data type dictated by <linux/clk-provider.h>, |
| 498 | * "fixing" this warning will break compilation |
| 499 | */ |
| 500 | static const char *parent_names_mux0_spdif[] = { |
| 501 | "sys" , "ref" , "psc-mclk-in" , "spdif-tx" , |
| 502 | }; |
| 503 | |
| 504 | static const char *parent_names_mux0_canin[] = { |
| 505 | "sys" , "ref" , "psc-mclk-in" , "can-clk-in" , |
| 506 | }; |
| 507 | |
| 508 | enum mclk_type { |
| 509 | MCLK_TYPE_PSC, |
| 510 | MCLK_TYPE_MSCAN, |
| 511 | MCLK_TYPE_SPDIF, |
| 512 | MCLK_TYPE_OUTCLK, |
| 513 | }; |
| 514 | |
| 515 | struct mclk_setup_data { |
| 516 | enum mclk_type type; |
| 517 | bool has_mclk1; |
| 518 | const char *name_mux0; |
| 519 | const char *name_en0; |
| 520 | const char *name_div0; |
| 521 | const char *parent_names_mux1[2]; |
| 522 | const char *name_mclk; |
| 523 | }; |
| 524 | |
| 525 | #define MCLK_SETUP_DATA_PSC(id) { \ |
| 526 | MCLK_TYPE_PSC, 0, \ |
| 527 | "psc" #id "-mux0", \ |
| 528 | "psc" #id "-en0", \ |
| 529 | "psc" #id "_mclk_div", \ |
| 530 | { "psc" #id "_mclk_div", "dummy", }, \ |
| 531 | "psc" #id "_mclk", \ |
| 532 | } |
| 533 | |
| 534 | #define MCLK_SETUP_DATA_MSCAN(id) { \ |
| 535 | MCLK_TYPE_MSCAN, 0, \ |
| 536 | "mscan" #id "-mux0", \ |
| 537 | "mscan" #id "-en0", \ |
| 538 | "mscan" #id "_mclk_div", \ |
| 539 | { "mscan" #id "_mclk_div", "dummy", }, \ |
| 540 | "mscan" #id "_mclk", \ |
| 541 | } |
| 542 | |
| 543 | #define MCLK_SETUP_DATA_SPDIF { \ |
| 544 | MCLK_TYPE_SPDIF, 1, \ |
| 545 | "spdif-mux0", \ |
| 546 | "spdif-en0", \ |
| 547 | "spdif_mclk_div", \ |
| 548 | { "spdif_mclk_div", "spdif-rx", }, \ |
| 549 | "spdif_mclk", \ |
| 550 | } |
| 551 | |
| 552 | #define MCLK_SETUP_DATA_OUTCLK(id) { \ |
| 553 | MCLK_TYPE_OUTCLK, 0, \ |
| 554 | "out" #id "-mux0", \ |
| 555 | "out" #id "-en0", \ |
| 556 | "out" #id "_mclk_div", \ |
| 557 | { "out" #id "_mclk_div", "dummy", }, \ |
| 558 | "out" #id "_clk", \ |
| 559 | } |
| 560 | |
| 561 | static struct mclk_setup_data mclk_psc_data[] = { |
| 562 | MCLK_SETUP_DATA_PSC(0), |
| 563 | MCLK_SETUP_DATA_PSC(1), |
| 564 | MCLK_SETUP_DATA_PSC(2), |
| 565 | MCLK_SETUP_DATA_PSC(3), |
| 566 | MCLK_SETUP_DATA_PSC(4), |
| 567 | MCLK_SETUP_DATA_PSC(5), |
| 568 | MCLK_SETUP_DATA_PSC(6), |
| 569 | MCLK_SETUP_DATA_PSC(7), |
| 570 | MCLK_SETUP_DATA_PSC(8), |
| 571 | MCLK_SETUP_DATA_PSC(9), |
| 572 | MCLK_SETUP_DATA_PSC(10), |
| 573 | MCLK_SETUP_DATA_PSC(11), |
| 574 | }; |
| 575 | |
| 576 | static struct mclk_setup_data mclk_mscan_data[] = { |
| 577 | MCLK_SETUP_DATA_MSCAN(0), |
| 578 | MCLK_SETUP_DATA_MSCAN(1), |
| 579 | MCLK_SETUP_DATA_MSCAN(2), |
| 580 | MCLK_SETUP_DATA_MSCAN(3), |
| 581 | }; |
| 582 | |
| 583 | static struct mclk_setup_data mclk_spdif_data[] = { |
| 584 | MCLK_SETUP_DATA_SPDIF, |
| 585 | }; |
| 586 | |
| 587 | static struct mclk_setup_data mclk_outclk_data[] = { |
| 588 | MCLK_SETUP_DATA_OUTCLK(0), |
| 589 | MCLK_SETUP_DATA_OUTCLK(1), |
| 590 | MCLK_SETUP_DATA_OUTCLK(2), |
| 591 | MCLK_SETUP_DATA_OUTCLK(3), |
| 592 | }; |
| 593 | |
| 594 | /* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */ |
| 595 | static void __init mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx) |
| 596 | { |
| 597 | size_t clks_idx_pub, clks_idx_int; |
| 598 | u32 __iomem *mccr_reg; /* MCLK control register (mux, en, div) */ |
| 599 | int div; |
| 600 | |
| 601 | /* derive a few parameters from the component type and index */ |
| 602 | switch (entry->type) { |
| 603 | case MCLK_TYPE_PSC: |
| 604 | clks_idx_pub = MPC512x_CLK_PSC0_MCLK + idx; |
| 605 | clks_idx_int = MPC512x_CLK_MCLKS_FIRST |
| 606 | + (idx) * MCLK_MAX_IDX; |
| 607 | mccr_reg = &clkregs->psc_ccr[idx]; |
| 608 | break; |
| 609 | case MCLK_TYPE_MSCAN: |
| 610 | clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + idx; |
| 611 | clks_idx_int = MPC512x_CLK_MCLKS_FIRST |
| 612 | + (NR_PSCS + idx) * MCLK_MAX_IDX; |
| 613 | mccr_reg = &clkregs->mscan_ccr[idx]; |
| 614 | break; |
| 615 | case MCLK_TYPE_SPDIF: |
| 616 | clks_idx_pub = MPC512x_CLK_SPDIF_MCLK; |
| 617 | clks_idx_int = MPC512x_CLK_MCLKS_FIRST |
| 618 | + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX; |
| 619 | mccr_reg = &clkregs->spccr; |
| 620 | break; |
| 621 | case MCLK_TYPE_OUTCLK: |
| 622 | clks_idx_pub = MPC512x_CLK_OUT0_CLK + idx; |
| 623 | clks_idx_int = MPC512x_CLK_MCLKS_FIRST |
| 624 | + (NR_PSCS + NR_MSCANS + NR_SPDIFS + idx) |
| 625 | * MCLK_MAX_IDX; |
| 626 | mccr_reg = &clkregs->out_ccr[idx]; |
| 627 | break; |
| 628 | default: |
| 629 | return; |
| 630 | } |
| 631 | |
| 632 | /* |
| 633 | * this was grabbed from the PPC_CLOCK implementation, which |
| 634 | * enforced a specific MCLK divider while the clock was gated |
| 635 | * during setup (that's a documented hardware requirement) |
| 636 | * |
| 637 | * the PPC_CLOCK implementation might even have violated the |
| 638 | * "MCLK <= IPS" constraint, the fixed divider value of 1 |
| 639 | * results in a divider of 2 and thus MCLK = SYS/2 which equals |
| 640 | * CSB which is greater than IPS; the serial port setup may have |
| 641 | * adjusted the divider which the clock setup might have left in |
| 642 | * an undesirable state |
| 643 | * |
| 644 | * initial setup is: |
| 645 | * - MCLK 0 from SYS |
| 646 | * - MCLK DIV such to not exceed the IPS clock |
| 647 | * - MCLK 0 enabled |
| 648 | * - MCLK 1 from MCLK DIV |
| 649 | */ |
| 650 | div = clk_get_rate(clk: clks[MPC512x_CLK_SYS]); |
| 651 | div /= clk_get_rate(clk: clks[MPC512x_CLK_IPS]); |
| 652 | out_be32(mccr_reg, (0 << 16)); |
| 653 | out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17)); |
| 654 | out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17)); |
| 655 | |
| 656 | /* |
| 657 | * create the 'struct clk' items of the MCLK's clock subtree |
| 658 | * |
| 659 | * note that by design we always create all nodes and won't take |
| 660 | * shortcuts here, because |
| 661 | * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are |
| 662 | * selectable inputs to the CFM while those who "actually use" |
| 663 | * the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK |
| 664 | * for their bitrate |
| 665 | * - in the absence of "aliases" for clocks we need to create |
| 666 | * individual 'struct clk' items for whatever might get |
| 667 | * referenced or looked up, even if several of those items are |
| 668 | * identical from the logical POV (their rate value) |
| 669 | * - for easier future maintenance and for better reflection of |
| 670 | * the SoC's documentation, it appears appropriate to generate |
| 671 | * clock items even for those muxers which actually are NOPs |
| 672 | * (those with two inputs of which one is reserved) |
| 673 | */ |
| 674 | clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed( |
| 675 | name: entry->name_mux0, |
| 676 | parent_names: soc_has_mclk_mux0_canin() |
| 677 | ? &parent_names_mux0_canin[0] |
| 678 | : &parent_names_mux0_spdif[0], |
| 679 | ARRAY_SIZE(parent_names_mux0_spdif), |
| 680 | reg: mccr_reg, pos: 14, len: 2); |
| 681 | clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated( |
| 682 | name: entry->name_en0, parent_name: entry->name_mux0, |
| 683 | reg: mccr_reg, pos: 16); |
| 684 | clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider( |
| 685 | name: entry->name_div0, |
| 686 | parent_name: entry->name_en0, CLK_SET_RATE_GATE, |
| 687 | reg: mccr_reg, pos: 17, len: 15, divflags: 0); |
| 688 | if (entry->has_mclk1) { |
| 689 | clks[clks_idx_pub] = mpc512x_clk_muxed( |
| 690 | name: entry->name_mclk, |
| 691 | parent_names: &entry->parent_names_mux1[0], |
| 692 | ARRAY_SIZE(entry->parent_names_mux1), |
| 693 | reg: mccr_reg, pos: 7, len: 1); |
| 694 | } else { |
| 695 | clks[clks_idx_pub] = mpc512x_clk_factor( |
| 696 | name: entry->name_mclk, |
| 697 | parent_name: entry->parent_names_mux1[0], |
| 698 | mul: 1, div: 1); |
| 699 | } |
| 700 | } |
| 701 | |
| 702 | /* }}} MCLK helpers */ |
| 703 | |
| 704 | static void __init mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq) |
| 705 | { |
| 706 | int sys_mul, sys_div, ips_div; |
| 707 | int mul, div; |
| 708 | size_t mclk_idx; |
| 709 | int freq; |
| 710 | |
| 711 | /* |
| 712 | * developer's notes: |
| 713 | * - consider whether to handle clocks which have both gates and |
| 714 | * dividers via intermediates or by means of composites |
| 715 | * - fractional dividers appear to not map well to composites |
| 716 | * since they can be seen as a fixed multiplier and an |
| 717 | * adjustable divider, while composites can only combine at |
| 718 | * most one of a mux, div, and gate each into one 'struct clk' |
| 719 | * item |
| 720 | * - PSC/MSCAN/SPDIF clock generation OTOH already is very |
| 721 | * specific and cannot get mapped to composites (at least not |
| 722 | * a single one, maybe two of them, but then some of these |
| 723 | * intermediate clock signals get referenced elsewhere (e.g. |
| 724 | * in the clock frequency measurement, CFM) and thus need |
| 725 | * publicly available names |
| 726 | * - the current source layout appropriately reflects the |
| 727 | * hardware setup, and it works, so it's questionable whether |
| 728 | * further changes will result in big enough a benefit |
| 729 | */ |
| 730 | |
| 731 | /* regardless of whether XTAL/OSC exists, have REF created */ |
| 732 | mpc512x_clk_setup_ref_clock(np, bus_freq: busfreq, sys_mul: &sys_mul, sys_div: &sys_div, ips_div: &ips_div); |
| 733 | |
| 734 | /* now setup the REF -> SYS -> CSB -> IPS hierarchy */ |
| 735 | clks[MPC512x_CLK_SYS] = mpc512x_clk_factor(name: "sys" , parent_name: "ref" , |
| 736 | mul: sys_mul, div: sys_div); |
| 737 | clks[MPC512x_CLK_CSB] = mpc512x_clk_factor(name: "csb" , parent_name: "sys" , mul: 1, div: 2); |
| 738 | clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable(name: "ips" , parent_name: "csb" , |
| 739 | reg: &clkregs->scfr1, pos: 23, len: 3, |
| 740 | divtab: divtab_2346); |
| 741 | /* now setup anything below SYS and CSB and IPS */ |
| 742 | |
| 743 | clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor(name: "ddr-ug" , parent_name: "sys" , mul: 1, div: 2); |
| 744 | |
| 745 | /* |
| 746 | * the Reference Manual discusses that for SDHC only even divide |
| 747 | * ratios are supported because clock domain synchronization |
| 748 | * between 'per' and 'ipg' is broken; |
| 749 | * keep the divider's bit 0 cleared (per reset value), and only |
| 750 | * allow to setup the divider's bits 7:1, which results in that |
| 751 | * only even divide ratios can get configured upon rate changes; |
| 752 | * keep the "x4" name because this bit shift hack is an internal |
| 753 | * implementation detail, the "fractional divider with quarters" |
| 754 | * semantics remains |
| 755 | */ |
| 756 | clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor(name: "sdhc-x4" , parent_name: "csb" , mul: 2, div: 1); |
| 757 | clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider(name: "sdhc-ug" , parent_name: "sdhc-x4" , clkflags: 0, |
| 758 | reg: &clkregs->scfr2, pos: 1, len: 7, |
| 759 | CLK_DIVIDER_ONE_BASED); |
| 760 | if (soc_has_sdhc2()) { |
| 761 | clks[MPC512x_CLK_SDHC2_UG] = mpc512x_clk_divider( |
| 762 | name: "sdhc2-ug" , parent_name: "sdhc-x4" , clkflags: 0, reg: &clkregs->scfr2, |
| 763 | pos: 9, len: 7, CLK_DIVIDER_ONE_BASED); |
| 764 | } |
| 765 | |
| 766 | clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor(name: "diu-x4" , parent_name: "csb" , mul: 4, div: 1); |
| 767 | clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider(name: "diu-ug" , parent_name: "diu-x4" , clkflags: 0, |
| 768 | reg: &clkregs->scfr1, pos: 0, len: 8, |
| 769 | CLK_DIVIDER_ONE_BASED); |
| 770 | |
| 771 | /* |
| 772 | * the "power architecture PLL" was setup from data which was |
| 773 | * sampled from the reset config word, at this point in time the |
| 774 | * configuration can be considered fixed and read only (i.e. no |
| 775 | * longer adjustable, or no longer in need of adjustment), which |
| 776 | * is why we don't register a PLL here but assume fixed factors |
| 777 | */ |
| 778 | mul = get_cpmf_mult_x2(); |
| 779 | div = 2; /* compensate for the fractional factor */ |
| 780 | clks[MPC512x_CLK_E300] = mpc512x_clk_factor(name: "e300" , parent_name: "csb" , mul, div); |
| 781 | |
| 782 | if (soc_has_mbx()) { |
| 783 | clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor( |
| 784 | name: "mbx-bus-ug" , parent_name: "csb" , mul: 1, div: 2); |
| 785 | clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable( |
| 786 | name: "mbx-ug" , parent_name: "mbx-bus-ug" , reg: &clkregs->scfr1, |
| 787 | pos: 14, len: 3, divtab: divtab_1234); |
| 788 | clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor( |
| 789 | name: "mbx-3d-ug" , parent_name: "mbx-ug" , mul: 1, div: 1); |
| 790 | } |
| 791 | if (soc_has_pci()) { |
| 792 | clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable( |
| 793 | name: "pci-ug" , parent_name: "csb" , reg: &clkregs->scfr1, |
| 794 | pos: 20, len: 3, divtab: divtab_2346); |
| 795 | } |
| 796 | if (soc_has_nfc_5125()) { |
| 797 | /* |
| 798 | * XXX TODO implement 5125 NFC clock setup logic, |
| 799 | * with high/low period counters in clkregs->scfr3, |
| 800 | * currently there are no users so it's ENOIMPL |
| 801 | */ |
| 802 | clks[MPC512x_CLK_NFC_UG] = ERR_PTR(error: -ENOTSUPP); |
| 803 | } else { |
| 804 | clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable( |
| 805 | name: "nfc-ug" , parent_name: "ips" , reg: &clkregs->scfr1, |
| 806 | pos: 8, len: 3, divtab: divtab_1234); |
| 807 | } |
| 808 | clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable(name: "lpc-ug" , parent_name: "ips" , |
| 809 | reg: &clkregs->scfr1, pos: 11, len: 3, |
| 810 | divtab: divtab_1234); |
| 811 | |
| 812 | clks[MPC512x_CLK_LPC] = mpc512x_clk_gated(name: "lpc" , parent_name: "lpc-ug" , |
| 813 | reg: &clkregs->sccr1, pos: 30); |
| 814 | clks[MPC512x_CLK_NFC] = mpc512x_clk_gated(name: "nfc" , parent_name: "nfc-ug" , |
| 815 | reg: &clkregs->sccr1, pos: 29); |
| 816 | if (soc_has_pata()) { |
| 817 | clks[MPC512x_CLK_PATA] = mpc512x_clk_gated( |
| 818 | name: "pata" , parent_name: "ips" , reg: &clkregs->sccr1, pos: 28); |
| 819 | } |
| 820 | /* for PSCs there is a "registers" gate and a bitrate MCLK subtree */ |
| 821 | for (mclk_idx = 0; mclk_idx < soc_max_pscnum(); mclk_idx++) { |
| 822 | char name[12]; |
| 823 | snprintf(buf: name, size: sizeof(name), fmt: "psc%d" , mclk_idx); |
| 824 | clks[MPC512x_CLK_PSC0 + mclk_idx] = mpc512x_clk_gated( |
| 825 | name, parent_name: "ips" , reg: &clkregs->sccr1, pos: 27 - mclk_idx); |
| 826 | mpc512x_clk_setup_mclk(entry: &mclk_psc_data[mclk_idx], idx: mclk_idx); |
| 827 | } |
| 828 | clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated(name: "psc-fifo" , parent_name: "ips" , |
| 829 | reg: &clkregs->sccr1, pos: 15); |
| 830 | if (soc_has_sata()) { |
| 831 | clks[MPC512x_CLK_SATA] = mpc512x_clk_gated( |
| 832 | name: "sata" , parent_name: "ips" , reg: &clkregs->sccr1, pos: 14); |
| 833 | } |
| 834 | clks[MPC512x_CLK_FEC] = mpc512x_clk_gated(name: "fec" , parent_name: "ips" , |
| 835 | reg: &clkregs->sccr1, pos: 13); |
| 836 | if (soc_has_pci()) { |
| 837 | clks[MPC512x_CLK_PCI] = mpc512x_clk_gated( |
| 838 | name: "pci" , parent_name: "pci-ug" , reg: &clkregs->sccr1, pos: 11); |
| 839 | } |
| 840 | clks[MPC512x_CLK_DDR] = mpc512x_clk_gated(name: "ddr" , parent_name: "ddr-ug" , |
| 841 | reg: &clkregs->sccr1, pos: 10); |
| 842 | if (soc_has_fec2()) { |
| 843 | clks[MPC512x_CLK_FEC2] = mpc512x_clk_gated( |
| 844 | name: "fec2" , parent_name: "ips" , reg: &clkregs->sccr1, pos: 9); |
| 845 | } |
| 846 | |
| 847 | clks[MPC512x_CLK_DIU] = mpc512x_clk_gated(name: "diu" , parent_name: "diu-ug" , |
| 848 | reg: &clkregs->sccr2, pos: 31); |
| 849 | if (soc_has_axe()) { |
| 850 | clks[MPC512x_CLK_AXE] = mpc512x_clk_gated( |
| 851 | name: "axe" , parent_name: "csb" , reg: &clkregs->sccr2, pos: 30); |
| 852 | } |
| 853 | clks[MPC512x_CLK_MEM] = mpc512x_clk_gated(name: "mem" , parent_name: "ips" , |
| 854 | reg: &clkregs->sccr2, pos: 29); |
| 855 | clks[MPC512x_CLK_USB1] = mpc512x_clk_gated(name: "usb1" , parent_name: "csb" , |
| 856 | reg: &clkregs->sccr2, pos: 28); |
| 857 | clks[MPC512x_CLK_USB2] = mpc512x_clk_gated(name: "usb2" , parent_name: "csb" , |
| 858 | reg: &clkregs->sccr2, pos: 27); |
| 859 | clks[MPC512x_CLK_I2C] = mpc512x_clk_gated(name: "i2c" , parent_name: "ips" , |
| 860 | reg: &clkregs->sccr2, pos: 26); |
| 861 | /* MSCAN differs from PSC with just one gate for multiple components */ |
| 862 | clks[MPC512x_CLK_BDLC] = mpc512x_clk_gated(name: "bdlc" , parent_name: "ips" , |
| 863 | reg: &clkregs->sccr2, pos: 25); |
| 864 | for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++) |
| 865 | mpc512x_clk_setup_mclk(entry: &mclk_mscan_data[mclk_idx], idx: mclk_idx); |
| 866 | clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated(name: "sdhc" , parent_name: "sdhc-ug" , |
| 867 | reg: &clkregs->sccr2, pos: 24); |
| 868 | /* there is only one SPDIF component, which shares MCLK support code */ |
| 869 | if (soc_has_spdif()) { |
| 870 | clks[MPC512x_CLK_SPDIF] = mpc512x_clk_gated( |
| 871 | name: "spdif" , parent_name: "ips" , reg: &clkregs->sccr2, pos: 23); |
| 872 | mpc512x_clk_setup_mclk(entry: &mclk_spdif_data[0], idx: 0); |
| 873 | } |
| 874 | if (soc_has_mbx()) { |
| 875 | clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated( |
| 876 | name: "mbx-bus" , parent_name: "mbx-bus-ug" , reg: &clkregs->sccr2, pos: 22); |
| 877 | clks[MPC512x_CLK_MBX] = mpc512x_clk_gated( |
| 878 | name: "mbx" , parent_name: "mbx-ug" , reg: &clkregs->sccr2, pos: 21); |
| 879 | clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated( |
| 880 | name: "mbx-3d" , parent_name: "mbx-3d-ug" , reg: &clkregs->sccr2, pos: 20); |
| 881 | } |
| 882 | clks[MPC512x_CLK_IIM] = mpc512x_clk_gated(name: "iim" , parent_name: "csb" , |
| 883 | reg: &clkregs->sccr2, pos: 19); |
| 884 | if (soc_has_viu()) { |
| 885 | clks[MPC512x_CLK_VIU] = mpc512x_clk_gated( |
| 886 | name: "viu" , parent_name: "csb" , reg: &clkregs->sccr2, pos: 18); |
| 887 | } |
| 888 | if (soc_has_sdhc2()) { |
| 889 | clks[MPC512x_CLK_SDHC2] = mpc512x_clk_gated( |
| 890 | name: "sdhc-2" , parent_name: "sdhc2-ug" , reg: &clkregs->sccr2, pos: 17); |
| 891 | } |
| 892 | |
| 893 | if (soc_has_outclk()) { |
| 894 | size_t idx; /* used as mclk_idx, just to trim line length */ |
| 895 | for (idx = 0; idx < ARRAY_SIZE(mclk_outclk_data); idx++) |
| 896 | mpc512x_clk_setup_mclk(entry: &mclk_outclk_data[idx], idx); |
| 897 | } |
| 898 | |
| 899 | /* |
| 900 | * externally provided clocks (when implemented in hardware, |
| 901 | * device tree may specify values which otherwise were unknown) |
| 902 | */ |
| 903 | freq = get_freq_from_dt(propname: "psc_mclk_in" ); |
| 904 | if (!freq) |
| 905 | freq = 25000000; |
| 906 | clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed(name: "psc_mclk_in" , rate: freq); |
| 907 | if (soc_has_mclk_mux0_canin()) { |
| 908 | freq = get_freq_from_dt(propname: "can_clk_in" ); |
| 909 | clks[MPC512x_CLK_CAN_CLK_IN] = mpc512x_clk_fixed( |
| 910 | name: "can_clk_in" , rate: freq); |
| 911 | } else { |
| 912 | freq = get_freq_from_dt(propname: "spdif_tx_in" ); |
| 913 | clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed( |
| 914 | name: "spdif_tx_in" , rate: freq); |
| 915 | freq = get_freq_from_dt(propname: "spdif_rx_in" ); |
| 916 | clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed( |
| 917 | name: "spdif_rx_in" , rate: freq); |
| 918 | } |
| 919 | |
| 920 | /* fixed frequency for AC97, always 24.567MHz */ |
| 921 | clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed(name: "ac97" , rate: 24567000); |
| 922 | |
| 923 | /* |
| 924 | * pre-enable those "internal" clock items which never get |
| 925 | * claimed by any peripheral driver, to not have the clock |
| 926 | * subsystem disable them late at startup |
| 927 | */ |
| 928 | clk_prepare_enable(clk: clks[MPC512x_CLK_DUMMY]); |
| 929 | clk_prepare_enable(clk: clks[MPC512x_CLK_E300]); /* PowerPC CPU */ |
| 930 | clk_prepare_enable(clk: clks[MPC512x_CLK_DDR]); /* DRAM */ |
| 931 | clk_prepare_enable(clk: clks[MPC512x_CLK_MEM]); /* SRAM */ |
| 932 | clk_prepare_enable(clk: clks[MPC512x_CLK_IPS]); /* SoC periph */ |
| 933 | clk_prepare_enable(clk: clks[MPC512x_CLK_LPC]); /* boot media */ |
| 934 | } |
| 935 | |
| 936 | /* |
| 937 | * registers the set of public clocks (those listed in the dt-bindings/ |
| 938 | * header file) for OF lookups, keeps the intermediates private to us |
| 939 | */ |
| 940 | static void __init mpc5121_clk_register_of_provider(struct device_node *np) |
| 941 | { |
| 942 | clk_data.clks = clks; |
| 943 | clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1; /* _not_ ARRAY_SIZE() */ |
| 944 | of_clk_add_provider(np, clk_src_get: of_clk_src_onecell_get, data: &clk_data); |
| 945 | } |
| 946 | |
| 947 | /* |
| 948 | * temporary support for the period of time between introduction of CCF |
| 949 | * support and the adjustment of peripheral drivers to OF based lookups |
| 950 | */ |
| 951 | static void __init mpc5121_clk_provide_migration_support(void) |
| 952 | { |
| 953 | struct device_node *np; |
| 954 | /* |
| 955 | * pre-enable those clock items which are not yet appropriately |
| 956 | * acquired by their peripheral driver |
| 957 | * |
| 958 | * the PCI clock cannot get acquired by its peripheral driver, |
| 959 | * because for this platform the driver won't probe(), instead |
| 960 | * initialization is done from within the .setup_arch() routine |
| 961 | * at a point in time where the clock provider has not been |
| 962 | * setup yet and thus isn't available yet |
| 963 | * |
| 964 | * so we "pre-enable" the clock here, to not have the clock |
| 965 | * subsystem automatically disable this item in a late init call |
| 966 | * |
| 967 | * this PCI clock pre-enable workaround only applies when there |
| 968 | * are device tree nodes for PCI and thus the peripheral driver |
| 969 | * has attached to bridges, otherwise the PCI clock remains |
| 970 | * unused and so it gets disabled |
| 971 | */ |
| 972 | clk_prepare_enable(clk: clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */ |
| 973 | np = of_find_compatible_node(NULL, type: "pci" , compat: "fsl,mpc5121-pci" ); |
| 974 | of_node_put(node: np); |
| 975 | if (np) |
| 976 | clk_prepare_enable(clk: clks[MPC512x_CLK_PCI]); |
| 977 | } |
| 978 | |
| 979 | /* |
| 980 | * those macros are not exactly pretty, but they encapsulate a lot |
| 981 | * of copy'n'paste heavy code which is even more ugly, and reduce |
| 982 | * the potential for inconsistencies in those many code copies |
| 983 | */ |
| 984 | #define FOR_NODES(compatname) \ |
| 985 | for_each_compatible_node(np, NULL, compatname) |
| 986 | |
| 987 | #define NODE_PREP do { \ |
| 988 | of_address_to_resource(np, 0, &res); \ |
| 989 | snprintf(devname, sizeof(devname), "%pa.%s", &res.start, np->name); \ |
| 990 | } while (0) |
| 991 | |
| 992 | #define NODE_CHK(clkname, clkitem, regnode, regflag) do { \ |
| 993 | struct clk *clk; \ |
| 994 | clk = of_clk_get_by_name(np, clkname); \ |
| 995 | if (IS_ERR(clk)) { \ |
| 996 | clk = clkitem; \ |
| 997 | clk_register_clkdev(clk, clkname, devname); \ |
| 998 | if (regnode) \ |
| 999 | clk_register_clkdev(clk, clkname, np->name); \ |
| 1000 | did_register |= DID_REG_ ## regflag; \ |
| 1001 | pr_debug("clock alias name '%s' for dev '%s' pointer %p\n", \ |
| 1002 | clkname, devname, clk); \ |
| 1003 | } else { \ |
| 1004 | clk_put(clk); \ |
| 1005 | } \ |
| 1006 | } while (0) |
| 1007 | |
| 1008 | /* |
| 1009 | * register source code provided fallback results for clock lookups, |
| 1010 | * these get consulted when OF based clock lookup fails (that is in the |
| 1011 | * case of not yet adjusted device tree data, where clock related specs |
| 1012 | * are missing) |
| 1013 | */ |
| 1014 | static void __init mpc5121_clk_provide_backwards_compat(void) |
| 1015 | { |
| 1016 | enum did_reg_flags { |
| 1017 | DID_REG_PSC = BIT(0), |
| 1018 | DID_REG_PSCFIFO = BIT(1), |
| 1019 | DID_REG_NFC = BIT(2), |
| 1020 | DID_REG_CAN = BIT(3), |
| 1021 | DID_REG_I2C = BIT(4), |
| 1022 | DID_REG_DIU = BIT(5), |
| 1023 | DID_REG_VIU = BIT(6), |
| 1024 | DID_REG_FEC = BIT(7), |
| 1025 | DID_REG_USB = BIT(8), |
| 1026 | DID_REG_PATA = BIT(9), |
| 1027 | }; |
| 1028 | |
| 1029 | int did_register; |
| 1030 | struct device_node *np; |
| 1031 | struct resource res; |
| 1032 | int idx; |
| 1033 | char devname[32]; |
| 1034 | |
| 1035 | did_register = 0; |
| 1036 | |
| 1037 | FOR_NODES(mpc512x_select_psc_compat()) { |
| 1038 | NODE_PREP; |
| 1039 | idx = (res.start >> 8) & 0xf; |
| 1040 | NODE_CHK("ipg" , clks[MPC512x_CLK_PSC0 + idx], 0, PSC); |
| 1041 | NODE_CHK("mclk" , clks[MPC512x_CLK_PSC0_MCLK + idx], 0, PSC); |
| 1042 | } |
| 1043 | |
| 1044 | FOR_NODES("fsl,mpc5121-psc-fifo" ) { |
| 1045 | NODE_PREP; |
| 1046 | NODE_CHK("ipg" , clks[MPC512x_CLK_PSC_FIFO], 1, PSCFIFO); |
| 1047 | } |
| 1048 | |
| 1049 | FOR_NODES("fsl,mpc5121-nfc" ) { |
| 1050 | NODE_PREP; |
| 1051 | NODE_CHK("ipg" , clks[MPC512x_CLK_NFC], 0, NFC); |
| 1052 | } |
| 1053 | |
| 1054 | FOR_NODES("fsl,mpc5121-mscan" ) { |
| 1055 | NODE_PREP; |
| 1056 | idx = 0; |
| 1057 | idx += (res.start & 0x2000) ? 2 : 0; |
| 1058 | idx += (res.start & 0x0080) ? 1 : 0; |
| 1059 | NODE_CHK("ipg" , clks[MPC512x_CLK_BDLC], 0, CAN); |
| 1060 | NODE_CHK("mclk" , clks[MPC512x_CLK_MSCAN0_MCLK + idx], 0, CAN); |
| 1061 | } |
| 1062 | |
| 1063 | /* |
| 1064 | * do register the 'ips', 'sys', and 'ref' names globally |
| 1065 | * instead of inside each individual CAN node, as there is no |
| 1066 | * potential for a name conflict (in contrast to 'ipg' and 'mclk') |
| 1067 | */ |
| 1068 | if (did_register & DID_REG_CAN) { |
| 1069 | clk_register_clkdev(clks[MPC512x_CLK_IPS], "ips" , NULL); |
| 1070 | clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys" , NULL); |
| 1071 | clk_register_clkdev(clks[MPC512x_CLK_REF], "ref" , NULL); |
| 1072 | } |
| 1073 | |
| 1074 | FOR_NODES("fsl,mpc5121-i2c" ) { |
| 1075 | NODE_PREP; |
| 1076 | NODE_CHK("ipg" , clks[MPC512x_CLK_I2C], 0, I2C); |
| 1077 | } |
| 1078 | |
| 1079 | /* |
| 1080 | * workaround for the fact that the I2C driver does an "anonymous" |
| 1081 | * lookup (NULL name spec, which yields the first clock spec) for |
| 1082 | * which we cannot register an alias -- a _global_ 'ipg' alias that |
| 1083 | * is not bound to any device name and returns the I2C clock item |
| 1084 | * is not a good idea |
| 1085 | * |
| 1086 | * so we have the lookup in the peripheral driver fail, which is |
| 1087 | * silent and non-fatal, and pre-enable the clock item here such |
| 1088 | * that register access is possible |
| 1089 | * |
| 1090 | * see commit b3bfce2b "i2c: mpc: cleanup clock API use" for |
| 1091 | * details, adjusting s/NULL/"ipg"/ in i2c-mpc.c would make this |
| 1092 | * workaround obsolete |
| 1093 | */ |
| 1094 | if (did_register & DID_REG_I2C) |
| 1095 | clk_prepare_enable(clk: clks[MPC512x_CLK_I2C]); |
| 1096 | |
| 1097 | FOR_NODES("fsl,mpc5121-diu" ) { |
| 1098 | NODE_PREP; |
| 1099 | NODE_CHK("ipg" , clks[MPC512x_CLK_DIU], 1, DIU); |
| 1100 | } |
| 1101 | |
| 1102 | FOR_NODES("fsl,mpc5121-viu" ) { |
| 1103 | NODE_PREP; |
| 1104 | NODE_CHK("ipg" , clks[MPC512x_CLK_VIU], 0, VIU); |
| 1105 | } |
| 1106 | |
| 1107 | /* |
| 1108 | * note that 2771399a "fs_enet: cleanup clock API use" did use the |
| 1109 | * "per" string for the clock lookup in contrast to the "ipg" name |
| 1110 | * which most other nodes are using -- this is not a fatal thing |
| 1111 | * but just something to keep in mind when doing compatibility |
| 1112 | * registration, it's a non-issue with up-to-date device tree data |
| 1113 | */ |
| 1114 | FOR_NODES("fsl,mpc5121-fec" ) { |
| 1115 | NODE_PREP; |
| 1116 | NODE_CHK("per" , clks[MPC512x_CLK_FEC], 0, FEC); |
| 1117 | } |
| 1118 | FOR_NODES("fsl,mpc5121-fec-mdio" ) { |
| 1119 | NODE_PREP; |
| 1120 | NODE_CHK("per" , clks[MPC512x_CLK_FEC], 0, FEC); |
| 1121 | } |
| 1122 | /* |
| 1123 | * MPC5125 has two FECs: FEC1 at 0x2800, FEC2 at 0x4800; |
| 1124 | * the clock items don't "form an array" since FEC2 was |
| 1125 | * added only later and was not allowed to shift all other |
| 1126 | * clock item indices, so the numbers aren't adjacent |
| 1127 | */ |
| 1128 | FOR_NODES("fsl,mpc5125-fec" ) { |
| 1129 | NODE_PREP; |
| 1130 | if (res.start & 0x4000) |
| 1131 | idx = MPC512x_CLK_FEC2; |
| 1132 | else |
| 1133 | idx = MPC512x_CLK_FEC; |
| 1134 | NODE_CHK("per" , clks[idx], 0, FEC); |
| 1135 | } |
| 1136 | |
| 1137 | FOR_NODES("fsl,mpc5121-usb2-dr" ) { |
| 1138 | NODE_PREP; |
| 1139 | idx = (res.start & 0x4000) ? 1 : 0; |
| 1140 | NODE_CHK("ipg" , clks[MPC512x_CLK_USB1 + idx], 0, USB); |
| 1141 | } |
| 1142 | |
| 1143 | FOR_NODES("fsl,mpc5121-pata" ) { |
| 1144 | NODE_PREP; |
| 1145 | NODE_CHK("ipg" , clks[MPC512x_CLK_PATA], 0, PATA); |
| 1146 | } |
| 1147 | |
| 1148 | /* |
| 1149 | * try to collapse diagnostics into a single line of output yet |
| 1150 | * provide a full list of what is missing, to avoid noise in the |
| 1151 | * absence of up-to-date device tree data -- backwards |
| 1152 | * compatibility to old DTBs is a requirement, updates may be |
| 1153 | * desirable or preferrable but are not at all mandatory |
| 1154 | */ |
| 1155 | if (did_register) { |
| 1156 | pr_notice("device tree lacks clock specs, adding fallbacks (0x%x,%s%s%s%s%s%s%s%s%s%s)\n" , |
| 1157 | did_register, |
| 1158 | (did_register & DID_REG_PSC) ? " PSC" : "" , |
| 1159 | (did_register & DID_REG_PSCFIFO) ? " PSCFIFO" : "" , |
| 1160 | (did_register & DID_REG_NFC) ? " NFC" : "" , |
| 1161 | (did_register & DID_REG_CAN) ? " CAN" : "" , |
| 1162 | (did_register & DID_REG_I2C) ? " I2C" : "" , |
| 1163 | (did_register & DID_REG_DIU) ? " DIU" : "" , |
| 1164 | (did_register & DID_REG_VIU) ? " VIU" : "" , |
| 1165 | (did_register & DID_REG_FEC) ? " FEC" : "" , |
| 1166 | (did_register & DID_REG_USB) ? " USB" : "" , |
| 1167 | (did_register & DID_REG_PATA) ? " PATA" : "" ); |
| 1168 | } else { |
| 1169 | pr_debug("device tree has clock specs, no fallbacks added\n" ); |
| 1170 | } |
| 1171 | } |
| 1172 | |
| 1173 | /* |
| 1174 | * The "fixed-clock" nodes (which includes the oscillator node if the board's |
| 1175 | * DT provides one) has already been scanned by the of_clk_init() in |
| 1176 | * time_init(). |
| 1177 | */ |
| 1178 | int __init mpc5121_clk_init(void) |
| 1179 | { |
| 1180 | struct device_node *clk_np; |
| 1181 | int busfreq; |
| 1182 | |
| 1183 | /* map the clock control registers */ |
| 1184 | clk_np = of_find_compatible_node(NULL, NULL, compat: "fsl,mpc5121-clock" ); |
| 1185 | if (!clk_np) |
| 1186 | return -ENODEV; |
| 1187 | clkregs = of_iomap(node: clk_np, index: 0); |
| 1188 | WARN_ON(!clkregs); |
| 1189 | |
| 1190 | /* determine the SoC variant we run on */ |
| 1191 | mpc512x_clk_determine_soc(); |
| 1192 | |
| 1193 | /* invalidate all not yet registered clock slots */ |
| 1194 | mpc512x_clk_preset_data(); |
| 1195 | |
| 1196 | /* |
| 1197 | * add a dummy clock for those situations where a clock spec is |
| 1198 | * required yet no real clock is involved |
| 1199 | */ |
| 1200 | clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed(name: "dummy" , rate: 0); |
| 1201 | |
| 1202 | /* |
| 1203 | * have all the real nodes in the clock tree populated from REF |
| 1204 | * down to all leaves, either starting from the OSC node or from |
| 1205 | * a REF root that was created from the IPS bus clock input |
| 1206 | */ |
| 1207 | busfreq = get_freq_from_dt(propname: "bus-frequency" ); |
| 1208 | mpc512x_clk_setup_clock_tree(np: clk_np, busfreq); |
| 1209 | |
| 1210 | /* register as an OF clock provider */ |
| 1211 | mpc5121_clk_register_of_provider(np: clk_np); |
| 1212 | |
| 1213 | of_node_put(node: clk_np); |
| 1214 | |
| 1215 | /* |
| 1216 | * unbreak not yet adjusted peripheral drivers during migration |
| 1217 | * towards fully operational common clock support, and allow |
| 1218 | * operation in the absence of clock related device tree specs |
| 1219 | */ |
| 1220 | mpc5121_clk_provide_migration_support(); |
| 1221 | mpc5121_clk_provide_backwards_compat(); |
| 1222 | |
| 1223 | return 0; |
| 1224 | } |
| 1225 | |