root/drivers/clk/berlin/bg2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. berlin2_clock_setup

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2014 Marvell Technology Group Ltd.
   4  *
   5  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
   6  * Alexandre Belloni <alexandre.belloni@free-electrons.com>
   7  */
   8 
   9 #include <linux/clk.h>
  10 #include <linux/clk-provider.h>
  11 #include <linux/io.h>
  12 #include <linux/kernel.h>
  13 #include <linux/of.h>
  14 #include <linux/of_address.h>
  15 #include <linux/slab.h>
  16 
  17 #include <dt-bindings/clock/berlin2.h>
  18 
  19 #include "berlin2-avpll.h"
  20 #include "berlin2-div.h"
  21 #include "berlin2-pll.h"
  22 #include "common.h"
  23 
  24 #define REG_PINMUX0             0x0000
  25 #define REG_PINMUX1             0x0004
  26 #define REG_SYSPLLCTL0          0x0014
  27 #define REG_SYSPLLCTL4          0x0024
  28 #define REG_MEMPLLCTL0          0x0028
  29 #define REG_MEMPLLCTL4          0x0038
  30 #define REG_CPUPLLCTL0          0x003c
  31 #define REG_CPUPLLCTL4          0x004c
  32 #define REG_AVPLLCTL0           0x0050
  33 #define REG_AVPLLCTL31          0x00cc
  34 #define REG_AVPLLCTL62          0x0148
  35 #define REG_PLLSTATUS           0x014c
  36 #define REG_CLKENABLE           0x0150
  37 #define REG_CLKSELECT0          0x0154
  38 #define REG_CLKSELECT1          0x0158
  39 #define REG_CLKSELECT2          0x015c
  40 #define REG_CLKSELECT3          0x0160
  41 #define REG_CLKSWITCH0          0x0164
  42 #define REG_CLKSWITCH1          0x0168
  43 #define REG_RESET_TRIGGER       0x0178
  44 #define REG_RESET_STATUS0       0x017c
  45 #define REG_RESET_STATUS1       0x0180
  46 #define REG_SW_GENERIC0         0x0184
  47 #define REG_SW_GENERIC3         0x0190
  48 #define REG_PRODUCTID           0x01cc
  49 #define REG_PRODUCTID_EXT       0x01d0
  50 #define REG_GFX3DCORE_CLKCTL    0x022c
  51 #define REG_GFX3DSYS_CLKCTL     0x0230
  52 #define REG_ARC_CLKCTL          0x0234
  53 #define REG_VIP_CLKCTL          0x0238
  54 #define REG_SDIO0XIN_CLKCTL     0x023c
  55 #define REG_SDIO1XIN_CLKCTL     0x0240
  56 #define REG_GFX3DEXTRA_CLKCTL   0x0244
  57 #define REG_GFX3D_RESET         0x0248
  58 #define REG_GC360_CLKCTL        0x024c
  59 #define REG_SDIO_DLLMST_CLKCTL  0x0250
  60 
  61 /*
  62  * BG2/BG2CD SoCs have the following audio/video I/O units:
  63  *
  64  * audiohd: HDMI TX audio
  65  * audio0:  7.1ch TX
  66  * audio1:  2ch TX
  67  * audio2:  2ch RX
  68  * audio3:  SPDIF TX
  69  * video0:  HDMI video
  70  * video1:  Secondary video
  71  * video2:  SD auxiliary video
  72  *
  73  * There are no external audio clocks (ACLKI0, ACLKI1) and
  74  * only one external video clock (VCLKI0).
  75  *
  76  * Currently missing bits and pieces:
  77  * - audio_fast_pll is unknown
  78  * - audiohd_pll is unknown
  79  * - video0_pll is unknown
  80  * - audio[023], audiohd parent pll is assumed to be audio_fast_pll
  81  *
  82  */
  83 
  84 #define MAX_CLKS 41
  85 static struct clk_hw_onecell_data *clk_data;
  86 static DEFINE_SPINLOCK(lock);
  87 static void __iomem *gbase;
  88 
  89 enum {
  90         REFCLK, VIDEO_EXT0,
  91         SYSPLL, MEMPLL, CPUPLL,
  92         AVPLL_A1, AVPLL_A2, AVPLL_A3, AVPLL_A4,
  93         AVPLL_A5, AVPLL_A6, AVPLL_A7, AVPLL_A8,
  94         AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
  95         AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
  96         AUDIO1_PLL, AUDIO_FAST_PLL,
  97         VIDEO0_PLL, VIDEO0_IN,
  98         VIDEO1_PLL, VIDEO1_IN,
  99         VIDEO2_PLL, VIDEO2_IN,
 100 };
 101 
 102 static const char *clk_names[] = {
 103         [REFCLK]                = "refclk",
 104         [VIDEO_EXT0]            = "video_ext0",
 105         [SYSPLL]                = "syspll",
 106         [MEMPLL]                = "mempll",
 107         [CPUPLL]                = "cpupll",
 108         [AVPLL_A1]              = "avpll_a1",
 109         [AVPLL_A2]              = "avpll_a2",
 110         [AVPLL_A3]              = "avpll_a3",
 111         [AVPLL_A4]              = "avpll_a4",
 112         [AVPLL_A5]              = "avpll_a5",
 113         [AVPLL_A6]              = "avpll_a6",
 114         [AVPLL_A7]              = "avpll_a7",
 115         [AVPLL_A8]              = "avpll_a8",
 116         [AVPLL_B1]              = "avpll_b1",
 117         [AVPLL_B2]              = "avpll_b2",
 118         [AVPLL_B3]              = "avpll_b3",
 119         [AVPLL_B4]              = "avpll_b4",
 120         [AVPLL_B5]              = "avpll_b5",
 121         [AVPLL_B6]              = "avpll_b6",
 122         [AVPLL_B7]              = "avpll_b7",
 123         [AVPLL_B8]              = "avpll_b8",
 124         [AUDIO1_PLL]            = "audio1_pll",
 125         [AUDIO_FAST_PLL]        = "audio_fast_pll",
 126         [VIDEO0_PLL]            = "video0_pll",
 127         [VIDEO0_IN]             = "video0_in",
 128         [VIDEO1_PLL]            = "video1_pll",
 129         [VIDEO1_IN]             = "video1_in",
 130         [VIDEO2_PLL]            = "video2_pll",
 131         [VIDEO2_IN]             = "video2_in",
 132 };
 133 
 134 static const struct berlin2_pll_map bg2_pll_map __initconst = {
 135         .vcodiv         = {10, 15, 20, 25, 30, 40, 50, 60, 80},
 136         .mult           = 10,
 137         .fbdiv_shift    = 6,
 138         .rfdiv_shift    = 1,
 139         .divsel_shift   = 7,
 140 };
 141 
 142 static const u8 default_parent_ids[] = {
 143         SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL
 144 };
 145 
 146 static const struct berlin2_div_data bg2_divs[] __initconst = {
 147         {
 148                 .name = "sys",
 149                 .parent_ids = (const u8 []){
 150                         SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
 151                 },
 152                 .num_parents = 6,
 153                 .map = {
 154                         BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
 155                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
 156                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
 157                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
 158                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
 159                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
 160                 },
 161                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 162                 .flags = CLK_IGNORE_UNUSED,
 163         },
 164         {
 165                 .name = "cpu",
 166                 .parent_ids = (const u8 []){
 167                         CPUPLL, MEMPLL, MEMPLL, MEMPLL, MEMPLL
 168                 },
 169                 .num_parents = 5,
 170                 .map = {
 171                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
 172                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
 173                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
 174                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
 175                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
 176                 },
 177                 .div_flags = BERLIN2_DIV_HAS_MUX,
 178                 .flags = 0,
 179         },
 180         {
 181                 .name = "drmfigo",
 182                 .parent_ids = default_parent_ids,
 183                 .num_parents = ARRAY_SIZE(default_parent_ids),
 184                 .map = {
 185                         BERLIN2_DIV_GATE(REG_CLKENABLE, 16),
 186                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 17),
 187                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 20),
 188                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
 189                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
 190                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
 191                 },
 192                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 193                 .flags = 0,
 194         },
 195         {
 196                 .name = "cfg",
 197                 .parent_ids = default_parent_ids,
 198                 .num_parents = ARRAY_SIZE(default_parent_ids),
 199                 .map = {
 200                         BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
 201                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 23),
 202                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 26),
 203                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
 204                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
 205                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
 206                 },
 207                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 208                 .flags = 0,
 209         },
 210         {
 211                 .name = "gfx",
 212                 .parent_ids = default_parent_ids,
 213                 .num_parents = ARRAY_SIZE(default_parent_ids),
 214                 .map = {
 215                         BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
 216                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 29),
 217                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 0),
 218                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
 219                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
 220                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
 221                 },
 222                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 223                 .flags = 0,
 224         },
 225         {
 226                 .name = "zsp",
 227                 .parent_ids = default_parent_ids,
 228                 .num_parents = ARRAY_SIZE(default_parent_ids),
 229                 .map = {
 230                         BERLIN2_DIV_GATE(REG_CLKENABLE, 5),
 231                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 3),
 232                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 6),
 233                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
 234                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
 235                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
 236                 },
 237                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 238                 .flags = 0,
 239         },
 240         {
 241                 .name = "perif",
 242                 .parent_ids = default_parent_ids,
 243                 .num_parents = ARRAY_SIZE(default_parent_ids),
 244                 .map = {
 245                         BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
 246                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 9),
 247                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 12),
 248                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
 249                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
 250                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
 251                 },
 252                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 253                 .flags = CLK_IGNORE_UNUSED,
 254         },
 255         {
 256                 .name = "pcube",
 257                 .parent_ids = default_parent_ids,
 258                 .num_parents = ARRAY_SIZE(default_parent_ids),
 259                 .map = {
 260                         BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
 261                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 15),
 262                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 18),
 263                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
 264                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
 265                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
 266                 },
 267                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 268                 .flags = 0,
 269         },
 270         {
 271                 .name = "vscope",
 272                 .parent_ids = default_parent_ids,
 273                 .num_parents = ARRAY_SIZE(default_parent_ids),
 274                 .map = {
 275                         BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
 276                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 21),
 277                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 24),
 278                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
 279                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
 280                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
 281                 },
 282                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 283                 .flags = 0,
 284         },
 285         {
 286                 .name = "nfc_ecc",
 287                 .parent_ids = default_parent_ids,
 288                 .num_parents = ARRAY_SIZE(default_parent_ids),
 289                 .map = {
 290                         BERLIN2_DIV_GATE(REG_CLKENABLE, 18),
 291                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 27),
 292                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 0),
 293                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
 294                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
 295                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
 296                 },
 297                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 298                 .flags = 0,
 299         },
 300         {
 301                 .name = "vpp",
 302                 .parent_ids = default_parent_ids,
 303                 .num_parents = ARRAY_SIZE(default_parent_ids),
 304                 .map = {
 305                         BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
 306                         BERLIN2_PLL_SELECT(REG_CLKSELECT2, 3),
 307                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 6),
 308                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 4),
 309                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 5),
 310                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 6),
 311                 },
 312                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 313                 .flags = 0,
 314         },
 315         {
 316                 .name = "app",
 317                 .parent_ids = default_parent_ids,
 318                 .num_parents = ARRAY_SIZE(default_parent_ids),
 319                 .map = {
 320                         BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
 321                         BERLIN2_PLL_SELECT(REG_CLKSELECT2, 9),
 322                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 12),
 323                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 7),
 324                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 8),
 325                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 9),
 326                 },
 327                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 328                 .flags = 0,
 329         },
 330         {
 331                 .name = "audio0",
 332                 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
 333                 .num_parents = 1,
 334                 .map = {
 335                         BERLIN2_DIV_GATE(REG_CLKENABLE, 22),
 336                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 17),
 337                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 10),
 338                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 11),
 339                 },
 340                 .div_flags = BERLIN2_DIV_HAS_GATE,
 341                 .flags = 0,
 342         },
 343         {
 344                 .name = "audio2",
 345                 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
 346                 .num_parents = 1,
 347                 .map = {
 348                         BERLIN2_DIV_GATE(REG_CLKENABLE, 24),
 349                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 20),
 350                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 14),
 351                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 15),
 352                 },
 353                 .div_flags = BERLIN2_DIV_HAS_GATE,
 354                 .flags = 0,
 355         },
 356         {
 357                 .name = "audio3",
 358                 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
 359                 .num_parents = 1,
 360                 .map = {
 361                         BERLIN2_DIV_GATE(REG_CLKENABLE, 25),
 362                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 23),
 363                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 16),
 364                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 17),
 365                 },
 366                 .div_flags = BERLIN2_DIV_HAS_GATE,
 367                 .flags = 0,
 368         },
 369         {
 370                 .name = "audio1",
 371                 .parent_ids = (const u8 []){ AUDIO1_PLL },
 372                 .num_parents = 1,
 373                 .map = {
 374                         BERLIN2_DIV_GATE(REG_CLKENABLE, 23),
 375                         BERLIN2_DIV_SELECT(REG_CLKSELECT3, 0),
 376                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 12),
 377                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 13),
 378                 },
 379                 .div_flags = BERLIN2_DIV_HAS_GATE,
 380                 .flags = 0,
 381         },
 382         {
 383                 .name = "gfx3d_core",
 384                 .parent_ids = default_parent_ids,
 385                 .num_parents = ARRAY_SIZE(default_parent_ids),
 386                 .map = {
 387                         BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL),
 388                 },
 389                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 390                 .flags = 0,
 391         },
 392         {
 393                 .name = "gfx3d_sys",
 394                 .parent_ids = default_parent_ids,
 395                 .num_parents = ARRAY_SIZE(default_parent_ids),
 396                 .map = {
 397                         BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL),
 398                 },
 399                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 400                 .flags = 0,
 401         },
 402         {
 403                 .name = "arc",
 404                 .parent_ids = default_parent_ids,
 405                 .num_parents = ARRAY_SIZE(default_parent_ids),
 406                 .map = {
 407                         BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL),
 408                 },
 409                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 410                 .flags = 0,
 411         },
 412         {
 413                 .name = "vip",
 414                 .parent_ids = default_parent_ids,
 415                 .num_parents = ARRAY_SIZE(default_parent_ids),
 416                 .map = {
 417                         BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL),
 418                 },
 419                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 420                 .flags = 0,
 421         },
 422         {
 423                 .name = "sdio0xin",
 424                 .parent_ids = default_parent_ids,
 425                 .num_parents = ARRAY_SIZE(default_parent_ids),
 426                 .map = {
 427                         BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
 428                 },
 429                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 430                 .flags = 0,
 431         },
 432         {
 433                 .name = "sdio1xin",
 434                 .parent_ids = default_parent_ids,
 435                 .num_parents = ARRAY_SIZE(default_parent_ids),
 436                 .map = {
 437                         BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
 438                 },
 439                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 440                 .flags = 0,
 441         },
 442         {
 443                 .name = "gfx3d_extra",
 444                 .parent_ids = default_parent_ids,
 445                 .num_parents = ARRAY_SIZE(default_parent_ids),
 446                 .map = {
 447                         BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL),
 448                 },
 449                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 450                 .flags = 0,
 451         },
 452         {
 453                 .name = "gc360",
 454                 .parent_ids = default_parent_ids,
 455                 .num_parents = ARRAY_SIZE(default_parent_ids),
 456                 .map = {
 457                         BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL),
 458                 },
 459                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 460                 .flags = 0,
 461         },
 462         {
 463                 .name = "sdio_dllmst",
 464                 .parent_ids = default_parent_ids,
 465                 .num_parents = ARRAY_SIZE(default_parent_ids),
 466                 .map = {
 467                         BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL),
 468                 },
 469                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
 470                 .flags = 0,
 471         },
 472 };
 473 
 474 static const struct berlin2_gate_data bg2_gates[] __initconst = {
 475         { "geth0",      "perif",        7 },
 476         { "geth1",      "perif",        8 },
 477         { "sata",       "perif",        9 },
 478         { "ahbapb",     "perif",        10, CLK_IGNORE_UNUSED },
 479         { "usb0",       "perif",        11 },
 480         { "usb1",       "perif",        12 },
 481         { "pbridge",    "perif",        13, CLK_IGNORE_UNUSED },
 482         { "sdio0",      "perif",        14 },
 483         { "sdio1",      "perif",        15 },
 484         { "nfc",        "perif",        17 },
 485         { "smemc",      "perif",        19 },
 486         { "audiohd",    "audiohd_pll",  26 },
 487         { "video0",     "video0_in",    27 },
 488         { "video1",     "video1_in",    28 },
 489         { "video2",     "video2_in",    29 },
 490 };
 491 
 492 static void __init berlin2_clock_setup(struct device_node *np)
 493 {
 494         struct device_node *parent_np = of_get_parent(np);
 495         const char *parent_names[9];
 496         struct clk *clk;
 497         struct clk_hw *hw;
 498         struct clk_hw **hws;
 499         u8 avpll_flags = 0;
 500         int n, ret;
 501 
 502         clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
 503         if (!clk_data)
 504                 return;
 505         clk_data->num = MAX_CLKS;
 506         hws = clk_data->hws;
 507 
 508         gbase = of_iomap(parent_np, 0);
 509         if (!gbase)
 510                 return;
 511 
 512         /* overwrite default clock names with DT provided ones */
 513         clk = of_clk_get_by_name(np, clk_names[REFCLK]);
 514         if (!IS_ERR(clk)) {
 515                 clk_names[REFCLK] = __clk_get_name(clk);
 516                 clk_put(clk);
 517         }
 518 
 519         clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
 520         if (!IS_ERR(clk)) {
 521                 clk_names[VIDEO_EXT0] = __clk_get_name(clk);
 522                 clk_put(clk);
 523         }
 524 
 525         /* simple register PLLs */
 526         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
 527                                    clk_names[SYSPLL], clk_names[REFCLK], 0);
 528         if (ret)
 529                 goto bg2_fail;
 530 
 531         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
 532                                    clk_names[MEMPLL], clk_names[REFCLK], 0);
 533         if (ret)
 534                 goto bg2_fail;
 535 
 536         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
 537                                    clk_names[CPUPLL], clk_names[REFCLK], 0);
 538         if (ret)
 539                 goto bg2_fail;
 540 
 541         if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
 542                 avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
 543 
 544         /* audio/video VCOs */
 545         ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
 546                          clk_names[REFCLK], avpll_flags, 0);
 547         if (ret)
 548                 goto bg2_fail;
 549 
 550         for (n = 0; n < 8; n++) {
 551                 ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
 552                              clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
 553                              avpll_flags, 0);
 554                 if (ret)
 555                         goto bg2_fail;
 556         }
 557 
 558         ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
 559                                  clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
 560                                  avpll_flags, 0);
 561         if (ret)
 562                 goto bg2_fail;
 563 
 564         for (n = 0; n < 8; n++) {
 565                 ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
 566                              clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
 567                              BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
 568                 if (ret)
 569                         goto bg2_fail;
 570         }
 571 
 572         /* reference clock bypass switches */
 573         parent_names[0] = clk_names[SYSPLL];
 574         parent_names[1] = clk_names[REFCLK];
 575         hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2,
 576                                0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
 577         if (IS_ERR(hw))
 578                 goto bg2_fail;
 579         clk_names[SYSPLL] = clk_hw_get_name(hw);
 580 
 581         parent_names[0] = clk_names[MEMPLL];
 582         parent_names[1] = clk_names[REFCLK];
 583         hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2,
 584                                0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
 585         if (IS_ERR(hw))
 586                 goto bg2_fail;
 587         clk_names[MEMPLL] = clk_hw_get_name(hw);
 588 
 589         parent_names[0] = clk_names[CPUPLL];
 590         parent_names[1] = clk_names[REFCLK];
 591         hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2,
 592                                0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
 593         if (IS_ERR(hw))
 594                 goto bg2_fail;
 595         clk_names[CPUPLL] = clk_hw_get_name(hw);
 596 
 597         /* clock muxes */
 598         parent_names[0] = clk_names[AVPLL_B3];
 599         parent_names[1] = clk_names[AVPLL_A3];
 600         hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
 601                                0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
 602         if (IS_ERR(hw))
 603                 goto bg2_fail;
 604 
 605         parent_names[0] = clk_names[VIDEO0_PLL];
 606         parent_names[1] = clk_names[VIDEO_EXT0];
 607         hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
 608                                0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
 609         if (IS_ERR(hw))
 610                 goto bg2_fail;
 611 
 612         parent_names[0] = clk_names[VIDEO1_PLL];
 613         parent_names[1] = clk_names[VIDEO_EXT0];
 614         hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
 615                                0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
 616         if (IS_ERR(hw))
 617                 goto bg2_fail;
 618 
 619         parent_names[0] = clk_names[AVPLL_A2];
 620         parent_names[1] = clk_names[AVPLL_B2];
 621         hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
 622                                0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
 623         if (IS_ERR(hw))
 624                 goto bg2_fail;
 625 
 626         parent_names[0] = clk_names[VIDEO2_PLL];
 627         parent_names[1] = clk_names[VIDEO_EXT0];
 628         hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
 629                                0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
 630         if (IS_ERR(hw))
 631                 goto bg2_fail;
 632 
 633         parent_names[0] = clk_names[AVPLL_B1];
 634         parent_names[1] = clk_names[AVPLL_A5];
 635         hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
 636                                0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
 637         if (IS_ERR(hw))
 638                 goto bg2_fail;
 639 
 640         /* clock divider cells */
 641         for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
 642                 const struct berlin2_div_data *dd = &bg2_divs[n];
 643                 int k;
 644 
 645                 for (k = 0; k < dd->num_parents; k++)
 646                         parent_names[k] = clk_names[dd->parent_ids[k]];
 647 
 648                 hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
 649                                 dd->name, dd->div_flags, parent_names,
 650                                 dd->num_parents, dd->flags, &lock);
 651         }
 652 
 653         /* clock gate cells */
 654         for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
 655                 const struct berlin2_gate_data *gd = &bg2_gates[n];
 656 
 657                 hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name,
 658                             gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
 659                             gd->bit_idx, 0, &lock);
 660         }
 661 
 662         /* twdclk is derived from cpu/3 */
 663         hws[CLKID_TWD] =
 664                 clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
 665 
 666         /* check for errors on leaf clocks */
 667         for (n = 0; n < MAX_CLKS; n++) {
 668                 if (!IS_ERR(hws[n]))
 669                         continue;
 670 
 671                 pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
 672                 goto bg2_fail;
 673         }
 674 
 675         /* register clk-provider */
 676         of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
 677 
 678         return;
 679 
 680 bg2_fail:
 681         iounmap(gbase);
 682 }
 683 CLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk",
 684                berlin2_clock_setup);

/* [<][>][^][v][top][bottom][index][help] */