uboot/arch/arm/mach-imx/imx9/clock_root.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2022 NXP
   4 *
   5 * Peng Fan <peng.fan@nxp.com>
   6 */
   7
   8#include <common.h>
   9#include <command.h>
  10#include <asm/arch/clock.h>
  11#include <asm/arch/sys_proto.h>
  12#include <asm/arch/ccm_regs.h>
  13#include <asm/global_data.h>
  14#include <linux/iopoll.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18static struct ccm_reg *ccm_reg = (struct ccm_reg *)CCM_BASE_ADDR;
  19
  20static enum ccm_clk_src clk_root_mux[][4] = {
  21        { OSC_24M_CLK, SYS_PLL_PFD0, SYS_PLL_PFD1, SYS_PLL_PFD2 }, /* bus */
  22        { OSC_24M_CLK, SYS_PLL_PFD0_DIV2, SYS_PLL_PFD1_DIV2, SYS_PLL_PFD2_DIV2 }, /* non-IO */
  23        { OSC_24M_CLK, SYS_PLL_PFD0_DIV2, SYS_PLL_PFD1_DIV2, VIDEO_PLL_CLK }, /* IO*/
  24        { OSC_24M_CLK, SYS_PLL_PFD0, AUDIO_PLL_CLK, EXT_CLK  }, /* TPM */
  25        { OSC_24M_CLK, AUDIO_PLL_CLK, VIDEO_PLL_CLK, EXT_CLK }, /* Audio */
  26        { OSC_24M_CLK, AUDIO_PLL_CLK, VIDEO_PLL_CLK, SYS_PLL_PFD0 }, /* Video */
  27        { OSC_24M_CLK, SYS_PLL_PFD0, SYS_PLL_PFD1, AUDIO_PLL_CLK }, /* CKO1 */
  28        { OSC_24M_CLK, SYS_PLL_PFD0, SYS_PLL_PFD1, VIDEO_PLL_CLK }, /* CKO2 */
  29        { OSC_24M_CLK, AUDIO_PLL_CLK, VIDEO_PLL_CLK, SYS_PLL_PFD2 }, /* CAMSCAN */
  30};
  31
  32static struct clk_root_map clk_root_array[] = {
  33        { ARM_A55_PERIPH_CLK_ROOT,      0 },
  34        { ARM_A55_MTR_BUS_CLK_ROOT,     2 },
  35        { ARM_A55_CLK_ROOT,             0 },
  36        { M33_CLK_ROOT,                 2 },
  37        { SENTINEL_CLK_ROOT,            2 },
  38        { BUS_WAKEUP_CLK_ROOT,          2 },
  39        { BUS_AON_CLK_ROOT,             2 },
  40        { WAKEUP_AXI_CLK_ROOT,          0 },
  41        { SWO_TRACE_CLK_ROOT,           2 },
  42        { M33_SYSTICK_CLK_ROOT,         2 },
  43        { FLEXIO1_CLK_ROOT,             2 },
  44        { FLEXIO2_CLK_ROOT,             2 },
  45        { LPIT1_CLK_ROOT,               2 },
  46        { LPIT2_CLK_ROOT,               2 },
  47        { LPTMR1_CLK_ROOT,              2 },
  48        { LPTMR2_CLK_ROOT,              2 },
  49        { TPM1_CLK_ROOT,                3 },
  50        { TPM2_CLK_ROOT,                3 },
  51        { TPM3_CLK_ROOT,                3 },
  52        { TPM4_CLK_ROOT,                3 },
  53        { TPM5_CLK_ROOT,                3 },
  54        { TPM6_CLK_ROOT,                3 },
  55        { FLEXSPI1_CLK_ROOT,            0 },
  56        { CAN1_CLK_ROOT,                2 },
  57        { CAN2_CLK_ROOT,                2 },
  58        { LPUART1_CLK_ROOT,             2 },
  59        { LPUART2_CLK_ROOT,             2 },
  60        { LPUART3_CLK_ROOT,             2 },
  61        { LPUART4_CLK_ROOT,             2 },
  62        { LPUART5_CLK_ROOT,             2 },
  63        { LPUART6_CLK_ROOT,             2 },
  64        { LPUART7_CLK_ROOT,             2 },
  65        { LPUART8_CLK_ROOT,             2 },
  66        { LPI2C1_CLK_ROOT,              2 },
  67        { LPI2C2_CLK_ROOT,              2 },
  68        { LPI2C3_CLK_ROOT,              2 },
  69        { LPI2C4_CLK_ROOT,              2 },
  70        { LPI2C5_CLK_ROOT,              2 },
  71        { LPI2C6_CLK_ROOT,              2 },
  72        { LPI2C7_CLK_ROOT,              2 },
  73        { LPI2C8_CLK_ROOT,              2 },
  74        { LPSPI1_CLK_ROOT,              2 },
  75        { LPSPI2_CLK_ROOT,              2 },
  76        { LPSPI3_CLK_ROOT,              2 },
  77        { LPSPI4_CLK_ROOT,              2 },
  78        { LPSPI5_CLK_ROOT,              2 },
  79        { LPSPI6_CLK_ROOT,              2 },
  80        { LPSPI7_CLK_ROOT,              2 },
  81        { LPSPI8_CLK_ROOT,              2 },
  82        { I3C1_CLK_ROOT,                2 },
  83        { I3C2_CLK_ROOT,                2 },
  84        { USDHC1_CLK_ROOT,              0 },
  85        { USDHC2_CLK_ROOT,              0 },
  86        { USDHC3_CLK_ROOT,              0 },
  87        { SAI1_CLK_ROOT,                4 },
  88        { SAI2_CLK_ROOT,                4 },
  89        { SAI3_CLK_ROOT,                4 },
  90        { CCM_CKO1_CLK_ROOT,            6 },
  91        { CCM_CKO2_CLK_ROOT,            7 },
  92        { CCM_CKO3_CLK_ROOT,            6 },
  93        { CCM_CKO4_CLK_ROOT,            7 },
  94        { HSIO_CLK_ROOT,                2 },
  95        { HSIO_USB_TEST_60M_CLK_ROOT,   2 },
  96        { HSIO_ACSCAN_80M_CLK_ROOT,     2 },
  97        { HSIO_ACSCAN_480M_CLK_ROOT,    0 },
  98        { NIC_CLK_ROOT,                 0 },
  99        { NIC_APB_CLK_ROOT,             2 },
 100        { ML_APB_CLK_ROOT,              2 },
 101        { ML_CLK_ROOT,                  0 },
 102        { MEDIA_AXI_CLK_ROOT,           0 },
 103        { MEDIA_APB_CLK_ROOT,           2 },
 104        { MEDIA_LDB_CLK_ROOT,           5 },
 105        { MEDIA_DISP_PIX_CLK_ROOT,      5 },
 106        { CAM_PIX_CLK_ROOT,             5 },
 107        { MIPI_TEST_BYTE_CLK_ROOT,      5 },
 108        { MIPI_PHY_CFG_CLK_ROOT,        5 },
 109        { DRAM_ALT_CLK_ROOT,            0 },
 110        { DRAM_APB_CLK_ROOT,            1 },
 111        { ADC_CLK_ROOT,                 2 },
 112        { PDM_CLK_ROOT,                 4 },
 113        { TSTMR1_CLK_ROOT,              2 },
 114        { TSTMR2_CLK_ROOT,              2 },
 115        { MQS1_CLK_ROOT,                4 },
 116        { MQS2_CLK_ROOT,                4 },
 117        { AUDIO_XCVR_CLK_ROOT,          1 },
 118        { SPDIF_CLK_ROOT,               4 },
 119        { ENET_CLK_ROOT,                1 },
 120        { ENET_TIMER1_CLK_ROOT,         2 },
 121        { ENET_TIMER2_CLK_ROOT,         2 },
 122        { ENET_REF_CLK_ROOT,            1 },
 123        { ENET_REF_PHY_CLK_ROOT,        2 },
 124        { I3C1_SLOW_CLK_ROOT,           2 },
 125        { I3C2_SLOW_CLK_ROOT,           2 },
 126        { USB_PHY_BURUNIN_CLK_ROOT,     2 },
 127        { PAL_CAME_SCAN_CLK_ROOT,       8 },
 128};
 129
 130int ccm_clk_src_on(enum ccm_clk_src oscpll, bool enable)
 131{
 132        u32 authen;
 133
 134        if (oscpll >= OSCPLL_END)
 135                return -EINVAL;
 136
 137        authen = readl(&ccm_reg->clk_oscplls[oscpll].authen);
 138
 139        /* If using cpulpm, need disable it first */
 140        if (authen & CCM_AUTHEN_CPULPM_MODE)
 141                return -EPERM;
 142
 143        if (enable)
 144                writel(1, &ccm_reg->clk_oscplls[oscpll].direct);
 145        else
 146                writel(0, &ccm_reg->clk_oscplls[oscpll].direct);
 147
 148        return 0;
 149}
 150
 151/* auto mode, enable =  DIRECT[ON] | STATUS0[IN_USE] */
 152int ccm_clk_src_auto(enum ccm_clk_src oscpll, bool enable)
 153{
 154        u32 authen;
 155
 156        if (oscpll >= OSCPLL_END)
 157                return -EINVAL;
 158
 159        authen = readl(&ccm_reg->clk_oscplls[oscpll].authen);
 160
 161        /* AUTO CTRL and CPULPM are mutual exclusion, need disable CPULPM first */
 162        if (authen & CCM_AUTHEN_CPULPM_MODE)
 163                return -EPERM;
 164
 165        if (enable)
 166                writel(authen | CCM_AUTHEN_AUTO_CTRL, &ccm_reg->clk_oscplls[oscpll].authen);
 167        else
 168                writel((authen & ~CCM_AUTHEN_AUTO_CTRL), &ccm_reg->clk_oscplls[oscpll].authen);
 169
 170        return 0;
 171}
 172
 173int ccm_clk_src_lpm(enum ccm_clk_src oscpll, bool enable)
 174{
 175        u32 authen;
 176
 177        if (oscpll >= OSCPLL_END)
 178                return -EINVAL;
 179
 180        authen = readl(&ccm_reg->clk_oscplls[oscpll].authen);
 181
 182        /* AUTO CTRL and CPULPM are mutual exclusion, need disable AUTO CTRL first */
 183        if (authen & CCM_AUTHEN_AUTO_CTRL)
 184                return -EPERM;
 185
 186        if (enable)
 187                writel(authen | CCM_AUTHEN_CPULPM_MODE, &ccm_reg->clk_oscplls[oscpll].authen);
 188        else
 189                writel((authen & ~CCM_AUTHEN_CPULPM_MODE), &ccm_reg->clk_oscplls[oscpll].authen);
 190
 191        return 0;
 192}
 193
 194int ccm_clk_src_config_lpm(enum ccm_clk_src oscpll, u32 domain, u32 lpm_val)
 195{
 196        u32 lpm, authen;
 197
 198        if (oscpll >= OSCPLL_END || domain >= 16)
 199                return -EINVAL;
 200
 201        authen = readl(&ccm_reg->clk_oscplls[oscpll].authen);
 202        if (!(authen & CCM_AUTHEN_CPULPM_MODE))
 203                return -EPERM;
 204
 205        if (domain > 7) {
 206                lpm = readl(&ccm_reg->clk_oscplls[oscpll].lpm1);
 207                lpm &= ~(0x3 << ((domain - 8) * 4));
 208                lpm |= (lpm_val & 0x3) << ((domain - 8) * 4);
 209                writel(lpm, &ccm_reg->clk_oscplls[oscpll].lpm1);
 210        } else {
 211                lpm = readl(&ccm_reg->clk_oscplls[oscpll].lpm0);
 212                lpm &= ~(0x3 << (domain * 4));
 213                lpm |= (lpm_val & 0x3) << (domain * 4);
 214                writel(lpm, &ccm_reg->clk_oscplls[oscpll].lpm0);
 215        }
 216
 217        return 0;
 218}
 219
 220bool ccm_clk_src_is_clk_on(enum ccm_clk_src oscpll)
 221{
 222        return !!(readl(&ccm_reg->clk_oscplls[oscpll].status0) & 0x1);
 223}
 224
 225int ccm_clk_src_tz_access(enum ccm_clk_src oscpll, bool non_secure, bool user_mode, bool lock_tz)
 226{
 227        u32 authen;
 228
 229        if (oscpll >= OSCPLL_END)
 230                return -EINVAL;
 231
 232        authen = readl(&ccm_reg->clk_oscplls[oscpll].authen);
 233
 234        authen |= non_secure ? CCM_AUTHEN_TZ_NS : 0;
 235        authen |= user_mode ? CCM_AUTHEN_TZ_USER : 0;
 236        authen |= lock_tz ? CCM_AUTHEN_LOCK_TZ : 0;
 237
 238        writel(authen, &ccm_reg->clk_oscplls[oscpll].authen);
 239
 240        return 0;
 241}
 242
 243int ccm_clk_root_cfg(u32 clk_root_id, enum ccm_clk_src src, u32 div)
 244{
 245        int i;
 246        int ret;
 247        u32 mux, status;
 248
 249        if (clk_root_id >= CLK_ROOT_NUM || div > 256 || div == 0)
 250                return -EINVAL;
 251
 252        mux = clk_root_array[clk_root_id].mux_type;
 253
 254        for (i = 0; i < 4; i++) {
 255                if (src == clk_root_mux[mux][i])
 256                        break;
 257        }
 258
 259        if (i == 4) {
 260                printf("Invalid source [%u] for this clk root\n", src);
 261                return -EINVAL;
 262        }
 263
 264        writel((i << 8) | (div - 1), &ccm_reg->clk_roots[clk_root_id].control);
 265
 266        ret = readl_poll_timeout(&ccm_reg->clk_roots[clk_root_id].status0, status,
 267                                 !(status & CLK_ROOT_STATUS_CHANGING), 200000);
 268        if (ret)
 269                printf("%s: failed, status: 0x%x\n", __func__,
 270                       readl(&ccm_reg->clk_roots[clk_root_id].status0));
 271
 272        return ret;
 273};
 274
 275u32 ccm_clk_root_get_rate(u32 clk_root_id)
 276{
 277        u32 mux, status, div, rate;
 278        enum ccm_clk_src src;
 279
 280        if (clk_root_id >= CLK_ROOT_NUM)
 281                return 0;
 282
 283        status = readl(&ccm_reg->clk_roots[clk_root_id].control);
 284
 285        if (status & CLK_ROOT_STATUS_OFF)
 286                return 0; /* clock is off */
 287
 288        mux = (status & CLK_ROOT_MUX_MASK) >> CLK_ROOT_MUX_SHIFT;
 289        div = status & CLK_ROOT_DIV_MASK;
 290        src = clk_root_mux[clk_root_array[clk_root_id].mux_type][mux];
 291
 292        rate = get_clk_src_rate(src) * 1000;
 293
 294        return rate / (div + 1); /* return in hz */
 295}
 296
 297int ccm_clk_root_tz_access(u32 clk_root_id, bool non_secure, bool user_mode, bool lock_tz)
 298{
 299        u32 authen;
 300
 301        if (clk_root_id >= CLK_ROOT_NUM)
 302                return -EINVAL;
 303
 304        authen = readl(&ccm_reg->clk_roots[clk_root_id].authen);
 305
 306        authen |= non_secure ? CCM_AUTHEN_TZ_NS : 0;
 307        authen |= user_mode ? CCM_AUTHEN_TZ_USER : 0;
 308        authen |= lock_tz ? CCM_AUTHEN_LOCK_TZ : 0;
 309
 310        writel(authen, &ccm_reg->clk_roots[clk_root_id].authen);
 311
 312        return 0;
 313}
 314
 315int ccm_lpcg_on(u32 lpcg, bool enable)
 316{
 317        u32 authen;
 318
 319        if (lpcg >= CCGR_NUM)
 320                return -EINVAL;
 321
 322        authen = readl(&ccm_reg->clk_lpcgs[lpcg].authen);
 323
 324        /* If using cpulpm, need disable it first */
 325        if (authen & CCM_AUTHEN_CPULPM_MODE)
 326                return -EPERM;
 327
 328        if (enable)
 329                writel(1, &ccm_reg->clk_lpcgs[lpcg].direct);
 330        else
 331                writel(0, &ccm_reg->clk_lpcgs[lpcg].direct);
 332
 333        return 0;
 334}
 335
 336int ccm_lpcg_lpm(u32 lpcg, bool enable)
 337{
 338        u32 authen;
 339
 340        if (lpcg >= CCGR_NUM)
 341                return -EINVAL;
 342
 343        authen = readl(&ccm_reg->clk_lpcgs[lpcg].authen);
 344
 345        if (enable)
 346                writel(authen | CCM_AUTHEN_CPULPM_MODE, &ccm_reg->clk_lpcgs[lpcg].authen);
 347        else
 348                writel((authen & ~CCM_AUTHEN_CPULPM_MODE), &ccm_reg->clk_lpcgs[lpcg].authen);
 349
 350        return 0;
 351}
 352
 353int ccm_lpcg_config_lpm(u32 lpcg, u32 domain, u32 lpm_val)
 354{
 355        u32 lpm, authen;
 356
 357        if (lpcg >= CCGR_NUM || domain >= 16)
 358                return -EINVAL;
 359
 360        authen = readl(&ccm_reg->clk_lpcgs[lpcg].authen);
 361        if (!(authen & CCM_AUTHEN_CPULPM_MODE))
 362                return -EPERM;
 363
 364        if (domain > 7) {
 365                lpm = readl(&ccm_reg->clk_lpcgs[lpcg].lpm1);
 366                lpm &= ~(0x3 << ((domain - 8) * 4));
 367                lpm |= (lpm_val & 0x3) << ((domain - 8) * 4);
 368                writel(lpm, &ccm_reg->clk_lpcgs[lpcg].lpm1);
 369        } else {
 370                lpm = readl(&ccm_reg->clk_lpcgs[lpcg].lpm0);
 371                lpm &= ~(0x3 << (domain * 4));
 372                lpm |= (lpm_val & 0x3) << (domain * 4);
 373                writel(lpm, &ccm_reg->clk_lpcgs[lpcg].lpm0);
 374        }
 375
 376        return 0;
 377}
 378
 379bool ccm_lpcg_is_clk_on(u32 lpcg)
 380{
 381        return !!(readl(&ccm_reg->clk_lpcgs[lpcg].status0) & 0x1);
 382}
 383
 384int ccm_lpcg_tz_access(u32 lpcg, bool non_secure, bool user_mode, bool lock_tz)
 385{
 386        u32 authen;
 387
 388        if (lpcg >= CCGR_NUM)
 389                return -EINVAL;
 390
 391        authen = readl(&ccm_reg->clk_lpcgs[lpcg].authen);
 392
 393        authen |= non_secure ? CCM_AUTHEN_TZ_NS : 0;
 394        authen |= user_mode ? CCM_AUTHEN_TZ_USER : 0;
 395        authen |= lock_tz ? CCM_AUTHEN_LOCK_TZ : 0;
 396
 397        writel(authen, &ccm_reg->clk_lpcgs[lpcg].authen);
 398
 399        return 0;
 400}
 401
 402int ccm_shared_gpr_set(u32 gpr, u32 val)
 403{
 404        if (gpr >= SHARED_GPR_NUM)
 405                return -EINVAL;
 406
 407        writel(val, &ccm_reg->clk_shared_gpr[gpr].gpr);
 408
 409        return 0;
 410}
 411
 412int ccm_shared_gpr_get(u32 gpr, u32 *val)
 413{
 414        if (gpr >= SHARED_GPR_NUM || !val)
 415                return -EINVAL;
 416
 417        *val = readl(&ccm_reg->clk_shared_gpr[gpr].gpr);
 418
 419        return 0;
 420}
 421
 422int ccm_shared_gpr_tz_access(u32 gpr, bool non_secure, bool user_mode, bool lock_tz)
 423{
 424        u32 authen;
 425
 426        if (gpr >= SHARED_GPR_NUM)
 427                return -EINVAL;
 428
 429        authen = readl(&ccm_reg->clk_shared_gpr[gpr].authen);
 430
 431        authen |= non_secure ? CCM_AUTHEN_TZ_NS : 0;
 432        authen |= user_mode ? CCM_AUTHEN_TZ_USER : 0;
 433        authen |= lock_tz ? CCM_AUTHEN_LOCK_TZ : 0;
 434
 435        writel(authen, &ccm_reg->clk_shared_gpr[gpr].authen);
 436
 437        return 0;
 438}
 439