1780e3f24SHeiko Stuebner /* 2780e3f24SHeiko Stuebner * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3780e3f24SHeiko Stuebner * 4780e3f24SHeiko Stuebner * SPDX-License-Identifier: BSD-3-Clause 5780e3f24SHeiko Stuebner */ 6780e3f24SHeiko Stuebner 7780e3f24SHeiko Stuebner #include <platform_def.h> 8780e3f24SHeiko Stuebner 9780e3f24SHeiko Stuebner #include <arch_helpers.h> 10780e3f24SHeiko Stuebner #include <common/debug.h> 11780e3f24SHeiko Stuebner #include <lib/mmio.h> 12780e3f24SHeiko Stuebner 13780e3f24SHeiko Stuebner #include <plat_private.h> 14780e3f24SHeiko Stuebner #include <rk3288_def.h> 15780e3f24SHeiko Stuebner #include <soc.h> 16780e3f24SHeiko Stuebner #include <secure.h> 17780e3f24SHeiko Stuebner 18780e3f24SHeiko Stuebner /* sleep data for pll suspend */ 19780e3f24SHeiko Stuebner static struct deepsleep_data_s slp_data; 20780e3f24SHeiko Stuebner 21780e3f24SHeiko Stuebner /* Table of regions to map using the MMU. */ 22780e3f24SHeiko Stuebner const mmap_region_t plat_rk_mmap[] = { 23780e3f24SHeiko Stuebner MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE, 24780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 25780e3f24SHeiko Stuebner MAP_REGION_FLAT(STIME_BASE, STIME_SIZE, 26780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 27780e3f24SHeiko Stuebner MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE, 28780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 29780e3f24SHeiko Stuebner MAP_REGION_FLAT(TZPC_BASE, TZPC_SIZE, 30780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 31780e3f24SHeiko Stuebner MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, 32780e3f24SHeiko Stuebner MT_MEMORY | MT_RW | MT_SECURE), 33780e3f24SHeiko Stuebner MAP_REGION_FLAT(SRAM_BASE, SRAM_SIZE, 34780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 35780e3f24SHeiko Stuebner MAP_REGION_FLAT(PMU_BASE, PMU_SIZE, 36780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 37*0957b9b2SChristoph Müllner MAP_REGION_FLAT(UART0_BASE, UART0_SIZE, 38*0957b9b2SChristoph Müllner MT_DEVICE | MT_RW | MT_SECURE), 39*0957b9b2SChristoph Müllner MAP_REGION_FLAT(UART1_BASE, UART1_SIZE, 40*0957b9b2SChristoph Müllner MT_DEVICE | MT_RW | MT_SECURE), 41*0957b9b2SChristoph Müllner MAP_REGION_FLAT(UART2_BASE, UART2_SIZE, 42*0957b9b2SChristoph Müllner MT_DEVICE | MT_RW | MT_SECURE), 43*0957b9b2SChristoph Müllner MAP_REGION_FLAT(UART3_BASE, UART3_SIZE, 44*0957b9b2SChristoph Müllner MT_DEVICE | MT_RW | MT_SECURE), 45*0957b9b2SChristoph Müllner MAP_REGION_FLAT(UART4_BASE, UART4_SIZE, 46780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 47780e3f24SHeiko Stuebner MAP_REGION_FLAT(CRU_BASE, CRU_SIZE, 48780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 49780e3f24SHeiko Stuebner MAP_REGION_FLAT(GRF_BASE, GRF_SIZE, 50780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 51780e3f24SHeiko Stuebner MAP_REGION_FLAT(DDR_PCTL0_BASE, DDR_PCTL0_SIZE, 52780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 53780e3f24SHeiko Stuebner MAP_REGION_FLAT(DDR_PHY0_BASE, DDR_PHY0_SIZE, 54780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 55780e3f24SHeiko Stuebner MAP_REGION_FLAT(DDR_PCTL1_BASE, DDR_PCTL1_SIZE, 56780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 57780e3f24SHeiko Stuebner MAP_REGION_FLAT(DDR_PHY1_BASE, DDR_PHY1_SIZE, 58780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 59780e3f24SHeiko Stuebner MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SIZE, 60780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 61780e3f24SHeiko Stuebner MAP_REGION_FLAT(CORE_AXI_BUS_BASE, CORE_AXI_BUS_SIZE, 62780e3f24SHeiko Stuebner MT_DEVICE | MT_RW | MT_SECURE), 63780e3f24SHeiko Stuebner { 0 } 64780e3f24SHeiko Stuebner }; 65780e3f24SHeiko Stuebner 66780e3f24SHeiko Stuebner /* The RockChip power domain tree descriptor */ 67780e3f24SHeiko Stuebner const unsigned char rockchip_power_domain_tree_desc[] = { 68780e3f24SHeiko Stuebner /* No of root nodes */ 69780e3f24SHeiko Stuebner PLATFORM_SYSTEM_COUNT, 70780e3f24SHeiko Stuebner /* No of children for the root node */ 71780e3f24SHeiko Stuebner PLATFORM_CLUSTER_COUNT, 72780e3f24SHeiko Stuebner /* No of children for the first cluster node */ 73780e3f24SHeiko Stuebner PLATFORM_CLUSTER0_CORE_COUNT, 74780e3f24SHeiko Stuebner }; 75780e3f24SHeiko Stuebner 76780e3f24SHeiko Stuebner void plat_rockchip_soc_init(void) 77780e3f24SHeiko Stuebner { 78780e3f24SHeiko Stuebner secure_timer_init(); 79780e3f24SHeiko Stuebner secure_sgrf_init(); 80780e3f24SHeiko Stuebner /* 81780e3f24SHeiko Stuebner * We cannot enable ddr security at this point, as the kernel 82780e3f24SHeiko Stuebner * seems to have an issue with it even living in the same 128MB 83780e3f24SHeiko Stuebner * memory block. Only when moving the kernel to the second 84780e3f24SHeiko Stuebner * 128MB block does it not conflict, but then we'd loose this 85780e3f24SHeiko Stuebner * memory area for use. Late maybe enable 86780e3f24SHeiko Stuebner * secure_sgrf_ddr_rgn_init(); 87780e3f24SHeiko Stuebner */ 88780e3f24SHeiko Stuebner } 89780e3f24SHeiko Stuebner 90780e3f24SHeiko Stuebner void regs_update_bits(uintptr_t addr, uint32_t val, 91780e3f24SHeiko Stuebner uint32_t mask, uint32_t shift) 92780e3f24SHeiko Stuebner { 93780e3f24SHeiko Stuebner uint32_t tmp, orig; 94780e3f24SHeiko Stuebner 95780e3f24SHeiko Stuebner orig = mmio_read_32(addr); 96780e3f24SHeiko Stuebner 97780e3f24SHeiko Stuebner tmp = orig & ~(mask << shift); 98780e3f24SHeiko Stuebner tmp |= (val & mask) << shift; 99780e3f24SHeiko Stuebner 100780e3f24SHeiko Stuebner if (tmp != orig) 101780e3f24SHeiko Stuebner mmio_write_32(addr, tmp); 102780e3f24SHeiko Stuebner dsb(); 103780e3f24SHeiko Stuebner } 104780e3f24SHeiko Stuebner 105780e3f24SHeiko Stuebner static void pll_save(uint32_t pll_id) 106780e3f24SHeiko Stuebner { 107780e3f24SHeiko Stuebner uint32_t *pll = slp_data.pll_con[pll_id]; 108780e3f24SHeiko Stuebner 109780e3f24SHeiko Stuebner pll[0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0)); 110780e3f24SHeiko Stuebner pll[1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1)); 111780e3f24SHeiko Stuebner pll[2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2)); 112780e3f24SHeiko Stuebner pll[3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3)); 113780e3f24SHeiko Stuebner } 114780e3f24SHeiko Stuebner 115780e3f24SHeiko Stuebner void clk_plls_suspend(void) 116780e3f24SHeiko Stuebner { 117780e3f24SHeiko Stuebner pll_save(NPLL_ID); 118780e3f24SHeiko Stuebner pll_save(CPLL_ID); 119780e3f24SHeiko Stuebner pll_save(GPLL_ID); 120780e3f24SHeiko Stuebner pll_save(APLL_ID); 121780e3f24SHeiko Stuebner slp_data.pll_mode = mmio_read_32(CRU_BASE + PLL_MODE_CON); 122780e3f24SHeiko Stuebner 123780e3f24SHeiko Stuebner /* 124780e3f24SHeiko Stuebner * Switch PLLs other than DPLL (for SDRAM) to slow mode to 125780e3f24SHeiko Stuebner * avoid crashes on resume. The Mask ROM on the system will 126780e3f24SHeiko Stuebner * put APLL, CPLL, and GPLL into slow mode at resume time 127780e3f24SHeiko Stuebner * anyway (which is why we restore them), but we might not 128780e3f24SHeiko Stuebner * even make it to the Mask ROM if this isn't done at suspend 129780e3f24SHeiko Stuebner * time. 130780e3f24SHeiko Stuebner * 131780e3f24SHeiko Stuebner * NOTE: only APLL truly matters here, but we'll do them all. 132780e3f24SHeiko Stuebner */ 133780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000); 134780e3f24SHeiko Stuebner } 135780e3f24SHeiko Stuebner 136780e3f24SHeiko Stuebner void clk_plls_resume(void) 137780e3f24SHeiko Stuebner { 138780e3f24SHeiko Stuebner /* restore pll-modes */ 139780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + PLL_MODE_CON, 140780e3f24SHeiko Stuebner slp_data.pll_mode | REG_SOC_WMSK); 141780e3f24SHeiko Stuebner } 142780e3f24SHeiko Stuebner 143780e3f24SHeiko Stuebner void clk_gate_con_save(void) 144780e3f24SHeiko Stuebner { 145780e3f24SHeiko Stuebner uint32_t i = 0; 146780e3f24SHeiko Stuebner 147780e3f24SHeiko Stuebner for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) 148780e3f24SHeiko Stuebner slp_data.cru_gate_con[i] = 149780e3f24SHeiko Stuebner mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i)); 150780e3f24SHeiko Stuebner } 151780e3f24SHeiko Stuebner 152780e3f24SHeiko Stuebner void clk_gate_con_disable(void) 153780e3f24SHeiko Stuebner { 154780e3f24SHeiko Stuebner uint32_t i; 155780e3f24SHeiko Stuebner 156780e3f24SHeiko Stuebner for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) 157780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), REG_SOC_WMSK); 158780e3f24SHeiko Stuebner } 159780e3f24SHeiko Stuebner 160780e3f24SHeiko Stuebner void clk_gate_con_restore(void) 161780e3f24SHeiko Stuebner { 162780e3f24SHeiko Stuebner uint32_t i; 163780e3f24SHeiko Stuebner 164780e3f24SHeiko Stuebner for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) 165780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 166780e3f24SHeiko Stuebner REG_SOC_WMSK | slp_data.cru_gate_con[i]); 167780e3f24SHeiko Stuebner } 168780e3f24SHeiko Stuebner 169780e3f24SHeiko Stuebner void clk_sel_con_save(void) 170780e3f24SHeiko Stuebner { 171780e3f24SHeiko Stuebner uint32_t i = 0; 172780e3f24SHeiko Stuebner 173780e3f24SHeiko Stuebner for (i = 0; i < CRU_CLKSELS_CON_CNT; i++) 174780e3f24SHeiko Stuebner slp_data.cru_sel_con[i] = 175780e3f24SHeiko Stuebner mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(i)); 176780e3f24SHeiko Stuebner } 177780e3f24SHeiko Stuebner 178780e3f24SHeiko Stuebner void clk_sel_con_restore(void) 179780e3f24SHeiko Stuebner { 180780e3f24SHeiko Stuebner uint32_t i, val; 181780e3f24SHeiko Stuebner 182780e3f24SHeiko Stuebner for (i = 0; i < CRU_CLKSELS_CON_CNT; i++) { 183780e3f24SHeiko Stuebner /* fractional dividers don't have write-masks */ 184780e3f24SHeiko Stuebner if ((i >= 7 && i <= 9) || 185780e3f24SHeiko Stuebner (i >= 17 && i <= 20) || 186780e3f24SHeiko Stuebner (i == 23) || (i == 41)) 187780e3f24SHeiko Stuebner val = slp_data.cru_sel_con[i]; 188780e3f24SHeiko Stuebner else 189780e3f24SHeiko Stuebner val = slp_data.cru_sel_con[i] | REG_SOC_WMSK; 190780e3f24SHeiko Stuebner 191780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(i), val); 192780e3f24SHeiko Stuebner } 193780e3f24SHeiko Stuebner } 194780e3f24SHeiko Stuebner 195780e3f24SHeiko Stuebner void __dead2 rockchip_soc_soft_reset(void) 196780e3f24SHeiko Stuebner { 197780e3f24SHeiko Stuebner uint32_t temp_val; 198780e3f24SHeiko Stuebner 199780e3f24SHeiko Stuebner /* 200780e3f24SHeiko Stuebner * Switch PLLs other than DPLL (for SDRAM) to slow mode to 201780e3f24SHeiko Stuebner * avoid crashes on resume. The Mask ROM on the system will 202780e3f24SHeiko Stuebner * put APLL, CPLL, and GPLL into slow mode at resume time 203780e3f24SHeiko Stuebner * anyway (which is why we restore them), but we might not 204780e3f24SHeiko Stuebner * even make it to the Mask ROM if this isn't done at suspend 205780e3f24SHeiko Stuebner * time. 206780e3f24SHeiko Stuebner * 207780e3f24SHeiko Stuebner * NOTE: only APLL truly matters here, but we'll do them all. 208780e3f24SHeiko Stuebner */ 209780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000); 210780e3f24SHeiko Stuebner 211780e3f24SHeiko Stuebner temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON); 212780e3f24SHeiko Stuebner temp_val &= ~PMU_RST_MASK; 213780e3f24SHeiko Stuebner temp_val |= PMU_RST_BY_SECOND_SFT; 214780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val); 215780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8); 216780e3f24SHeiko Stuebner 217780e3f24SHeiko Stuebner /* 218780e3f24SHeiko Stuebner * Maybe the HW needs some times to reset the system, 219780e3f24SHeiko Stuebner * so we do not hope the core to excute valid codes. 220780e3f24SHeiko Stuebner */ 221780e3f24SHeiko Stuebner while (1) 222780e3f24SHeiko Stuebner ; 223780e3f24SHeiko Stuebner } 224