1 /* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <arch_helpers.h> 32 #include <assert.h> 33 #include <debug.h> 34 #include <delay_timer.h> 35 #include <dfs.h> 36 #include <dram.h> 37 #include <mmio.h> 38 #include <m0_ctl.h> 39 #include <platform_def.h> 40 #include <plat_private.h> 41 #include <rk3399_def.h> 42 #include <secure.h> 43 #include <soc.h> 44 45 /* Table of regions to map using the MMU. */ 46 const mmap_region_t plat_rk_mmap[] = { 47 MAP_REGION_FLAT(DEV_RNG0_BASE, DEV_RNG0_SIZE, 48 MT_DEVICE | MT_RW | MT_SECURE), 49 MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, 50 MT_MEMORY | MT_RW | MT_SECURE), 51 52 { 0 } 53 }; 54 55 /* The RockChip power domain tree descriptor */ 56 const unsigned char rockchip_power_domain_tree_desc[] = { 57 /* No of root nodes */ 58 PLATFORM_SYSTEM_COUNT, 59 /* No of children for the root node */ 60 PLATFORM_CLUSTER_COUNT, 61 /* No of children for the first cluster node */ 62 PLATFORM_CLUSTER0_CORE_COUNT, 63 /* No of children for the second cluster node */ 64 PLATFORM_CLUSTER1_CORE_COUNT 65 }; 66 67 /* sleep data for pll suspend */ 68 static struct deepsleep_data_s slp_data; 69 70 static void set_pll_slow_mode(uint32_t pll_id) 71 { 72 if (pll_id == PPLL_ID) 73 mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_SLOW_MODE); 74 else 75 mmio_write_32((CRU_BASE + 76 CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE); 77 } 78 79 static void set_pll_normal_mode(uint32_t pll_id) 80 { 81 if (pll_id == PPLL_ID) 82 mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_NOMAL_MODE); 83 else 84 mmio_write_32(CRU_BASE + 85 CRU_PLL_CON(pll_id, 3), PLL_NOMAL_MODE); 86 } 87 88 static void set_pll_bypass(uint32_t pll_id) 89 { 90 if (pll_id == PPLL_ID) 91 mmio_write_32(PMUCRU_BASE + 92 PMUCRU_PPLL_CON(3), PLL_BYPASS_MODE); 93 else 94 mmio_write_32(CRU_BASE + 95 CRU_PLL_CON(pll_id, 3), PLL_BYPASS_MODE); 96 } 97 98 static void _pll_suspend(uint32_t pll_id) 99 { 100 set_pll_slow_mode(pll_id); 101 set_pll_bypass(pll_id); 102 } 103 104 /** 105 * disable_dvfs_plls - To suspend the specific PLLs 106 * 107 * When we close the center logic, the DPLL will be closed, 108 * so we need to keep the ABPLL and switch to it to supply 109 * clock for DDR during suspend, then we should not close 110 * the ABPLL and exclude ABPLL_ID. 111 */ 112 void disable_dvfs_plls(void) 113 { 114 _pll_suspend(CPLL_ID); 115 _pll_suspend(NPLL_ID); 116 _pll_suspend(VPLL_ID); 117 _pll_suspend(GPLL_ID); 118 _pll_suspend(ALPLL_ID); 119 } 120 121 /** 122 * disable_nodvfs_plls - To suspend the PPLL 123 */ 124 void disable_nodvfs_plls(void) 125 { 126 _pll_suspend(PPLL_ID); 127 } 128 129 /** 130 * restore_pll - Copy PLL settings from memory to a PLL. 131 * 132 * This will copy PLL settings from an array in memory to the memory mapped 133 * registers for a PLL. 134 * 135 * Note that: above the PLL exclude PPLL. 136 * 137 * pll_id: One of the values from enum plls_id 138 * src: Pointer to the array of values to restore from 139 */ 140 static void restore_pll(int pll_id, uint32_t *src) 141 { 142 /* Nice to have PLL off while configuring */ 143 mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE); 144 145 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK); 146 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK); 147 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]); 148 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK); 149 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK); 150 151 /* Do PLL_CON3 since that will enable things */ 152 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK); 153 154 /* Wait for PLL lock done */ 155 while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) & 156 0x80000000) == 0x0) 157 ; 158 } 159 160 /** 161 * save_pll - Copy PLL settings a PLL to memory 162 * 163 * This will copy PLL settings from the memory mapped registers for a PLL to 164 * an array in memory. 165 * 166 * Note that: above the PLL exclude PPLL. 167 * 168 * pll_id: One of the values from enum plls_id 169 * src: Pointer to the array of values to save to. 170 */ 171 static void save_pll(uint32_t *dst, int pll_id) 172 { 173 int i; 174 175 for (i = 0; i < PLL_CON_COUNT; i++) 176 dst[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, i)); 177 } 178 179 /** 180 * prepare_abpll_for_ddrctrl - Copy DPLL settings to ABPLL 181 * 182 * This will copy DPLL settings from the memory mapped registers for a PLL to 183 * an array in memory. 184 */ 185 void prepare_abpll_for_ddrctrl(void) 186 { 187 save_pll(slp_data.plls_con[ABPLL_ID], ABPLL_ID); 188 save_pll(slp_data.plls_con[DPLL_ID], DPLL_ID); 189 190 restore_pll(ABPLL_ID, slp_data.plls_con[DPLL_ID]); 191 } 192 193 void restore_abpll(void) 194 { 195 restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]); 196 } 197 198 void restore_dpll(void) 199 { 200 restore_pll(DPLL_ID, slp_data.plls_con[DPLL_ID]); 201 } 202 203 void clk_gate_con_save(void) 204 { 205 uint32_t i = 0; 206 207 for (i = 0; i < PMUCRU_GATE_COUNT; i++) 208 slp_data.pmucru_gate_con[i] = 209 mmio_read_32(PMUCRU_BASE + PMUCRU_GATE_CON(i)); 210 211 for (i = 0; i < CRU_GATE_COUNT; i++) 212 slp_data.cru_gate_con[i] = 213 mmio_read_32(CRU_BASE + CRU_GATE_CON(i)); 214 } 215 216 void clk_gate_con_disable(void) 217 { 218 uint32_t i; 219 220 for (i = 0; i < PMUCRU_GATE_COUNT; i++) 221 mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i), REG_SOC_WMSK); 222 223 for (i = 0; i < CRU_GATE_COUNT; i++) 224 mmio_write_32(CRU_BASE + CRU_GATE_CON(i), REG_SOC_WMSK); 225 } 226 227 void clk_gate_con_restore(void) 228 { 229 uint32_t i; 230 231 for (i = 0; i < PMUCRU_GATE_COUNT; i++) 232 mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i), 233 REG_SOC_WMSK | slp_data.pmucru_gate_con[i]); 234 235 for (i = 0; i < CRU_GATE_COUNT; i++) 236 mmio_write_32(CRU_BASE + CRU_GATE_CON(i), 237 REG_SOC_WMSK | slp_data.cru_gate_con[i]); 238 } 239 240 static void set_plls_nobypass(uint32_t pll_id) 241 { 242 if (pll_id == PPLL_ID) 243 mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), 244 PLL_NO_BYPASS_MODE); 245 else 246 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), 247 PLL_NO_BYPASS_MODE); 248 } 249 250 static void _pll_resume(uint32_t pll_id) 251 { 252 set_plls_nobypass(pll_id); 253 set_pll_normal_mode(pll_id); 254 } 255 256 /** 257 * enable_dvfs_plls - To resume the specific PLLs 258 * 259 * Please see the comment at the disable_dvfs_plls() 260 * we don't suspend the ABPLL, so don't need resume 261 * it too. 262 */ 263 void enable_dvfs_plls(void) 264 { 265 _pll_resume(ALPLL_ID); 266 _pll_resume(GPLL_ID); 267 _pll_resume(VPLL_ID); 268 _pll_resume(NPLL_ID); 269 _pll_resume(CPLL_ID); 270 } 271 272 /** 273 * enable_nodvfs_plls - To resume the PPLL 274 */ 275 void enable_nodvfs_plls(void) 276 { 277 _pll_resume(PPLL_ID); 278 } 279 280 void soc_global_soft_reset_init(void) 281 { 282 mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1), 283 CRU_PMU_SGRF_RST_RLS); 284 285 mmio_clrbits_32(CRU_BASE + CRU_GLB_RST_CON, 286 CRU_PMU_WDTRST_MSK | CRU_PMU_FIRST_SFTRST_MSK); 287 } 288 289 void __dead2 soc_global_soft_reset(void) 290 { 291 set_pll_slow_mode(VPLL_ID); 292 set_pll_slow_mode(NPLL_ID); 293 set_pll_slow_mode(GPLL_ID); 294 set_pll_slow_mode(CPLL_ID); 295 set_pll_slow_mode(PPLL_ID); 296 set_pll_slow_mode(ABPLL_ID); 297 set_pll_slow_mode(ALPLL_ID); 298 299 dsb(); 300 301 mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL); 302 303 /* 304 * Maybe the HW needs some times to reset the system, 305 * so we do not hope the core to excute valid codes. 306 */ 307 while (1) 308 ; 309 } 310 311 void plat_rockchip_soc_init(void) 312 { 313 secure_timer_init(); 314 secure_sgrf_init(); 315 secure_sgrf_ddr_rgn_init(); 316 soc_global_soft_reset_init(); 317 plat_rockchip_gpio_init(); 318 m0_init(); 319 dram_init(); 320 dram_dfs_init(); 321 } 322