1 /* 2 * Copyright 2013 Broadcom Corporation. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 /* 8 * 9 * bcm281xx-specific clock tables 10 * 11 */ 12 13 #include <common.h> 14 #include <asm/io.h> 15 #include <asm/errno.h> 16 #include <asm/arch/sysmap.h> 17 #include <asm/kona-common/clk.h> 18 #include "clk-core.h" 19 20 #define CLOCK_1K 1000 21 #define CLOCK_1M (CLOCK_1K * 1000) 22 23 /* declare a reference clock */ 24 #define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \ 25 static struct refclk clk_name = { \ 26 .clk = { \ 27 .name = #clk_name, \ 28 .parent = clk_parent, \ 29 .rate = clk_rate, \ 30 .div = clk_div, \ 31 .ops = &ref_clk_ops, \ 32 }, \ 33 } 34 35 /* 36 * Reference clocks 37 */ 38 39 /* Declare a list of reference clocks */ 40 DECLARE_REF_CLK(ref_crystal, 0, 26 * CLOCK_1M, 1); 41 DECLARE_REF_CLK(var_96m, 0, 96 * CLOCK_1M, 1); 42 DECLARE_REF_CLK(ref_96m, 0, 96 * CLOCK_1M, 1); 43 DECLARE_REF_CLK(ref_312m, 0, 312 * CLOCK_1M, 0); 44 DECLARE_REF_CLK(ref_104m, &ref_312m.clk, 104 * CLOCK_1M, 3); 45 DECLARE_REF_CLK(ref_52m, &ref_104m.clk, 52 * CLOCK_1M, 2); 46 DECLARE_REF_CLK(ref_13m, &ref_52m.clk, 13 * CLOCK_1M, 4); 47 DECLARE_REF_CLK(var_312m, 0, 312 * CLOCK_1M, 0); 48 DECLARE_REF_CLK(var_104m, &var_312m.clk, 104 * CLOCK_1M, 3); 49 DECLARE_REF_CLK(var_52m, &var_104m.clk, 52 * CLOCK_1M, 2); 50 DECLARE_REF_CLK(var_13m, &var_52m.clk, 13 * CLOCK_1M, 4); 51 52 struct refclk_lkup { 53 struct refclk *procclk; 54 const char *name; 55 }; 56 57 /* Lookup table for string to clk tranlation */ 58 #define MKSTR(x) {&x, #x} 59 static struct refclk_lkup refclk_str_tbl[] = { 60 MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m), 61 MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m), 62 MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m), 63 MKSTR(var_52m), MKSTR(var_13m), 64 }; 65 66 int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]); 67 68 /* convert ref clock string to clock structure pointer */ 69 struct refclk *refclk_str_to_clk(const char *name) 70 { 71 int i; 72 struct refclk_lkup *tblp = refclk_str_tbl; 73 for (i = 0; i < refclk_entries; i++, tblp++) { 74 if (!(strcmp(name, tblp->name))) 75 return tblp->procclk; 76 } 77 return NULL; 78 } 79 80 /* frequency tables indexed by freq_id */ 81 unsigned long master_axi_freq_tbl[8] = { 82 26 * CLOCK_1M, 83 52 * CLOCK_1M, 84 104 * CLOCK_1M, 85 156 * CLOCK_1M, 86 156 * CLOCK_1M, 87 208 * CLOCK_1M, 88 312 * CLOCK_1M, 89 312 * CLOCK_1M 90 }; 91 92 unsigned long master_ahb_freq_tbl[8] = { 93 26 * CLOCK_1M, 94 52 * CLOCK_1M, 95 52 * CLOCK_1M, 96 52 * CLOCK_1M, 97 78 * CLOCK_1M, 98 104 * CLOCK_1M, 99 104 * CLOCK_1M, 100 156 * CLOCK_1M 101 }; 102 103 unsigned long slave_axi_freq_tbl[8] = { 104 26 * CLOCK_1M, 105 52 * CLOCK_1M, 106 78 * CLOCK_1M, 107 104 * CLOCK_1M, 108 156 * CLOCK_1M, 109 156 * CLOCK_1M 110 }; 111 112 unsigned long slave_apb_freq_tbl[8] = { 113 26 * CLOCK_1M, 114 26 * CLOCK_1M, 115 39 * CLOCK_1M, 116 52 * CLOCK_1M, 117 52 * CLOCK_1M, 118 78 * CLOCK_1M 119 }; 120 121 static struct bus_clk_data bsc1_apb_data = { 122 .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1), 123 }; 124 125 static struct bus_clk_data bsc2_apb_data = { 126 .gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1), 127 }; 128 129 static struct bus_clk_data bsc3_apb_data = { 130 .gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1), 131 }; 132 133 /* * Master CCU clocks */ 134 static struct peri_clk_data sdio1_data = { 135 .gate = HW_SW_GATE(0x0358, 18, 2, 3), 136 .clocks = CLOCKS("ref_crystal", 137 "var_52m", 138 "ref_52m", 139 "var_96m", 140 "ref_96m"), 141 .sel = SELECTOR(0x0a28, 0, 3), 142 .div = DIVIDER(0x0a28, 4, 14), 143 .trig = TRIGGER(0x0afc, 9), 144 }; 145 146 static struct peri_clk_data sdio2_data = { 147 .gate = HW_SW_GATE(0x035c, 18, 2, 3), 148 .clocks = CLOCKS("ref_crystal", 149 "var_52m", 150 "ref_52m", 151 "var_96m", 152 "ref_96m"), 153 .sel = SELECTOR(0x0a2c, 0, 3), 154 .div = DIVIDER(0x0a2c, 4, 14), 155 .trig = TRIGGER(0x0afc, 10), 156 }; 157 158 static struct peri_clk_data sdio3_data = { 159 .gate = HW_SW_GATE(0x0364, 18, 2, 3), 160 .clocks = CLOCKS("ref_crystal", 161 "var_52m", 162 "ref_52m", 163 "var_96m", 164 "ref_96m"), 165 .sel = SELECTOR(0x0a34, 0, 3), 166 .div = DIVIDER(0x0a34, 4, 14), 167 .trig = TRIGGER(0x0afc, 12), 168 }; 169 170 static struct peri_clk_data sdio4_data = { 171 .gate = HW_SW_GATE(0x0360, 18, 2, 3), 172 .clocks = CLOCKS("ref_crystal", 173 "var_52m", 174 "ref_52m", 175 "var_96m", 176 "ref_96m"), 177 .sel = SELECTOR(0x0a30, 0, 3), 178 .div = DIVIDER(0x0a30, 4, 14), 179 .trig = TRIGGER(0x0afc, 11), 180 }; 181 182 static struct peri_clk_data sdio1_sleep_data = { 183 .clocks = CLOCKS("ref_32k"), 184 .gate = SW_ONLY_GATE(0x0358, 20, 4), 185 }; 186 187 static struct peri_clk_data sdio2_sleep_data = { 188 .clocks = CLOCKS("ref_32k"), 189 .gate = SW_ONLY_GATE(0x035c, 20, 4), 190 }; 191 192 static struct peri_clk_data sdio3_sleep_data = { 193 .clocks = CLOCKS("ref_32k"), 194 .gate = SW_ONLY_GATE(0x0364, 20, 4), 195 }; 196 197 static struct peri_clk_data sdio4_sleep_data = { 198 .clocks = CLOCKS("ref_32k"), 199 .gate = SW_ONLY_GATE(0x0360, 20, 4), 200 }; 201 202 static struct bus_clk_data sdio1_ahb_data = { 203 .gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1), 204 }; 205 206 static struct bus_clk_data sdio2_ahb_data = { 207 .gate = HW_SW_GATE_AUTO(0x035c, 16, 0, 1), 208 }; 209 210 static struct bus_clk_data sdio3_ahb_data = { 211 .gate = HW_SW_GATE_AUTO(0x0364, 16, 0, 1), 212 }; 213 214 static struct bus_clk_data sdio4_ahb_data = { 215 .gate = HW_SW_GATE_AUTO(0x0360, 16, 0, 1), 216 }; 217 218 /* * Slave CCU clocks */ 219 static struct peri_clk_data bsc1_data = { 220 .gate = HW_SW_GATE(0x0458, 18, 2, 3), 221 .clocks = CLOCKS("ref_crystal", 222 "var_104m", 223 "ref_104m", 224 "var_13m", 225 "ref_13m"), 226 .sel = SELECTOR(0x0a64, 0, 3), 227 .trig = TRIGGER(0x0afc, 23), 228 }; 229 230 static struct peri_clk_data bsc2_data = { 231 .gate = HW_SW_GATE(0x045c, 18, 2, 3), 232 .clocks = CLOCKS("ref_crystal", 233 "var_104m", 234 "ref_104m", 235 "var_13m", 236 "ref_13m"), 237 .sel = SELECTOR(0x0a68, 0, 3), 238 .trig = TRIGGER(0x0afc, 24), 239 }; 240 241 static struct peri_clk_data bsc3_data = { 242 .gate = HW_SW_GATE(0x0484, 18, 2, 3), 243 .clocks = CLOCKS("ref_crystal", 244 "var_104m", 245 "ref_104m", 246 "var_13m", 247 "ref_13m"), 248 .sel = SELECTOR(0x0a84, 0, 3), 249 .trig = TRIGGER(0x0b00, 2), 250 }; 251 252 /* 253 * CCU clocks 254 */ 255 256 static struct ccu_clock kpm_ccu_clk = { 257 .clk = { 258 .name = "kpm_ccu_clk", 259 .ops = &ccu_clk_ops, 260 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 261 }, 262 .num_policy_masks = 1, 263 .policy_freq_offset = 0x00000008, 264 .freq_bit_shift = 8, 265 .policy_ctl_offset = 0x0000000c, 266 .policy0_mask_offset = 0x00000010, 267 .policy1_mask_offset = 0x00000014, 268 .policy2_mask_offset = 0x00000018, 269 .policy3_mask_offset = 0x0000001c, 270 .lvm_en_offset = 0x00000034, 271 .freq_id = 2, 272 .freq_tbl = master_axi_freq_tbl, 273 }; 274 275 static struct ccu_clock kps_ccu_clk = { 276 .clk = { 277 .name = "kps_ccu_clk", 278 .ops = &ccu_clk_ops, 279 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, 280 }, 281 .num_policy_masks = 2, 282 .policy_freq_offset = 0x00000008, 283 .freq_bit_shift = 8, 284 .policy_ctl_offset = 0x0000000c, 285 .policy0_mask_offset = 0x00000010, 286 .policy1_mask_offset = 0x00000014, 287 .policy2_mask_offset = 0x00000018, 288 .policy3_mask_offset = 0x0000001c, 289 .policy0_mask2_offset = 0x00000048, 290 .policy1_mask2_offset = 0x0000004c, 291 .policy2_mask2_offset = 0x00000050, 292 .policy3_mask2_offset = 0x00000054, 293 .lvm_en_offset = 0x00000034, 294 .freq_id = 2, 295 .freq_tbl = slave_axi_freq_tbl, 296 }; 297 298 /* 299 * Bus clocks 300 */ 301 302 /* KPM bus clocks */ 303 static struct bus_clock sdio1_ahb_clk = { 304 .clk = { 305 .name = "sdio1_ahb_clk", 306 .parent = &kpm_ccu_clk.clk, 307 .ops = &bus_clk_ops, 308 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 309 }, 310 .freq_tbl = master_ahb_freq_tbl, 311 .data = &sdio1_ahb_data, 312 }; 313 314 static struct bus_clock sdio2_ahb_clk = { 315 .clk = { 316 .name = "sdio2_ahb_clk", 317 .parent = &kpm_ccu_clk.clk, 318 .ops = &bus_clk_ops, 319 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 320 }, 321 .freq_tbl = master_ahb_freq_tbl, 322 .data = &sdio2_ahb_data, 323 }; 324 325 static struct bus_clock sdio3_ahb_clk = { 326 .clk = { 327 .name = "sdio3_ahb_clk", 328 .parent = &kpm_ccu_clk.clk, 329 .ops = &bus_clk_ops, 330 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 331 }, 332 .freq_tbl = master_ahb_freq_tbl, 333 .data = &sdio3_ahb_data, 334 }; 335 336 static struct bus_clock sdio4_ahb_clk = { 337 .clk = { 338 .name = "sdio4_ahb_clk", 339 .parent = &kpm_ccu_clk.clk, 340 .ops = &bus_clk_ops, 341 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 342 }, 343 .freq_tbl = master_ahb_freq_tbl, 344 .data = &sdio4_ahb_data, 345 }; 346 347 static struct bus_clock bsc1_apb_clk = { 348 .clk = { 349 .name = "bsc1_apb_clk", 350 .parent = &kps_ccu_clk.clk, 351 .ops = &bus_clk_ops, 352 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, 353 }, 354 .freq_tbl = slave_apb_freq_tbl, 355 .data = &bsc1_apb_data, 356 }; 357 358 static struct bus_clock bsc2_apb_clk = { 359 .clk = { 360 .name = "bsc2_apb_clk", 361 .parent = &kps_ccu_clk.clk, 362 .ops = &bus_clk_ops, 363 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, 364 }, 365 .freq_tbl = slave_apb_freq_tbl, 366 .data = &bsc2_apb_data, 367 }; 368 369 static struct bus_clock bsc3_apb_clk = { 370 .clk = { 371 .name = "bsc3_apb_clk", 372 .parent = &kps_ccu_clk.clk, 373 .ops = &bus_clk_ops, 374 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, 375 }, 376 .freq_tbl = slave_apb_freq_tbl, 377 .data = &bsc3_apb_data, 378 }; 379 380 /* KPM peripheral */ 381 static struct peri_clock sdio1_clk = { 382 .clk = { 383 .name = "sdio1_clk", 384 .parent = &ref_52m.clk, 385 .ops = &peri_clk_ops, 386 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 387 }, 388 .data = &sdio1_data, 389 }; 390 391 static struct peri_clock sdio2_clk = { 392 .clk = { 393 .name = "sdio2_clk", 394 .parent = &ref_52m.clk, 395 .ops = &peri_clk_ops, 396 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 397 }, 398 .data = &sdio2_data, 399 }; 400 401 static struct peri_clock sdio3_clk = { 402 .clk = { 403 .name = "sdio3_clk", 404 .parent = &ref_52m.clk, 405 .ops = &peri_clk_ops, 406 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 407 }, 408 .data = &sdio3_data, 409 }; 410 411 static struct peri_clock sdio4_clk = { 412 .clk = { 413 .name = "sdio4_clk", 414 .parent = &ref_52m.clk, 415 .ops = &peri_clk_ops, 416 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 417 }, 418 .data = &sdio4_data, 419 }; 420 421 static struct peri_clock sdio1_sleep_clk = { 422 .clk = { 423 .name = "sdio1_sleep_clk", 424 .parent = &kpm_ccu_clk.clk, 425 .ops = &bus_clk_ops, 426 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 427 }, 428 .data = &sdio1_sleep_data, 429 }; 430 431 static struct peri_clock sdio2_sleep_clk = { 432 .clk = { 433 .name = "sdio2_sleep_clk", 434 .parent = &kpm_ccu_clk.clk, 435 .ops = &bus_clk_ops, 436 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 437 }, 438 .data = &sdio2_sleep_data, 439 }; 440 441 static struct peri_clock sdio3_sleep_clk = { 442 .clk = { 443 .name = "sdio3_sleep_clk", 444 .parent = &kpm_ccu_clk.clk, 445 .ops = &bus_clk_ops, 446 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 447 }, 448 .data = &sdio3_sleep_data, 449 }; 450 451 static struct peri_clock sdio4_sleep_clk = { 452 .clk = { 453 .name = "sdio4_sleep_clk", 454 .parent = &kpm_ccu_clk.clk, 455 .ops = &bus_clk_ops, 456 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, 457 }, 458 .data = &sdio4_sleep_data, 459 }; 460 461 /* KPS peripheral clock */ 462 static struct peri_clock bsc1_clk = { 463 .clk = { 464 .name = "bsc1_clk", 465 .parent = &ref_13m.clk, 466 .rate = 13 * CLOCK_1M, 467 .div = 1, 468 .ops = &peri_clk_ops, 469 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, 470 }, 471 .data = &bsc1_data, 472 }; 473 474 static struct peri_clock bsc2_clk = { 475 .clk = { 476 .name = "bsc2_clk", 477 .parent = &ref_13m.clk, 478 .rate = 13 * CLOCK_1M, 479 .div = 1, 480 .ops = &peri_clk_ops, 481 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, 482 }, 483 .data = &bsc2_data, 484 }; 485 486 static struct peri_clock bsc3_clk = { 487 .clk = { 488 .name = "bsc3_clk", 489 .parent = &ref_13m.clk, 490 .rate = 13 * CLOCK_1M, 491 .div = 1, 492 .ops = &peri_clk_ops, 493 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, 494 }, 495 .data = &bsc3_data, 496 }; 497 498 /* public table for registering clocks */ 499 struct clk_lookup arch_clk_tbl[] = { 500 /* Peripheral clocks */ 501 CLK_LK(sdio1), 502 CLK_LK(sdio2), 503 CLK_LK(sdio3), 504 CLK_LK(sdio4), 505 CLK_LK(sdio1_sleep), 506 CLK_LK(sdio2_sleep), 507 CLK_LK(sdio3_sleep), 508 CLK_LK(sdio4_sleep), 509 CLK_LK(bsc1), 510 CLK_LK(bsc2), 511 CLK_LK(bsc3), 512 /* Bus clocks */ 513 CLK_LK(sdio1_ahb), 514 CLK_LK(sdio2_ahb), 515 CLK_LK(sdio3_ahb), 516 CLK_LK(sdio4_ahb), 517 CLK_LK(bsc1_apb), 518 CLK_LK(bsc2_apb), 519 CLK_LK(bsc3_apb), 520 }; 521 522 /* public array size */ 523 unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl); 524