1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * SDRAM timing related functions for OMAP2xxx 4 * 5 * Copyright (C) 2005, 2008 Texas Instruments Inc. 6 * Copyright (C) 2005, 2008 Nokia Corporation 7 * 8 * Tony Lindgren <tony@atomide.com> 9 * Paul Walmsley 10 * Richard Woodruff <r-woodruff2@ti.com> 11 */ 12 13 #include <linux/module.h> 14 #include <linux/kernel.h> 15 #include <linux/device.h> 16 #include <linux/list.h> 17 #include <linux/errno.h> 18 #include <linux/delay.h> 19 #include <linux/clk.h> 20 #include <linux/io.h> 21 22 #include "soc.h" 23 #include "iomap.h" 24 #include "common.h" 25 #include "prm2xxx.h" 26 #include "clock.h" 27 #include "sdrc.h" 28 #include "sram.h" 29 30 /* Memory timing, DLL mode flags */ 31 #define M_DDR 1 32 #define M_LOCK_CTRL (1 << 2) 33 #define M_UNLOCK 0 34 #define M_LOCK 1 35 36 37 static struct memory_timings mem_timings; 38 static u32 curr_perf_level = CORE_CLK_SRC_DPLL_X2; 39 40 static u32 omap2xxx_sdrc_get_slow_dll_ctrl(void) 41 { 42 return mem_timings.slow_dll_ctrl; 43 } 44 45 static u32 omap2xxx_sdrc_get_fast_dll_ctrl(void) 46 { 47 return mem_timings.fast_dll_ctrl; 48 } 49 50 static u32 omap2xxx_sdrc_get_type(void) 51 { 52 return mem_timings.m_type; 53 } 54 55 /* 56 * Check the DLL lock state, and return tue if running in unlock mode. 57 * This is needed to compensate for the shifted DLL value in unlock mode. 58 */ 59 u32 omap2xxx_sdrc_dll_is_unlocked(void) 60 { 61 /* dlla and dllb are a set */ 62 u32 dll_state = sdrc_read_reg(SDRC_DLLA_CTRL); 63 64 if ((dll_state & (1 << 2)) == (1 << 2)) 65 return 1; 66 else 67 return 0; 68 } 69 70 /* 71 * 'level' is the value to store to CM_CLKSEL2_PLL.CORE_CLK_SRC. 72 * Practical values are CORE_CLK_SRC_DPLL (for CORE_CLK = DPLL_CLK) or 73 * CORE_CLK_SRC_DPLL_X2 (for CORE_CLK = * DPLL_CLK * 2) 74 * 75 * Used by the clock framework during CORE DPLL changes 76 */ 77 u32 omap2xxx_sdrc_reprogram(u32 level, u32 force) 78 { 79 u32 dll_ctrl, m_type; 80 u32 prev = curr_perf_level; 81 unsigned long flags; 82 83 if ((curr_perf_level == level) && !force) 84 return prev; 85 86 if (level == CORE_CLK_SRC_DPLL) 87 dll_ctrl = omap2xxx_sdrc_get_slow_dll_ctrl(); 88 else if (level == CORE_CLK_SRC_DPLL_X2) 89 dll_ctrl = omap2xxx_sdrc_get_fast_dll_ctrl(); 90 else 91 return prev; 92 93 m_type = omap2xxx_sdrc_get_type(); 94 95 local_irq_save(flags); 96 /* 97 * XXX These calls should be abstracted out through a 98 * prm2xxx.c function 99 */ 100 if (cpu_is_omap2420()) 101 writel_relaxed(0xffff, OMAP2420_PRCM_VOLTSETUP); 102 else 103 writel_relaxed(0xffff, OMAP2430_PRCM_VOLTSETUP); 104 omap2_sram_reprogram_sdrc(level, dll_ctrl, m_type); 105 curr_perf_level = level; 106 local_irq_restore(flags); 107 108 return prev; 109 } 110 111 /* Used by the clock framework during CORE DPLL changes */ 112 void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode) 113 { 114 unsigned long dll_cnt; 115 u32 fast_dll = 0; 116 117 /* DDR = 1, SDR = 0 */ 118 mem_timings.m_type = !((sdrc_read_reg(SDRC_MR_0) & 0x3) == 0x1); 119 120 /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others. 121 * In the case of 2422, its ok to use CS1 instead of CS0. 122 */ 123 if (cpu_is_omap2422()) 124 mem_timings.base_cs = 1; 125 else 126 mem_timings.base_cs = 0; 127 128 if (mem_timings.m_type != M_DDR) 129 return; 130 131 /* With DDR we need to determine the low frequency DLL value */ 132 if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL)) 133 mem_timings.dll_mode = M_UNLOCK; 134 else 135 mem_timings.dll_mode = M_LOCK; 136 137 if (mem_timings.base_cs == 0) { 138 fast_dll = sdrc_read_reg(SDRC_DLLA_CTRL); 139 dll_cnt = sdrc_read_reg(SDRC_DLLA_STATUS) & 0xff00; 140 } else { 141 fast_dll = sdrc_read_reg(SDRC_DLLB_CTRL); 142 dll_cnt = sdrc_read_reg(SDRC_DLLB_STATUS) & 0xff00; 143 } 144 if (force_lock_to_unlock_mode) { 145 fast_dll &= ~0xff00; 146 fast_dll |= dll_cnt; /* Current lock mode */ 147 } 148 /* set fast timings with DLL filter disabled */ 149 mem_timings.fast_dll_ctrl = (fast_dll | (3 << 8)); 150 151 /* No disruptions, DDR will be offline & C-ABI not followed */ 152 omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl, 153 mem_timings.fast_dll_ctrl, 154 mem_timings.base_cs, 155 force_lock_to_unlock_mode); 156 mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */ 157 158 /* Turn status into unlock ctrl */ 159 mem_timings.slow_dll_ctrl |= 160 ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2)); 161 162 /* 90 degree phase for anything below 133MHz + disable DLL filter */ 163 mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8)); 164 } 165