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