imx: imx8ulp: add ND/LD clock

Add a new ddr script, defconfig for ND
Configure the clock for ND mode
changing A35 to 960MHz for OD mode
Update NIC CLK for the various modes
Introduce clock_init_early/late, late is used after pmic voltage
setting, early is used in the very early stage for upower mu, lpuart and
etc.

Note: NIC runs at 324MHz, 442MHz has some random kernel hang issue with
cpuidle enabled now.

Reviewed-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
This commit is contained in:
Peng Fan 2022-04-06 14:30:12 +08:00 committed by Stefano Babic
parent 4ddb33dac5
commit a092f33305
9 changed files with 1252 additions and 48 deletions

View File

@ -146,10 +146,10 @@ struct cgc2_regs {
}; };
u32 cgc_clk_get_rate(enum cgc_clk clk); u32 cgc_clk_get_rate(enum cgc_clk clk);
void cgc1_pll3_init(void); void cgc1_pll3_init(ulong freq);
void cgc1_pll2_init(void); void cgc1_pll2_init(ulong freq);
void cgc1_soscdiv_init(void); void cgc1_soscdiv_init(void);
void cgc1_init_core_clk(void); void cgc1_init_core_clk(ulong freq);
void cgc2_pll4_init(void); void cgc2_pll4_init(void);
void cgc2_ddrclk_config(u32 src, u32 div); void cgc2_ddrclk_config(u32 src, u32 div);
void cgc2_ddrclk_wait_unlock(void); void cgc2_ddrclk_wait_unlock(void);

View File

