uboot/drivers/clk/rockchip/clk_rk3588.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
   4 * Author: Elaine Zhang <zhangqing@rock-chips.com>
   5 */
   6
   7#include <common.h>
   8#include <bitfield.h>
   9#include <clk-uclass.h>
  10#include <dm.h>
  11#include <errno.h>
  12#include <scmi_protocols.h>
  13#include <syscon.h>
  14#include <asm/arch-rockchip/cru_rk3588.h>
  15#include <asm/arch-rockchip/clock.h>
  16#include <asm/arch-rockchip/hardware.h>
  17#include <asm/io.h>
  18#include <dm/device-internal.h>
  19#include <dm/lists.h>
  20#include <dt-bindings/clock/rockchip,rk3588-cru.h>
  21
  22DECLARE_GLOBAL_DATA_PTR;
  23
  24#define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
  25
  26static struct rockchip_pll_rate_table rk3588_pll_rates[] = {
  27        /* _mhz, _p, _m, _s, _k */
  28        RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
  29        RK3588_PLL_RATE(1200000000, 2, 200, 1, 0),
  30        RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
  31        RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
  32        RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
  33        RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
  34        RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
  35        RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
  36        RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
  37        RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
  38        RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
  39        RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
  40        RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
  41        RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
  42        RK3588_PLL_RATE(200000000, 3, 400, 4, 0),
  43        RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
  44        { /* sentinel */ },
  45};
  46
  47static struct rockchip_pll_clock rk3588_pll_clks[] = {
  48        [B0PLL] = PLL(pll_rk3588, PLL_B0PLL, RK3588_B0_PLL_CON(0),
  49                      RK3588_B0_PLL_MODE_CON, 0, 15, 0,
  50                      rk3588_pll_rates),
  51        [B1PLL] = PLL(pll_rk3588, PLL_B1PLL, RK3588_B1_PLL_CON(8),
  52                      RK3588_B1_PLL_MODE_CON, 0, 15, 0,
  53                      rk3588_pll_rates),
  54        [LPLL] = PLL(pll_rk3588, PLL_LPLL, RK3588_LPLL_CON(16),
  55                     RK3588_LPLL_MODE_CON, 0, 15, 0, rk3588_pll_rates),
  56        [V0PLL] = PLL(pll_rk3588, PLL_V0PLL, RK3588_PLL_CON(88),
  57                      RK3588_MODE_CON0, 4, 15, 0, rk3588_pll_rates),
  58        [AUPLL] = PLL(pll_rk3588, PLL_AUPLL, RK3588_PLL_CON(96),
  59                      RK3588_MODE_CON0, 6, 15, 0, rk3588_pll_rates),
  60        [CPLL] = PLL(pll_rk3588, PLL_CPLL, RK3588_PLL_CON(104),
  61                     RK3588_MODE_CON0, 8, 15, 0, rk3588_pll_rates),
  62        [GPLL] = PLL(pll_rk3588, PLL_GPLL, RK3588_PLL_CON(112),
  63                     RK3588_MODE_CON0, 2, 15, 0, rk3588_pll_rates),
  64        [NPLL] = PLL(pll_rk3588, PLL_NPLL, RK3588_PLL_CON(120),
  65                     RK3588_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
  66        [PPLL] = PLL(pll_rk3588, PLL_PPLL, RK3588_PMU_PLL_CON(128),
  67                     RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates),
  68};
  69
  70#ifndef CONFIG_SPL_BUILD
  71/*
  72 *
  73 * rational_best_approximation(31415, 10000,
  74 *              (1 << 8) - 1, (1 << 5) - 1, &n, &d);
  75 *
  76 * you may look at given_numerator as a fixed point number,
  77 * with the fractional part size described in given_denominator.
  78 *
  79 * for theoretical background, see:
  80 * http://en.wikipedia.org/wiki/Continued_fraction
  81 */
  82static void rational_best_approximation(unsigned long given_numerator,
  83                                        unsigned long given_denominator,
  84                                        unsigned long max_numerator,
  85                                        unsigned long max_denominator,
  86                                        unsigned long *best_numerator,
  87                                        unsigned long *best_denominator)
  88{
  89        unsigned long n, d, n0, d0, n1, d1;
  90
  91        n = given_numerator;
  92        d = given_denominator;
  93        n0 = 0;
  94        d1 = 0;
  95        n1 = 1;
  96        d0 = 1;
  97        for (;;) {
  98                unsigned long t, a;
  99
 100                if (n1 > max_numerator || d1 > max_denominator) {
 101                        n1 = n0;
 102                        d1 = d0;
 103                        break;
 104                }
 105                if (d == 0)
 106                        break;
 107                t = d;
 108                a = n / d;
 109                d = n % d;
 110                n = t;
 111                t = n0 + a * n1;
 112                n0 = n1;
 113                n1 = t;
 114                t = d0 + a * d1;
 115                d0 = d1;
 116                d1 = t;
 117        }
 118        *best_numerator = n1;
 119        *best_denominator = d1;
 120}
 121#endif
 122
 123static ulong rk3588_center_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
 124{
 125        struct rk3588_cru *cru = priv->cru;
 126        u32 con, sel, rate;
 127
 128        switch (clk_id) {
 129        case ACLK_CENTER_ROOT:
 130                con = readl(&cru->clksel_con[165]);
 131                sel = (con & ACLK_CENTER_ROOT_SEL_MASK) >>
 132                      ACLK_CENTER_ROOT_SEL_SHIFT;
 133                if (sel == ACLK_CENTER_ROOT_SEL_700M)
 134                        rate = 702 * MHz;
 135                else if (sel == ACLK_CENTER_ROOT_SEL_400M)
 136                        rate = 396 * MHz;
 137                else if (sel == ACLK_CENTER_ROOT_SEL_200M)
 138                        rate = 200 * MHz;
 139                else
 140                        rate = OSC_HZ;
 141                break;
 142        case ACLK_CENTER_LOW_ROOT:
 143                con = readl(&cru->clksel_con[165]);
 144                sel = (con & ACLK_CENTER_LOW_ROOT_SEL_MASK) >>
 145                      ACLK_CENTER_LOW_ROOT_SEL_SHIFT;
 146                if (sel == ACLK_CENTER_LOW_ROOT_SEL_500M)
 147                        rate = 500 * MHz;
 148                else if (sel == ACLK_CENTER_LOW_ROOT_SEL_250M)
 149                        rate = 250 * MHz;
 150                else if (sel == ACLK_CENTER_LOW_ROOT_SEL_100M)
 151                        rate = 100 * MHz;
 152                else
 153                        rate = OSC_HZ;
 154                break;
 155        case HCLK_CENTER_ROOT:
 156                con = readl(&cru->clksel_con[165]);
 157                sel = (con & HCLK_CENTER_ROOT_SEL_MASK) >>
 158                      HCLK_CENTER_ROOT_SEL_SHIFT;
 159                if (sel == HCLK_CENTER_ROOT_SEL_400M)
 160                        rate = 396 * MHz;
 161                else if (sel == HCLK_CENTER_ROOT_SEL_200M)
 162                        rate = 200 * MHz;
 163                else if (sel == HCLK_CENTER_ROOT_SEL_100M)
 164                        rate = 100 * MHz;
 165                else
 166                        rate = OSC_HZ;
 167                break;
 168        case PCLK_CENTER_ROOT:
 169                con = readl(&cru->clksel_con[165]);
 170                sel = (con & PCLK_CENTER_ROOT_SEL_MASK) >>
 171                      PCLK_CENTER_ROOT_SEL_SHIFT;
 172                if (sel == PCLK_CENTER_ROOT_SEL_200M)
 173                        rate = 200 * MHz;
 174                else if (sel == PCLK_CENTER_ROOT_SEL_100M)
 175                        rate = 100 * MHz;
 176                else if (sel == PCLK_CENTER_ROOT_SEL_50M)
 177                        rate = 50 * MHz;
 178                else
 179                        rate = OSC_HZ;
 180                break;
 181        default:
 182                return -ENOENT;
 183        }
 184
 185        return rate;
 186}
 187
 188static ulong rk3588_center_set_clk(struct rk3588_clk_priv *priv,
 189                                   ulong clk_id, ulong rate)
 190{
 191        struct rk3588_cru *cru = priv->cru;
 192        int src_clk;
 193
 194        switch (clk_id) {
 195        case ACLK_CENTER_ROOT:
 196                if (rate >= 700 * MHz)
 197                        src_clk = ACLK_CENTER_ROOT_SEL_700M;
 198                else if (rate >= 396 * MHz)
 199                        src_clk = ACLK_CENTER_ROOT_SEL_400M;
 200                else if (rate >= 200 * MHz)
 201                        src_clk = ACLK_CENTER_ROOT_SEL_200M;
 202                else
 203                        src_clk = ACLK_CENTER_ROOT_SEL_24M;
 204                rk_clrsetreg(&cru->clksel_con[165],
 205                             ACLK_CENTER_ROOT_SEL_MASK,
 206                             src_clk << ACLK_CENTER_ROOT_SEL_SHIFT);
 207                break;
 208        case ACLK_CENTER_LOW_ROOT:
 209                if (rate >= 500 * MHz)
 210                        src_clk = ACLK_CENTER_LOW_ROOT_SEL_500M;
 211                else if (rate >= 250 * MHz)
 212                        src_clk = ACLK_CENTER_LOW_ROOT_SEL_250M;
 213                else if (rate >= 99 * MHz)
 214                        src_clk = ACLK_CENTER_LOW_ROOT_SEL_100M;
 215                else
 216                        src_clk = ACLK_CENTER_LOW_ROOT_SEL_24M;
 217                rk_clrsetreg(&cru->clksel_con[165],
 218                             ACLK_CENTER_LOW_ROOT_SEL_MASK,
 219                             src_clk << ACLK_CENTER_LOW_ROOT_SEL_SHIFT);
 220                break;
 221        case HCLK_CENTER_ROOT:
 222                if (rate >= 396 * MHz)
 223                        src_clk = HCLK_CENTER_ROOT_SEL_400M;
 224                else if (rate >= 198 * MHz)
 225                        src_clk = HCLK_CENTER_ROOT_SEL_200M;
 226                else if (rate >= 99 * MHz)
 227                        src_clk = HCLK_CENTER_ROOT_SEL_100M;
 228                else
 229                        src_clk = HCLK_CENTER_ROOT_SEL_24M;
 230                rk_clrsetreg(&cru->clksel_con[165],
 231                             HCLK_CENTER_ROOT_SEL_MASK,
 232                             src_clk << HCLK_CENTER_ROOT_SEL_SHIFT);
 233                break;
 234        case PCLK_CENTER_ROOT:
 235                if (rate >= 198 * MHz)
 236                        src_clk = PCLK_CENTER_ROOT_SEL_200M;
 237                else if (rate >= 99 * MHz)
 238                        src_clk = PCLK_CENTER_ROOT_SEL_100M;
 239                else if (rate >= 50 * MHz)
 240                        src_clk = PCLK_CENTER_ROOT_SEL_50M;
 241                else
 242                        src_clk = PCLK_CENTER_ROOT_SEL_24M;
 243                rk_clrsetreg(&cru->clksel_con[165],
 244                             PCLK_CENTER_ROOT_SEL_MASK,
 245                             src_clk << PCLK_CENTER_ROOT_SEL_SHIFT);
 246                break;
 247        default:
 248                printf("do not support this center freq\n");
 249                return -EINVAL;
 250        }
 251
 252        return rk3588_center_get_clk(priv, clk_id);
 253}
 254
 255static ulong rk3588_top_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
 256{
 257        struct rk3588_cru *cru = priv->cru;
 258        u32 con, sel, div, rate, prate;
 259
 260        switch (clk_id) {
 261        case ACLK_TOP_ROOT:
 262                con = readl(&cru->clksel_con[8]);
 263                div = (con & ACLK_TOP_ROOT_DIV_MASK) >>
 264                      ACLK_TOP_ROOT_DIV_SHIFT;
 265                sel = (con & ACLK_TOP_ROOT_SRC_SEL_MASK) >>
 266                      ACLK_TOP_ROOT_SRC_SEL_SHIFT;
 267                if (sel == ACLK_TOP_ROOT_SRC_SEL_CPLL)
 268                        prate = priv->cpll_hz;
 269                else
 270                        prate = priv->gpll_hz;
 271                return DIV_TO_RATE(prate, div);
 272        case ACLK_LOW_TOP_ROOT:
 273                con = readl(&cru->clksel_con[8]);
 274                div = (con & ACLK_LOW_TOP_ROOT_DIV_MASK) >>
 275                      ACLK_LOW_TOP_ROOT_DIV_SHIFT;
 276                sel = (con & ACLK_LOW_TOP_ROOT_SRC_SEL_MASK) >>
 277                      ACLK_LOW_TOP_ROOT_SRC_SEL_SHIFT;
 278                if (sel == ACLK_LOW_TOP_ROOT_SRC_SEL_CPLL)
 279                        prate = priv->cpll_hz;
 280                else
 281                        prate = priv->gpll_hz;
 282                return DIV_TO_RATE(prate, div);
 283        case PCLK_TOP_ROOT:
 284                con = readl(&cru->clksel_con[8]);
 285                sel = (con & PCLK_TOP_ROOT_SEL_MASK) >> PCLK_TOP_ROOT_SEL_SHIFT;
 286                if (sel == PCLK_TOP_ROOT_SEL_100M)
 287                        rate = 100 * MHz;
 288                else if (sel == PCLK_TOP_ROOT_SEL_50M)
 289                        rate = 50 * MHz;
 290                else
 291                        rate = OSC_HZ;
 292                break;
 293        default:
 294                return -ENOENT;
 295        }
 296
 297        return rate;
 298}
 299
 300static ulong rk3588_top_set_clk(struct rk3588_clk_priv *priv,
 301                                ulong clk_id, ulong rate)
 302{
 303        struct rk3588_cru *cru = priv->cru;
 304        int src_clk, src_clk_div;
 305
 306        switch (clk_id) {
 307        case ACLK_TOP_ROOT:
 308                src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
 309                assert(src_clk_div - 1 <= 31);
 310                rk_clrsetreg(&cru->clksel_con[8],
 311                             ACLK_TOP_ROOT_DIV_MASK |
 312                             ACLK_TOP_ROOT_SRC_SEL_MASK,
 313                             (ACLK_TOP_ROOT_SRC_SEL_GPLL <<
 314                              ACLK_TOP_ROOT_SRC_SEL_SHIFT) |
 315                             (src_clk_div - 1) << ACLK_TOP_ROOT_DIV_SHIFT);
 316                break;
 317        case ACLK_LOW_TOP_ROOT:
 318                src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
 319                assert(src_clk_div - 1 <= 31);
 320                rk_clrsetreg(&cru->clksel_con[8],
 321                             ACLK_LOW_TOP_ROOT_DIV_MASK |
 322                             ACLK_LOW_TOP_ROOT_SRC_SEL_MASK,
 323                             (ACLK_LOW_TOP_ROOT_SRC_SEL_GPLL <<
 324                              ACLK_LOW_TOP_ROOT_SRC_SEL_SHIFT) |
 325                             (src_clk_div - 1) << ACLK_LOW_TOP_ROOT_DIV_SHIFT);
 326                break;
 327        case PCLK_TOP_ROOT:
 328                if (rate == 100 * MHz)
 329                        src_clk = PCLK_TOP_ROOT_SEL_100M;
 330                else if (rate == 50 * MHz)
 331                        src_clk = PCLK_TOP_ROOT_SEL_50M;
 332                else
 333                        src_clk = PCLK_TOP_ROOT_SEL_24M;
 334                rk_clrsetreg(&cru->clksel_con[8],
 335                             PCLK_TOP_ROOT_SEL_MASK,
 336                             src_clk << PCLK_TOP_ROOT_SEL_SHIFT);
 337                break;
 338        default:
 339                printf("do not support this top freq\n");
 340                return -EINVAL;
 341        }
 342
 343        return rk3588_top_get_clk(priv, clk_id);
 344}
 345
 346static ulong rk3588_i2c_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
 347{
 348        struct rk3588_cru *cru = priv->cru;
 349        u32 sel, con;
 350        ulong rate;
 351
 352        switch (clk_id) {
 353        case CLK_I2C0:
 354                con = readl(&cru->pmuclksel_con[3]);
 355                sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
 356                break;
 357        case CLK_I2C1:
 358                con = readl(&cru->clksel_con[38]);
 359                sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
 360                break;
 361        case CLK_I2C2:
 362                con = readl(&cru->clksel_con[38]);
 363                sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
 364                break;
 365        case CLK_I2C3:
 366                con = readl(&cru->clksel_con[38]);
 367                sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
 368                break;
 369        case CLK_I2C4:
 370                con = readl(&cru->clksel_con[38]);
 371                sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
 372                break;
 373        case CLK_I2C5:
 374                con = readl(&cru->clksel_con[38]);
 375                sel = (con & CLK_I2C5_SEL_MASK) >> CLK_I2C5_SEL_SHIFT;
 376                break;
 377        case CLK_I2C6:
 378                con = readl(&cru->clksel_con[38]);
 379                sel = (con & CLK_I2C6_SEL_MASK) >> CLK_I2C6_SEL_SHIFT;
 380                break;
 381        case CLK_I2C7:
 382                con = readl(&cru->clksel_con[38]);
 383                sel = (con & CLK_I2C7_SEL_MASK) >> CLK_I2C7_SEL_SHIFT;
 384                break;
 385        case CLK_I2C8:
 386                con = readl(&cru->clksel_con[38]);
 387                sel = (con & CLK_I2C8_SEL_MASK) >> CLK_I2C8_SEL_SHIFT;
 388                break;
 389        default:
 390                return -ENOENT;
 391        }
 392        if (sel == CLK_I2C_SEL_200M)
 393                rate = 200 * MHz;
 394        else
 395                rate = 100 * MHz;
 396
 397        return rate;
 398}
 399
 400static ulong rk3588_i2c_set_clk(struct rk3588_clk_priv *priv, ulong clk_id,
 401                                ulong rate)
 402{
 403        struct rk3588_cru *cru = priv->cru;
 404        int src_clk;
 405
 406        if (rate >= 198 * MHz)
 407                src_clk = CLK_I2C_SEL_200M;
 408        else
 409                src_clk = CLK_I2C_SEL_100M;
 410
 411        switch (clk_id) {
 412        case CLK_I2C0:
 413                rk_clrsetreg(&cru->pmuclksel_con[3], CLK_I2C0_SEL_MASK,
 414                             src_clk << CLK_I2C0_SEL_SHIFT);
 415                break;
 416        case CLK_I2C1:
 417                rk_clrsetreg(&cru->clksel_con[38], CLK_I2C1_SEL_MASK,
 418                             src_clk << CLK_I2C1_SEL_SHIFT);
 419                break;
 420        case CLK_I2C2:
 421                rk_clrsetreg(&cru->clksel_con[38], CLK_I2C2_SEL_MASK,
 422                             src_clk << CLK_I2C2_SEL_SHIFT);
 423                break;
 424        case CLK_I2C3:
 425                rk_clrsetreg(&cru->clksel_con[38], CLK_I2C3_SEL_MASK,
 426                             src_clk << CLK_I2C3_SEL_SHIFT);
 427                break;
 428        case CLK_I2C4:
 429                rk_clrsetreg(&cru->clksel_con[38], CLK_I2C4_SEL_MASK,
 430                             src_clk << CLK_I2C4_SEL_SHIFT);
 431                break;
 432        case CLK_I2C5:
 433                rk_clrsetreg(&cru->clksel_con[38], CLK_I2C5_SEL_MASK,
 434                             src_clk << CLK_I2C5_SEL_SHIFT);
 435                break;
 436        case CLK_I2C6:
 437                rk_clrsetreg(&cru->clksel_con[38], CLK_I2C6_SEL_MASK,
 438                             src_clk << CLK_I2C6_SEL_SHIFT);
 439                break;
 440        case CLK_I2C7:
 441                rk_clrsetreg(&cru->clksel_con[38], CLK_I2C7_SEL_MASK,
 442                             src_clk << CLK_I2C7_SEL_SHIFT);
 443                break;
 444        case CLK_I2C8:
 445                rk_clrsetreg(&cru->clksel_con[38], CLK_I2C8_SEL_MASK,
 446                             src_clk << CLK_I2C8_SEL_SHIFT);
 447                break;
 448        default:
 449                return -ENOENT;
 450        }
 451
 452        return rk3588_i2c_get_clk(priv, clk_id);
 453}
 454
 455static ulong rk3588_spi_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
 456{
 457        struct rk3588_cru *cru = priv->cru;
 458        u32 sel, con;
 459
 460        con = readl(&cru->clksel_con[59]);
 461
 462        switch (clk_id) {
 463        case CLK_SPI0:
 464                sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
 465                break;
 466        case CLK_SPI1:
 467                sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
 468                break;
 469        case CLK_SPI2:
 470                sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
 471                break;
 472        case CLK_SPI3:
 473                sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
 474                break;
 475        case CLK_SPI4:
 476                sel = (con & CLK_SPI4_SEL_MASK) >> CLK_SPI4_SEL_SHIFT;
 477                break;
 478        default:
 479                return -ENOENT;
 480        }
 481
 482        switch (sel) {
 483        case CLK_SPI_SEL_200M:
 484                return 200 * MHz;
 485        case CLK_SPI_SEL_150M:
 486                return 150 * MHz;
 487        case CLK_SPI_SEL_24M:
 488                return OSC_HZ;
 489        default:
 490                return -ENOENT;
 491        }
 492}
 493
 494static ulong rk3588_spi_set_clk(struct rk3588_clk_priv *priv,
 495                                ulong clk_id, ulong rate)
 496{
 497        struct rk3588_cru *cru = priv->cru;
 498        int src_clk;
 499
 500        if (rate >= 198 * MHz)
 501                src_clk = CLK_SPI_SEL_200M;
 502        else if (rate >= 140 * MHz)
 503                src_clk = CLK_SPI_SEL_150M;
 504        else
 505                src_clk = CLK_SPI_SEL_24M;
 506
 507        switch (clk_id) {
 508        case CLK_SPI0:
 509                rk_clrsetreg(&cru->clksel_con[59],
 510                             CLK_SPI0_SEL_MASK,
 511                             src_clk << CLK_SPI0_SEL_SHIFT);
 512                break;
 513        case CLK_SPI1:
 514                rk_clrsetreg(&cru->clksel_con[59],
 515                             CLK_SPI1_SEL_MASK,
 516                             src_clk << CLK_SPI1_SEL_SHIFT);
 517                break;
 518        case CLK_SPI2:
 519                rk_clrsetreg(&cru->clksel_con[59],
 520                             CLK_SPI2_SEL_MASK,
 521                             src_clk << CLK_SPI2_SEL_SHIFT);
 522                break;
 523        case CLK_SPI3:
 524                rk_clrsetreg(&cru->clksel_con[59],
 525                             CLK_SPI3_SEL_MASK,
 526                             src_clk << CLK_SPI3_SEL_SHIFT);
 527                break;
 528        case CLK_SPI4:
 529                rk_clrsetreg(&cru->clksel_con[59],
 530                             CLK_SPI4_SEL_MASK,
 531                             src_clk << CLK_SPI4_SEL_SHIFT);
 532                break;
 533        default:
 534                return -ENOENT;
 535        }
 536
 537        return rk3588_spi_get_clk(priv, clk_id);
 538}
 539
 540static ulong rk3588_pwm_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
 541{
 542        struct rk3588_cru *cru = priv->cru;
 543        u32 sel, con;
 544
 545        switch (clk_id) {
 546        case CLK_PWM1:
 547                con = readl(&cru->clksel_con[59]);
 548                sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
 549                break;
 550        case CLK_PWM2:
 551                con = readl(&cru->clksel_con[59]);
 552                sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
 553                break;
 554        case CLK_PWM3:
 555                con = readl(&cru->clksel_con[60]);
 556                sel = (con & CLK_PWM3_SEL_MASK) >> CLK_PWM3_SEL_SHIFT;
 557                break;
 558        case CLK_PMU1PWM:
 559                con = readl(&cru->pmuclksel_con[2]);
 560                sel = (con & CLK_PMU1PWM_SEL_MASK) >> CLK_PMU1PWM_SEL_SHIFT;
 561                break;
 562        default:
 563                return -ENOENT;
 564        }
 565
 566        switch (sel) {
 567        case CLK_PWM_SEL_100M:
 568                return 100 * MHz;
 569        case CLK_PWM_SEL_50M:
 570                return 50 * MHz;
 571        case CLK_PWM_SEL_24M:
 572                return OSC_HZ;
 573        default:
 574                return -ENOENT;
 575        }
 576}
 577
 578static ulong rk3588_pwm_set_clk(struct rk3588_clk_priv *priv,
 579                                ulong clk_id, ulong rate)
 580{
 581        struct rk3588_cru *cru = priv->cru;
 582        int src_clk;
 583
 584        if (rate >= 99 * MHz)
 585                src_clk = CLK_PWM_SEL_100M;
 586        else if (rate >= 50 * MHz)
 587                src_clk = CLK_PWM_SEL_50M;
 588        else
 589                src_clk = CLK_PWM_SEL_24M;
 590
 591        switch (clk_id) {
 592        case CLK_PWM1:
 593                rk_clrsetreg(&cru->clksel_con[59],
 594                             CLK_PWM1_SEL_MASK,
 595                             src_clk << CLK_PWM1_SEL_SHIFT);
 596                break;
 597        case CLK_PWM2:
 598                rk_clrsetreg(&cru->clksel_con[59],
 599                             CLK_PWM2_SEL_MASK,
 600                             src_clk << CLK_PWM2_SEL_SHIFT);
 601                break;
 602        case CLK_PWM3:
 603                rk_clrsetreg(&cru->clksel_con[60],
 604                             CLK_PWM3_SEL_MASK,
 605                             src_clk << CLK_PWM3_SEL_SHIFT);
 606                break;
 607        case CLK_PMU1PWM:
 608                rk_clrsetreg(&cru->pmuclksel_con[2],
 609                             CLK_PMU1PWM_SEL_MASK,
 610                             src_clk << CLK_PMU1PWM_SEL_SHIFT);
 611                break;
 612        default:
 613                return -ENOENT;
 614        }
 615
 616        return rk3588_pwm_get_clk(priv, clk_id);
 617}
 618
 619static ulong rk3588_adc_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
 620{
 621        struct rk3588_cru *cru = priv->cru;
 622        u32 div, sel, con, prate;
 623
 624        switch (clk_id) {
 625        case CLK_SARADC:
 626                con = readl(&cru->clksel_con[40]);
 627                div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
 628                sel = (con & CLK_SARADC_SEL_MASK) >>
 629                      CLK_SARADC_SEL_SHIFT;
 630                if (sel == CLK_SARADC_SEL_24M)
 631                        prate = OSC_HZ;
 632                else
 633                        prate = priv->gpll_hz;
 634                return DIV_TO_RATE(prate, div);
 635        case CLK_TSADC:
 636                con = readl(&cru->clksel_con[41]);
 637                div = (con & CLK_TSADC_DIV_MASK) >>
 638                      CLK_TSADC_DIV_SHIFT;
 639                sel = (con & CLK_TSADC_SEL_MASK) >>
 640                      CLK_TSADC_SEL_SHIFT;
 641                if (sel == CLK_TSADC_SEL_24M)
 642                        prate = OSC_HZ;
 643                else
 644                        prate = 100 * MHz;
 645                return DIV_TO_RATE(prate, div);
 646        default:
 647                return -ENOENT;
 648        }
 649}
 650
 651static ulong rk3588_adc_set_clk(struct rk3588_clk_priv *priv,
 652                                ulong clk_id, ulong rate)
 653{
 654        struct rk3588_cru *cru = priv->cru;
 655        int src_clk_div;
 656
 657        switch (clk_id) {
 658        case CLK_SARADC:
 659                if (!(OSC_HZ % rate)) {
 660                        src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
 661                        assert(src_clk_div - 1 <= 255);
 662                        rk_clrsetreg(&cru->clksel_con[40],
 663                                     CLK_SARADC_SEL_MASK |
 664                                     CLK_SARADC_DIV_MASK,
 665                                     (CLK_SARADC_SEL_24M <<
 666                                      CLK_SARADC_SEL_SHIFT) |
 667                                     (src_clk_div - 1) <<
 668                                     CLK_SARADC_DIV_SHIFT);
 669                } else {
 670                        src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
 671                        assert(src_clk_div - 1 <= 255);
 672                        rk_clrsetreg(&cru->clksel_con[40],
 673                                     CLK_SARADC_SEL_MASK |
 674                                     CLK_SARADC_DIV_MASK,
 675                                     (CLK_SARADC_SEL_GPLL <<
 676                                      CLK_SARADC_SEL_SHIFT) |
 677                                     (src_clk_div - 1) <<
 678                                     CLK_SARADC_DIV_SHIFT);
 679                }
 680                break;
 681        case CLK_TSADC:
 682                if (!(OSC_HZ % rate)) {
 683                        src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
 684                        assert(src_clk_div - 1 <= 255);
 685                        rk_clrsetreg(&cru->clksel_con[41],
 686                                     CLK_TSADC_SEL_MASK |
 687                                     CLK_TSADC_DIV_MASK,
 688                                     (CLK_TSADC_SEL_24M <<
 689                                      CLK_TSADC_SEL_SHIFT) |
 690                                     (src_clk_div - 1) <<
 691                                     CLK_TSADC_DIV_SHIFT);
 692                } else {
 693                        src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
 694                        assert(src_clk_div - 1 <= 7);
 695                        rk_clrsetreg(&cru->clksel_con[41],
 696                                     CLK_TSADC_SEL_MASK |
 697                                     CLK_TSADC_DIV_MASK,
 698                                     (CLK_TSADC_SEL_GPLL <<
 699                                      CLK_TSADC_SEL_SHIFT) |
 700                                     (src_clk_div - 1) <<
 701                                     CLK_TSADC_DIV_SHIFT);
 702                }
 703                break;
 704        default:
 705                return -ENOENT;
 706        }
 707        return rk3588_adc_get_clk(priv, clk_id);
 708}
 709
 710static ulong rk3588_mmc_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
 711{
 712        struct rk3588_cru *cru = priv->cru;
 713        u32 sel, con, div, prate;
 714
 715        switch (clk_id) {
 716        case CCLK_SRC_SDIO:
 717                con = readl(&cru->clksel_con[172]);
 718                div = (con & CCLK_SDIO_SRC_DIV_MASK) >> CCLK_SDIO_SRC_DIV_SHIFT;
 719                sel = (con & CCLK_SDIO_SRC_SEL_MASK) >>
 720                      CCLK_SDIO_SRC_SEL_SHIFT;
 721                if (sel == CCLK_SDIO_SRC_SEL_GPLL)
 722                        prate = priv->gpll_hz;
 723                else if (sel == CCLK_SDIO_SRC_SEL_CPLL)
 724                        prate = priv->cpll_hz;
 725                else
 726                        prate = OSC_HZ;
 727                return DIV_TO_RATE(prate, div);
 728        case CCLK_EMMC:
 729                con = readl(&cru->clksel_con[77]);
 730                div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
 731                sel = (con & CCLK_EMMC_SEL_MASK) >>
 732                      CCLK_EMMC_SEL_SHIFT;
 733                if (sel == CCLK_EMMC_SEL_GPLL)
 734                        prate = priv->gpll_hz;
 735                else if (sel == CCLK_EMMC_SEL_CPLL)
 736                        prate = priv->cpll_hz;
 737                else
 738                        prate = OSC_HZ;
 739                return DIV_TO_RATE(prate, div);
 740        case BCLK_EMMC:
 741                con = readl(&cru->clksel_con[78]);
 742                div = (con & BCLK_EMMC_DIV_MASK) >> BCLK_EMMC_DIV_SHIFT;
 743                sel = (con & BCLK_EMMC_SEL_MASK) >>
 744                      BCLK_EMMC_SEL_SHIFT;
 745                if (sel == CCLK_EMMC_SEL_CPLL)
 746                        prate = priv->cpll_hz;
 747                else
 748                        prate = priv->gpll_hz;
 749                return DIV_TO_RATE(prate, div);
 750        case SCLK_SFC:
 751                con = readl(&cru->clksel_con[78]);
 752                div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT;
 753                sel = (con & SCLK_SFC_SEL_MASK) >>
 754                      SCLK_SFC_SEL_SHIFT;
 755                if (sel == SCLK_SFC_SEL_GPLL)
 756                        prate = priv->gpll_hz;
 757                else if (sel == SCLK_SFC_SEL_CPLL)
 758                        prate = priv->cpll_hz;
 759                else
 760                        prate = OSC_HZ;
 761                return DIV_TO_RATE(prate, div);
 762        case DCLK_DECOM:
 763                con = readl(&cru->clksel_con[62]);
 764                div = (con & DCLK_DECOM_DIV_MASK) >> DCLK_DECOM_DIV_SHIFT;
 765                sel = (con & DCLK_DECOM_SEL_MASK) >>
 766                      DCLK_DECOM_SEL_SHIFT;
 767                if (sel == DCLK_DECOM_SEL_SPLL)
 768                        prate = 702 * MHz;
 769                else
 770                        prate = priv->gpll_hz;
 771                return DIV_TO_RATE(prate, div);
 772        default:
 773                return -ENOENT;
 774        }
 775}
 776
 777static ulong rk3588_mmc_set_clk(struct rk3588_clk_priv *priv,
 778                                ulong clk_id, ulong rate)
 779{
 780        struct rk3588_cru *cru = priv->cru;
 781        int src_clk, div;
 782
 783        switch (clk_id) {
 784        case CCLK_SRC_SDIO:
 785        case CCLK_EMMC:
 786        case SCLK_SFC:
 787                if (!(OSC_HZ % rate)) {
 788                        src_clk = SCLK_SFC_SEL_24M;
 789                        div = DIV_ROUND_UP(OSC_HZ, rate);
 790                } else if (!(priv->cpll_hz % rate)) {
 791                        src_clk = SCLK_SFC_SEL_CPLL;
 792                        div = DIV_ROUND_UP(priv->cpll_hz, rate);
 793                } else {
 794                        src_clk = SCLK_SFC_SEL_GPLL;
 795                        div = DIV_ROUND_UP(priv->gpll_hz, rate);
 796                }
 797                break;
 798        case BCLK_EMMC:
 799                if (!(priv->cpll_hz % rate)) {
 800                        src_clk = CCLK_EMMC_SEL_CPLL;
 801                        div = DIV_ROUND_UP(priv->cpll_hz, rate);
 802                } else {
 803                        src_clk = CCLK_EMMC_SEL_GPLL;
 804                        div = DIV_ROUND_UP(priv->gpll_hz, rate);
 805                }
 806                break;
 807        case DCLK_DECOM:
 808                if (!(702 * MHz % rate)) {
 809                        src_clk = DCLK_DECOM_SEL_SPLL;
 810                        div = DIV_ROUND_UP(702 * MHz, rate);
 811                } else {
 812                        src_clk = DCLK_DECOM_SEL_GPLL;
 813                        div = DIV_ROUND_UP(priv->gpll_hz, rate);
 814                }
 815                break;
 816        default:
 817                return -ENOENT;
 818        }
 819
 820        switch (clk_id) {
 821        case CCLK_SRC_SDIO:
 822                rk_clrsetreg(&cru->clksel_con[172],
 823                             CCLK_SDIO_SRC_SEL_MASK |
 824                             CCLK_SDIO_SRC_DIV_MASK,
 825                             (src_clk << CCLK_SDIO_SRC_SEL_SHIFT) |
 826                             (div - 1) << CCLK_SDIO_SRC_DIV_SHIFT);
 827                break;
 828        case CCLK_EMMC:
 829                rk_clrsetreg(&cru->clksel_con[77],
 830                             CCLK_EMMC_SEL_MASK |
 831                             CCLK_EMMC_DIV_MASK,
 832                             (src_clk << CCLK_EMMC_SEL_SHIFT) |
 833                             (div - 1) << CCLK_EMMC_DIV_SHIFT);
 834                break;
 835        case BCLK_EMMC:
 836                rk_clrsetreg(&cru->clksel_con[78],
 837                             BCLK_EMMC_DIV_MASK |
 838                             BCLK_EMMC_SEL_MASK,
 839                             (src_clk << BCLK_EMMC_SEL_SHIFT) |
 840                             (div - 1) << BCLK_EMMC_DIV_SHIFT);
 841                break;
 842        case SCLK_SFC:
 843                rk_clrsetreg(&cru->clksel_con[78],
 844                             SCLK_SFC_DIV_MASK |
 845                             SCLK_SFC_SEL_MASK,
 846                             (src_clk << SCLK_SFC_SEL_SHIFT) |
 847                             (div - 1) << SCLK_SFC_DIV_SHIFT);
 848                break;
 849        case DCLK_DECOM:
 850                rk_clrsetreg(&cru->clksel_con[62],
 851                             DCLK_DECOM_DIV_MASK |
 852                             DCLK_DECOM_SEL_MASK,
 853                             (src_clk << DCLK_DECOM_SEL_SHIFT) |
 854                             (div - 1) << DCLK_DECOM_DIV_SHIFT);
 855                break;
 856        default:
 857                return -ENOENT;
 858        }
 859
 860        return rk3588_mmc_get_clk(priv, clk_id);
 861}
 862
 863#ifndef CONFIG_SPL_BUILD
 864static ulong rk3588_aux16m_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
 865{
 866        struct rk3588_cru *cru = priv->cru;
 867        u32 div, con, parent;
 868
 869        parent = priv->gpll_hz;
 870        con = readl(&cru->clksel_con[117]);
 871
 872        switch (clk_id) {
 873        case CLK_AUX16M_0:
 874                div = (con & CLK_AUX16MHZ_0_DIV_MASK) >> CLK_AUX16MHZ_0_DIV_SHIFT;
 875                return DIV_TO_RATE(parent, div);
 876        case CLK_AUX16M_1:
 877                div = (con & CLK_AUX16MHZ_1_DIV_MASK) >> CLK_AUX16MHZ_1_DIV_SHIFT;
 878                return DIV_TO_RATE(parent, div);
 879        default:
 880                return -ENOENT;
 881        }
 882}
 883
 884static ulong rk3588_aux16m_set_clk(struct rk3588_clk_priv *priv,
 885                                   ulong clk_id, ulong rate)
 886{
 887        struct rk3588_cru *cru = priv->cru;
 888        u32 div;
 889
 890        if (!priv->gpll_hz) {
 891                printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
 892                return -ENOENT;
 893        }
 894
 895        div = DIV_ROUND_UP(priv->gpll_hz, rate);
 896
 897        switch (clk_id) {
 898        case CLK_AUX16M_0:
 899                rk_clrsetreg(&cru->clksel_con[117], CLK_AUX16MHZ_0_DIV_MASK,
 900                             (div - 1) << CLK_AUX16MHZ_0_DIV_SHIFT);
 901                break;
 902        case CLK_AUX16M_1:
 903                rk_clrsetreg(&cru->clksel_con[117], CLK_AUX16MHZ_1_DIV_MASK,
 904                             (div - 1) << CLK_AUX16MHZ_1_DIV_SHIFT);
 905                break;
 906        default:
 907                return -ENOENT;
 908        }
 909
 910        return rk3588_aux16m_get_clk(priv, clk_id);
 911}
 912
 913static ulong rk3588_aclk_vop_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
 914{
 915        struct rk3588_cru *cru = priv->cru;
 916        u32 div, sel, con, parent;
 917
 918        switch (clk_id) {
 919        case ACLK_VOP_ROOT:
 920        case ACLK_VOP:
 921                con = readl(&cru->clksel_con[110]);
 922                div = (con & ACLK_VOP_ROOT_DIV_MASK) >> ACLK_VOP_ROOT_DIV_SHIFT;
 923                sel = (con & ACLK_VOP_ROOT_SEL_MASK) >> ACLK_VOP_ROOT_SEL_SHIFT;
 924                if (sel == ACLK_VOP_ROOT_SEL_GPLL)
 925                        parent = priv->gpll_hz;
 926                else if (sel == ACLK_VOP_ROOT_SEL_CPLL)
 927                        parent = priv->cpll_hz;
 928                else if (sel == ACLK_VOP_ROOT_SEL_AUPLL)
 929                        parent = priv->aupll_hz;
 930                else if (sel == ACLK_VOP_ROOT_SEL_NPLL)
 931                        parent = priv->npll_hz;
 932                else
 933                        parent = 702 * MHz;
 934                return DIV_TO_RATE(parent, div);
 935        case ACLK_VOP_LOW_ROOT:
 936                con = readl(&cru->clksel_con[110]);
 937                sel = (con & ACLK_VOP_LOW_ROOT_SEL_MASK) >>
 938                      ACLK_VOP_LOW_ROOT_SEL_SHIFT;
 939                if (sel == ACLK_VOP_LOW_ROOT_SEL_400M)
 940                        return 396 * MHz;
 941                else if (sel == ACLK_VOP_LOW_ROOT_SEL_200M)
 942                        return 200 * MHz;
 943                else if (sel == ACLK_VOP_LOW_ROOT_SEL_100M)
 944                        return 100 * MHz;
 945                else
 946                        return OSC_HZ;
 947        case HCLK_VOP_ROOT:
 948                con = readl(&cru->clksel_con[110]);
 949                sel = (con & HCLK_VOP_ROOT_SEL_MASK) >> HCLK_VOP_ROOT_SEL_SHIFT;
 950                if (sel == HCLK_VOP_ROOT_SEL_200M)
 951                        return 200 * MHz;
 952                else if (sel == HCLK_VOP_ROOT_SEL_100M)
 953                        return 100 * MHz;
 954                else if (sel == HCLK_VOP_ROOT_SEL_50M)
 955                        return 50 * MHz;
 956                else
 957                        return OSC_HZ;
 958        default:
 959                return -ENOENT;
 960        }
 961}
 962
 963static ulong rk3588_aclk_vop_set_clk(struct rk3588_clk_priv *priv,
 964                                     ulong clk_id, ulong rate)
 965{
 966        struct rk3588_cru *cru = priv->cru;
 967        int src_clk, div;
 968
 969        switch (clk_id) {
 970        case ACLK_VOP_ROOT:
 971        case ACLK_VOP:
 972                if (rate >= 850 * MHz) {
 973                        src_clk = ACLK_VOP_ROOT_SEL_NPLL;
 974                        div = 1;
 975                } else if (rate >= 750 * MHz) {
 976                        src_clk = ACLK_VOP_ROOT_SEL_CPLL;
 977                        div = 2;
 978                } else if (rate >= 700 * MHz) {
 979                        src_clk = ACLK_VOP_ROOT_SEL_SPLL;
 980                        div = 1;
 981                } else if (!(priv->cpll_hz % rate)) {
 982                        src_clk = ACLK_VOP_ROOT_SEL_CPLL;
 983                        div = DIV_ROUND_UP(priv->cpll_hz, rate);
 984                } else {
 985                        src_clk = ACLK_VOP_ROOT_SEL_GPLL;
 986                        div = DIV_ROUND_UP(priv->gpll_hz, rate);
 987                }
 988                rk_clrsetreg(&cru->clksel_con[110],
 989                             ACLK_VOP_ROOT_DIV_MASK |
 990                             ACLK_VOP_ROOT_SEL_MASK,
 991                             (src_clk << ACLK_VOP_ROOT_SEL_SHIFT) |
 992                             (div - 1) << ACLK_VOP_ROOT_DIV_SHIFT);
 993                break;
 994        case ACLK_VOP_LOW_ROOT:
 995                if (rate == 400 * MHz || rate == 396 * MHz)
 996                        src_clk = ACLK_VOP_LOW_ROOT_SEL_400M;
 997                else if (rate == 200 * MHz)
 998                        src_clk = ACLK_VOP_LOW_ROOT_SEL_200M;
 999                else if (rate == 100 * MHz)
1000                        src_clk = ACLK_VOP_LOW_ROOT_SEL_100M;
1001                else
1002                        src_clk = ACLK_VOP_LOW_ROOT_SEL_24M;
1003                rk_clrsetreg(&cru->clksel_con[110],
1004                             ACLK_VOP_LOW_ROOT_SEL_MASK,
1005                             src_clk << ACLK_VOP_LOW_ROOT_SEL_SHIFT);
1006                break;
1007        case HCLK_VOP_ROOT:
1008                if (rate == 200 * MHz)
1009                        src_clk = HCLK_VOP_ROOT_SEL_200M;
1010                else if (rate == 100 * MHz)
1011                        src_clk = HCLK_VOP_ROOT_SEL_100M;
1012                else if (rate == 50 * MHz)
1013                        src_clk = HCLK_VOP_ROOT_SEL_50M;
1014                else
1015                        src_clk = HCLK_VOP_ROOT_SEL_24M;
1016                rk_clrsetreg(&cru->clksel_con[110],
1017                             HCLK_VOP_ROOT_SEL_MASK,
1018                             src_clk << HCLK_VOP_ROOT_SEL_SHIFT);
1019                break;
1020        default:
1021                return -ENOENT;
1022        }
1023
1024        return rk3588_aclk_vop_get_clk(priv, clk_id);
1025}
1026
1027static ulong rk3588_dclk_vop_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
1028{
1029        struct rk3588_cru *cru = priv->cru;
1030        u32 div, sel, con, parent;
1031
1032        switch (clk_id) {
1033        case DCLK_VOP0:
1034        case DCLK_VOP0_SRC:
1035                con = readl(&cru->clksel_con[111]);
1036                div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
1037                sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1038                break;
1039        case DCLK_VOP1:
1040        case DCLK_VOP1_SRC:
1041                con = readl(&cru->clksel_con[111]);
1042                div = (con & DCLK1_VOP_SRC_DIV_MASK) >> DCLK1_VOP_SRC_DIV_SHIFT;
1043                sel = (con & DCLK1_VOP_SRC_SEL_MASK) >> DCLK1_VOP_SRC_SEL_SHIFT;
1044                break;
1045        case DCLK_VOP2:
1046        case DCLK_VOP2_SRC:
1047                con = readl(&cru->clksel_con[112]);
1048                div = (con & DCLK2_VOP_SRC_DIV_MASK) >> DCLK2_VOP_SRC_DIV_SHIFT;
1049                sel = (con & DCLK2_VOP_SRC_SEL_MASK) >> DCLK2_VOP_SRC_SEL_SHIFT;
1050                break;
1051        case DCLK_VOP3:
1052                con = readl(&cru->clksel_con[113]);
1053                div = (con & DCLK3_VOP_SRC_DIV_MASK) >> DCLK3_VOP_SRC_DIV_SHIFT;
1054                sel = (con & DCLK3_VOP_SRC_SEL_MASK) >> DCLK3_VOP_SRC_SEL_SHIFT;
1055                break;
1056        default:
1057                return -ENOENT;
1058        }
1059
1060        if (sel == DCLK_VOP_SRC_SEL_AUPLL)
1061                parent = priv->aupll_hz;
1062        else if (sel == DCLK_VOP_SRC_SEL_V0PLL)
1063                parent = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
1064                                               priv->cru, V0PLL);
1065        else if (sel == DCLK_VOP_SRC_SEL_GPLL)
1066                parent = priv->gpll_hz;
1067        else if (sel == DCLK_VOP_SRC_SEL_CPLL)
1068                parent = priv->cpll_hz;
1069        else
1070                return -ENOENT;
1071
1072        return DIV_TO_RATE(parent, div);
1073}
1074
1075#define RK3588_VOP_PLL_LIMIT_FREQ 600000000
1076
1077static ulong rk3588_dclk_vop_set_clk(struct rk3588_clk_priv *priv,
1078                                     ulong clk_id, ulong rate)
1079{
1080        struct rk3588_cru *cru = priv->cru;
1081        ulong pll_rate, now, best_rate = 0;
1082        u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
1083        u32 mask, div_shift, sel_shift;
1084
1085        switch (clk_id) {
1086        case DCLK_VOP0:
1087        case DCLK_VOP0_SRC:
1088                conid = 111;
1089                con = readl(&cru->clksel_con[111]);
1090                sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1091                mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
1092                div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
1093                sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
1094                break;
1095        case DCLK_VOP1:
1096        case DCLK_VOP1_SRC:
1097                conid = 111;
1098                con = readl(&cru->clksel_con[111]);
1099                sel = (con & DCLK1_VOP_SRC_SEL_MASK) >> DCLK1_VOP_SRC_SEL_SHIFT;
1100                mask = DCLK1_VOP_SRC_SEL_MASK | DCLK1_VOP_SRC_DIV_MASK;
1101                div_shift = DCLK1_VOP_SRC_DIV_SHIFT;
1102                sel_shift = DCLK1_VOP_SRC_SEL_SHIFT;
1103                break;
1104        case DCLK_VOP2:
1105        case DCLK_VOP2_SRC:
1106                conid = 112;
1107                con = readl(&cru->clksel_con[112]);
1108                sel = (con & DCLK2_VOP_SRC_SEL_MASK) >> DCLK2_VOP_SRC_SEL_SHIFT;
1109                mask = DCLK2_VOP_SRC_SEL_MASK | DCLK2_VOP_SRC_DIV_MASK;
1110                div_shift = DCLK2_VOP_SRC_DIV_SHIFT;
1111                sel_shift = DCLK2_VOP_SRC_SEL_SHIFT;
1112                break;
1113        case DCLK_VOP3:
1114                conid = 113;
1115                con = readl(&cru->clksel_con[113]);
1116                sel = (con & DCLK3_VOP_SRC_SEL_MASK) >> DCLK3_VOP_SRC_SEL_SHIFT;
1117                mask = DCLK3_VOP_SRC_SEL_MASK | DCLK3_VOP_SRC_DIV_MASK;
1118                div_shift = DCLK3_VOP_SRC_DIV_SHIFT;
1119                sel_shift = DCLK3_VOP_SRC_SEL_SHIFT;
1120                break;
1121        default:
1122                return -ENOENT;
1123        }
1124
1125        if (sel == DCLK_VOP_SRC_SEL_V0PLL) {
1126                div = DIV_ROUND_UP(RK3588_VOP_PLL_LIMIT_FREQ, rate);
1127                rk_clrsetreg(&cru->clksel_con[conid],
1128                             mask,
1129                             DCLK_VOP_SRC_SEL_V0PLL << sel_shift |
1130                             ((div - 1) << div_shift));
1131                rockchip_pll_set_rate(&rk3588_pll_clks[V0PLL],
1132                                      priv->cru, V0PLL, div * rate);
1133        } else {
1134                for (i = 0; i <= DCLK_VOP_SRC_SEL_AUPLL; i++) {
1135                        switch (i) {
1136                        case DCLK_VOP_SRC_SEL_GPLL:
1137                                pll_rate = priv->gpll_hz;
1138                                break;
1139                        case DCLK_VOP_SRC_SEL_CPLL:
1140                                pll_rate = priv->cpll_hz;
1141                                break;
1142                        case DCLK_VOP_SRC_SEL_AUPLL:
1143                                pll_rate = priv->aupll_hz;
1144                                break;
1145                        case DCLK_VOP_SRC_SEL_V0PLL:
1146                                pll_rate = 0;
1147                                break;
1148                        default:
1149                                printf("do not support this vop pll sel\n");
1150                                return -EINVAL;
1151                        }
1152
1153                        div = DIV_ROUND_UP(pll_rate, rate);
1154                        if (div > 255)
1155                                continue;
1156                        now = pll_rate / div;
1157                        if (abs(rate - now) < abs(rate - best_rate)) {
1158                                best_rate = now;
1159                                best_div = div;
1160                                best_sel = i;
1161                        }
1162                        debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1163                              pll_rate, best_rate, best_div, best_sel);
1164                }
1165
1166                if (best_rate) {
1167                        rk_clrsetreg(&cru->clksel_con[conid],
1168                                     mask,
1169                                     best_sel << sel_shift |
1170                                     (best_div - 1) << div_shift);
1171                } else {
1172                        printf("do not support this vop freq %lu\n", rate);
1173                        return -EINVAL;
1174                }
1175        }
1176        return rk3588_dclk_vop_get_clk(priv, clk_id);
1177}
1178
1179static ulong rk3588_gmac_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
1180{
1181        struct rk3588_cru *cru = priv->cru;
1182        u32 con, div;
1183
1184        switch (clk_id) {
1185        case CLK_GMAC0_PTP_REF:
1186                con = readl(&cru->clksel_con[81]);
1187                div = (con & CLK_GMAC0_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
1188                return DIV_TO_RATE(priv->cpll_hz, div);
1189        case CLK_GMAC1_PTP_REF:
1190                con = readl(&cru->clksel_con[81]);
1191                div = (con & CLK_GMAC1_PTP_DIV_MASK) >> CLK_GMAC1_PTP_DIV_SHIFT;
1192                return DIV_TO_RATE(priv->cpll_hz, div);
1193        case CLK_GMAC_125M:
1194                con = readl(&cru->clksel_con[83]);
1195                div = (con & CLK_GMAC_125M_DIV_MASK) >> CLK_GMAC_125M_DIV_SHIFT;
1196                return DIV_TO_RATE(priv->cpll_hz, div);
1197        case CLK_GMAC_50M:
1198                con = readl(&cru->clksel_con[84]);
1199                div = (con & CLK_GMAC_50M_DIV_MASK) >> CLK_GMAC_50M_DIV_SHIFT;
1200                return DIV_TO_RATE(priv->cpll_hz, div);
1201        default:
1202                return -ENOENT;
1203        }
1204}
1205
1206static ulong rk3588_gmac_set_clk(struct rk3588_clk_priv *priv,
1207                                 ulong clk_id, ulong rate)
1208{
1209        struct rk3588_cru *cru = priv->cru;
1210        int div;
1211
1212        div = DIV_ROUND_UP(priv->cpll_hz, rate);
1213
1214        switch (clk_id) {
1215        case CLK_GMAC0_PTP_REF:
1216                rk_clrsetreg(&cru->clksel_con[81],
1217                             CLK_GMAC0_PTP_DIV_MASK | CLK_GMAC0_PTP_SEL_MASK,
1218                             CLK_GMAC0_PTP_SEL_CPLL << CLK_GMAC0_PTP_SEL_SHIFT |
1219                             (div - 1) << CLK_GMAC0_PTP_DIV_SHIFT);
1220                break;
1221        case CLK_GMAC1_PTP_REF:
1222                rk_clrsetreg(&cru->clksel_con[81],
1223                             CLK_GMAC1_PTP_DIV_MASK | CLK_GMAC1_PTP_SEL_MASK,
1224                             CLK_GMAC1_PTP_SEL_CPLL << CLK_GMAC1_PTP_SEL_SHIFT |
1225                             (div - 1) << CLK_GMAC1_PTP_DIV_SHIFT);
1226                break;
1227
1228        case CLK_GMAC_125M:
1229                rk_clrsetreg(&cru->clksel_con[83],
1230                             CLK_GMAC_125M_DIV_MASK | CLK_GMAC_125M_SEL_MASK,
1231                             CLK_GMAC_125M_SEL_CPLL << CLK_GMAC_125M_SEL_SHIFT |
1232                             (div - 1) << CLK_GMAC_125M_DIV_SHIFT);
1233                break;
1234        case CLK_GMAC_50M:
1235                rk_clrsetreg(&cru->clksel_con[84],
1236                             CLK_GMAC_50M_DIV_MASK | CLK_GMAC_50M_SEL_MASK,
1237                             CLK_GMAC_50M_SEL_CPLL << CLK_GMAC_50M_SEL_SHIFT |
1238                             (div - 1) << CLK_GMAC_50M_DIV_SHIFT);
1239                break;
1240        default:
1241                return -ENOENT;
1242        }
1243
1244        return rk3588_gmac_get_clk(priv, clk_id);
1245}
1246
1247static ulong rk3588_uart_get_rate(struct rk3588_clk_priv *priv, ulong clk_id)
1248{
1249        struct rk3588_cru *cru = priv->cru;
1250        u32 reg, con, fracdiv, div, src, p_src, p_rate;
1251        unsigned long m, n;
1252
1253        switch (clk_id) {
1254        case SCLK_UART1:
1255                reg = 41;
1256                break;
1257        case SCLK_UART2:
1258                reg = 43;
1259                break;
1260        case SCLK_UART3:
1261                reg = 45;
1262                break;
1263        case SCLK_UART4:
1264                reg = 47;
1265                break;
1266        case SCLK_UART5:
1267                reg = 49;
1268                break;
1269        case SCLK_UART6:
1270                reg = 51;
1271                break;
1272        case SCLK_UART7:
1273                reg = 53;
1274                break;
1275        case SCLK_UART8:
1276                reg = 55;
1277                break;
1278        case SCLK_UART9:
1279                reg = 57;
1280                break;
1281        default:
1282                return -ENOENT;
1283        }
1284        con = readl(&cru->clksel_con[reg + 2]);
1285        src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
1286        con = readl(&cru->clksel_con[reg]);
1287        div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
1288        p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
1289        if (p_src == CLK_UART_SRC_SEL_GPLL)
1290                p_rate = priv->gpll_hz;
1291        else
1292                p_rate = priv->cpll_hz;
1293
1294        if (src == CLK_UART_SEL_SRC) {
1295                return DIV_TO_RATE(p_rate, div);
1296        } else if (src == CLK_UART_SEL_FRAC) {
1297                fracdiv = readl(&cru->clksel_con[reg + 1]);
1298                n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
1299                n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
1300                m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
1301                m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
1302                return DIV_TO_RATE(p_rate, div) * n / m;
1303        } else {
1304                return OSC_HZ;
1305        }
1306}
1307
1308static ulong rk3588_uart_set_rate(struct rk3588_clk_priv *priv,
1309                                  ulong clk_id, ulong rate)
1310{
1311        struct rk3588_cru *cru = priv->cru;
1312        u32 reg, clk_src, uart_src, div;
1313        unsigned long m = 0, n = 0, val;
1314
1315        if (priv->gpll_hz % rate == 0) {
1316                clk_src = CLK_UART_SRC_SEL_GPLL;
1317                uart_src = CLK_UART_SEL_SRC;
1318                div = DIV_ROUND_UP(priv->gpll_hz, rate);
1319        } else if (priv->cpll_hz % rate == 0) {
1320                clk_src = CLK_UART_SRC_SEL_CPLL;
1321                uart_src = CLK_UART_SEL_SRC;
1322                div = DIV_ROUND_UP(priv->gpll_hz, rate);
1323        } else if (rate == OSC_HZ) {
1324                clk_src = CLK_UART_SRC_SEL_GPLL;
1325                uart_src = CLK_UART_SEL_XIN24M;
1326                div = 2;
1327        } else {
1328                clk_src = CLK_UART_SRC_SEL_GPLL;
1329                uart_src = CLK_UART_SEL_FRAC;
1330                div = 2;
1331                rational_best_approximation(rate, priv->gpll_hz / div,
1332                                            GENMASK(16 - 1, 0),
1333                                            GENMASK(16 - 1, 0),
1334                                            &m, &n);
1335        }
1336
1337        switch (clk_id) {
1338        case SCLK_UART1:
1339                reg = 41;
1340                break;
1341        case SCLK_UART2:
1342                reg = 43;
1343                break;
1344        case SCLK_UART3:
1345                reg = 45;
1346                break;
1347        case SCLK_UART4:
1348                reg = 47;
1349                break;
1350        case SCLK_UART5:
1351                reg = 49;
1352                break;
1353        case SCLK_UART6:
1354                reg = 51;
1355                break;
1356        case SCLK_UART7:
1357                reg = 53;
1358                break;
1359        case SCLK_UART8:
1360                reg = 55;
1361                break;
1362        case SCLK_UART9:
1363                reg = 57;
1364                break;
1365        default:
1366                return -ENOENT;
1367        }
1368        rk_clrsetreg(&cru->clksel_con[reg],
1369                     CLK_UART_SRC_SEL_MASK |
1370                     CLK_UART_SRC_DIV_MASK,
1371                     (clk_src << CLK_UART_SRC_SEL_SHIFT) |
1372                     ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
1373        rk_clrsetreg(&cru->clksel_con[reg + 2],
1374                     CLK_UART_SEL_MASK,
1375                     (uart_src << CLK_UART_SEL_SHIFT));
1376        if (m && n) {
1377                val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
1378                writel(val, &cru->clksel_con[reg + 1]);
1379        }
1380
1381        return rk3588_uart_get_rate(priv, clk_id);
1382}
1383
1384static ulong rk3588_pciephy_get_rate(struct rk3588_clk_priv *priv, ulong clk_id)
1385{
1386        struct rk3588_cru *cru = priv->cru;
1387        u32 con, div, src;
1388
1389        switch (clk_id) {
1390        case CLK_REF_PIPE_PHY0:
1391                con = readl(&cru->clksel_con[177]);
1392                src = (con & CLK_PCIE_PHY0_REF_SEL_MASK) >> CLK_PCIE_PHY0_REF_SEL_SHIFT;
1393                con = readl(&cru->clksel_con[176]);
1394                div = (con & CLK_PCIE_PHY0_PLL_DIV_MASK) >> CLK_PCIE_PHY0_PLL_DIV_SHIFT;
1395                break;
1396        case CLK_REF_PIPE_PHY1:
1397                con = readl(&cru->clksel_con[177]);
1398                src = (con & CLK_PCIE_PHY1_REF_SEL_MASK) >> CLK_PCIE_PHY1_REF_SEL_SHIFT;
1399                con = readl(&cru->clksel_con[176]);
1400                div = (con & CLK_PCIE_PHY1_PLL_DIV_MASK) >> CLK_PCIE_PHY1_PLL_DIV_SHIFT;
1401                break;
1402        case CLK_REF_PIPE_PHY2:
1403                con = readl(&cru->clksel_con[177]);
1404                src = (con & CLK_PCIE_PHY2_REF_SEL_MASK) >> CLK_PCIE_PHY2_REF_SEL_SHIFT;
1405                div = (con & CLK_PCIE_PHY2_PLL_DIV_MASK) >> CLK_PCIE_PHY2_PLL_DIV_SHIFT;
1406                break;
1407        default:
1408                return -ENOENT;
1409        }
1410
1411        if (src == CLK_PCIE_PHY_REF_SEL_PPLL)
1412                return DIV_TO_RATE(priv->ppll_hz, div);
1413        else
1414                return OSC_HZ;
1415}
1416
1417static ulong rk3588_pciephy_set_rate(struct rk3588_clk_priv *priv,
1418                                     ulong clk_id, ulong rate)
1419{
1420        struct rk3588_cru *cru = priv->cru;
1421        u32 clk_src, div;
1422
1423        if (rate == OSC_HZ) {
1424                clk_src = CLK_PCIE_PHY_REF_SEL_24M;
1425                div = 1;
1426        } else {
1427                clk_src = CLK_PCIE_PHY_REF_SEL_PPLL;
1428                div = DIV_ROUND_UP(priv->ppll_hz, rate);
1429        }
1430
1431        switch (clk_id) {
1432        case CLK_REF_PIPE_PHY0:
1433                rk_clrsetreg(&cru->clksel_con[177], CLK_PCIE_PHY0_REF_SEL_MASK,
1434                             (clk_src << CLK_PCIE_PHY0_REF_SEL_SHIFT));
1435                rk_clrsetreg(&cru->clksel_con[176], CLK_PCIE_PHY0_PLL_DIV_MASK,
1436                             ((div - 1) << CLK_PCIE_PHY0_PLL_DIV_SHIFT));
1437                break;
1438        case CLK_REF_PIPE_PHY1:
1439                rk_clrsetreg(&cru->clksel_con[177], CLK_PCIE_PHY1_REF_SEL_MASK,
1440                             (clk_src << CLK_PCIE_PHY1_REF_SEL_SHIFT));
1441                rk_clrsetreg(&cru->clksel_con[176], CLK_PCIE_PHY1_PLL_DIV_MASK,
1442                             ((div - 1) << CLK_PCIE_PHY1_PLL_DIV_SHIFT));
1443                break;
1444        case CLK_REF_PIPE_PHY2:
1445                rk_clrsetreg(&cru->clksel_con[177], CLK_PCIE_PHY2_REF_SEL_MASK |
1446                             CLK_PCIE_PHY2_PLL_DIV_MASK,
1447                             (clk_src << CLK_PCIE_PHY2_REF_SEL_SHIFT) |
1448                             ((div - 1) << CLK_PCIE_PHY2_PLL_DIV_SHIFT));
1449                break;
1450        default:
1451                return -ENOENT;
1452        }
1453
1454        return rk3588_pciephy_get_rate(priv, clk_id);
1455}
1456#endif
1457
1458static ulong rk3588_clk_get_rate(struct clk *clk)
1459{
1460        struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
1461        ulong rate = 0;
1462
1463        if (!priv->gpll_hz) {
1464                printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1465                return -ENOENT;
1466        }
1467
1468        if (!priv->ppll_hz) {
1469                priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1470                                                      priv->cru, PPLL);
1471        }
1472
1473        switch (clk->id) {
1474        case PLL_LPLL:
1475                rate = rockchip_pll_get_rate(&rk3588_pll_clks[LPLL], priv->cru,
1476                                             LPLL);
1477                break;
1478        case PLL_B0PLL:
1479                rate = rockchip_pll_get_rate(&rk3588_pll_clks[B0PLL], priv->cru,
1480                                             B0PLL);
1481                break;
1482        case PLL_B1PLL:
1483                rate = rockchip_pll_get_rate(&rk3588_pll_clks[B1PLL], priv->cru,
1484                                             B1PLL);
1485                break;
1486        case PLL_GPLL:
1487                rate = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL], priv->cru,
1488                                             GPLL);
1489                break;
1490        case PLL_CPLL:
1491                rate = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL], priv->cru,
1492                                             CPLL);
1493                break;
1494        case PLL_NPLL:
1495                rate = rockchip_pll_get_rate(&rk3588_pll_clks[NPLL], priv->cru,
1496                                             NPLL);
1497                break;
1498        case PLL_V0PLL:
1499                rate = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL], priv->cru,
1500                                             V0PLL);
1501                break;
1502        case PLL_AUPLL:
1503                rate = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL], priv->cru,
1504                                             AUPLL);
1505                break;
1506        case PLL_PPLL:
1507                rate = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL], priv->cru,
1508                                             PPLL);
1509                break;
1510        case ACLK_CENTER_ROOT:
1511        case PCLK_CENTER_ROOT:
1512        case HCLK_CENTER_ROOT:
1513        case ACLK_CENTER_LOW_ROOT:
1514                rate = rk3588_center_get_clk(priv, clk->id);
1515                break;
1516        case ACLK_TOP_ROOT:
1517        case PCLK_TOP_ROOT:
1518        case ACLK_LOW_TOP_ROOT:
1519                rate = rk3588_top_get_clk(priv, clk->id);
1520                break;
1521        case CLK_I2C0:
1522        case CLK_I2C1:
1523        case CLK_I2C2:
1524        case CLK_I2C3:
1525        case CLK_I2C4:
1526        case CLK_I2C5:
1527        case CLK_I2C6:
1528        case CLK_I2C7:
1529        case CLK_I2C8:
1530                rate = rk3588_i2c_get_clk(priv, clk->id);
1531                break;
1532        case CLK_SPI0:
1533        case CLK_SPI1:
1534        case CLK_SPI2:
1535        case CLK_SPI3:
1536        case CLK_SPI4:
1537                rate = rk3588_spi_get_clk(priv, clk->id);
1538                break;
1539        case CLK_PWM1:
1540        case CLK_PWM2:
1541        case CLK_PWM3:
1542        case CLK_PMU1PWM:
1543                rate = rk3588_pwm_get_clk(priv, clk->id);
1544                break;
1545        case CLK_SARADC:
1546        case CLK_TSADC:
1547                rate = rk3588_adc_get_clk(priv, clk->id);
1548                break;
1549        case CCLK_SRC_SDIO:
1550        case CCLK_EMMC:
1551        case BCLK_EMMC:
1552        case SCLK_SFC:
1553        case DCLK_DECOM:
1554                rate = rk3588_mmc_get_clk(priv, clk->id);
1555                break;
1556        case TMCLK_EMMC:
1557        case TCLK_WDT0:
1558                rate = OSC_HZ;
1559                break;
1560        case PCLK_PMU0_ROOT:
1561                rate = 100000000;
1562                break;
1563        case HCLK_PMU_CM0_ROOT:
1564                rate = 200000000;
1565                break;
1566        case ACLK_BUS_ROOT:
1567                rate = 375000000;
1568                break;
1569        case CLK_150M_SRC:
1570                rate = 150000000;
1571                break;
1572        case CLK_GPU:
1573                rate = 200000000;
1574                break;
1575#ifndef CONFIG_SPL_BUILD
1576        case CLK_AUX16M_0:
1577        case CLK_AUX16M_1:
1578                rate = rk3588_aux16m_get_clk(priv, clk->id);
1579                break;
1580        case ACLK_VOP_ROOT:
1581        case ACLK_VOP:
1582        case ACLK_VOP_LOW_ROOT:
1583        case HCLK_VOP_ROOT:
1584                rate = rk3588_aclk_vop_get_clk(priv, clk->id);
1585                break;
1586        case DCLK_VOP0:
1587        case DCLK_VOP0_SRC:
1588        case DCLK_VOP1:
1589        case DCLK_VOP1_SRC:
1590        case DCLK_VOP2:
1591        case DCLK_VOP2_SRC:
1592        case DCLK_VOP3:
1593                rate = rk3588_dclk_vop_get_clk(priv, clk->id);
1594                break;
1595        case CLK_GMAC0_PTP_REF:
1596        case CLK_GMAC1_PTP_REF:
1597        case CLK_GMAC_125M:
1598        case CLK_GMAC_50M:
1599                rate = rk3588_gmac_get_clk(priv, clk->id);
1600                break;
1601        case SCLK_UART1:
1602        case SCLK_UART2:
1603        case SCLK_UART3:
1604        case SCLK_UART4:
1605        case SCLK_UART5:
1606        case SCLK_UART6:
1607        case SCLK_UART7:
1608        case SCLK_UART8:
1609        case SCLK_UART9:
1610                rate = rk3588_uart_get_rate(priv, clk->id);
1611                break;
1612        case CLK_REF_PIPE_PHY0:
1613        case CLK_REF_PIPE_PHY1:
1614        case CLK_REF_PIPE_PHY2:
1615                rate = rk3588_pciephy_get_rate(priv, clk->id);
1616                break;
1617#endif
1618        default:
1619                return -ENOENT;
1620        }
1621
1622        return rate;
1623};
1624
1625static ulong rk3588_clk_set_rate(struct clk *clk, ulong rate)
1626{
1627        struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
1628        ulong ret = 0;
1629
1630        if (!priv->gpll_hz) {
1631                printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1632                return -ENOENT;
1633        }
1634
1635        if (!priv->ppll_hz) {
1636                priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1637                                                      priv->cru, PPLL);
1638        }
1639
1640        switch (clk->id) {
1641        case PLL_CPLL:
1642                ret = rockchip_pll_set_rate(&rk3588_pll_clks[CPLL], priv->cru,
1643                                            CPLL, rate);
1644                priv->cpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL],
1645                                                      priv->cru, CPLL);
1646                break;
1647        case PLL_GPLL:
1648                ret = rockchip_pll_set_rate(&rk3588_pll_clks[GPLL], priv->cru,
1649                                            GPLL, rate);
1650                priv->gpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL],
1651                                                      priv->cru, GPLL);
1652                break;
1653        case PLL_NPLL:
1654                ret = rockchip_pll_set_rate(&rk3588_pll_clks[NPLL], priv->cru,
1655                                            NPLL, rate);
1656                break;
1657        case PLL_V0PLL:
1658                ret = rockchip_pll_set_rate(&rk3588_pll_clks[V0PLL], priv->cru,
1659                                            V0PLL, rate);
1660                priv->v0pll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
1661                                                       priv->cru, V0PLL);
1662                break;
1663        case PLL_AUPLL:
1664                ret = rockchip_pll_set_rate(&rk3588_pll_clks[AUPLL], priv->cru,
1665                                            AUPLL, rate);
1666                priv->aupll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL],
1667                                                       priv->cru, AUPLL);
1668                break;
1669        case PLL_PPLL:
1670                ret = rockchip_pll_set_rate(&rk3588_pll_clks[PPLL], priv->cru,
1671                                            PPLL, rate);
1672                priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1673                                                      priv->cru, PPLL);
1674                break;
1675        case ACLK_CENTER_ROOT:
1676        case PCLK_CENTER_ROOT:
1677        case HCLK_CENTER_ROOT:
1678        case ACLK_CENTER_LOW_ROOT:
1679                ret = rk3588_center_set_clk(priv, clk->id, rate);
1680                break;
1681        case ACLK_TOP_ROOT:
1682        case PCLK_TOP_ROOT:
1683        case ACLK_LOW_TOP_ROOT:
1684                ret = rk3588_top_set_clk(priv, clk->id, rate);
1685                break;
1686        case CLK_I2C0:
1687        case CLK_I2C1:
1688        case CLK_I2C2:
1689        case CLK_I2C3:
1690        case CLK_I2C4:
1691        case CLK_I2C5:
1692        case CLK_I2C6:
1693        case CLK_I2C7:
1694        case CLK_I2C8:
1695                ret = rk3588_i2c_set_clk(priv, clk->id, rate);
1696                break;
1697        case CLK_SPI0:
1698        case CLK_SPI1:
1699        case CLK_SPI2:
1700        case CLK_SPI3:
1701        case CLK_SPI4:
1702                ret = rk3588_spi_set_clk(priv, clk->id, rate);
1703                break;
1704        case CLK_PWM1:
1705        case CLK_PWM2:
1706        case CLK_PWM3:
1707        case CLK_PMU1PWM:
1708                ret = rk3588_pwm_set_clk(priv, clk->id, rate);
1709                break;
1710        case CLK_SARADC:
1711        case CLK_TSADC:
1712                ret = rk3588_adc_set_clk(priv, clk->id, rate);
1713                break;
1714        case CCLK_SRC_SDIO:
1715        case CCLK_EMMC:
1716        case BCLK_EMMC:
1717        case SCLK_SFC:
1718        case DCLK_DECOM:
1719                ret = rk3588_mmc_set_clk(priv, clk->id, rate);
1720                break;
1721        case TMCLK_EMMC:
1722        case TCLK_WDT0:
1723                ret = OSC_HZ;
1724                break;
1725        case PCLK_PMU0_ROOT:
1726        case CLK_GPU:
1727        case HCLK_PMU_CM0_ROOT:
1728        case ACLK_BUS_ROOT:
1729        case CLK_150M_SRC:
1730                ret = 0;
1731                break;
1732#ifndef CONFIG_SPL_BUILD
1733        case CLK_AUX16M_0:
1734        case CLK_AUX16M_1:
1735                ret = rk3588_aux16m_set_clk(priv, clk->id, rate);
1736                break;
1737        case ACLK_VOP_ROOT:
1738        case ACLK_VOP:
1739        case ACLK_VOP_LOW_ROOT:
1740        case HCLK_VOP_ROOT:
1741                ret = rk3588_aclk_vop_set_clk(priv, clk->id, rate);
1742                break;
1743        case DCLK_VOP0:
1744        case DCLK_VOP0_SRC:
1745        case DCLK_VOP1:
1746        case DCLK_VOP1_SRC:
1747        case DCLK_VOP2:
1748        case DCLK_VOP2_SRC:
1749        case DCLK_VOP3:
1750                ret = rk3588_dclk_vop_set_clk(priv, clk->id, rate);
1751                break;
1752        case CLK_GMAC0_PTP_REF:
1753        case CLK_GMAC1_PTP_REF:
1754        case CLK_GMAC_125M:
1755        case CLK_GMAC_50M:
1756                ret = rk3588_gmac_set_clk(priv, clk->id, rate);
1757                break;
1758        case SCLK_UART1:
1759        case SCLK_UART2:
1760        case SCLK_UART3:
1761        case SCLK_UART4:
1762        case SCLK_UART5:
1763        case SCLK_UART6:
1764        case SCLK_UART7:
1765        case SCLK_UART8:
1766        case SCLK_UART9:
1767                ret = rk3588_uart_set_rate(priv, clk->id, rate);
1768                break;
1769        case CLK_REF_PIPE_PHY0:
1770        case CLK_REF_PIPE_PHY1:
1771        case CLK_REF_PIPE_PHY2:
1772                ret = rk3588_pciephy_set_rate(priv, clk->id, rate);
1773                break;
1774#endif
1775        default:
1776                return -ENOENT;
1777        }
1778
1779        return ret;
1780};
1781
1782#define ROCKCHIP_MMC_DELAY_SEL          BIT(10)
1783#define ROCKCHIP_MMC_DEGREE_MASK        0x3
1784#define ROCKCHIP_MMC_DELAYNUM_OFFSET    2
1785#define ROCKCHIP_MMC_DELAYNUM_MASK      (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1786
1787#define PSECS_PER_SEC 1000000000000LL
1788/*
1789 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1790 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1791 */
1792#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1793
1794#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
1795static int __maybe_unused rk3588_dclk_vop_set_parent(struct clk *clk,
1796                                                     struct clk *parent)
1797{
1798        struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
1799        struct rk3588_cru *cru = priv->cru;
1800        u32 sel;
1801        const char *clock_dev_name = parent->dev->name;
1802
1803        if (parent->id == PLL_V0PLL)
1804                sel = 2;
1805        else if (parent->id == PLL_GPLL)
1806                sel = 0;
1807        else if (parent->id == PLL_CPLL)
1808                sel = 1;
1809        else
1810                sel = 3;
1811
1812        switch (clk->id) {
1813        case DCLK_VOP0_SRC:
1814                rk_clrsetreg(&cru->clksel_con[111], DCLK0_VOP_SRC_SEL_MASK,
1815                             sel << DCLK0_VOP_SRC_SEL_SHIFT);
1816                break;
1817        case DCLK_VOP1_SRC:
1818                rk_clrsetreg(&cru->clksel_con[111], DCLK1_VOP_SRC_SEL_MASK,
1819                             sel << DCLK1_VOP_SRC_SEL_SHIFT);
1820                break;
1821        case DCLK_VOP2_SRC:
1822                rk_clrsetreg(&cru->clksel_con[112], DCLK2_VOP_SRC_SEL_MASK,
1823                             sel << DCLK2_VOP_SRC_SEL_SHIFT);
1824                break;
1825        case DCLK_VOP3:
1826                rk_clrsetreg(&cru->clksel_con[113], DCLK3_VOP_SRC_SEL_MASK,
1827                             sel << DCLK3_VOP_SRC_SEL_SHIFT);
1828                break;
1829        case DCLK_VOP0:
1830                if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1831                        sel = 1;
1832                else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1833                        sel = 2;
1834                else
1835                        sel = 0;
1836                rk_clrsetreg(&cru->clksel_con[112], DCLK0_VOP_SEL_MASK,
1837                             sel << DCLK0_VOP_SEL_SHIFT);
1838                break;
1839        case DCLK_VOP1:
1840                if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1841                        sel = 1;
1842                else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1843                        sel = 2;
1844                else
1845                        sel = 0;
1846                rk_clrsetreg(&cru->clksel_con[112], DCLK1_VOP_SEL_MASK,
1847                             sel << DCLK1_VOP_SEL_SHIFT);
1848                break;
1849        case DCLK_VOP2:
1850                if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1851                        sel = 1;
1852                else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1853                        sel = 2;
1854                else
1855                        sel = 0;
1856                rk_clrsetreg(&cru->clksel_con[112], DCLK2_VOP_SEL_MASK,
1857                             sel << DCLK2_VOP_SEL_SHIFT);
1858                break;
1859        default:
1860                return -EINVAL;
1861        }
1862        return 0;
1863}
1864
1865static int rk3588_clk_set_parent(struct clk *clk, struct clk *parent)
1866{
1867        switch (clk->id) {
1868        case DCLK_VOP0_SRC:
1869        case DCLK_VOP1_SRC:
1870        case DCLK_VOP2_SRC:
1871        case DCLK_VOP0:
1872        case DCLK_VOP1:
1873        case DCLK_VOP2:
1874        case DCLK_VOP3:
1875                return rk3588_dclk_vop_set_parent(clk, parent);
1876        default:
1877                return -ENOENT;
1878        }
1879
1880        return 0;
1881}
1882#endif
1883
1884static struct clk_ops rk3588_clk_ops = {
1885        .get_rate = rk3588_clk_get_rate,
1886        .set_rate = rk3588_clk_set_rate,
1887#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
1888        .set_parent = rk3588_clk_set_parent,
1889#endif
1890};
1891
1892static void rk3588_clk_init(struct rk3588_clk_priv *priv)
1893{
1894        int ret, div;
1895
1896        div = DIV_ROUND_UP(GPLL_HZ, 300 * MHz);
1897        rk_clrsetreg(&priv->cru->clksel_con[38],
1898                     ACLK_BUS_ROOT_SEL_MASK |
1899                     ACLK_BUS_ROOT_DIV_MASK,
1900                     div << ACLK_BUS_ROOT_DIV_SHIFT);
1901
1902        if (priv->cpll_hz != CPLL_HZ) {
1903                ret = rockchip_pll_set_rate(&rk3588_pll_clks[CPLL], priv->cru,
1904                                            CPLL, CPLL_HZ);
1905                if (!ret)
1906                        priv->cpll_hz = CPLL_HZ;
1907        }
1908        if (priv->gpll_hz != GPLL_HZ) {
1909                ret = rockchip_pll_set_rate(&rk3588_pll_clks[GPLL], priv->cru,
1910                                            GPLL, GPLL_HZ);
1911                if (!ret)
1912                        priv->gpll_hz = GPLL_HZ;
1913        }
1914
1915#ifdef CONFIG_PCI
1916        if (priv->ppll_hz != PPLL_HZ) {
1917                ret = rockchip_pll_set_rate(&rk3588_pll_clks[PPLL], priv->cru,
1918                                            PPLL, PPLL_HZ);
1919                priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1920                                                      priv->cru, PPLL);
1921        }
1922#endif
1923        rk_clrsetreg(&priv->cru->clksel_con[9],
1924                     ACLK_TOP_S400_SEL_MASK |
1925                     ACLK_TOP_S200_SEL_MASK,
1926                     (ACLK_TOP_S400_SEL_400M << ACLK_TOP_S400_SEL_SHIFT) |
1927                     (ACLK_TOP_S200_SEL_200M << ACLK_TOP_S200_SEL_SHIFT));
1928}
1929
1930static int rk3588_clk_probe(struct udevice *dev)
1931{
1932        struct rk3588_clk_priv *priv = dev_get_priv(dev);
1933        int ret;
1934
1935        priv->sync_kernel = false;
1936
1937#ifdef CONFIG_SPL_BUILD
1938        rockchip_pll_set_rate(&rk3588_pll_clks[B0PLL], priv->cru,
1939                              B0PLL, LPLL_HZ);
1940        rockchip_pll_set_rate(&rk3588_pll_clks[B1PLL], priv->cru,
1941                              B1PLL, LPLL_HZ);
1942        if (!priv->armclk_enter_hz) {
1943                ret = rockchip_pll_set_rate(&rk3588_pll_clks[LPLL], priv->cru,
1944                                            LPLL, LPLL_HZ);
1945                priv->armclk_enter_hz =
1946                        rockchip_pll_get_rate(&rk3588_pll_clks[LPLL],
1947                                              priv->cru, LPLL);
1948                priv->armclk_init_hz = priv->armclk_enter_hz;
1949        }
1950#endif
1951
1952        priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
1953        if (IS_ERR(priv->grf))
1954                return PTR_ERR(priv->grf);
1955
1956        rk3588_clk_init(priv);
1957
1958        /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1959        ret = clk_set_defaults(dev, 1);
1960        if (ret)
1961                debug("%s clk_set_defaults failed %d\n", __func__, ret);
1962        else
1963                priv->sync_kernel = true;
1964
1965        return 0;
1966}
1967
1968static int rk3588_clk_ofdata_to_platdata(struct udevice *dev)
1969{
1970        struct rk3588_clk_priv *priv = dev_get_priv(dev);
1971
1972        priv->cru = dev_read_addr_ptr(dev);
1973
1974        return 0;
1975}
1976
1977static int rk3588_clk_bind(struct udevice *dev)
1978{
1979        int ret;
1980        struct udevice *sys_child;
1981        struct sysreset_reg *priv;
1982
1983        /* The reset driver does not have a device node, so bind it here */
1984        ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1985                                 &sys_child);
1986        if (ret) {
1987                debug("Warning: No sysreset driver: ret=%d\n", ret);
1988        } else {
1989                priv = malloc(sizeof(struct sysreset_reg));
1990                priv->glb_srst_fst_value = offsetof(struct rk3588_cru,
1991                                                    glb_srst_fst);
1992                priv->glb_srst_snd_value = offsetof(struct rk3588_cru,
1993                                                    glb_srsr_snd);
1994                dev_set_priv(sys_child, priv);
1995        }
1996
1997#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
1998        ret = offsetof(struct rk3588_cru, softrst_con[0]);
1999        ret = rk3588_reset_bind_lut(dev, ret, 49158);
2000        if (ret)
2001                debug("Warning: software reset driver bind failed\n");
2002#endif
2003
2004        return 0;
2005}
2006
2007static const struct udevice_id rk3588_clk_ids[] = {
2008        { .compatible = "rockchip,rk3588-cru" },
2009        { }
2010};
2011
2012U_BOOT_DRIVER(rockchip_rk3588_cru) = {
2013        .name           = "rockchip_rk3588_cru",
2014        .id             = UCLASS_CLK,
2015        .of_match       = rk3588_clk_ids,
2016        .priv_auto      = sizeof(struct rk3588_clk_priv),
2017        .of_to_plat     = rk3588_clk_ofdata_to_platdata,
2018        .ops            = &rk3588_clk_ops,
2019        .bind           = rk3588_clk_bind,
2020        .probe          = rk3588_clk_probe,
2021};
2022
2023#ifdef CONFIG_SPL_BUILD
2024#define SCRU_BASE                       0xfd7d0000
2025
2026static ulong rk3588_scru_clk_get_rate(struct clk *clk)
2027{
2028        u32 con, div, sel, parent;
2029
2030        switch (clk->id) {
2031        case SCMI_CCLK_SD:
2032                con = readl(SCRU_BASE + RK3588_CLKSEL_CON(3));
2033                sel = (con & SCMI_CCLK_SD_SEL_MASK) >> SCMI_CCLK_SD_SEL_SHIFT;
2034                div = (con & SCMI_CCLK_SD_DIV_MASK) >> SCMI_CCLK_SD_DIV_SHIFT;
2035                if (sel == SCMI_CCLK_SD_SEL_GPLL)
2036                        parent = GPLL_HZ;
2037                else if (sel == SCMI_CCLK_SD_SEL_SPLL)
2038                        parent = SPLL_HZ;
2039                else
2040                        parent = OSC_HZ;
2041                return DIV_TO_RATE(parent, div);
2042        case SCMI_HCLK_SD:
2043                con = readl(SCRU_BASE + RK3588_CLKSEL_CON(1));
2044                sel = (con & SCMI_HCLK_SD_SEL_MASK) >> SCMI_HCLK_SD_SEL_SHIFT;
2045                if (sel == SCMI_HCLK_SD_SEL_150M)
2046                        return 150 * MHz;
2047                else if (sel == SCMI_HCLK_SD_SEL_100M)
2048                        return 100 * MHz;
2049                else if (sel == SCMI_HCLK_SD_SEL_50M)
2050                        return 50 * MHz;
2051                else
2052                        return OSC_HZ;
2053        default:
2054                return -ENOENT;
2055        }
2056}
2057
2058static ulong rk3588_scru_clk_set_rate(struct clk *clk, ulong rate)
2059{
2060        u32 div, sel;
2061
2062        switch (clk->id) {
2063        case SCMI_CCLK_SD:
2064                if ((OSC_HZ % rate) == 0) {
2065                        sel = SCMI_CCLK_SD_SEL_24M;
2066                        div = DIV_ROUND_UP(OSC_HZ, rate);
2067                } else if ((SPLL_HZ % rate) == 0) {
2068                        sel = SCMI_CCLK_SD_SEL_SPLL;
2069                        div = DIV_ROUND_UP(SPLL_HZ, rate);
2070                } else {
2071                        sel = SCMI_CCLK_SD_SEL_GPLL;
2072                        div = DIV_ROUND_UP(GPLL_HZ, rate);
2073                }
2074                rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(3),
2075                             SCMI_CCLK_SD_SEL_MASK | SCMI_CCLK_SD_DIV_MASK,
2076                             sel << SCMI_CCLK_SD_SEL_SHIFT |
2077                             (div - 1) << SCMI_CCLK_SD_DIV_SHIFT);
2078                break;
2079        case SCMI_HCLK_SD:
2080                if (rate >= 150 * MHz)
2081                        sel = SCMI_HCLK_SD_SEL_150M;
2082                else if (rate >= 100 * MHz)
2083                        sel = SCMI_HCLK_SD_SEL_100M;
2084                else if (rate >= 50 * MHz)
2085                        sel = SCMI_HCLK_SD_SEL_50M;
2086                else
2087                        sel = SCMI_HCLK_SD_SEL_24M;
2088                rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(1),
2089                             SCMI_HCLK_SD_SEL_MASK,
2090                             sel << SCMI_HCLK_SD_SEL_SHIFT);
2091                break;
2092        default:
2093                return -ENOENT;
2094        }
2095
2096        return rk3588_scru_clk_get_rate(clk);
2097}
2098
2099static const struct clk_ops rk3588_scru_clk_ops = {
2100        .get_rate = rk3588_scru_clk_get_rate,
2101        .set_rate = rk3588_scru_clk_set_rate,
2102};
2103
2104U_BOOT_DRIVER(rockchip_rk3588_scru) = {
2105        .name = "rockchip_rk3588_scru",
2106        .id = UCLASS_CLK,
2107        .ops = &rk3588_scru_clk_ops,
2108};
2109
2110static int rk3588_scmi_spl_glue_bind(struct udevice *dev)
2111{
2112        ofnode node;
2113        u32 protocol_id;
2114        const char *name;
2115
2116        dev_for_each_subnode(node, dev) {
2117                if (!ofnode_is_enabled(node))
2118                        continue;
2119
2120                if (ofnode_read_u32(node, "reg", &protocol_id))
2121                        continue;
2122
2123                if (protocol_id != SCMI_PROTOCOL_ID_CLOCK)
2124                        continue;
2125
2126                name = ofnode_get_name(node);
2127                return device_bind_driver_to_node(dev, "rockchip_rk3588_scru",
2128                                                  name, node, NULL);
2129        }
2130
2131        return -ENOENT;
2132}
2133
2134static const struct udevice_id rk3588_scmi_spl_glue_ids[] = {
2135        { .compatible = "arm,scmi-smc" },
2136        { }
2137};
2138
2139U_BOOT_DRIVER(rk3588_scmi_spl_glue) = {
2140        .name           = "rk3588_scmi_spl_glue",
2141        .id             = UCLASS_NOP,
2142        .of_match       = rk3588_scmi_spl_glue_ids,
2143        .bind           = rk3588_scmi_spl_glue_bind,
2144};
2145#endif
2146