uboot/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2013 Broadcom Corporation.
   4 */
   5
   6/*
   7 *
   8 * bcm281xx-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 = 2,
 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        .policy0_mask2_offset = 0x00000048,
 303        .policy1_mask2_offset = 0x0000004c,
 304        .policy2_mask2_offset = 0x00000050,
 305        .policy3_mask2_offset = 0x00000054,
 306        .lvm_en_offset = 0x00000034,
 307        .freq_id = 2,
 308        .freq_tbl = slave_axi_freq_tbl,
 309};
 310
 311#ifdef CONFIG_BCM_SF2_ETH
 312static struct ccu_clock esub_ccu_clk = {
 313        .clk = {
 314                .name = "esub_ccu_clk",
 315                .ops = &ccu_clk_ops,
 316                .ccu_clk_mgr_base = ESUB_CLK_BASE_ADDR,
 317        },
 318        .num_policy_masks = 1,
 319        .policy_freq_offset = 0x00000008,
 320        .freq_bit_shift = 8,
 321        .policy_ctl_offset = 0x0000000c,
 322        .policy0_mask_offset = 0x00000010,
 323        .policy1_mask_offset = 0x00000014,
 324        .policy2_mask_offset = 0x00000018,
 325        .policy3_mask_offset = 0x0000001c,
 326        .lvm_en_offset = 0x00000034,
 327        .freq_id = 2,
 328        .freq_tbl = esub_freq_tbl,
 329};
 330#endif
 331
 332/*
 333 * Bus clocks
 334 */
 335
 336/* KPM bus clocks */
 337static struct bus_clock usb_otg_ahb_clk = {
 338        .clk = {
 339                .name = "usb_otg_ahb_clk",
 340                .parent = &kpm_ccu_clk.clk,
 341                .ops = &bus_clk_ops,
 342                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 343        },
 344        .freq_tbl = master_ahb_freq_tbl,
 345        .data = &usb_otg_ahb_data,
 346};
 347
 348static struct bus_clock sdio1_ahb_clk = {
 349        .clk = {
 350                .name = "sdio1_ahb_clk",
 351                .parent = &kpm_ccu_clk.clk,
 352                .ops = &bus_clk_ops,
 353                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 354        },
 355        .freq_tbl = master_ahb_freq_tbl,
 356        .data = &sdio1_ahb_data,
 357};
 358
 359static struct bus_clock sdio2_ahb_clk = {
 360        .clk = {
 361                .name = "sdio2_ahb_clk",
 362                .parent = &kpm_ccu_clk.clk,
 363                .ops = &bus_clk_ops,
 364                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 365        },
 366        .freq_tbl = master_ahb_freq_tbl,
 367        .data = &sdio2_ahb_data,
 368};
 369
 370static struct bus_clock sdio3_ahb_clk = {
 371        .clk = {
 372                .name = "sdio3_ahb_clk",
 373                .parent = &kpm_ccu_clk.clk,
 374                .ops = &bus_clk_ops,
 375                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 376        },
 377        .freq_tbl = master_ahb_freq_tbl,
 378        .data = &sdio3_ahb_data,
 379};
 380
 381static struct bus_clock sdio4_ahb_clk = {
 382        .clk = {
 383                .name = "sdio4_ahb_clk",
 384                .parent = &kpm_ccu_clk.clk,
 385                .ops = &bus_clk_ops,
 386                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 387        },
 388        .freq_tbl = master_ahb_freq_tbl,
 389        .data = &sdio4_ahb_data,
 390};
 391
 392static struct bus_clock bsc1_apb_clk = {
 393        .clk = {
 394                .name = "bsc1_apb_clk",
 395                .parent = &kps_ccu_clk.clk,
 396                .ops = &bus_clk_ops,
 397                .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
 398        },
 399        .freq_tbl = slave_apb_freq_tbl,
 400        .data = &bsc1_apb_data,
 401};
 402
 403static struct bus_clock bsc2_apb_clk = {
 404        .clk = {
 405                .name = "bsc2_apb_clk",
 406                .parent = &kps_ccu_clk.clk,
 407                .ops = &bus_clk_ops,
 408                .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
 409                },
 410        .freq_tbl = slave_apb_freq_tbl,
 411        .data = &bsc2_apb_data,
 412};
 413
 414static struct bus_clock bsc3_apb_clk = {
 415        .clk = {
 416                .name = "bsc3_apb_clk",
 417                .parent = &kps_ccu_clk.clk,
 418                .ops = &bus_clk_ops,
 419                .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
 420                },
 421        .freq_tbl = slave_apb_freq_tbl,
 422        .data = &bsc3_apb_data,
 423};
 424
 425/* KPM peripheral */
 426static struct peri_clock sdio1_clk = {
 427        .clk = {
 428                .name = "sdio1_clk",
 429                .parent = &ref_52m.clk,
 430                .ops = &peri_clk_ops,
 431                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 432        },
 433        .data = &sdio1_data,
 434};
 435
 436static struct peri_clock sdio2_clk = {
 437        .clk = {
 438                .name = "sdio2_clk",
 439                .parent = &ref_52m.clk,
 440                .ops = &peri_clk_ops,
 441                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 442        },
 443        .data = &sdio2_data,
 444};
 445
 446static struct peri_clock sdio3_clk = {
 447        .clk = {
 448                .name = "sdio3_clk",
 449                .parent = &ref_52m.clk,
 450                .ops = &peri_clk_ops,
 451                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 452        },
 453        .data = &sdio3_data,
 454};
 455
 456static struct peri_clock sdio4_clk = {
 457        .clk = {
 458                .name = "sdio4_clk",
 459                .parent = &ref_52m.clk,
 460                .ops = &peri_clk_ops,
 461                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 462        },
 463        .data = &sdio4_data,
 464};
 465
 466static struct peri_clock sdio1_sleep_clk = {
 467        .clk = {
 468                .name = "sdio1_sleep_clk",
 469                .parent = &kpm_ccu_clk.clk,
 470                .ops = &bus_clk_ops,
 471                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 472        },
 473        .data = &sdio1_sleep_data,
 474};
 475
 476static struct peri_clock sdio2_sleep_clk = {
 477        .clk = {
 478                .name = "sdio2_sleep_clk",
 479                .parent = &kpm_ccu_clk.clk,
 480                .ops = &bus_clk_ops,
 481                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 482        },
 483        .data = &sdio2_sleep_data,
 484};
 485
 486static struct peri_clock sdio3_sleep_clk = {
 487        .clk = {
 488                .name = "sdio3_sleep_clk",
 489                .parent = &kpm_ccu_clk.clk,
 490                .ops = &bus_clk_ops,
 491                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 492        },
 493        .data = &sdio3_sleep_data,
 494};
 495
 496static struct peri_clock sdio4_sleep_clk = {
 497        .clk = {
 498                .name = "sdio4_sleep_clk",
 499                .parent = &kpm_ccu_clk.clk,
 500                .ops = &bus_clk_ops,
 501                .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
 502        },
 503        .data = &sdio4_sleep_data,
 504};
 505
 506/* KPS peripheral clock */
 507static struct peri_clock bsc1_clk = {
 508        .clk = {
 509                .name = "bsc1_clk",
 510                .parent = &ref_13m.clk,
 511                .rate = 13 * CLOCK_1M,
 512                .div = 1,
 513                .ops = &peri_clk_ops,
 514                .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
 515        },
 516        .data = &bsc1_data,
 517};
 518
 519static struct peri_clock bsc2_clk = {
 520        .clk = {
 521                .name = "bsc2_clk",
 522                .parent = &ref_13m.clk,
 523                .rate = 13 * CLOCK_1M,
 524                .div = 1,
 525                .ops = &peri_clk_ops,
 526                .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
 527        },
 528        .data = &bsc2_data,
 529};
 530
 531static struct peri_clock bsc3_clk = {
 532        .clk = {
 533                .name = "bsc3_clk",
 534                .parent = &ref_13m.clk,
 535                .rate = 13 * CLOCK_1M,
 536                .div = 1,
 537                .ops = &peri_clk_ops,
 538                .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
 539        },
 540        .data = &bsc3_data,
 541};
 542
 543/* public table for registering clocks */
 544struct clk_lookup arch_clk_tbl[] = {
 545        /* Peripheral clocks */
 546        CLK_LK(sdio1),
 547        CLK_LK(sdio2),
 548        CLK_LK(sdio3),
 549        CLK_LK(sdio4),
 550        CLK_LK(sdio1_sleep),
 551        CLK_LK(sdio2_sleep),
 552        CLK_LK(sdio3_sleep),
 553        CLK_LK(sdio4_sleep),
 554        CLK_LK(bsc1),
 555        CLK_LK(bsc2),
 556        CLK_LK(bsc3),
 557        /* Bus clocks */
 558        CLK_LK(usb_otg_ahb),
 559        CLK_LK(sdio1_ahb),
 560        CLK_LK(sdio2_ahb),
 561        CLK_LK(sdio3_ahb),
 562        CLK_LK(sdio4_ahb),
 563        CLK_LK(bsc1_apb),
 564        CLK_LK(bsc2_apb),
 565        CLK_LK(bsc3_apb),
 566#ifdef CONFIG_BCM_SF2_ETH
 567        CLK_LK(esub_ccu),
 568#endif
 569};
 570
 571/* public array size */
 572unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);
 573