@ -9,6 +9,8 @@
#include <asm/arch/pcc.h> #include <asm/arch/pcc.h>
#include <asm/arch/cgc.h> #include <asm/arch/cgc.h>
#define MHZ(X) ((X) * 1000000UL)
/* Mainly for compatible to imx common code. */ /* Mainly for compatible to imx common code. */
enum mxc_clock { enum mxc_clock {
MXC_ARM_CLK = 0, MXC_ARM_CLK = 0,
@ -39,7 +41,8 @@ void init_clk_usdhc(u32 index);
void init_clk_fspi(int index); void init_clk_fspi(int index);
void init_clk_ddr(void); void init_clk_ddr(void);
int set_ddr_clk(u32 phy_freq_mhz); int set_ddr_clk(u32 phy_freq_mhz);
void clock_init(void); void clock_init_early(void);
void clock_init_late(void);
void cgc1_enet_stamp_sel(u32 clk_src); void cgc1_enet_stamp_sel(u32 clk_src);
void mxs_set_lcdclk(u32 base_addr, u32 freq_in_khz); void mxs_set_lcdclk(u32 base_addr, u32 freq_in_khz);
void reset_lcdclk(void); void reset_lcdclk(void);

View File

@ -6,6 +6,12 @@ config IMX8ULP
config SYS_SOC config SYS_SOC
default "imx8ulp" default "imx8ulp"
config IMX8ULP_LD_MODE
bool
config IMX8ULP_ND_MODE
bool "i.MX8ULP Low Driver Mode"
choice choice
prompt "i.MX8ULP board select" prompt "i.MX8ULP board select"
optional optional

View File

@ -9,9 +9,11 @@
#include <errno.h> #include <errno.h>
#include <asm/arch/imx-regs.h> #include <asm/arch/imx-regs.h>
#include <asm/arch/cgc.h> #include <asm/arch/cgc.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h> #include <asm/arch/sys_proto.h>
#include <asm/global_data.h> #include <asm/global_data.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <hang.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
@ -29,7 +31,7 @@ void cgc1_soscdiv_init(void)
clrbits_le32(&cgc1_regs->frodiv, BIT(7)); clrbits_le32(&cgc1_regs->frodiv, BIT(7));
} }
void cgc1_pll2_init(void) void cgc1_pll2_init(ulong freq)
{ {
u32 reg; u32 reg;
@ -44,8 +46,8 @@ void cgc1_pll2_init(void)
while ((readl(&cgc1_regs->pll2csr) & BIT(24))) while ((readl(&cgc1_regs->pll2csr) & BIT(24)))
; ;
/* Select SOSC as source, freq = 31 * 24 =744mhz */ /* Select SOSC as source */
reg = 31 << 16; reg = (freq / MHZ(24)) << 16;
writel(reg, &cgc1_regs->pll2cfg); writel(reg, &cgc1_regs->pll2cfg);
/* Enable PLL2 */ /* Enable PLL2 */
@ -74,7 +76,7 @@ static void cgc1_set_a35_clk(u32 clk_src, u32 div_core)
; ;
} }
void cgc1_init_core_clk(void) void cgc1_init_core_clk(ulong freq)
{ {
u32 reg = readl(&cgc1_regs->ca35clk); u32 reg = readl(&cgc1_regs->ca35clk);
@ -82,8 +84,7 @@ void cgc1_init_core_clk(void)
if (((reg >> 28) & 0x3) == 0x1) if (((reg >> 28) & 0x3) == 0x1)
cgc1_set_a35_clk(0, 1); cgc1_set_a35_clk(0, 1);
/* Set pll2 to 750Mhz for 1V */ cgc1_pll2_init(freq);
cgc1_pll2_init();
/* Set A35 clock to pll2 */ /* Set A35 clock to pll2 */
cgc1_set_a35_clk(1, 1); cgc1_set_a35_clk(1, 1);
@ -94,7 +95,7 @@ void cgc1_enet_stamp_sel(u32 clk_src)
writel((clk_src & 0x7) << 24, &cgc1_regs->enetstamp); writel((clk_src & 0x7) << 24, &cgc1_regs->enetstamp);
} }
void cgc1_pll3_init(void) void cgc1_pll3_init(ulong freq)
{ {
/* Gate off VCO */ /* Gate off VCO */
setbits_le32(&cgc1_regs->pll3div_vco, BIT(7)); setbits_le32(&cgc1_regs->pll3div_vco, BIT(7));
@ -115,11 +116,15 @@ void cgc1_pll3_init(void)
/* Select SOSC as source */ /* Select SOSC as source */
clrbits_le32(&cgc1_regs->pll3cfg, BIT(0)); clrbits_le32(&cgc1_regs->pll3cfg, BIT(0));
//setbits_le32(&cgc1_regs->pll3cfg, 22 << 16); switch (freq) {
writel(22 << 16, &cgc1_regs->pll3cfg); case 540672000:
writel(0x16 << 16, &cgc1_regs->pll3cfg);
writel(578, &cgc1_regs->pll3num); writel(0x16e3600, &cgc1_regs->pll3denom);
writel(1000, &cgc1_regs->pll3denom); writel(0xc15c00, &cgc1_regs->pll3num);
break;
default:
hang();
}
/* Enable PLL3 */ /* Enable PLL3 */
setbits_le32(&cgc1_regs->pll3csr, BIT(0)); setbits_le32(&cgc1_regs->pll3csr, BIT(0));
@ -130,23 +135,30 @@ void cgc1_pll3_init(void)
/* Gate on VCO */ /* Gate on VCO */
clrbits_le32(&cgc1_regs->pll3div_vco, BIT(7)); clrbits_le32(&cgc1_regs->pll3div_vco, BIT(7));
/*
* PFD0: 380MHz/396/396/328
*/
clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F); clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F);
setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 0);
if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE)) {
setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 0);
clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(26, 21), 3 << 21); /* 195M */
} else if (IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) {
setbits_le32(&cgc1_regs->pll3pfdcfg, 21 << 0);
clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(26, 21), 1 << 21); /* 231M */
} else {
setbits_le32(&cgc1_regs->pll3pfdcfg, 30 << 0); /* 324M */
}
clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(7)); clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(7));
while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(6))) while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(6)))
; ;
clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 8); clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 8);
setbits_le32(&cgc1_regs->pll3pfdcfg, 24 << 8); setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 8);
clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(15)); clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(15));
while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(14))) while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(14)))
; ;
clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 16); clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 16);
setbits_le32(&cgc1_regs->pll3pfdcfg, 24 << 16); setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 16);
clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(23)); clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(23));
while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(22))) while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(22)))
; ;
@ -166,6 +178,13 @@ void cgc1_pll3_init(void)
clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(15)); clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(15));
clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(23)); clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(23));
clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(31)); clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(31));
if (!IS_ENABLED(CONFIG_IMX8ULP_LD_MODE) && !IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) {
/* nicclk select pll3 pfd0 */
clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(29, 28), BIT(28));
while (!(readl(&cgc1_regs->nicclk) & BIT(27)))
;
}
} }
void cgc2_pll4_init(void) void cgc2_pll4_init(void)
@ -189,10 +208,21 @@ void cgc2_pll4_init(void)
; ;
/* Enable all 4 PFDs */ /* Enable all 4 PFDs */
setbits_le32(&cgc2_regs->pll4pfdcfg, 18 << 0); setbits_le32(&cgc2_regs->pll4pfdcfg, 18 << 0); /* 528 */
setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 8); /* 316.8Mhz for NIC_LPAV */ if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE)) {
setbits_le32(&cgc2_regs->pll4pfdcfg, 12 << 16); setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 8);
setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 24); /* 99Mhz for NIC_LPAV */
clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21), 3 << 21);
} else if (IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) {
setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 8);
/* 198Mhz for NIC_LPAV */
clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21), 1 << 21);
} else {
setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 8); /* 316.8Mhz for NIC_LPAV */
clrbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21));
}
setbits_le32(&cgc2_regs->pll4pfdcfg, 12 << 16); /* 792 */
setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 24); /* 396 */
clrbits_le32(&cgc2_regs->pll4pfdcfg, BIT(7) | BIT(15) | BIT(23) | BIT(31)); clrbits_le32(&cgc2_regs->pll4pfdcfg, BIT(7) | BIT(15) | BIT(23) | BIT(31));
@ -203,6 +233,10 @@ void cgc2_pll4_init(void)
/* Enable PFD DIV */ /* Enable PFD DIV */
clrbits_le32(&cgc2_regs->pll4div_pfd0, BIT(7) | BIT(15) | BIT(23) | BIT(31)); clrbits_le32(&cgc2_regs->pll4div_pfd0, BIT(7) | BIT(15) | BIT(23) | BIT(31));
clrbits_le32(&cgc2_regs->pll4div_pfd1, BIT(7) | BIT(15) | BIT(23) | BIT(31)); clrbits_le32(&cgc2_regs->pll4div_pfd1, BIT(7) | BIT(15) | BIT(23) | BIT(31));
clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(29, 28), BIT(28));
while (!(readl(&cgc2_regs->niclpavclk) & BIT(27)))
;
} }
void cgc2_pll4_pfd_config(enum cgc_clk pllpfd, u32 pfd) void cgc2_pll4_pfd_config(enum cgc_clk pllpfd, u32 pfd)

