1 /* 2 * Copyright 2018-2022 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) & (1 << 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 2400: 92 mmio_write_32(DRAM_PLL_CTRL + 0x4, (300 << 12) | (3 << 4) | 2); 93 break; 94 case 1600: 95 mmio_write_32(DRAM_PLL_CTRL + 0x4, (400 << 12) | (3 << 4) | 3); 96 break; 97 case 1066: 98 mmio_write_32(DRAM_PLL_CTRL + 0x4, (266 << 12) | (3 << 4) | 3); 99 break; 100 case 667: 101 mmio_write_32(DRAM_PLL_CTRL + 0x4, (334 << 12) | (3 << 4) | 4); 102 break; 103 default: 104 break; 105 } 106 107 mmio_setbits_32(DRAM_PLL_CTRL, BIT(9)); 108 /* wait for PLL locked */ 109 while (!(mmio_read_32(DRAM_PLL_CTRL) & BIT(31))) { 110 ; 111 } 112 113 /* unbypass the PLL */ 114 mmio_clrbits_32(DRAM_PLL_CTRL, BIT(16)); 115 } 116 #endif 117 118 /* change the dram clock frequency */ 119 void dram_clock_switch(unsigned int target_drate, bool bypass_mode) 120 { 121 if (bypass_mode) { 122 switch (target_drate) { 123 case 400: 124 ddr_pll_bypass_400mts(); 125 break; 126 case 100: 127 ddr_pll_bypass_100mts(); 128 break; 129 default: 130 ddr_pll_unbypass(); 131 break; 132 } 133 } else { 134 dram_pll_init(target_drate); 135 } 136 } 137