uboot/arch/arm/mach-imx/imx8ulp/clock.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2020 NXP
   4 */
   5
   6#include <common.h>
   7#include <command.h>
   8#include <div64.h>
   9#include <asm/arch/imx-regs.h>
  10#include <asm/io.h>
  11#include <errno.h>
  12#include <asm/arch/clock.h>
  13#include <asm/arch/pcc.h>
  14#include <asm/arch/cgc.h>
  15#include <asm/arch/sys_proto.h>
  16#include <asm/global_data.h>
  17#include <linux/delay.h>
  18
  19DECLARE_GLOBAL_DATA_PTR;
  20
  21#define PLL_USB_EN_USB_CLKS_MASK        (0x01 << 6)
  22#define PLL_USB_PWR_MASK                (0x01 << 12)
  23#define PLL_USB_ENABLE_MASK             (0x01 << 13)
  24#define PLL_USB_BYPASS_MASK             (0x01 << 16)
  25#define PLL_USB_REG_ENABLE_MASK         (0x01 << 21)
  26#define PLL_USB_DIV_SEL_MASK            (0x07 << 22)
  27#define PLL_USB_LOCK_MASK               (0x01 << 31)
  28#define PCC5_LPDDR4_ADDR 0x2da70108
  29
  30static void lpuart_set_clk(u32 index, enum cgc1_clk clk)
  31{
  32        const u32 lpuart_pcc_slots[] = {
  33                LPUART4_PCC3_SLOT,
  34                LPUART5_PCC3_SLOT,
  35                LPUART6_PCC4_SLOT,
  36                LPUART7_PCC4_SLOT,
  37        };
  38
  39        const u32 lpuart_pcc[] = {
  40                3, 3, 4, 4,
  41        };
  42
  43        if (index > 3)
  44                return;
  45
  46        pcc_clock_enable(lpuart_pcc[index], lpuart_pcc_slots[index], false);
  47        pcc_clock_sel(lpuart_pcc[index], lpuart_pcc_slots[index], clk);
  48        pcc_clock_enable(lpuart_pcc[index], lpuart_pcc_slots[index], true);
  49
  50        pcc_reset_peripheral(lpuart_pcc[index], lpuart_pcc_slots[index], false);
  51}
  52
  53static void init_clk_lpuart(void)
  54{
  55        u32 index = 0, i;
  56
  57        const u32 lpuart_array[] = {
  58                LPUART4_RBASE,
  59                LPUART5_RBASE,
  60                LPUART6_RBASE,
  61                LPUART7_RBASE,
  62        };
  63
  64        for (i = 0; i < 4; i++) {
  65                if (lpuart_array[i] == LPUART_BASE) {
  66                        index = i;
  67                        break;
  68                }
  69        }
  70
  71        lpuart_set_clk(index, SOSC_DIV2);
  72}
  73
  74void init_clk_fspi(int index)
  75{
  76        pcc_clock_enable(4, FLEXSPI2_PCC4_SLOT, false);
  77        pcc_clock_sel(4, FLEXSPI2_PCC4_SLOT, PLL3_PFD2_DIV1);
  78        pcc_clock_div_config(4, FLEXSPI2_PCC4_SLOT, false, 8);
  79        pcc_clock_enable(4, FLEXSPI2_PCC4_SLOT, true);
  80        pcc_reset_peripheral(4, FLEXSPI2_PCC4_SLOT, false);
  81}
  82
  83void setclkout_ddr(void)
  84{
  85        writel(0x12800000, 0x2DA60020);
  86        writel(0xa00, 0x298C0000); /* PTD0 */
  87}
  88
  89void ddrphy_pll_lock(void)
  90{
  91        writel(0x00011542, 0x2E065964);
  92        writel(0x00011542, 0x2E06586C);
  93
  94        writel(0x00000B01, 0x2E062000);
  95        writel(0x00000B01, 0x2E060000);
  96}
  97
  98void init_clk_ddr(void)
  99{
 100        /* enable pll4 and ddrclk*/
 101        cgc2_pll4_init();
 102        cgc2_ddrclk_config(1, 1);
 103
 104        /* enable ddr pcc */
 105        writel(0xd0000000, PCC5_LPDDR4_ADDR);
 106
 107        /* for debug */
 108        /* setclkout_ddr(); */
 109}
 110
 111int set_ddr_clk(u32 phy_freq_mhz)
 112{
 113        debug("%s %u\n", __func__, phy_freq_mhz);
 114
 115        if (phy_freq_mhz == 48) {
 116                writel(0x90000000, PCC5_LPDDR4_ADDR); /* disable ddr pcc */
 117                cgc2_ddrclk_config(2, 0); /* 24Mhz DDR clock */
 118                writel(0xd0000000, PCC5_LPDDR4_ADDR); /* enable ddr pcc */
 119        } else if (phy_freq_mhz == 384) {
 120                writel(0x90000000, PCC5_LPDDR4_ADDR); /* disable ddr pcc */
 121                cgc2_ddrclk_config(0, 0); /* 192Mhz DDR clock */
 122                writel(0xd0000000, PCC5_LPDDR4_ADDR); /* enable ddr pcc */
 123        } else if (phy_freq_mhz == 528) {
 124                writel(0x90000000, PCC5_LPDDR4_ADDR); /* disable ddr pcc */
 125                cgc2_ddrclk_config(4, 1); /* 264Mhz DDR clock */
 126                writel(0xd0000000, PCC5_LPDDR4_ADDR); /* enable ddr pcc */
 127        } else if (phy_freq_mhz == 264) {
 128                writel(0x90000000, PCC5_LPDDR4_ADDR); /* disable ddr pcc */
 129                cgc2_ddrclk_config(4, 3); /* 132Mhz DDR clock */
 130                writel(0xd0000000, PCC5_LPDDR4_ADDR); /* enable ddr pcc */
 131        } else if (phy_freq_mhz == 192) {
 132                writel(0x90000000, PCC5_LPDDR4_ADDR); /* disable ddr pcc */
 133                cgc2_ddrclk_config(0, 1); /* 96Mhz DDR clock */
 134                writel(0xd0000000, PCC5_LPDDR4_ADDR); /* enable ddr pcc */
 135        } else if (phy_freq_mhz == 96) {
 136                writel(0x90000000, PCC5_LPDDR4_ADDR); /* disable ddr pcc */
 137                cgc2_ddrclk_config(0, 3); /* 48Mhz DDR clock */
 138                writel(0xd0000000, PCC5_LPDDR4_ADDR); /* enable ddr pcc */
 139        } else {
 140                printf("ddr phy clk %uMhz is not supported\n", phy_freq_mhz);
 141                return -EINVAL;
 142        }
 143
 144        return 0;
 145}
 146
 147void clock_init(void)
 148{
 149        cgc1_soscdiv_init();
 150        cgc1_init_core_clk();
 151
 152        init_clk_lpuart();
 153
 154        pcc_clock_enable(4, SDHC0_PCC4_SLOT, false);
 155        pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD1_DIV2);
 156        pcc_clock_enable(4, SDHC0_PCC4_SLOT, true);
 157        pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false);
 158
 159        pcc_clock_enable(4, SDHC1_PCC4_SLOT, false);
 160        pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD2_DIV1);
 161        pcc_clock_enable(4, SDHC1_PCC4_SLOT, true);
 162        pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false);
 163
 164        pcc_clock_enable(4, SDHC2_PCC4_SLOT, false);
 165        pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD2_DIV1);
 166        pcc_clock_enable(4, SDHC2_PCC4_SLOT, true);
 167        pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false);
 168
 169        /* Enable upower mu1 clk */
 170        pcc_clock_enable(3, UPOWER_PCC3_SLOT, true);
 171
 172        /*
 173         * Enable clock division
 174         * TODO: may not needed after ROM ready.
 175         */
 176}
 177
 178#if IS_ENABLED(CONFIG_SYS_I2C_IMX_LPI2C)
 179int enable_i2c_clk(unsigned char enable, u32 i2c_num)
 180{
 181        /* Set parent to FIRC DIV2 clock */
 182        const u32 lpi2c_pcc_clks[] = {
 183                LPI2C4_PCC3_SLOT << 8 | 3,
 184                LPI2C5_PCC3_SLOT << 8 | 3,
 185                LPI2C6_PCC4_SLOT << 8 | 4,
 186                LPI2C7_PCC4_SLOT << 8 | 4,
 187        };
 188
 189        if (i2c_num < 4 || i2c_num > 7)
 190                return -EINVAL;
 191
 192        if (enable) {
 193                pcc_clock_enable(lpi2c_pcc_clks[i2c_num - 4] & 0xff,
 194                                 lpi2c_pcc_clks[i2c_num - 4] >> 8, false);
 195                pcc_clock_sel(lpi2c_pcc_clks[i2c_num - 4] & 0xff,
 196                              lpi2c_pcc_clks[i2c_num - 4] >> 8, SOSC_DIV2);
 197                pcc_clock_enable(lpi2c_pcc_clks[i2c_num - 4] & 0xff,
 198                                 lpi2c_pcc_clks[i2c_num - 4] >> 8, true);
 199                pcc_reset_peripheral(lpi2c_pcc_clks[i2c_num - 4] & 0xff,
 200                                     lpi2c_pcc_clks[i2c_num - 4] >> 8, false);
 201        } else {
 202                pcc_clock_enable(lpi2c_pcc_clks[i2c_num - 4] & 0xff,
 203                                 lpi2c_pcc_clks[i2c_num - 4] >> 8, false);
 204        }
 205        return 0;
 206}
 207
 208u32 imx_get_i2cclk(u32 i2c_num)
 209{
 210        const u32 lpi2c_pcc_clks[] = {
 211                LPI2C4_PCC3_SLOT << 8 | 3,
 212                LPI2C5_PCC3_SLOT << 8 | 3,
 213                LPI2C6_PCC4_SLOT << 8 | 4,
 214                LPI2C7_PCC4_SLOT << 8 | 4,
 215        };
 216
 217        if (i2c_num < 4 || i2c_num > 7)
 218                return 0;
 219
 220        return pcc_clock_get_rate(lpi2c_pcc_clks[i2c_num - 4] & 0xff,
 221                                  lpi2c_pcc_clks[i2c_num - 4] >> 8);
 222}
 223#endif
 224
 225void enable_usboh3_clk(unsigned char enable)
 226{
 227        if (enable) {
 228                pcc_clock_enable(4, USB0_PCC4_SLOT, true);
 229                pcc_clock_enable(4, USBPHY_PCC4_SLOT, true);
 230                pcc_reset_peripheral(4, USB0_PCC4_SLOT, false);
 231                pcc_reset_peripheral(4, USBPHY_PCC4_SLOT, false);
 232
 233#ifdef CONFIG_USB_MAX_CONTROLLER_COUNT
 234                if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1) {
 235                        pcc_clock_enable(4, USB1_PCC4_SLOT, true);
 236                        pcc_clock_enable(4, USB1PHY_PCC4_SLOT, true);
 237                        pcc_reset_peripheral(4, USB1_PCC4_SLOT, false);
 238                        pcc_reset_peripheral(4, USB1PHY_PCC4_SLOT, false);
 239                }
 240#endif
 241
 242                pcc_clock_enable(4, USB_XBAR_PCC4_SLOT, true);
 243        } else {
 244                pcc_clock_enable(4, USB0_PCC4_SLOT, false);
 245                pcc_clock_enable(4, USB1_PCC4_SLOT, false);
 246                pcc_clock_enable(4, USBPHY_PCC4_SLOT, false);
 247                pcc_clock_enable(4, USB1PHY_PCC4_SLOT, false);
 248                pcc_clock_enable(4, USB_XBAR_PCC4_SLOT, false);
 249        }
 250}
 251
 252int enable_usb_pll(ulong usb_phy_base)
 253{
 254        u32 sosc_rate;
 255        s32 timeout = 1000000;
 256
 257        struct usbphy_regs *usbphy =
 258                (struct usbphy_regs *)usb_phy_base;
 259
 260        sosc_rate = cgc1_sosc_div(SOSC);
 261        if (!sosc_rate)
 262                return -EPERM;
 263
 264        if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) {
 265                writel(0x1c00000, &usbphy->usb1_pll_480_ctrl_clr);
 266
 267                switch (sosc_rate) {
 268                case 24000000:
 269                        writel(0xc00000, &usbphy->usb1_pll_480_ctrl_set);
 270                        break;
 271
 272                case 30000000:
 273                        writel(0x800000, &usbphy->usb1_pll_480_ctrl_set);
 274                        break;
 275
 276                case 19200000:
 277                        writel(0x1400000, &usbphy->usb1_pll_480_ctrl_set);
 278                        break;
 279
 280                default:
 281                        writel(0xc00000, &usbphy->usb1_pll_480_ctrl_set);
 282                        break;
 283                }
 284
 285                /* Enable the regulator first */
 286                writel(PLL_USB_REG_ENABLE_MASK,
 287                       &usbphy->usb1_pll_480_ctrl_set);
 288
 289                /* Wait at least 15us */
 290                udelay(15);
 291
 292                /* Enable the power */
 293                writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set);
 294
 295                /* Wait lock */
 296                while (timeout--) {
 297                        if (readl(&usbphy->usb1_pll_480_ctrl) &
 298                            PLL_USB_LOCK_MASK)
 299                                break;
 300                }
 301
 302                if (timeout <= 0) {
 303                        /* If timeout, we power down the pll */
 304                        writel(PLL_USB_PWR_MASK,
 305                               &usbphy->usb1_pll_480_ctrl_clr);
 306                        return -ETIME;
 307                }
 308        }
 309
 310        /* Clear the bypass */
 311        writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr);
 312
 313        /* Enable the PLL clock out to USB */
 314        writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK),
 315               &usbphy->usb1_pll_480_ctrl_set);
 316
 317        return 0;
 318}
 319
 320u32 mxc_get_clock(enum mxc_clock clk)
 321{
 322        switch (clk) {
 323        case MXC_ESDHC_CLK:
 324                return pcc_clock_get_rate(4, SDHC0_PCC4_SLOT);
 325        case MXC_ESDHC2_CLK:
 326                return pcc_clock_get_rate(4, SDHC1_PCC4_SLOT);
 327        case MXC_ESDHC3_CLK:
 328                return pcc_clock_get_rate(4, SDHC2_PCC4_SLOT);
 329        case MXC_ARM_CLK:
 330                return cgc1_clk_get_rate(PLL2);
 331        default:
 332                return 0;
 333        }
 334}
 335
 336u32 get_lpuart_clk(void)
 337{
 338        int index = 0;
 339
 340        const u32 lpuart_array[] = {
 341                LPUART4_RBASE,
 342                LPUART5_RBASE,
 343                LPUART6_RBASE,
 344                LPUART7_RBASE,
 345        };
 346
 347        const u32 lpuart_pcc_slots[] = {
 348                LPUART4_PCC3_SLOT,
 349                LPUART5_PCC3_SLOT,
 350                LPUART6_PCC4_SLOT,
 351                LPUART7_PCC4_SLOT,
 352        };
 353
 354        const u32 lpuart_pcc[] = {
 355                3, 3, 4, 4,
 356        };
 357
 358        for (index = 0; index < 4; index++) {
 359                if (lpuart_array[index] == LPUART_BASE)
 360                        break;
 361        }
 362
 363        if (index > 3)
 364                return 0;
 365
 366        return pcc_clock_get_rate(lpuart_pcc[index], lpuart_pcc_slots[index]);
 367}
 368
 369#ifndef CONFIG_SPL_BUILD
 370/*
 371 * Dump some core clockes.
 372 */
 373int do_mx8ulp_showclocks(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
 374{
 375        printf("SDHC0 %8d MHz\n", pcc_clock_get_rate(4, SDHC0_PCC4_SLOT) / 1000000);
 376        printf("SDHC1 %8d MHz\n", pcc_clock_get_rate(4, SDHC1_PCC4_SLOT) / 1000000);
 377        printf("SDHC2 %8d MHz\n", pcc_clock_get_rate(4, SDHC2_PCC4_SLOT) / 1000000);
 378
 379        printf("SOSC %8d MHz\n", cgc1_clk_get_rate(SOSC) / 1000000);
 380        printf("FRO %8d MHz\n", cgc1_clk_get_rate(FRO) / 1000000);
 381        printf("PLL2 %8d MHz\n", cgc1_clk_get_rate(PLL2) / 1000000);
 382        printf("PLL3 %8d MHz\n", cgc1_clk_get_rate(PLL3) / 1000000);
 383        printf("PLL3_VCODIV %8d MHz\n", cgc1_clk_get_rate(PLL3_VCODIV) / 1000000);
 384        printf("PLL3_PFD0 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD0) / 1000000);
 385        printf("PLL3_PFD1 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD1) / 1000000);
 386        printf("PLL3_PFD2 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD2) / 1000000);
 387        printf("PLL3_PFD3 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD3) / 1000000);
 388
 389        return 0;
 390}
 391
 392U_BOOT_CMD(
 393        clocks, CONFIG_SYS_MAXARGS, 1, do_mx8ulp_showclocks,
 394        "display clocks",
 395        ""
 396);
 397#endif
 398