View File

@ -102,7 +102,7 @@ void init_clk_ddr(void)
/* enable pll4 and ddrclk*/ /* enable pll4 and ddrclk*/
cgc2_pll4_init(); cgc2_pll4_init();
cgc2_ddrclk_config(1, 1); cgc2_ddrclk_config(4, 1);
/* enable ddr pcc */ /* enable ddr pcc */
writel(0xd0000000, PCC5_LPDDR4_ADDR); writel(0xd0000000, PCC5_LPDDR4_ADDR);
@ -153,30 +153,66 @@ int set_ddr_clk(u32 phy_freq_mhz)
return 0; return 0;
} }
void clock_init(void) void clock_init_early(void)
{ {
cgc1_soscdiv_init(); cgc1_soscdiv_init();
cgc1_init_core_clk();
init_clk_lpuart(); init_clk_lpuart();
pcc_clock_enable(4, SDHC0_PCC4_SLOT, false);
pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD1_DIV2);
pcc_clock_enable(4, SDHC0_PCC4_SLOT, true);
pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false);
pcc_clock_enable(4, SDHC1_PCC4_SLOT, false);
pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD2_DIV1);
pcc_clock_enable(4, SDHC1_PCC4_SLOT, true);
pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false);
pcc_clock_enable(4, SDHC2_PCC4_SLOT, false);
pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD2_DIV1);
pcc_clock_enable(4, SDHC2_PCC4_SLOT, true);
pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false);
/* Enable upower mu1 clk */ /* Enable upower mu1 clk */
pcc_clock_enable(3, UPOWER_PCC3_SLOT, true); pcc_clock_enable(3, UPOWER_PCC3_SLOT, true);
}
/* This will be invoked after pmic voltage setting */
void clock_init_late(void)
{
if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE))
cgc1_init_core_clk(MHZ(500));
else if (IS_ENABLED(CONFIG_IMX8ULP_ND_MODE))
cgc1_init_core_clk(MHZ(750));
else
cgc1_init_core_clk(MHZ(960));
/*
* Audio use this frequency in kernel dts,
* however nic use pll3 pfd0, we have to
* make the freqency same as kernel to make nic
* not being disabled
*/
cgc1_pll3_init(540672000);
if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE) || IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) {
pcc_clock_enable(4, SDHC0_PCC4_SLOT, false);
pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD2_DIV2);
pcc_clock_enable(4, SDHC0_PCC4_SLOT, true);
pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false);
pcc_clock_enable(4, SDHC1_PCC4_SLOT, false);
pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD2_DIV2);
pcc_clock_enable(4, SDHC1_PCC4_SLOT, true);
pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false);
pcc_clock_enable(4, SDHC2_PCC4_SLOT, false);
pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD2_DIV2);
pcc_clock_enable(4, SDHC2_PCC4_SLOT, true);
pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false);
} else {
pcc_clock_enable(4, SDHC0_PCC4_SLOT, false);
pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD1_DIV2);
pcc_clock_enable(4, SDHC0_PCC4_SLOT, true);
pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false);
pcc_clock_enable(4, SDHC1_PCC4_SLOT, false);
pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD2_DIV1);
pcc_clock_enable(4, SDHC1_PCC4_SLOT, true);
pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false);
pcc_clock_enable(4, SDHC2_PCC4_SLOT, false);
pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD2_DIV1);
pcc_clock_enable(4, SDHC2_PCC4_SLOT, true);
pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false);
}
/* /*
* Enable clock division * Enable clock division

View File

@ -597,7 +597,7 @@ int arch_cpu_init(void)
xrdc_mrc_region_set_access(2, CONFIG_SPL_TEXT_BASE, 0xE00); xrdc_mrc_region_set_access(2, CONFIG_SPL_TEXT_BASE, 0xE00);
clock_init(); clock_init_early();
} else { } else {
/* reconfigure core0 reset vector to ROM */ /* reconfigure core0 reset vector to ROM */
set_core0_reset_vector(0x1000); set_core0_reset_vector(0x1000);

