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