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