View File

@ -3,5 +3,10 @@
obj-y += imx8ulp_evk.o obj-y += imx8ulp_evk.o
ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_BUILD
obj-y += spl.o ddr_init.o lpddr4_timing.o obj-y += spl.o ddr_init.o
ifdef CONFIG_IMX8ULP_ND_MODE
obj-y += lpddr4_timing_264.o
else
obj-y += lpddr4_timing.o
endif
endif endif

File diff suppressed because it is too large Load Diff

View File

@ -35,8 +35,17 @@ u32 spl_boot_device(void)
int power_init_board(void) int power_init_board(void)
{ {
/* Set buck3 to 1.1v OD */ if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE)) {
upower_pmic_i2c_write(0x22, 0x28); /* Set buck3 to 0.9v LD */
upower_pmic_i2c_write(0x22, 0x18);
} else if (IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) {
/* Set buck3 to 1.0v ND */
upower_pmic_i2c_write(0x22, 0x20);
} else {
/* Set buck3 to 1.1v OD */
upower_pmic_i2c_write(0x22, 0x28);
}
return 0; return 0;
} }
@ -69,6 +78,8 @@ void spl_board_init(void)
power_init_board(); power_init_board();
clock_init_late();
/* DDR initialization */ /* DDR initialization */
spl_dram_init(); spl_dram_init();