Tom Rini | dec7ea0 | 2024-05-20 13:35:03 -0600 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* |
| 3 | * (C) Copyright 2022 - Analog Devices, Inc. |
| 4 | * |
| 5 | * Written and/or maintained by Timesys Corporation |
| 6 | * |
| 7 | * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> |
| 8 | * Contact: Greg Malysa <greg.malysa@timesys.com> |
| 9 | */ |
| 10 | |
| 11 | #include <asm/arch-adi/sc5xx/sc5xx.h> |
| 12 | #include <asm/io.h> |
| 13 | #include <linux/types.h> |
| 14 | #include "clkinit.h" |
| 15 | #include "dmcinit.h" |
| 16 | |
| 17 | #ifdef CONFIG_CGU0_SCLK0_DIV |
| 18 | #define VAL_CGU0_SCLK0_DIV CONFIG_CGU0_SCLK0_DIV |
| 19 | #else |
| 20 | #define VAL_CGU0_SCLK0_DIV 1 |
| 21 | #endif |
| 22 | #ifdef CONFIG_CGU0_SCLK1_DIV |
| 23 | #define VAL_CGU0_SCLK1_DIV CONFIG_CGU0_SCLK1_DIV |
| 24 | #else |
| 25 | #define VAL_CGU0_SCLK1_DIV 1 |
| 26 | #endif |
| 27 | #ifdef CONFIG_CGU0_DIV_S0SELEX |
| 28 | #define VAL_CGU0_DIV_S0SELEX CONFIG_CGU0_DIV_S0SELEX |
| 29 | #else |
| 30 | #define VAL_CGU0_DIV_S0SELEX -1 |
| 31 | #endif |
| 32 | #ifdef CONFIG_CGU0_DIV_S1SELEX |
| 33 | #define VAL_CGU0_DIV_S1SELEX CONFIG_CGU0_DIV_S1SELEX |
| 34 | #else |
| 35 | #define VAL_CGU0_DIV_S1SELEX -1 |
| 36 | #endif |
| 37 | #ifdef CONFIG_CGU0_CLKOUTSEL |
| 38 | #define VAL_CGU0_CLKOUTSEL CONFIG_CGU0_CLKOUTSEL |
| 39 | #else |
| 40 | #define VAL_CGU0_CLKOUTSEL -1 |
| 41 | #endif |
| 42 | #ifdef CONFIG_CGU1_SCLK0_DIV |
| 43 | #define VAL_CGU1_SCLK0_DIV CONFIG_CGU1_SCLK0_DIV |
| 44 | #else |
| 45 | #define VAL_CGU1_SCLK0_DIV 1 |
| 46 | #endif |
| 47 | #ifdef CONFIG_CGU1_SCLK1_DIV |
| 48 | #define VAL_CGU1_SCLK1_DIV CONFIG_CGU1_SCLK1_DIV |
| 49 | #else |
| 50 | #define VAL_CGU1_SCLK1_DIV 1 |
| 51 | #endif |
| 52 | #ifdef CONFIG_CGU1_DIV_S0SELEX |
| 53 | #define VAL_CGU1_DIV_S0SELEX CONFIG_CGU1_DIV_S0SELEX |
| 54 | #else |
| 55 | #define VAL_CGU1_DIV_S0SELEX -1 |
| 56 | #endif |
| 57 | #ifdef CONFIG_CGU1_DIV_S1SELEX |
| 58 | #define VAL_CGU1_DIV_S1SELEX CONFIG_CGU1_DIV_S1SELEX |
| 59 | #else |
| 60 | #define VAL_CGU1_DIV_S1SELEX -1 |
| 61 | #endif |
| 62 | #ifdef CONFIG_CGU1_CLKOUTSEL |
| 63 | #define VAL_CGU1_CLKOUTSEL CONFIG_CGU1_CLKOUTSEL |
| 64 | #else |
| 65 | #define VAL_CGU1_CLKOUTSEL -1 |
| 66 | #endif |
| 67 | |
| 68 | #define REG_MISC_REG10_tst_addr 0x310A902C |
| 69 | |
| 70 | #define CGU0_REGBASE 0x3108D000 |
| 71 | #define CGU1_REGBASE 0x3108E000 |
| 72 | |
| 73 | #define CGU_CTL 0x00 // CGU0 Control Register |
| 74 | #define CGU_PLLCTL 0x04 // CGU0 PLL Control Register |
| 75 | #define CGU_STAT 0x08 // CGU0 Status Register |
| 76 | #define CGU_DIV 0x0C // CGU0 Clocks Divisor Register |
| 77 | #define CGU_CLKOUTSEL 0x10 // CGU0 CLKOUT Select Register |
| 78 | #define CGU_DIVEX 0x40 // CGU0 DIV Register Extension |
| 79 | |
| 80 | #define BITP_CGU_DIV_OSEL 22 // OUTCLK Divisor |
| 81 | #define BITP_CGU_DIV_DSEL 16 // DCLK Divisor |
| 82 | #define BITP_CGU_DIV_S1SEL 13 // SCLK 1 Divisor |
| 83 | #define BITP_CGU_DIV_SYSSEL 8 // SYSCLK Divisor |
| 84 | #define BITP_CGU_DIV_S0SEL 5 // SCLK 0 Divisor |
| 85 | #define BITP_CGU_DIV_CSEL 0 // CCLK Divisor |
| 86 | |
| 87 | #define BITP_CGU_CTL_MSEL 8 // Multiplier Select |
| 88 | #define BITP_CGU_CTL_DF 0 // Divide Frequency |
| 89 | |
| 90 | #define BITM_CGU_STAT_CLKSALGN 0x00000008 |
| 91 | #define BITM_CGU_STAT_PLOCK 0x00000004 |
| 92 | #define BITM_CGU_STAT_PLLBP 0x00000002 |
| 93 | #define BITM_CGU_STAT_PLLEN 0x00000001 |
| 94 | |
| 95 | /* PLL Multiplier and Divisor Selections (Required Value, Bit Position) */ |
| 96 | /* PLL Multiplier Select */ |
| 97 | #define MSEL(X) (((X) << BITP_CGU_CTL_MSEL) & \ |
| 98 | BITM_CGU_CTL_MSEL) |
| 99 | /* Divide frequency[true or false] */ |
| 100 | #define DF(X) (((X) << BITP_CGU_CTL_DF) & \ |
| 101 | BITM_CGU_CTL_DF) |
| 102 | /* Core Clock Divisor Select */ |
| 103 | #define CSEL(X) (((X) << BITP_CGU_DIV_CSEL) & \ |
| 104 | BITM_CGU_DIV_CSEL) |
| 105 | /* System Clock Divisor Select */ |
| 106 | #define SYSSEL(X) (((X) << BITP_CGU_DIV_SYSSEL) & \ |
| 107 | BITM_CGU_DIV_SYSSEL) |
| 108 | /* SCLK0 Divisor Select */ |
| 109 | #define S0SEL(X) (((X) << BITP_CGU_DIV_S0SEL) & \ |
| 110 | BITM_CGU_DIV_S0SEL) |
| 111 | /* SCLK1 Divisor Select */ |
| 112 | #define S1SEL(X) (((X) << BITP_CGU_DIV_S1SEL) & \ |
| 113 | BITM_CGU_DIV_S1SEL) |
| 114 | /* DDR Clock Divisor Select */ |
| 115 | #define DSEL(X) (((X) << BITP_CGU_DIV_DSEL) & \ |
| 116 | BITM_CGU_DIV_DSEL) |
| 117 | /* OUTCLK Divisor Select */ |
| 118 | #define OSEL(X) (((X) << BITP_CGU_DIV_OSEL) & \ |
| 119 | BITM_CGU_DIV_OSEL) |
| 120 | /* CLKOUT select */ |
| 121 | #define CLKOUTSEL(X) (((X) << BITP_CGU_CLKOUTSEL_CLKOUTSEL) & \ |
| 122 | BITM_CGU_CLKOUTSEL_CLKOUTSEL) |
| 123 | #define S0SELEX(X) (((X) << BITP_CGU_DIVEX_S0SELEX) & \ |
| 124 | BITM_CGU_DIVEX_S0SELEX) |
| 125 | #define S1SELEX(X) (((X) << BITP_CGU_DIVEX_S1SELEX) & \ |
| 126 | BITM_CGU_DIVEX_S1SELEX) |
| 127 | |
| 128 | struct CGU_Settings { |
| 129 | phys_addr_t rbase; |
| 130 | u32 ctl_MSEL:7; |
| 131 | u32 ctl_DF:1; |
| 132 | u32 div_CSEL:5; |
| 133 | u32 div_SYSSEL:5; |
| 134 | u32 div_S0SEL:3; |
| 135 | u32 div_S1SEL:3; |
| 136 | u32 div_DSEL:5; |
| 137 | u32 div_OSEL:7; |
| 138 | s16 divex_S0SELEX; |
| 139 | s16 divex_S1SELEX; |
| 140 | s8 clkoutsel; |
| 141 | }; |
| 142 | |
| 143 | /* CGU Registers */ |
| 144 | #define BITM_CGU_CTL_LOCK 0x80000000 /* Lock */ |
| 145 | |
| 146 | #define BITM_CGU_CTL_MSEL 0x00007F00 /* Multiplier Select */ |
| 147 | #define BITM_CGU_CTL_DF 0x00000001 /* Divide Frequency */ |
| 148 | #define BITM_CGU_CTL_S1SELEXEN 0x00020000 /* SCLK1 Extension Divider Enable */ |
| 149 | #define BITM_CGU_CTL_S0SELEXEN 0x00010000 /* SCLK0 Extension Divider Enable */ |
| 150 | |
| 151 | #define BITM_CGU_DIV_LOCK 0x80000000 /* Lock */ |
| 152 | #define BITM_CGU_DIV_UPDT 0x40000000 /* Update Clock Divisors */ |
| 153 | #define BITM_CGU_DIV_ALGN 0x20000000 /* Align */ |
| 154 | #define BITM_CGU_DIV_OSEL 0x1FC00000 /* OUTCLK Divisor */ |
| 155 | #define BITM_CGU_DIV_DSEL 0x001F0000 /* DCLK Divisor */ |
| 156 | #define BITM_CGU_DIV_S1SEL 0x0000E000 /* SCLK 1 Divisor */ |
| 157 | #define BITM_CGU_DIV_SYSSEL 0x00001F00 /* SYSCLK Divisor */ |
| 158 | #define BITM_CGU_DIV_S0SEL 0x000000E0 /* SCLK 0 Divisor */ |
| 159 | #define BITM_CGU_DIV_CSEL 0x0000001F /* CCLK Divisor */ |
| 160 | |
| 161 | #define BITP_CGU_DIVEX_S0SELEX 0 |
| 162 | #define BITM_CGU_DIVEX_S0SELEX 0x000000FF /* SCLK 0 Extension Divisor */ |
| 163 | |
| 164 | #define BITP_CGU_DIVEX_S1SELEX 16 |
| 165 | #define BITM_CGU_DIVEX_S1SELEX 0x00FF0000 /* SCLK 1 Extension Divisor */ |
| 166 | |
| 167 | #define BITM_CGU_PLLCTL_PLLEN 0x00000008 /* PLL Enable */ |
| 168 | #define BITM_CGU_PLLCTL_PLLBPCL 0x00000002 /* PLL Bypass Clear */ |
| 169 | #define BITM_CGU_PLLCTL_PLLBPST 0x00000001 /* PLL Bypass Set */ |
| 170 | |
| 171 | #define BITP_CGU_CLKOUTSEL_CLKOUTSEL 0 /* CLKOUT Select */ |
| 172 | #define BITM_CGU_CLKOUTSEL_CLKOUTSEL 0x0000001F /* CLKOUT Select */ |
| 173 | |
| 174 | #define CGU_STAT_MASK (BITM_CGU_STAT_PLLEN | BITM_CGU_STAT_PLOCK | \ |
| 175 | BITM_CGU_STAT_CLKSALGN) |
| 176 | #define CGU_STAT_ALGN_LOCK (BITM_CGU_STAT_PLLEN | BITM_CGU_STAT_PLOCK) |
| 177 | |
| 178 | /* Clock Distribution Unit Registers */ |
| 179 | #define REG_CDU0_CFG0 0x3108F000 |
| 180 | #define REG_CDU0_CFG1 0x3108F004 |
| 181 | #define REG_CDU0_CFG2 0x3108F008 |
| 182 | #define REG_CDU0_CFG3 0x3108F00C |
| 183 | #define REG_CDU0_CFG4 0x3108F010 |
| 184 | #define REG_CDU0_CFG5 0x3108F014 |
| 185 | #define REG_CDU0_CFG6 0x3108F018 |
| 186 | #define REG_CDU0_CFG7 0x3108F01C |
| 187 | #define REG_CDU0_CFG8 0x3108F020 |
| 188 | #define REG_CDU0_CFG9 0x3108F024 |
| 189 | #define REG_CDU0_CFG10 0x3108F028 |
| 190 | #define REG_CDU0_CFG11 0x3108F02C |
| 191 | #define REG_CDU0_CFG12 0x3108F030 |
| 192 | #define REG_CDU0_CFG13 0x3108F034 |
| 193 | #define REG_CDU0_CFG14 0x3108F038 |
| 194 | #define REG_CDU0_STAT 0x3108F040 |
| 195 | #define REG_CDU0_CLKINSEL 0x3108F044 |
| 196 | #define REG_CDU0_REVID 0x3108F048 |
| 197 | |
| 198 | #define BITM_REG10_MSEL3 0x000007F0 |
| 199 | #define BITP_REG10_MSEL3 4 |
| 200 | |
| 201 | #define BITM_REG10_DSEL3 0x0001F000 |
| 202 | #define BITP_REG10_DSEL3 12 |
| 203 | |
| 204 | /* Selected clock macros */ |
| 205 | #define CGUn_MULT(cgu) ((CONFIG_CGU##cgu##_VCO_MULT == 0) ? \ |
| 206 | 128 : CONFIG_CGU##cgu##_VCO_MULT) |
| 207 | #define CGUn_DIV(clkname, cgu) ((CONFIG_CGU##cgu##_##clkname##_DIV == 0) ? \ |
| 208 | 32 : CONFIG_CGU##cgu##_##clkname##_DIV) |
| 209 | #define CCLK1_n_RATIO(cgu) (((CGUn_MULT(cgu)) / \ |
| 210 | (1 + CONFIG_CGU##cgu##_DF_DIV)) / \ |
| 211 | CGUn_DIV(CCLK, cgu)) |
| 212 | #define CCLK2_n_RATIO(cgu) (((CGUn_MULT(cgu) * 2) / 3) / \ |
| 213 | (1 + CONFIG_CGU##cgu##_DF_DIV)) |
| 214 | #define DCLK_n_RATIO(cgu) (((CGUn_MULT(cgu)) / \ |
| 215 | (1 + CONFIG_CGU##cgu##_DF_DIV)) / \ |
| 216 | CGUn_DIV(DCLK, cgu)) |
| 217 | #define SYSCLK_n_RATIO(cgu) (((CGUn_MULT(cgu)) / \ |
| 218 | (1 + CONFIG_CGU##cgu##_DF_DIV)) / \ |
| 219 | CGUn_DIV(SCLK, cgu)) |
| 220 | #define PLL3_RATIO ((CONFIG_CGU1_PLL3_VCO_MSEL) / \ |
| 221 | (CONFIG_CGU1_PLL3_DCLK_DIV)) |
| 222 | |
| 223 | #if (1 == CONFIG_CDU0_CLKO2) |
| 224 | #define ARMCLK_IN 0 |
| 225 | #define ARMCLK_RATIO CCLK1_n_RATIO(0) |
| 226 | #elif (3 == CONFIG_CDU0_CLKO2) && \ |
| 227 | (defined(CONFIG_SC57X) || defined(CONFIG_SC58X)) |
| 228 | #define ARMCLK_IN 0 |
| 229 | #define ARMCLK_RATIO SYSCLK_n_RATIO(0) |
| 230 | #elif (5 == CONFIG_CDU0_CLKO2) && defined(CONFIG_SC59X_64) |
| 231 | #define ARMCLK_IN 0 |
| 232 | #define ARMCLK_RATIO CCLK2_n_RATIO(0) |
| 233 | #elif (7 == CONFIG_CDU0_CLKO2) && defined(CONFIG_SC59X_64) |
| 234 | #define ARMCLK_IN CDU0_CGU1_CLKIN |
| 235 | #define ARMCLK_RATIO CCLK2_n_RATIO(1) |
| 236 | #endif |
| 237 | |
| 238 | #ifdef CONFIG_CGU1_PLL3_DDRCLK |
| 239 | #define DDRCLK_IN CDU0_CGU1_CLKIN |
| 240 | #define DDRCLK_RATIO PLL3_RATIO |
| 241 | #elif (1 == CONFIG_CDU0_CLKO3) |
| 242 | #define DDRCLK_IN 0 |
| 243 | #define DDRCLK_RATIO DCLK_n_RATIO(0) |
| 244 | #elif (3 == CONFIG_CDU0_CLKO3) |
| 245 | #define DDRCLK_IN CDU0_CGU1_CLKIN |
| 246 | #define DDRCLK_RATIO DCLK_n_RATIO(1) |
| 247 | #endif |
| 248 | |
| 249 | #ifndef ARMCLK_RATIO |
| 250 | #error Invalid/unknown ARMCLK selection! |
| 251 | #endif |
| 252 | #ifndef DDRCLK_RATIO |
| 253 | #error Invalid/unknown DDRCLK selection! |
| 254 | #endif |
| 255 | |
| 256 | #define ARMDDR_CLK_RATIO_FPERCISION 1000 |
| 257 | |
| 258 | #if ARMCLK_IN != DDRCLK_IN |
| 259 | #ifndef CUSTOM_ARMDDR_CLK_RATIO |
| 260 | /** |
| 261 | * SYS_CLKINx are defined within the device tree, not configs. |
| 262 | * Thus, we can only determine cross-CGU clock ratios if they |
| 263 | * use the same SYS_CLKINx. |
| 264 | */ |
| 265 | #error Define CUSTOM_ARMDDR_CLK_RATIO for different SYS_CLKINs |
| 266 | #else |
| 267 | #define ARMDDR_CLK_RATIO CUSTOM_ARMDDR_CLK_RATIO |
| 268 | #endif |
| 269 | #else |
| 270 | #define ARMDDR_CLK_RATIO (ARMDDR_CLK_RATIO_FPERCISION *\ |
| 271 | ARMCLK_RATIO / DDRCLK_RATIO) |
| 272 | #endif |
| 273 | |
| 274 | void dmcdelay(uint32_t delay) |
| 275 | { |
| 276 | /* There is no zero-overhead loop on ARM, so assume each iteration |
| 277 | * takes 4 processor cycles (based on examination of -O3 and -Ofast |
| 278 | * output). |
| 279 | */ |
| 280 | u32 i, remainder; |
| 281 | |
| 282 | /* Convert DDR cycles to core clock cycles */ |
| 283 | u32 f = delay * ARMDDR_CLK_RATIO; |
| 284 | |
| 285 | delay = f + 500; |
| 286 | delay /= ARMDDR_CLK_RATIO_FPERCISION; |
| 287 | |
| 288 | /* Round up to multiple of 4 */ |
| 289 | remainder = delay % 4; |
| 290 | if (remainder != 0u) |
| 291 | delay += (4u - remainder); |
| 292 | |
| 293 | for (i = 0; i < delay; i += 4) |
| 294 | asm("nop"); |
| 295 | } |
| 296 | |
| 297 | static void program_cgu(const struct CGU_Settings *cgu) |
| 298 | { |
| 299 | const uintptr_t b = cgu->rbase; |
| 300 | const bool use_extension0 = cgu->divex_S0SELEX >= 0; |
| 301 | const bool use_extension1 = cgu->divex_S1SELEX >= 0; |
| 302 | u32 temp; |
| 303 | |
| 304 | temp = OSEL(cgu->div_OSEL); |
| 305 | temp |= SYSSEL(cgu->div_SYSSEL); |
| 306 | temp |= CSEL(cgu->div_CSEL); |
| 307 | temp |= DSEL(cgu->div_DSEL); |
| 308 | temp |= (S0SEL(cgu->div_S0SEL)); |
| 309 | temp |= (S1SEL(cgu->div_S1SEL)); |
| 310 | temp &= ~BITM_CGU_DIV_LOCK; |
| 311 | |
| 312 | //Put PLL in to Bypass Mode |
| 313 | writel(BITM_CGU_PLLCTL_PLLEN | BITM_CGU_PLLCTL_PLLBPST, |
| 314 | b + CGU_PLLCTL); |
| 315 | while (!(readl(b + CGU_STAT) & BITM_CGU_STAT_PLLBP)) |
| 316 | ; |
| 317 | |
| 318 | while (!((readl(b + CGU_STAT) & CGU_STAT_MASK) == CGU_STAT_ALGN_LOCK)) |
| 319 | ; |
| 320 | |
| 321 | dmcdelay(1000); |
| 322 | |
| 323 | writel(temp & (~BITM_CGU_DIV_ALGN) & (~BITM_CGU_DIV_UPDT), |
| 324 | b + CGU_DIV); |
| 325 | |
| 326 | dmcdelay(1000); |
| 327 | |
| 328 | temp = MSEL(cgu->ctl_MSEL) | DF(cgu->ctl_DF); |
| 329 | if (use_extension0) |
| 330 | temp |= BITM_CGU_CTL_S0SELEXEN; |
| 331 | if (use_extension1) |
| 332 | temp |= BITM_CGU_CTL_S1SELEXEN; |
| 333 | |
| 334 | writel(temp & (~BITM_CGU_CTL_LOCK), b + CGU_CTL); |
| 335 | |
| 336 | if (use_extension0 || use_extension1) { |
| 337 | u32 mask = BITM_CGU_CTL_S1SELEXEN | BITM_CGU_CTL_S0SELEXEN; |
| 338 | |
| 339 | while (!(readl(b + CGU_CTL) & mask)) |
| 340 | ; |
| 341 | |
| 342 | temp = readl(b + CGU_DIVEX); |
| 343 | |
| 344 | if (use_extension0) { |
| 345 | temp &= ~BITM_CGU_DIVEX_S0SELEX; |
| 346 | temp |= S0SELEX(cgu->divex_S0SELEX); |
| 347 | } |
| 348 | |
| 349 | if (use_extension1) { |
| 350 | temp &= ~BITM_CGU_DIVEX_S1SELEX; |
| 351 | temp |= S1SELEX(cgu->divex_S1SELEX); |
| 352 | } |
| 353 | |
| 354 | writel(temp, b + CGU_DIVEX); |
| 355 | } |
| 356 | |
| 357 | dmcdelay(1000); |
| 358 | |
| 359 | //Take PLL out of Bypass Mode |
| 360 | writel(BITM_CGU_PLLCTL_PLLEN | BITM_CGU_PLLCTL_PLLBPCL, |
| 361 | b + CGU_PLLCTL); |
| 362 | while ((readl(b + CGU_STAT) & |
| 363 | (BITM_CGU_STAT_PLLBP | BITM_CGU_STAT_CLKSALGN))) |
| 364 | ; |
| 365 | |
| 366 | dmcdelay(1000); |
| 367 | |
| 368 | if (cgu->clkoutsel >= 0) { |
| 369 | temp = readl(b + CGU_CLKOUTSEL); |
| 370 | temp &= ~BITM_CGU_CLKOUTSEL_CLKOUTSEL; |
| 371 | temp |= CLKOUTSEL(cgu->clkoutsel); |
| 372 | writel(temp, b + CGU_CLKOUTSEL); |
| 373 | } |
| 374 | } |
| 375 | |
| 376 | void adi_config_third_pll(void) |
| 377 | { |
| 378 | #if defined(CONFIG_CGU1_PLL3_VCO_MSEL) && defined(CONFIG_CGU1_PLL3_DCLK_DIV) |
| 379 | u32 temp; |
| 380 | |
| 381 | u32 msel = CONFIG_CGU1_PLL3_VCO_MSEL - 1; |
| 382 | u32 dsel = CONFIG_CGU1_PLL3_DCLK_DIV - 1; |
| 383 | |
| 384 | temp = readl(REG_MISC_REG10_tst_addr); |
| 385 | temp &= 0xFFFE0000; |
| 386 | writel(temp, REG_MISC_REG10_tst_addr); |
| 387 | |
| 388 | dmcdelay(4000u); |
| 389 | |
| 390 | //update MSEL [10:4] |
| 391 | temp = readl(REG_MISC_REG10_tst_addr); |
| 392 | temp |= ((msel << BITP_REG10_MSEL3) & BITM_REG10_MSEL3); |
| 393 | writel(temp, REG_MISC_REG10_tst_addr); |
| 394 | |
| 395 | temp = readl(REG_MISC_REG10_tst_addr); |
| 396 | temp |= 0x2; |
| 397 | writel(temp, REG_MISC_REG10_tst_addr); |
| 398 | |
| 399 | dmcdelay(100000u); |
| 400 | |
| 401 | temp = readl(REG_MISC_REG10_tst_addr); |
| 402 | temp |= 0x1; |
| 403 | writel(temp, REG_MISC_REG10_tst_addr); |
| 404 | |
| 405 | temp = readl(REG_MISC_REG10_tst_addr); |
| 406 | temp |= 0x800; |
| 407 | writel(temp, REG_MISC_REG10_tst_addr); |
| 408 | |
| 409 | temp = readl(REG_MISC_REG10_tst_addr); |
| 410 | temp &= 0xFFFFF7F8; |
| 411 | writel(temp, REG_MISC_REG10_tst_addr); |
| 412 | |
| 413 | dmcdelay(4000u); |
| 414 | |
| 415 | temp = readl(REG_MISC_REG10_tst_addr); |
| 416 | temp |= ((dsel << BITP_REG10_DSEL3) & BITM_REG10_DSEL3); |
| 417 | writel(temp, REG_MISC_REG10_tst_addr); |
| 418 | |
| 419 | temp = readl(REG_MISC_REG10_tst_addr); |
| 420 | temp |= 0x4; |
| 421 | writel(temp, REG_MISC_REG10_tst_addr); |
| 422 | |
| 423 | dmcdelay(100000u); |
| 424 | |
| 425 | temp = readl(REG_MISC_REG10_tst_addr); |
| 426 | temp |= 0x1; |
| 427 | writel(temp, REG_MISC_REG10_tst_addr); |
| 428 | |
| 429 | temp = readl(REG_MISC_REG10_tst_addr); |
| 430 | temp |= 0x800; |
| 431 | writel(temp, REG_MISC_REG10_tst_addr); |
| 432 | #endif |
| 433 | } |
| 434 | |
| 435 | static void Active_To_Fullon(const struct CGU_Settings *pCGU) |
| 436 | { |
| 437 | u32 tmp; |
| 438 | |
| 439 | while (1) { |
| 440 | tmp = readl(pCGU->rbase + CGU_STAT); |
| 441 | if ((tmp & BITM_CGU_STAT_PLLEN) && |
| 442 | (tmp & BITM_CGU_STAT_PLLBP)) |
| 443 | break; |
| 444 | } |
| 445 | |
| 446 | writel(BITM_CGU_PLLCTL_PLLBPCL, pCGU->rbase + CGU_PLLCTL); |
| 447 | |
| 448 | while (1) { |
| 449 | tmp = readl(pCGU->rbase + CGU_STAT); |
| 450 | if ((tmp & BITM_CGU_STAT_PLLEN) && |
| 451 | ~(tmp & BITM_CGU_STAT_PLLBP) && |
| 452 | ~(tmp & BITM_CGU_STAT_CLKSALGN)) |
| 453 | break; |
| 454 | } |
| 455 | } |
| 456 | |
| 457 | static void CGU_Init(const struct CGU_Settings *pCGU) |
| 458 | { |
| 459 | const uintptr_t b = pCGU->rbase; |
| 460 | |
| 461 | #if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64) |
| 462 | if (readl(b + CGU_STAT) & BITM_CGU_STAT_PLLEN) |
| 463 | writel(BITM_CGU_PLLCTL_PLLEN, b + CGU_PLLCTL); |
| 464 | |
| 465 | dmcdelay(1000); |
| 466 | #endif |
| 467 | |
| 468 | /* Check if processor is in Active mode */ |
| 469 | if (readl(b + CGU_STAT) & BITM_CGU_STAT_PLLBP) |
| 470 | Active_To_Fullon(pCGU); |
| 471 | |
| 472 | #if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64) |
| 473 | dmcdelay(1000); |
| 474 | #endif |
| 475 | |
| 476 | program_cgu(pCGU); |
| 477 | } |
| 478 | |
| 479 | void cgu_init(void) |
| 480 | { |
| 481 | const struct CGU_Settings dividers0 = { |
| 482 | .rbase = CGU0_REGBASE, |
| 483 | .ctl_MSEL = CONFIG_CGU0_VCO_MULT, |
| 484 | .ctl_DF = CONFIG_CGU0_DF_DIV, |
| 485 | .div_CSEL = CONFIG_CGU0_CCLK_DIV, |
| 486 | .div_SYSSEL = CONFIG_CGU0_SCLK_DIV, |
| 487 | .div_S0SEL = VAL_CGU0_SCLK0_DIV, |
| 488 | .div_S1SEL = VAL_CGU0_SCLK1_DIV, |
| 489 | .div_DSEL = CONFIG_CGU0_DCLK_DIV, |
| 490 | .div_OSEL = CONFIG_CGU0_OCLK_DIV, |
| 491 | .divex_S0SELEX = VAL_CGU0_DIV_S0SELEX, |
| 492 | .divex_S1SELEX = VAL_CGU0_DIV_S1SELEX, |
| 493 | .clkoutsel = VAL_CGU0_CLKOUTSEL, |
| 494 | }; |
| 495 | const struct CGU_Settings dividers1 = { |
| 496 | .rbase = CGU1_REGBASE, |
| 497 | .ctl_MSEL = CONFIG_CGU1_VCO_MULT, |
| 498 | .ctl_DF = CONFIG_CGU1_DF_DIV, |
| 499 | .div_CSEL = CONFIG_CGU1_CCLK_DIV, |
| 500 | .div_SYSSEL = CONFIG_CGU1_SCLK_DIV, |
| 501 | .div_S0SEL = VAL_CGU1_SCLK0_DIV, |
| 502 | .div_S1SEL = VAL_CGU1_SCLK1_DIV, |
| 503 | .div_DSEL = CONFIG_CGU1_DCLK_DIV, |
| 504 | .div_OSEL = CONFIG_CGU1_OCLK_DIV, |
| 505 | .divex_S0SELEX = VAL_CGU1_DIV_S0SELEX, |
| 506 | .divex_S1SELEX = VAL_CGU1_DIV_S1SELEX, |
| 507 | .clkoutsel = VAL_CGU1_CLKOUTSEL, |
| 508 | }; |
| 509 | |
| 510 | CGU_Init(÷rs0); |
| 511 | CGU_Init(÷rs1); |
| 512 | } |
| 513 | |
| 514 | #define CONFIGURE_CDU0(a, b, c) \ |
| 515 | writel(a, b); \ |
| 516 | while (readl(REG_CDU0_STAT) & (1 << (c))) |
| 517 | |
| 518 | void cdu_init(void) |
| 519 | { |
| 520 | while (readl(REG_CDU0_STAT) & 0xffff) |
| 521 | ; |
| 522 | writel((CONFIG_CDU0_CGU1_CLKIN & 0x1), REG_CDU0_CLKINSEL); |
| 523 | |
| 524 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO0, REG_CDU0_CFG0, 0); |
| 525 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO1, REG_CDU0_CFG1, 1); |
| 526 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO2, REG_CDU0_CFG2, 2); |
| 527 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO3, REG_CDU0_CFG3, 3); |
| 528 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO4, REG_CDU0_CFG4, 4); |
| 529 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO5, REG_CDU0_CFG5, 5); |
| 530 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO6, REG_CDU0_CFG6, 6); |
| 531 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO7, REG_CDU0_CFG7, 7); |
| 532 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO8, REG_CDU0_CFG8, 8); |
| 533 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO9, REG_CDU0_CFG9, 9); |
| 534 | #ifdef CONFIG_CDU0_CLKO10 |
| 535 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO10, REG_CDU0_CFG10, 10); |
| 536 | #endif |
| 537 | #ifdef CONFIG_CDU0_CLKO12 |
| 538 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO12, REG_CDU0_CFG12, 12); |
| 539 | #endif |
| 540 | #ifdef CONFIG_CDU0_CLKO13 |
| 541 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO13, REG_CDU0_CFG13, 13); |
| 542 | #endif |
| 543 | #ifdef CONFIG_CDU0_CLKO14 |
| 544 | CONFIGURE_CDU0(CONFIG_CDU0_CLKO14, REG_CDU0_CFG14, 14); |
| 545 | #endif |
| 546 | } |
| 547 | |
| 548 | void clks_init(void) |
| 549 | { |
| 550 | adi_dmc_reset_lanes(true); |
| 551 | |
| 552 | cdu_init(); |
| 553 | cgu_init(); |
| 554 | |
| 555 | adi_config_third_pll(); |
| 556 | |
| 557 | adi_dmc_reset_lanes(false); |
| 558 | } |