diff options
author | Tom Rini <trini@konsulko.com> | 2022-02-07 12:13:53 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-02-07 12:13:53 -0500 |
commit | 8b139f4e1c08c4ffb1a8e739db128ed02cbc637f (patch) | |
tree | 0bff6bd0fadc7230538d712b1b1f112e424dbea0 /arch/arm/mach-imx/imx8ulp/clock.c | |
parent | b5c5b9a0bee56030f9f05ece52334b5207b72673 (diff) | |
parent | 530780a69cb5d32a7794dcc322afaa25cdbdab96 (diff) |
Merge tag 'u-boot-imx-20220207' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
u-boot-imx-20211022
-------------------
CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/10887
- imx8 : Toradex Verdin MX8M Plus
Kontron pitx-imx8m
- imx8ulp: several fixes and improvements
- imx6ull fixes
- switching to binman
Diffstat (limited to 'arch/arm/mach-imx/imx8ulp/clock.c')
-rw-r--r-- | arch/arm/mach-imx/imx8ulp/clock.c | 156 |
1 files changed, 144 insertions, 12 deletions
diff --git a/arch/arm/mach-imx/imx8ulp/clock.c b/arch/arm/mach-imx/imx8ulp/clock.c index ebbaad4106..91580b2c29 100644 --- a/arch/arm/mach-imx/imx8ulp/clock.c +++ b/arch/arm/mach-imx/imx8ulp/clock.c @@ -27,7 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; #define PLL_USB_LOCK_MASK (0x01 << 31) #define PCC5_LPDDR4_ADDR 0x2da70108 -static void lpuart_set_clk(u32 index, enum cgc1_clk clk) +static void lpuart_set_clk(u32 index, enum cgc_clk clk) { const u32 lpuart_pcc_slots[] = { LPUART4_PCC3_SLOT, @@ -97,6 +97,9 @@ void ddrphy_pll_lock(void) void init_clk_ddr(void) { + /* disable the ddr pcc */ + writel(0xc0000000, PCC5_LPDDR4_ADDR); + /* enable pll4 and ddrclk*/ cgc2_pll4_init(); cgc2_ddrclk_config(1, 1); @@ -104,6 +107,9 @@ void init_clk_ddr(void) /* enable ddr pcc */ writel(0xd0000000, PCC5_LPDDR4_ADDR); + /* Wait until ddrclk reg lock bit is cleared, so that the div update is finished */ + cgc2_ddrclk_wait_unlock(); + /* for debug */ /* setclkout_ddr(); */ } @@ -141,6 +147,9 @@ int set_ddr_clk(u32 phy_freq_mhz) return -EINVAL; } + /* Wait until ddrclk reg lock bit is cleared, so that the div update is finished */ + cgc2_ddrclk_wait_unlock(); + return 0; } @@ -186,6 +195,9 @@ int enable_i2c_clk(unsigned char enable, u32 i2c_num) LPI2C7_PCC4_SLOT << 8 | 4, }; + if (i2c_num == 0) + return 0; + if (i2c_num < 4 || i2c_num > 7) return -EINVAL; @@ -214,6 +226,9 @@ u32 imx_get_i2cclk(u32 i2c_num) LPI2C7_PCC4_SLOT << 8 | 4, }; + if (i2c_num == 0) + return 24000000; + if (i2c_num < 4 || i2c_num > 7) return 0; @@ -317,6 +332,99 @@ int enable_usb_pll(ulong usb_phy_base) return 0; } +void enable_mipi_dsi_clk(unsigned char enable) +{ + if (enable) { + pcc_clock_enable(5, DSI_PCC5_SLOT, false); + pcc_reset_peripheral(5, DSI_PCC5_SLOT, true); + pcc_clock_sel(5, DSI_PCC5_SLOT, PLL4_PFD3_DIV2); + pcc_clock_div_config(5, DSI_PCC5_SLOT, 0, 6); + pcc_clock_enable(5, DSI_PCC5_SLOT, true); + pcc_reset_peripheral(5, DSI_PCC5_SLOT, false); + } else { + pcc_clock_enable(5, DSI_PCC5_SLOT, false); + pcc_reset_peripheral(5, DSI_PCC5_SLOT, true); + } +} + +void enable_adc1_clk(bool enable) +{ + if (enable) { + pcc_clock_enable(1, ADC1_PCC1_SLOT, false); + pcc_clock_sel(1, ADC1_PCC1_SLOT, CM33_BUSCLK); + pcc_clock_enable(1, ADC1_PCC1_SLOT, true); + pcc_reset_peripheral(1, ADC1_PCC1_SLOT, false); + } else { + pcc_clock_enable(1, ADC1_PCC1_SLOT, false); + } +} + +void reset_lcdclk(void) +{ + /* Disable clock and reset dcnano*/ + pcc_clock_enable(5, DCNANO_PCC5_SLOT, false); + pcc_reset_peripheral(5, DCNANO_PCC5_SLOT, true); +} + +void mxs_set_lcdclk(u32 base_addr, u32 freq_in_khz) +{ + u8 pcd, best_pcd = 0; + u32 frac, rate, parent_rate, pfd, div; + u32 best_pfd = 0, best_frac = 0, best = 0, best_div = 0; + u32 pll4_rate; + + pcc_clock_enable(5, DCNANO_PCC5_SLOT, false); + + pll4_rate = cgc_clk_get_rate(PLL4); + pll4_rate = pll4_rate / 1000; /* Change to khz*/ + + debug("PLL4 rate %ukhz\n", pll4_rate); + + for (pfd = 12; pfd <= 35; pfd++) { + parent_rate = pll4_rate; + parent_rate = parent_rate * 18 / pfd; + + for (div = 1; div <= 64; div++) { + parent_rate = parent_rate / div; + + for (pcd = 0; pcd < 8; pcd++) { + for (frac = 0; frac < 2; frac++) { + if (pcd == 0 && frac == 1) + continue; + + rate = parent_rate * (frac + 1) / (pcd + 1); + if (rate > freq_in_khz) + continue; + + if (best == 0 || rate > best) { + best = rate; + best_pfd = pfd; + best_frac = frac; + best_pcd = pcd; + best_div = div; + } + } + } + } + } + + if (best == 0) { + printf("Can't find parent clock for LCDIF, target freq: %u\n", freq_in_khz); + return; + } + + debug("LCD target rate %ukhz, best rate %ukhz, frac %u, pcd %u, best_pfd %u, best_div %u\n", + freq_in_khz, best, best_frac, best_pcd, best_pfd, best_div); + + cgc2_pll4_pfd_config(PLL4_PFD0, best_pfd); + cgc2_pll4_pfddiv_config(PLL4_PFD0_DIV1, best_div - 1); + + pcc_clock_sel(5, DCNANO_PCC5_SLOT, PLL4_PFD0_DIV1); + pcc_clock_div_config(5, DCNANO_PCC5_SLOT, best_frac, best_pcd + 1); + pcc_clock_enable(5, DCNANO_PCC5_SLOT, true); + pcc_reset_peripheral(5, DCNANO_PCC5_SLOT, false); +} + u32 mxc_get_clock(enum mxc_clock clk) { switch (clk) { @@ -327,7 +435,7 @@ u32 mxc_get_clock(enum mxc_clock clk) case MXC_ESDHC3_CLK: return pcc_clock_get_rate(4, SDHC2_PCC4_SLOT); case MXC_ARM_CLK: - return cgc1_clk_get_rate(PLL2); + return cgc_clk_get_rate(PLL2); default: return 0; } @@ -376,16 +484,40 @@ int do_mx8ulp_showclocks(struct cmd_tbl *cmdtp, int flag, int argc, char * const printf("SDHC1 %8d MHz\n", pcc_clock_get_rate(4, SDHC1_PCC4_SLOT) / 1000000); printf("SDHC2 %8d MHz\n", pcc_clock_get_rate(4, SDHC2_PCC4_SLOT) / 1000000); - printf("SOSC %8d MHz\n", cgc1_clk_get_rate(SOSC) / 1000000); - printf("FRO %8d MHz\n", cgc1_clk_get_rate(FRO) / 1000000); - printf("PLL2 %8d MHz\n", cgc1_clk_get_rate(PLL2) / 1000000); - printf("PLL3 %8d MHz\n", cgc1_clk_get_rate(PLL3) / 1000000); - printf("PLL3_VCODIV %8d MHz\n", cgc1_clk_get_rate(PLL3_VCODIV) / 1000000); - printf("PLL3_PFD0 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD0) / 1000000); - printf("PLL3_PFD1 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD1) / 1000000); - printf("PLL3_PFD2 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD2) / 1000000); - printf("PLL3_PFD3 %8d MHz\n", cgc1_clk_get_rate(PLL3_PFD3) / 1000000); - + printf("SOSC %8d MHz\n", cgc_clk_get_rate(SOSC) / 1000000); + printf("FRO %8d MHz\n", cgc_clk_get_rate(FRO) / 1000000); + printf("PLL2 %8d MHz\n", cgc_clk_get_rate(PLL2) / 1000000); + printf("PLL3 %8d MHz\n", cgc_clk_get_rate(PLL3) / 1000000); + printf("PLL3_VCODIV %8d MHz\n", cgc_clk_get_rate(PLL3_VCODIV) / 1000000); + printf("PLL3_PFD0 %8d MHz\n", cgc_clk_get_rate(PLL3_PFD0) / 1000000); + printf("PLL3_PFD1 %8d MHz\n", cgc_clk_get_rate(PLL3_PFD1) / 1000000); + printf("PLL3_PFD2 %8d MHz\n", cgc_clk_get_rate(PLL3_PFD2) / 1000000); + printf("PLL3_PFD3 %8d MHz\n", cgc_clk_get_rate(PLL3_PFD3) / 1000000); + + printf("PLL4_PFD0 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD0) / 1000000); + printf("PLL4_PFD1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD1) / 1000000); + printf("PLL4_PFD2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD2) / 1000000); + printf("PLL4_PFD3 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD3) / 1000000); + + printf("PLL4_PFD0_DIV1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD0_DIV1) / 1000000); + printf("PLL4_PFD0_DIV2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD0_DIV2) / 1000000); + printf("PLL4_PFD1_DIV1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD1_DIV1) / 1000000); + printf("PLL4_PFD1_DIV2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD1_DIV2) / 1000000); + + printf("PLL4_PFD2_DIV1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD2_DIV1) / 1000000); + printf("PLL4_PFD2_DIV2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD2_DIV2) / 1000000); + printf("PLL4_PFD3_DIV1 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD3_DIV1) / 1000000); + printf("PLL4_PFD3_DIV2 %8d MHz\n", cgc_clk_get_rate(PLL4_PFD3_DIV2) / 1000000); + + printf("LPAV_AXICLK %8d MHz\n", cgc_clk_get_rate(LPAV_AXICLK) / 1000000); + printf("LPAV_AHBCLK %8d MHz\n", cgc_clk_get_rate(LPAV_AHBCLK) / 1000000); + printf("LPAV_BUSCLK %8d MHz\n", cgc_clk_get_rate(LPAV_BUSCLK) / 1000000); + printf("NIC_APCLK %8d MHz\n", cgc_clk_get_rate(NIC_APCLK) / 1000000); + + printf("NIC_PERCLK %8d MHz\n", cgc_clk_get_rate(NIC_PERCLK) / 1000000); + printf("XBAR_APCLK %8d MHz\n", cgc_clk_get_rate(XBAR_APCLK) / 1000000); + printf("XBAR_BUSCLK %8d MHz\n", cgc_clk_get_rate(XBAR_BUSCLK) / 1000000); + printf("AD_SLOWCLK %8d MHz\n", cgc_clk_get_rate(AD_SLOWCLK) / 1000000); return 0; } |