1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright 2018-2023 NXP 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <stdbool.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <lib/mmio.h> 10*91f16700Schasinglulu #include <platform_def.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #define IMX_CCM_IP_BASE (IMX_CCM_BASE + 0xa000) 13*91f16700Schasinglulu #define DRAM_SEL_CFG (IMX_CCM_BASE + 0x9800) 14*91f16700Schasinglulu #define CCM_IP_CLK_ROOT_GEN_TAGET(i) (IMX_CCM_IP_BASE + 0x80 * (i) + 0x00) 15*91f16700Schasinglulu #define CCM_IP_CLK_ROOT_GEN_TAGET_SET(i) (IMX_CCM_IP_BASE + 0x80 * (i) + 0x04) 16*91f16700Schasinglulu #define CCM_IP_CLK_ROOT_GEN_TAGET_CLR(i) (IMX_CCM_IP_BASE + 0x80 * (i) + 0x08) 17*91f16700Schasinglulu #define PLL_FREQ_800M U(0x00ece580) 18*91f16700Schasinglulu #define PLL_FREQ_400M U(0x00ec6984) 19*91f16700Schasinglulu #define PLL_FREQ_167M U(0x00f5a406) 20*91f16700Schasinglulu 21*91f16700Schasinglulu void ddr_pll_bypass_100mts(void) 22*91f16700Schasinglulu { 23*91f16700Schasinglulu /* change the clock source of dram_alt_clk_root to source 2 --100MHz */ 24*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(0), (0x7 << 24) | (0x7 << 16)); 25*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(0), (0x2 << 24)); 26*91f16700Schasinglulu 27*91f16700Schasinglulu /* change the clock source of dram_apb_clk_root to source 2 --40MHz/2 */ 28*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16)); 29*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x2 << 24) | (0x1 << 16)); 30*91f16700Schasinglulu 31*91f16700Schasinglulu /* configure pll bypass mode */ 32*91f16700Schasinglulu mmio_write_32(DRAM_SEL_CFG + 0x4, BIT(24)); 33*91f16700Schasinglulu } 34*91f16700Schasinglulu 35*91f16700Schasinglulu void ddr_pll_bypass_400mts(void) 36*91f16700Schasinglulu { 37*91f16700Schasinglulu /* change the clock source of dram_alt_clk_root to source 1 --400MHz */ 38*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(0), (0x7 << 24) | (0x7 << 16)); 39*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(0), (0x1 << 24) | (0x1 << 16)); 40*91f16700Schasinglulu 41*91f16700Schasinglulu /* change the clock source of dram_apb_clk_root to source 3 --160MHz/2 */ 42*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16)); 43*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x3 << 24) | (0x1 << 16)); 44*91f16700Schasinglulu 45*91f16700Schasinglulu /* configure pll bypass mode */ 46*91f16700Schasinglulu mmio_write_32(DRAM_SEL_CFG + 0x4, BIT(24)); 47*91f16700Schasinglulu } 48*91f16700Schasinglulu 49*91f16700Schasinglulu void ddr_pll_unbypass(void) 50*91f16700Schasinglulu { 51*91f16700Schasinglulu mmio_write_32(DRAM_SEL_CFG + 0x8, BIT(24)); 52*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16)); 53*91f16700Schasinglulu /* to source 4 --800MHz/5 */ 54*91f16700Schasinglulu mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x4 << 24) | (0x4 << 16)); 55*91f16700Schasinglulu } 56*91f16700Schasinglulu 57*91f16700Schasinglulu #if defined(PLAT_imx8mq) 58*91f16700Schasinglulu void dram_pll_init(unsigned int drate) 59*91f16700Schasinglulu { 60*91f16700Schasinglulu /* bypass the PLL */ 61*91f16700Schasinglulu mmio_setbits_32(HW_DRAM_PLL_CFG0, 0x30); 62*91f16700Schasinglulu 63*91f16700Schasinglulu switch (drate) { 64*91f16700Schasinglulu case 3200: 65*91f16700Schasinglulu mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_800M); 66*91f16700Schasinglulu break; 67*91f16700Schasinglulu case 1600: 68*91f16700Schasinglulu mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_400M); 69*91f16700Schasinglulu break; 70*91f16700Schasinglulu case 667: 71*91f16700Schasinglulu mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_167M); 72*91f16700Schasinglulu break; 73*91f16700Schasinglulu default: 74*91f16700Schasinglulu break; 75*91f16700Schasinglulu } 76*91f16700Schasinglulu 77*91f16700Schasinglulu /* unbypass the PLL */ 78*91f16700Schasinglulu mmio_clrbits_32(HW_DRAM_PLL_CFG0, 0x30); 79*91f16700Schasinglulu while (!(mmio_read_32(HW_DRAM_PLL_CFG0) & BIT(31))) { 80*91f16700Schasinglulu ; 81*91f16700Schasinglulu } 82*91f16700Schasinglulu } 83*91f16700Schasinglulu #else 84*91f16700Schasinglulu void dram_pll_init(unsigned int drate) 85*91f16700Schasinglulu { 86*91f16700Schasinglulu /* bypass the PLL */ 87*91f16700Schasinglulu mmio_setbits_32(DRAM_PLL_CTRL, (1 << 16)); 88*91f16700Schasinglulu mmio_clrbits_32(DRAM_PLL_CTRL, (1 << 9)); 89*91f16700Schasinglulu 90*91f16700Schasinglulu switch (drate) { 91*91f16700Schasinglulu case 4000: 92*91f16700Schasinglulu mmio_write_32(DRAM_PLL_CTRL + 0x4, (250 << 12) | (3 << 4) | 1); 93*91f16700Schasinglulu break; 94*91f16700Schasinglulu case 3733: 95*91f16700Schasinglulu case 3732: 96*91f16700Schasinglulu mmio_write_32(DRAM_PLL_CTRL + 0x4, (311 << 12) | (4 << 4) | 1); 97*91f16700Schasinglulu break; 98*91f16700Schasinglulu case 3200: 99*91f16700Schasinglulu mmio_write_32(DRAM_PLL_CTRL + 0x4, (200 << 12) | (3 << 4) | 1); 100*91f16700Schasinglulu break; 101*91f16700Schasinglulu case 2400: 102*91f16700Schasinglulu mmio_write_32(DRAM_PLL_CTRL + 0x4, (300 << 12) | (3 << 4) | 2); 103*91f16700Schasinglulu break; 104*91f16700Schasinglulu case 1600: 105*91f16700Schasinglulu mmio_write_32(DRAM_PLL_CTRL + 0x4, (400 << 12) | (3 << 4) | 3); 106*91f16700Schasinglulu break; 107*91f16700Schasinglulu case 1066: 108*91f16700Schasinglulu mmio_write_32(DRAM_PLL_CTRL + 0x4, (266 << 12) | (3 << 4) | 3); 109*91f16700Schasinglulu break; 110*91f16700Schasinglulu case 667: 111*91f16700Schasinglulu mmio_write_32(DRAM_PLL_CTRL + 0x4, (334 << 12) | (3 << 4) | 4); 112*91f16700Schasinglulu break; 113*91f16700Schasinglulu default: 114*91f16700Schasinglulu break; 115*91f16700Schasinglulu } 116*91f16700Schasinglulu 117*91f16700Schasinglulu mmio_setbits_32(DRAM_PLL_CTRL, BIT(9)); 118*91f16700Schasinglulu /* wait for PLL locked */ 119*91f16700Schasinglulu while (!(mmio_read_32(DRAM_PLL_CTRL) & BIT(31))) { 120*91f16700Schasinglulu ; 121*91f16700Schasinglulu } 122*91f16700Schasinglulu 123*91f16700Schasinglulu /* unbypass the PLL */ 124*91f16700Schasinglulu mmio_clrbits_32(DRAM_PLL_CTRL, BIT(16)); 125*91f16700Schasinglulu } 126*91f16700Schasinglulu #endif 127*91f16700Schasinglulu 128*91f16700Schasinglulu /* change the dram clock frequency */ 129*91f16700Schasinglulu void dram_clock_switch(unsigned int target_drate, bool bypass_mode) 130*91f16700Schasinglulu { 131*91f16700Schasinglulu if (bypass_mode) { 132*91f16700Schasinglulu switch (target_drate) { 133*91f16700Schasinglulu case 400: 134*91f16700Schasinglulu ddr_pll_bypass_400mts(); 135*91f16700Schasinglulu break; 136*91f16700Schasinglulu case 100: 137*91f16700Schasinglulu ddr_pll_bypass_100mts(); 138*91f16700Schasinglulu break; 139*91f16700Schasinglulu default: 140*91f16700Schasinglulu ddr_pll_unbypass(); 141*91f16700Schasinglulu break; 142*91f16700Schasinglulu } 143*91f16700Schasinglulu } else { 144*91f16700Schasinglulu dram_pll_init(target_drate); 145*91f16700Schasinglulu } 146*91f16700Schasinglulu } 147