diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
commit | 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 (patch) | |
tree | bcf648efac40ca6139842707f0eba5a4496a6dd2 /plat/rockchip/rk3368 | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-upstream.tar.xz arm-trusted-firmware-upstream.zip |
Adding upstream version 2.8.0+dfsg.upstream/2.8.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plat/rockchip/rk3368')
-rw-r--r-- | plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c | 482 | ||||
-rw-r--r-- | plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h | 247 | ||||
-rw-r--r-- | plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S | 17 | ||||
-rw-r--r-- | plat/rockchip/rk3368/drivers/pmu/pmu.c | 373 | ||||
-rw-r--r-- | plat/rockchip/rk3368/drivers/pmu/pmu.h | 207 | ||||
-rw-r--r-- | plat/rockchip/rk3368/drivers/soc/soc.c | 209 | ||||
-rw-r--r-- | plat/rockchip/rk3368/drivers/soc/soc.h | 141 | ||||
-rw-r--r-- | plat/rockchip/rk3368/include/plat.ld.S | 37 | ||||
-rw-r--r-- | plat/rockchip/rk3368/include/plat_sip_calls.h | 12 | ||||
-rw-r--r-- | plat/rockchip/rk3368/include/platform_def.h | 120 | ||||
-rw-r--r-- | plat/rockchip/rk3368/plat_sip_calls.c | 25 | ||||
-rw-r--r-- | plat/rockchip/rk3368/platform.mk | 67 | ||||
-rw-r--r-- | plat/rockchip/rk3368/rk3368_def.h | 116 |
13 files changed, 2053 insertions, 0 deletions
diff --git a/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c new file mode 100644 index 0000000..fa98eb3 --- /dev/null +++ b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> +#include <string.h> + +#include <platform_def.h> + +#include <common/debug.h> +#include <lib/mmio.h> + +#include <ddr_rk3368.h> +#include <pmu.h> +#include <rk3368_def.h> +#include <soc.h> + +/* GRF_SOC_STATUS0 */ +#define DPLL_LOCK (0x1 << 2) + +/* GRF_DDRC0_CON0 */ +#define GRF_DDR_16BIT_EN (((0x1 << 3) << 16) | (0x1 << 3)) +#define GRF_DDR_32BIT_EN (((0x1 << 3) << 16) | (0x0 << 3)) +#define GRF_MOBILE_DDR_EN (((0x1 << 4) << 16) | (0x1 << 4)) +#define GRF_MOBILE_DDR_DISB (((0x1 << 4) << 16) | (0x0 << 4)) +#define GRF_DDR3_EN (((0x1 << 2) << 16) | (0x1 << 2)) +#define GRF_LPDDR2_3_EN (((0x1 << 2) << 16) | (0x0 << 2)) + +/* PMUGRF_SOC_CON0 */ +#define ddrphy_bufferen_io_en(n) ((0x1 << (9 + 16)) | (n << 9)) +#define ddrphy_bufferen_core_en(n) ((0x1 << (8 + 16)) | (n << 8)) + +struct PCTRL_TIMING_TAG { + uint32_t ddrfreq; + uint32_t TOGCNT1U; + uint32_t TINIT; + uint32_t TRSTH; + uint32_t TOGCNT100N; + uint32_t TREFI; + uint32_t TMRD; + uint32_t TRFC; + uint32_t TRP; + uint32_t TRTW; + uint32_t TAL; + uint32_t TCL; + uint32_t TCWL; + uint32_t TRAS; + uint32_t TRC; + uint32_t TRCD; + uint32_t TRRD; + uint32_t TRTP; + uint32_t TWR; + uint32_t TWTR; + uint32_t TEXSR; + uint32_t TXP; + uint32_t TXPDLL; + uint32_t TZQCS; + uint32_t TZQCSI; + uint32_t TDQS; + uint32_t TCKSRE; + uint32_t TCKSRX; + uint32_t TCKE; + uint32_t TMOD; + uint32_t TRSTL; + uint32_t TZQCL; + uint32_t TMRR; + uint32_t TCKESR; + uint32_t TDPD; + uint32_t TREFI_MEM_DDR3; +}; + +struct MSCH_SAVE_REG_TAG { + uint32_t ddrconf; + uint32_t ddrtiming; + uint32_t ddrmode; + uint32_t readlatency; + uint32_t activate; + uint32_t devtodev; +}; + +/* ddr suspend need save reg */ +struct PCTL_SAVE_REG_TAG { + uint32_t SCFG; + uint32_t CMDTSTATEN; + uint32_t MCFG1; + uint32_t MCFG; + uint32_t PPCFG; + struct PCTRL_TIMING_TAG pctl_timing; + /* DFI Control Registers */ + uint32_t DFITCTRLDELAY; + uint32_t DFIODTCFG; + uint32_t DFIODTCFG1; + uint32_t DFIODTRANKMAP; + /* DFI Write Data Registers */ + uint32_t DFITPHYWRDATA; + uint32_t DFITPHYWRLAT; + uint32_t DFITPHYWRDATALAT; + /* DFI Read Data Registers */ + uint32_t DFITRDDATAEN; + uint32_t DFITPHYRDLAT; + /* DFI Update Registers */ + uint32_t DFITPHYUPDTYPE0; + uint32_t DFITPHYUPDTYPE1; + uint32_t DFITPHYUPDTYPE2; + uint32_t DFITPHYUPDTYPE3; + uint32_t DFITCTRLUPDMIN; + uint32_t DFITCTRLUPDMAX; + uint32_t DFITCTRLUPDDLY; + uint32_t DFIUPDCFG; + uint32_t DFITREFMSKI; + uint32_t DFITCTRLUPDI; + /* DFI Status Registers */ + uint32_t DFISTCFG0; + uint32_t DFISTCFG1; + uint32_t DFITDRAMCLKEN; + uint32_t DFITDRAMCLKDIS; + uint32_t DFISTCFG2; + /* DFI Low Power Register */ + uint32_t DFILPCFG0; +}; + +struct DDRPHY_SAVE_REG_TAG { + uint32_t PHY_REG0; + uint32_t PHY_REG1; + uint32_t PHY_REGB; + uint32_t PHY_REGC; + uint32_t PHY_REG11; + uint32_t PHY_REG13; + uint32_t PHY_REG14; + uint32_t PHY_REG16; + uint32_t PHY_REG20; + uint32_t PHY_REG21; + uint32_t PHY_REG26; + uint32_t PHY_REG27; + uint32_t PHY_REG28; + uint32_t PHY_REG30; + uint32_t PHY_REG31; + uint32_t PHY_REG36; + uint32_t PHY_REG37; + uint32_t PHY_REG38; + uint32_t PHY_REG40; + uint32_t PHY_REG41; + uint32_t PHY_REG46; + uint32_t PHY_REG47; + uint32_t PHY_REG48; + uint32_t PHY_REG50; + uint32_t PHY_REG51; + uint32_t PHY_REG56; + uint32_t PHY_REG57; + uint32_t PHY_REG58; + uint32_t PHY_REGDLL; + uint32_t PHY_REGEC; + uint32_t PHY_REGED; + uint32_t PHY_REGEE; + uint32_t PHY_REGEF; + uint32_t PHY_REGFB; + uint32_t PHY_REGFC; + uint32_t PHY_REGFD; + uint32_t PHY_REGFE; +}; + +struct BACKUP_REG_TAG { + uint32_t tag; + uint32_t pctladdr; + struct PCTL_SAVE_REG_TAG pctl; + uint32_t phyaddr; + struct DDRPHY_SAVE_REG_TAG phy; + uint32_t nocaddr; + struct MSCH_SAVE_REG_TAG noc; + uint32_t pllselect; + uint32_t phypllockaddr; + uint32_t phyplllockmask; + uint32_t phyplllockval; + uint32_t pllpdstat; + uint32_t dpllmodeaddr; + uint32_t dpllslowmode; + uint32_t dpllnormalmode; + uint32_t dpllresetaddr; + uint32_t dpllreset; + uint32_t dplldereset; + uint32_t dpllconaddr; + uint32_t dpllcon[4]; + uint32_t dplllockaddr; + uint32_t dplllockmask; + uint32_t dplllockval; + uint32_t ddrpllsrcdivaddr; + uint32_t ddrpllsrcdiv; + uint32_t retendisaddr; + uint32_t retendisval; + uint32_t grfregaddr; + uint32_t grfddrcreg; + uint32_t crupctlphysoftrstaddr; + uint32_t cruresetpctlphy; + uint32_t cruderesetphy; + uint32_t cruderesetpctlphy; + uint32_t physoftrstaddr; + uint32_t endtag; +}; + +static uint32_t ddr_get_phy_pll_freq(void) +{ + uint32_t ret = 0; + uint32_t fb_div, pre_div; + + fb_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC); + fb_div |= (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED) & 0x1) << 8; + + pre_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) & 0xff; + ret = 2 * 24 * fb_div / (4 * pre_div); + + return ret; +} + +static void ddr_copy(uint32_t *pdest, uint32_t *psrc, uint32_t words) +{ + uint32_t i; + + for (i = 0; i < words; i++) + pdest[i] = psrc[i]; +} + +static void ddr_get_dpll_cfg(uint32_t *p) +{ + uint32_t nmhz, NO, NF, NR; + + nmhz = ddr_get_phy_pll_freq(); + if (nmhz <= 150) + NO = 6; + else if (nmhz <= 250) + NO = 4; + else if (nmhz <= 500) + NO = 2; + else + NO = 1; + + NR = 1; + NF = 2 * nmhz * NR * NO / 24; + + p[0] = SET_NR(NR) | SET_NO(NO); + p[1] = SET_NF(NF); + p[2] = SET_NB(NF / 2); +} + +void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr) +{ + struct BACKUP_REG_TAG *p_ddr_reg = (struct BACKUP_REG_TAG *)base_addr; + struct PCTL_SAVE_REG_TAG *pctl_tim = &p_ddr_reg->pctl; + + p_ddr_reg->tag = 0x56313031; + p_ddr_reg->pctladdr = DDR_PCTL_BASE; + p_ddr_reg->phyaddr = DDR_PHY_BASE; + p_ddr_reg->nocaddr = SERVICE_BUS_BASE; + + /* PCTLR */ + ddr_copy((uint32_t *)&pctl_tim->pctl_timing.TOGCNT1U, + (uint32_t *)(DDR_PCTL_BASE + DDR_PCTL_TOGCNT1U), 35); + pctl_tim->pctl_timing.TREFI |= DDR_UPD_REF_ENABLE; + pctl_tim->SCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_SCFG); + pctl_tim->CMDTSTATEN = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_CMDTSTATEN); + pctl_tim->MCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG1); + pctl_tim->MCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG); + pctl_tim->PPCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_PPCFG); + pctl_tim->pctl_timing.ddrfreq = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_TOGCNT1U * 2); + pctl_tim->DFITCTRLDELAY = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLDELAY); + pctl_tim->DFIODTCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIODTCFG); + pctl_tim->DFIODTCFG1 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFIODTCFG1); + pctl_tim->DFIODTRANKMAP = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFIODTRANKMAP); + pctl_tim->DFITPHYWRDATA = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYWRDATA); + pctl_tim->DFITPHYWRLAT = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYWRLAT); + pctl_tim->DFITPHYWRDATALAT = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYWRDATALAT); + pctl_tim->DFITRDDATAEN = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITRDDATAEN); + pctl_tim->DFITPHYRDLAT = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYRDLAT); + pctl_tim->DFITPHYUPDTYPE0 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYUPDTYPE0); + pctl_tim->DFITPHYUPDTYPE1 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYUPDTYPE1); + pctl_tim->DFITPHYUPDTYPE2 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYUPDTYPE2); + pctl_tim->DFITPHYUPDTYPE3 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYUPDTYPE3); + pctl_tim->DFITCTRLUPDMIN = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLUPDMIN); + pctl_tim->DFITCTRLUPDMAX = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLUPDMAX); + pctl_tim->DFITCTRLUPDDLY = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLUPDDLY); + + pctl_tim->DFIUPDCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIUPDCFG); + pctl_tim->DFITREFMSKI = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITREFMSKI); + pctl_tim->DFITCTRLUPDI = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLUPDI); + pctl_tim->DFISTCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG0); + pctl_tim->DFISTCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG1); + pctl_tim->DFITDRAMCLKEN = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITDRAMCLKEN); + pctl_tim->DFITDRAMCLKDIS = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITDRAMCLKDIS); + pctl_tim->DFISTCFG2 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG2); + pctl_tim->DFILPCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFILPCFG0); + + /* PHY */ + p_ddr_reg->phy.PHY_REG0 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG0); + p_ddr_reg->phy.PHY_REG1 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG1); + p_ddr_reg->phy.PHY_REGB = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGB); + p_ddr_reg->phy.PHY_REGC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGC); + p_ddr_reg->phy.PHY_REG11 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG11); + p_ddr_reg->phy.PHY_REG13 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG13); + p_ddr_reg->phy.PHY_REG14 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG14); + p_ddr_reg->phy.PHY_REG16 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG16); + p_ddr_reg->phy.PHY_REG20 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG20); + p_ddr_reg->phy.PHY_REG21 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG21); + p_ddr_reg->phy.PHY_REG26 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG26); + p_ddr_reg->phy.PHY_REG27 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG27); + p_ddr_reg->phy.PHY_REG28 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG28); + p_ddr_reg->phy.PHY_REG30 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG30); + p_ddr_reg->phy.PHY_REG31 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG31); + p_ddr_reg->phy.PHY_REG36 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG36); + p_ddr_reg->phy.PHY_REG37 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG37); + p_ddr_reg->phy.PHY_REG38 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG38); + p_ddr_reg->phy.PHY_REG40 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG40); + p_ddr_reg->phy.PHY_REG41 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG41); + p_ddr_reg->phy.PHY_REG46 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG46); + p_ddr_reg->phy.PHY_REG47 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG47); + p_ddr_reg->phy.PHY_REG48 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG48); + p_ddr_reg->phy.PHY_REG50 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG50); + p_ddr_reg->phy.PHY_REG51 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG51); + p_ddr_reg->phy.PHY_REG56 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG56); + p_ddr_reg->phy.PHY_REG57 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG57); + p_ddr_reg->phy.PHY_REG58 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG58); + p_ddr_reg->phy.PHY_REGDLL = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGDLL); + p_ddr_reg->phy.PHY_REGEC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC); + p_ddr_reg->phy.PHY_REGED = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED); + p_ddr_reg->phy.PHY_REGEE = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE); + p_ddr_reg->phy.PHY_REGEF = 0; + + if (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG2) & 0x2) { + p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REG2C); + p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REG3C); + p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REG4C); + p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REG5C); + } else { + p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGFB); + p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGFC); + p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGFD); + p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGFE); + } + + /* NOC */ + p_ddr_reg->noc.ddrconf = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRCONF); + p_ddr_reg->noc.ddrtiming = mmio_read_32(SERVICE_BUS_BASE + + MSCH_DDRTIMING); + p_ddr_reg->noc.ddrmode = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRMODE); + p_ddr_reg->noc.readlatency = mmio_read_32(SERVICE_BUS_BASE + + MSCH_READLATENCY); + p_ddr_reg->noc.activate = mmio_read_32(SERVICE_BUS_BASE + + MSCH_ACTIVATE); + p_ddr_reg->noc.devtodev = mmio_read_32(SERVICE_BUS_BASE + + MSCH_DEVTODEV); + + p_ddr_reg->pllselect = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) * 0x1; + p_ddr_reg->phypllockaddr = GRF_BASE + GRF_SOC_STATUS0; + p_ddr_reg->phyplllockmask = GRF_DDRPHY_LOCK; + p_ddr_reg->phyplllockval = 0; + + /* PLLPD */ + p_ddr_reg->pllpdstat = pllpdstat; + /* DPLL */ + p_ddr_reg->dpllmodeaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3); + /* slow mode and power on */ + p_ddr_reg->dpllslowmode = DPLL_WORK_SLOW_MODE | DPLL_POWER_DOWN; + p_ddr_reg->dpllnormalmode = DPLL_WORK_NORMAL_MODE; + p_ddr_reg->dpllresetaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3); + p_ddr_reg->dpllreset = DPLL_RESET_CONTROL_NORMAL; + p_ddr_reg->dplldereset = DPLL_RESET_CONTROL_RESET; + p_ddr_reg->dpllconaddr = CRU_BASE + PLL_CONS(DPLL_ID, 0); + + if (p_ddr_reg->pllselect == 0) { + p_ddr_reg->dpllcon[0] = (mmio_read_32(CRU_BASE + + PLL_CONS(DPLL_ID, 0)) + & 0xffff) | + (0xFFFFu << 16); + p_ddr_reg->dpllcon[1] = (mmio_read_32(CRU_BASE + + PLL_CONS(DPLL_ID, 1)) + & 0xffff); + p_ddr_reg->dpllcon[2] = (mmio_read_32(CRU_BASE + + PLL_CONS(DPLL_ID, 2)) + & 0xffff); + p_ddr_reg->dpllcon[3] = (mmio_read_32(CRU_BASE + + PLL_CONS(DPLL_ID, 3)) + & 0xffff) | + (0xFFFFu << 16); + } else { + ddr_get_dpll_cfg(&p_ddr_reg->dpllcon[0]); + } + + p_ddr_reg->pllselect = 0; + p_ddr_reg->dplllockaddr = CRU_BASE + PLL_CONS(DPLL_ID, 1); + p_ddr_reg->dplllockmask = DPLL_STATUS_LOCK; + p_ddr_reg->dplllockval = DPLL_STATUS_LOCK; + + /* SET_DDR_PLL_SRC */ + p_ddr_reg->ddrpllsrcdivaddr = CRU_BASE + CRU_CLKSELS_CON(13); + p_ddr_reg->ddrpllsrcdiv = (mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(13)) + & DDR_PLL_SRC_MASK) + | (DDR_PLL_SRC_MASK << 16); + p_ddr_reg->retendisaddr = PMU_BASE + PMU_PWRMD_COM; + p_ddr_reg->retendisval = PD_PERI_PWRDN_ENABLE; + p_ddr_reg->grfregaddr = GRF_BASE + GRF_DDRC0_CON0; + p_ddr_reg->grfddrcreg = (mmio_read_32(GRF_BASE + GRF_DDRC0_CON0) & + DDR_PLL_SRC_MASK) | + (DDR_PLL_SRC_MASK << 16); + + /* pctl phy soft reset */ + p_ddr_reg->crupctlphysoftrstaddr = CRU_BASE + CRU_SOFTRSTS_CON(10); + p_ddr_reg->cruresetpctlphy = DDRCTRL0_PSRSTN_REQ(1) | + DDRCTRL0_SRSTN_REQ(1) | + DDRPHY0_PSRSTN_REQ(1) | + DDRPHY0_SRSTN_REQ(1); + p_ddr_reg->cruderesetphy = DDRCTRL0_PSRSTN_REQ(1) | + DDRCTRL0_SRSTN_REQ(1) | + DDRPHY0_PSRSTN_REQ(0) | + DDRPHY0_SRSTN_REQ(0); + + p_ddr_reg->cruderesetpctlphy = DDRCTRL0_PSRSTN_REQ(0) | + DDRCTRL0_SRSTN_REQ(0) | + DDRPHY0_PSRSTN_REQ(0) | + DDRPHY0_SRSTN_REQ(0); + + p_ddr_reg->physoftrstaddr = DDR_PHY_BASE + DDR_PHY_REG0; + + p_ddr_reg->endtag = 0xFFFFFFFF; +} + +/* + * "rk3368_ddr_reg_resume_V1.05.bin" is an executable bin which is generated + * by ARM DS5 for resuming ddr controller. If the soc wakes up from system + * suspend, ddr needs to be resumed and the resuming code needs to be run in + * sram. But there is not a way to pointing the resuming code to the PMUSRAM + * when linking .o files of bl31, so we use the + * "rk3368_ddr_reg_resume_V1.05.bin" whose code is position-independent and + * it can be loaded anywhere and run. + */ +static __aligned(4) unsigned int ddr_reg_resume[] = { + #include "rk3368_ddr_reg_resume_V1.05.bin" +}; + +uint32_t ddr_get_resume_code_size(void) +{ + return sizeof(ddr_reg_resume); +} + +uint32_t ddr_get_resume_data_size(void) +{ + return sizeof(struct BACKUP_REG_TAG); +} + +uint32_t *ddr_get_resume_code_base(void) +{ + return (unsigned int *)ddr_reg_resume; +} diff --git a/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h new file mode 100644 index 0000000..6663bcb --- /dev/null +++ b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DDR_RK3368_H +#define DDR_RK3368_H + +#define DDR_PCTL_SCFG 0x0 +#define DDR_PCTL_SCTL 0x4 +#define DDR_PCTL_STAT 0x8 +#define DDR_PCTL_INTRSTAT 0xc + +#define DDR_PCTL_MCMD 0x40 +#define DDR_PCTL_POWCTL 0x44 +#define DDR_PCTL_POWSTAT 0x48 +#define DDR_PCTL_CMDTSTAT 0x4c +#define DDR_PCTL_CMDTSTATEN 0x50 +#define DDR_PCTL_MRRCFG0 0x60 +#define DDR_PCTL_MRRSTAT0 0x64 +#define DDR_PCTL_MRRSTAT1 0x68 +#define DDR_PCTL_MCFG1 0x7c +#define DDR_PCTL_MCFG 0x80 +#define DDR_PCTL_PPCFG 0x84 +#define DDR_PCTL_MSTAT 0x88 +#define DDR_PCTL_LPDDR2ZQCFG 0x8c +#define DDR_PCTL_DTUPDES 0x94 +#define DDR_PCTL_DTUNA 0x98 +#define DDR_PCTL_DTUNE 0x9c +#define DDR_PCTL_DTUPRD0 0xa0 +#define DDR_PCTL_DTUPRD1 0xa4 +#define DDR_PCTL_DTUPRD2 0xa8 +#define DDR_PCTL_DTUPRD3 0xac +#define DDR_PCTL_DTUAWDT 0xb0 +#define DDR_PCTL_TOGCNT1U 0xc0 +#define DDR_PCTL_TINIT 0xc4 +#define DDR_PCTL_TRSTH 0xc8 +#define DDR_PCTL_TOGCNT100N 0xcc +#define DDR_PCTL_TREFI 0xd0 +#define DDR_PCTL_TMRD 0xd4 +#define DDR_PCTL_TRFC 0xd8 +#define DDR_PCTL_TRP 0xdc +#define DDR_PCTL_TRTW 0xe0 +#define DDR_PCTL_TAL 0xe4 +#define DDR_PCTL_TCL 0xe8 +#define DDR_PCTL_TCWL 0xec +#define DDR_PCTL_TRAS 0xf0 +#define DDR_PCTL_TRC 0xf4 +#define DDR_PCTL_TRCD 0xf8 +#define DDR_PCTL_TRRD 0xfc +#define DDR_PCTL_TRTP 0x100 +#define DDR_PCTL_TWR 0x104 +#define DDR_PCTL_TWTR 0x108 +#define DDR_PCTL_TEXSR 0x10c +#define DDR_PCTL_TXP 0x110 +#define DDR_PCTL_TXPDLL 0x114 +#define DDR_PCTL_TZQCS 0x118 +#define DDR_PCTL_TZQCSI 0x11c +#define DDR_PCTL_TDQS 0x120 +#define DDR_PCTL_TCKSRE 0x124 +#define DDR_PCTL_TCKSRX 0x128 +#define DDR_PCTL_TCKE 0x12c +#define DDR_PCTL_TMOD 0x130 +#define DDR_PCTL_TRSTL 0x134 +#define DDR_PCTL_TZQCL 0x138 +#define DDR_PCTL_TMRR 0x13c +#define DDR_PCTL_TCKESR 0x140 +#define DDR_PCTL_TDPD 0x144 +#define DDR_PCTL_TREFI_MEM_DDR3 0x148 +#define DDR_PCTL_ECCCFG 0x180 +#define DDR_PCTL_ECCTST 0x184 +#define DDR_PCTL_ECCCLR 0x188 +#define DDR_PCTL_ECCLOG 0x18c +#define DDR_PCTL_DTUWACTL 0x200 +#define DDR_PCTL_DTURACTL 0x204 +#define DDR_PCTL_DTUCFG 0x208 +#define DDR_PCTL_DTUECTL 0x20c +#define DDR_PCTL_DTUWD0 0x210 +#define DDR_PCTL_DTUWD1 0x214 +#define DDR_PCTL_DTUWD2 0x218 +#define DDR_PCTL_DTUWD3 0x21c +#define DDR_PCTL_DTUWDM 0x220 +#define DDR_PCTL_DTURD0 0x224 +#define DDR_PCTL_DTURD1 0x228 +#define DDR_PCTL_DTURD2 0x22c +#define DDR_PCTL_DTURD3 0x230 +#define DDR_PCTL_DTULFSRWD 0x234 +#define DDR_PCTL_DTULFSRRD 0x238 +#define DDR_PCTL_DTUEAF 0x23c +#define DDR_PCTL_DFITCTRLDELAY 0x240 +#define DDR_PCTL_DFIODTCFG 0x244 +#define DDR_PCTL_DFIODTCFG1 0x248 +#define DDR_PCTL_DFIODTRANKMAP 0x24c +#define DDR_PCTL_DFITPHYWRDATA 0x250 +#define DDR_PCTL_DFITPHYWRLAT 0x254 +#define DDR_PCTL_DFITPHYWRDATALAT 0x258 +#define DDR_PCTL_DFITRDDATAEN 0x260 +#define DDR_PCTL_DFITPHYRDLAT 0x264 +#define DDR_PCTL_DFITPHYUPDTYPE0 0x270 +#define DDR_PCTL_DFITPHYUPDTYPE1 0x274 +#define DDR_PCTL_DFITPHYUPDTYPE2 0x278 +#define DDR_PCTL_DFITPHYUPDTYPE3 0x27c +#define DDR_PCTL_DFITCTRLUPDMIN 0x280 +#define DDR_PCTL_DFITCTRLUPDMAX 0x284 +#define DDR_PCTL_DFITCTRLUPDDLY 0x288 +#define DDR_PCTL_DFIUPDCFG 0x290 +#define DDR_PCTL_DFITREFMSKI 0x294 +#define DDR_PCTL_DFITCTRLUPDI 0x298 +#define DDR_PCTL_DFITRCFG0 0x2ac +#define DDR_PCTL_DFITRSTAT0 0x2b0 +#define DDR_PCTL_DFITRWRLVLEN 0x2b4 +#define DDR_PCTL_DFITRRDLVLEN 0x2b8 +#define DDR_PCTL_DFITRRDLVLGATEEN 0x2bc +#define DDR_PCTL_DFISTSTAT0 0x2c0 +#define DDR_PCTL_DFISTCFG0 0x2c4 +#define DDR_PCTL_DFISTCFG1 0x2c8 +#define DDR_PCTL_DFITDRAMCLKEN 0x2d0 +#define DDR_PCTL_DFITDRAMCLKDIS 0x2d4 +#define DDR_PCTL_DFISTCFG2 0x2d8 +#define DDR_PCTL_DFISTPARCLR 0x2dc +#define DDR_PCTL_DFISTPARLOG 0x2e0 +#define DDR_PCTL_DFILPCFG0 0x2f0 +#define DDR_PCTL_DFITRWRLVLRESP0 0x300 +#define DDR_PCTL_DFITRWRLVLRESP1 0x304 +#define DDR_PCTL_DFITRWRLVLRESP2 0x308 +#define DDR_PCTL_DFITRRDLVLRESP0 0x30c +#define DDR_PCTL_DFITRRDLVLRESP1 0x310 +#define DDR_PCTL_DFITRRDLVLRESP2 0x314 +#define DDR_PCTL_DFITRWRLVLDELAY0 0x318 +#define DDR_PCTL_DFITRWRLVLDELAY1 0x31c +#define DDR_PCTL_DFITRWRLVLDELAY2 0x320 +#define DDR_PCTL_DFITRRDLVLDELAY0 0x324 +#define DDR_PCTL_DFITRRDLVLDELAY1 0x328 +#define DDR_PCTL_DFITRRDLVLDELAY2 0x32c +#define DDR_PCTL_DFITRRDLVLGATEDELAY0 0x330 +#define DDR_PCTL_DFITRRDLVLGATEDELAY1 0x334 +#define DDR_PCTL_DFITRRDLVLGATEDELAY2 0x338 +#define DDR_PCTL_DFITRCMD 0x33c +#define DDR_PCTL_IPVR 0x3f8 +#define DDR_PCTL_IPTR 0x3fc + +/* DDR PHY REG */ +#define DDR_PHY_REG0 0x0 +#define DDR_PHY_REG1 0x4 +#define DDR_PHY_REG2 0x8 +#define DDR_PHY_REG3 0xc +#define DDR_PHY_REG4 0x10 +#define DDR_PHY_REG5 0x14 +#define DDR_PHY_REG6 0x18 +#define DDR_PHY_REGB 0x2c +#define DDR_PHY_REGC 0x30 +#define DDR_PHY_REG11 0x44 +#define DDR_PHY_REG12 0x48 +#define DDR_PHY_REG13 0x4c +#define DDR_PHY_REG14 0x50 +#define DDR_PHY_REG16 0x58 +#define DDR_PHY_REG20 0x80 +#define DDR_PHY_REG21 0x84 +#define DDR_PHY_REG26 0x98 +#define DDR_PHY_REG27 0x9c +#define DDR_PHY_REG28 0xa0 +#define DDR_PHY_REG2C 0xb0 +#define DDR_PHY_REG30 0xc0 +#define DDR_PHY_REG31 0xc4 +#define DDR_PHY_REG36 0xd8 +#define DDR_PHY_REG37 0xdc +#define DDR_PHY_REG38 0xe0 +#define DDR_PHY_REG3C 0xf0 +#define DDR_PHY_REG40 0x100 +#define DDR_PHY_REG41 0x104 +#define DDR_PHY_REG46 0x118 +#define DDR_PHY_REG47 0x11c +#define DDR_PHY_REG48 0x120 +#define DDR_PHY_REG4C 0x130 +#define DDR_PHY_REG50 0x140 +#define DDR_PHY_REG51 0x144 +#define DDR_PHY_REG56 0x158 +#define DDR_PHY_REG57 0x15c +#define DDR_PHY_REG58 0x160 +#define DDR_PHY_REG5C 0x170 +#define DDR_PHY_REGDLL 0x290 +#define DDR_PHY_REGEC 0x3b0 +#define DDR_PHY_REGED 0x3b4 +#define DDR_PHY_REGEE 0x3b8 +#define DDR_PHY_REGEF 0x3bc +#define DDR_PHY_REGF0 0x3c0 +#define DDR_PHY_REGF1 0x3c4 +#define DDR_PHY_REGF2 0x3c8 +#define DDR_PHY_REGFA 0x3e8 +#define DDR_PHY_REGFB 0x3ec +#define DDR_PHY_REGFC 0x3f0 +#define DDR_PHY_REGFD 0x3f4 +#define DDR_PHY_REGFE 0x3f8 +#define DDR_PHY_REGFF 0x3fc + +/* MSCH REG define */ +#define MSCH_COREID 0x0 +#define MSCH_DDRCONF 0x8 +#define MSCH_DDRTIMING 0xc +#define MSCH_DDRMODE 0x10 +#define MSCH_READLATENCY 0x14 +#define MSCH_ACTIVATE 0x38 +#define MSCH_DEVTODEV 0x3c + +#define SET_NR(n) ((0x3f << (8 + 16)) | ((n - 1) << 8)) +#define SET_NO(n) ((0xf << (0 + 16)) | ((n - 1) << 0)) +#define SET_NF(n) ((n - 1) & 0x1fff) +#define SET_NB(n) ((n - 1) & 0xfff) +#define PLLMODE(n) ((0x3 << (8 + 16)) | (n << 8)) + +/* GRF REG define */ +#define GRF_SOC_STATUS0 0x480 +#define GRF_DDRPHY_LOCK (0x1 << 15) +#define GRF_DDRC0_CON0 0x600 + +/* CRU softreset ddr pctl, phy */ +#define DDRMSCH0_SRSTN_REQ(n) (((0x1 << 10) << 16) | (n << 10)) +#define DDRCTRL0_PSRSTN_REQ(n) (((0x1 << 3) << 16) | (n << 3)) +#define DDRCTRL0_SRSTN_REQ(n) (((0x1 << 2) << 16) | (n << 2)) +#define DDRPHY0_PSRSTN_REQ(n) (((0x1 << 1) << 16) | (n << 1)) +#define DDRPHY0_SRSTN_REQ(n) (((0x1 << 0) << 16) | (n << 0)) + +/* CRU_DPLL_CON2 */ +#define DPLL_STATUS_LOCK (1U << 31) + +/* CRU_DPLL_CON3 */ +#define DPLL_POWER_DOWN ((0x1 << (1 + 16)) | (0 << 1)) +#define DPLL_WORK_NORMAL_MODE ((0x3 << (8 + 16)) | (0 << 8)) +#define DPLL_WORK_SLOW_MODE ((0x3 << (8 + 16)) | (1 << 8)) +#define DPLL_RESET_CONTROL_NORMAL ((0x1 << (5 + 16)) | (0x0 << 5)) +#define DPLL_RESET_CONTROL_RESET ((0x1 << (5 + 16)) | (0x1 << 5)) + +/* PMU_PWRDN_CON */ +#define PD_PERI_PWRDN_ENABLE (1 << 13) + +#define DDR_PLL_SRC_MASK 0x13 + +/* DDR_PCTL_TREFI */ +#define DDR_UPD_REF_ENABLE (0X1u << 31) + +uint32_t ddr_get_resume_code_size(void); +uint32_t ddr_get_resume_data_size(void); +uint32_t *ddr_get_resume_code_base(void); +void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr); + +#endif /* DDR_RK3368_H */ diff --git a/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..399f61c --- /dev/null +++ b/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + +.macro func_rockchip_clst_warmboot + /* Nothing to do for rk3368 */ +.endm + +.macro rockchip_clst_warmboot_data + /* Nothing to do for rk3368 */ +.endm diff --git a/plat/rockchip/rk3368/drivers/pmu/pmu.c b/plat/rockchip/rk3368/drivers/pmu/pmu.c new file mode 100644 index 0000000..e277a18 --- /dev/null +++ b/plat/rockchip/rk3368/drivers/pmu/pmu.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <ddr_rk3368.h> +#include <plat_private.h> +#include <pmu.h> +#include <pmu_com.h> +#include <rk3368_def.h> +#include <soc.h> + +DEFINE_BAKERY_LOCK(rockchip_pd_lock); + +static uint32_t cpu_warm_boot_addr; + +void rk3368_flash_l2_b(void) +{ + uint32_t wait_cnt = 0; + + regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b); + dsb(); + + while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) + & BIT(clst_b_l2_flsh_done))) { + wait_cnt++; + if (!(wait_cnt % MAX_WAIT_CONUT)) + WARN("%s:reg %x,wait\n", __func__, + mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); + } + + regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b); +} + +static inline int rk3368_pmu_bus_idle(uint32_t req, uint32_t idle) +{ + uint32_t mask = BIT(req); + uint32_t idle_mask = 0; + uint32_t idle_target = 0; + uint32_t val; + uint32_t wait_cnt = 0; + + switch (req) { + case bus_ide_req_clst_l: + idle_mask = BIT(pmu_idle_ack_cluster_l); + idle_target = (idle << pmu_idle_ack_cluster_l); + break; + + case bus_ide_req_clst_b: + idle_mask = BIT(pmu_idle_ack_cluster_b); + idle_target = (idle << pmu_idle_ack_cluster_b); + break; + + case bus_ide_req_cxcs: + idle_mask = BIT(pmu_idle_ack_cxcs); + idle_target = ((!idle) << pmu_idle_ack_cxcs); + break; + + case bus_ide_req_cci400: + idle_mask = BIT(pmu_idle_ack_cci400); + idle_target = ((!idle) << pmu_idle_ack_cci400); + break; + + case bus_ide_req_gpu: + idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu); + idle_target = (idle << pmu_idle_ack_gpu) | + (idle << pmu_idle_gpu); + break; + + case bus_ide_req_core: + idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core); + idle_target = (idle << pmu_idle_ack_core) | + (idle << pmu_idle_core); + break; + + case bus_ide_req_bus: + idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus); + idle_target = (idle << pmu_idle_ack_bus) | + (idle << pmu_idle_bus); + break; + case bus_ide_req_dma: + idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma); + idle_target = (idle << pmu_idle_ack_dma) | + (idle << pmu_idle_dma); + break; + + case bus_ide_req_peri: + idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri); + idle_target = (idle << pmu_idle_ack_peri) | + (idle << pmu_idle_peri); + break; + + case bus_ide_req_video: + idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video); + idle_target = (idle << pmu_idle_ack_video) | + (idle << pmu_idle_video); + break; + + case bus_ide_req_vio: + idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio); + idle_target = (pmu_idle_ack_vio) | + (idle << pmu_idle_vio); + break; + + case bus_ide_req_alive: + idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive); + idle_target = (idle << pmu_idle_ack_alive) | + (idle << pmu_idle_alive); + break; + + case bus_ide_req_pmu: + idle_mask = BIT(pmu_idle_ack_pmu) | BIT(pmu_idle_pmu); + idle_target = (idle << pmu_idle_ack_pmu) | + (idle << pmu_idle_pmu); + break; + + case bus_ide_req_msch: + idle_mask = BIT(pmu_idle_ack_msch) | BIT(pmu_idle_msch); + idle_target = (idle << pmu_idle_ack_msch) | + (idle << pmu_idle_msch); + break; + + case bus_ide_req_cci: + idle_mask = BIT(pmu_idle_ack_cci) | BIT(pmu_idle_cci); + idle_target = (idle << pmu_idle_ack_cci) | + (idle << pmu_idle_cci); + break; + + default: + ERROR("%s: Unsupported the idle request\n", __func__); + break; + } + + val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ); + if (idle) + val |= mask; + else + val &= ~mask; + + mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val); + + while ((mmio_read_32(PMU_BASE + + PMU_BUS_IDE_ST) & idle_mask) != idle_target) { + wait_cnt++; + if (!(wait_cnt % MAX_WAIT_CONUT)) + WARN("%s:st=%x(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST), + idle_mask); + } + + return 0; +} + +void pmu_scu_b_pwrup(void) +{ + regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b); + rk3368_pmu_bus_idle(bus_ide_req_clst_b, 0); +} + +static void pmu_scu_b_pwrdn(void) +{ + uint32_t wait_cnt = 0; + + if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & + PM_PWRDM_CPUSB_MSK) != PM_PWRDM_CPUSB_MSK) { + ERROR("%s: not all cpus is off\n", __func__); + return; + } + + rk3368_flash_l2_b(); + + regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b); + + while (!(mmio_read_32(PMU_BASE + + PMU_CORE_PWR_ST) & BIT(clst_b_l2_wfi))) { + wait_cnt++; + if (!(wait_cnt % MAX_WAIT_CONUT)) + ERROR("%s:wait cluster-b l2(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); + } + rk3368_pmu_bus_idle(bus_ide_req_clst_b, 1); +} + +static void pmu_sleep_mode_config(void) +{ + uint32_t pwrmd_core, pwrmd_com; + + pwrmd_core = BIT(pmu_mdcr_cpu0_pd) | + BIT(pmu_mdcr_scu_l_pd) | + BIT(pmu_mdcr_l2_flush) | + BIT(pmu_mdcr_l2_idle) | + BIT(pmu_mdcr_clr_clst_l) | + BIT(pmu_mdcr_clr_core) | + BIT(pmu_mdcr_clr_cci) | + BIT(pmu_mdcr_core_pd); + + pwrmd_com = BIT(pmu_mode_en) | + BIT(pmu_mode_sref_enter) | + BIT(pmu_mode_pwr_off); + + regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_l_wkup_en); + regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_b_wkup_en); + regs_updata_bit_clr(PMU_BASE + PMU_WKUP_CFG2, pmu_gpio_wkup_en); + + mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT, CYCL_24M_CNT_MS(2)); + mmio_write_32(PMU_BASE + PMU_PLLRST_CNT, CYCL_24M_CNT_US(100)); + mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_24M_CNT_MS(2)); + mmio_write_32(PMU_BASE + PMU_PWRMD_CORE, pwrmd_core); + mmio_write_32(PMU_BASE + PMU_PWRMD_COM, pwrmd_com); + dsb(); +} + +static void pmu_set_sleep_mode(void) +{ + pmu_sleep_mode_config(); + soc_sleep_config(); + regs_updata_bit_set(PMU_BASE + PMU_PWRMD_CORE, pmu_mdcr_global_int_dis); + regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_glbl_int_dis_b); + pmu_scu_b_pwrdn(); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), + ((uintptr_t)&pmu_cpuson_entrypoint >> + CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), + ((uintptr_t)&pmu_cpuson_entrypoint >> + CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); +} + +static int cpus_id_power_domain(uint32_t cluster, + uint32_t cpu, + uint32_t pd_state, + uint32_t wfie_msk) +{ + uint32_t pd; + uint64_t mpidr; + + if (cluster) + pd = PD_CPUB0 + cpu; + else + pd = PD_CPUL0 + cpu; + + if (pmu_power_domain_st(pd) == pd_state) + return 0; + + if (pd_state == pmu_pd_off) { + mpidr = (cluster << MPIDR_AFF1_SHIFT) | cpu; + if (check_cpu_wfie(mpidr, wfie_msk)) + return -EINVAL; + } + + return pmu_power_domain_ctr(pd, pd_state); +} + +static void nonboot_cpus_off(void) +{ + uint32_t boot_cpu, boot_cluster, cpu; + + boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1()); + boot_cluster = MPIDR_AFFLVL1_VAL(read_mpidr_el1()); + + /* turn off noboot cpus */ + for (cpu = 0; cpu < PLATFORM_CLUSTER0_CORE_COUNT; cpu++) { + if (!boot_cluster && (cpu == boot_cpu)) + continue; + cpus_id_power_domain(0, cpu, pmu_pd_off, CKECK_WFEI_MSK); + } + + for (cpu = 0; cpu < PLATFORM_CLUSTER1_CORE_COUNT; cpu++) { + if (boot_cluster && (cpu == boot_cpu)) + continue; + cpus_id_power_domain(1, cpu, pmu_pd_off, CKECK_WFEI_MSK); + } +} + +void sram_save(void) +{ + /* TODO: support the sdram save for rk3368 SoCs*/ +} + +void sram_restore(void) +{ + /* TODO: support the sdram restore for rk3368 SoCs */ +} + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) +{ + uint32_t cpu, cluster; + uint32_t cpuon_id; + + cpu = MPIDR_AFFLVL0_VAL(mpidr); + cluster = MPIDR_AFFLVL1_VAL(mpidr); + + /* Make sure the cpu is off,Before power up the cpu! */ + cpus_id_power_domain(cluster, cpu, pmu_pd_off, CKECK_WFEI_MSK); + + cpuon_id = (cluster * PLATFORM_CLUSTER0_CORE_COUNT) + cpu; + assert(cpuon_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpuon_id] == 0); + cpuson_flags[cpuon_id] = PMU_CPU_HOTPLUG; + cpuson_entry_point[cpuon_id] = entrypoint; + + /* Switch boot addr to pmusram */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster), + (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + dsb(); + + cpus_id_power_domain(cluster, cpu, pmu_pd_on, CKECK_WFEI_MSK); + + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster), + (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + + return 0; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + return 0; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), + (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), + (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + pm_plls_resume(); + pmu_scu_b_pwrup(); + + return 0; +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + nonboot_cpus_off(); + pmu_set_sleep_mode(); + + return 0; +} + +void rockchip_plat_mmu_el3(void) +{ + /* TODO: support the el3 for rk3368 SoCs */ +} + +void plat_rockchip_pmu_init(void) +{ + uint32_t cpu; + + /* register requires 32bits mode, switch it to 32 bits */ + cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; + + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) + cpuson_flags[cpu] = 0; + + nonboot_cpus_off(); + INFO("%s(%d): pd status %x\n", __func__, __LINE__, + mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); +} diff --git a/plat/rockchip/rk3368/drivers/pmu/pmu.h b/plat/rockchip/rk3368/drivers/pmu/pmu.h new file mode 100644 index 0000000..b4d4807 --- /dev/null +++ b/plat/rockchip/rk3368/drivers/pmu/pmu.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_H +#define PMU_H + +/* Allocate sp reginon in pmusram */ +#define PSRAM_SP_SIZE 0x80 +#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE) + +/***************************************************************************** + * pmu con,reg + *****************************************************************************/ +#define PMU_WKUP_CFG0 0x0 +#define PMU_WKUP_CFG1 0x4 +#define PMU_WKUP_CFG2 0x8 +#define PMU_TIMEOUT_CNT 0x7c +#define PMU_PWRDN_CON 0xc +#define PMU_PWRDN_ST 0x10 +#define PMU_CORE_PWR_ST 0x38 + +#define PMU_PWRMD_CORE 0x14 +#define PMU_PWRMD_COM 0x18 +#define PMU_SFT_CON 0x1c +#define PMU_BUS_IDE_REQ 0x3c +#define PMU_BUS_IDE_ST 0x40 +#define PMU_OSC_CNT 0x48 +#define PMU_PLLLOCK_CNT 0x4c +#define PMU_PLLRST_CNT 0x50 +#define PMU_STABLE_CNT 0x54 +#define PMU_DDRIO_PWR_CNT 0x58 +#define PMU_WKUPRST_CNT 0x5c + +enum pmu_powermode_core { + pmu_mdcr_global_int_dis = 0, + pmu_mdcr_core_src_gt, + pmu_mdcr_clr_cci, + pmu_mdcr_cpu0_pd, + pmu_mdcr_clr_clst_l = 4, + pmu_mdcr_clr_core, + pmu_mdcr_scu_l_pd, + pmu_mdcr_core_pd, + pmu_mdcr_l2_idle = 8, + pmu_mdcr_l2_flush +}; + +/* + * the shift of bits for cores status + */ +enum pmu_core_pwrst_shift { + clstl_cpu_wfe = 2, + clstl_cpu_wfi = 6, + clstb_cpu_wfe = 12, + clstb_cpu_wfi = 16 +}; + +enum pmu_pdid { + PD_CPUL0 = 0, + PD_CPUL1, + PD_CPUL2, + PD_CPUL3, + PD_SCUL, + PD_CPUB0 = 5, + PD_CPUB1, + PD_CPUB2, + PD_CPUB3, + PD_SCUB = 9, + PD_PERI = 13, + PD_VIDEO, + PD_VIO, + PD_GPU0, + PD_GPU1, + PD_END +}; + +enum pmu_bus_ide { + bus_ide_req_clst_l = 0, + bus_ide_req_clst_b, + bus_ide_req_gpu, + bus_ide_req_core, + bus_ide_req_bus = 4, + bus_ide_req_dma, + bus_ide_req_peri, + bus_ide_req_video, + bus_ide_req_vio = 8, + bus_ide_req_res0, + bus_ide_req_cxcs, + bus_ide_req_alive, + bus_ide_req_pmu = 12, + bus_ide_req_msch, + bus_ide_req_cci, + bus_ide_req_cci400 = 15, + bus_ide_req_end +}; + +enum pmu_powermode_common { + pmu_mode_en = 0, + pmu_mode_res0, + pmu_mode_bus_pd, + pmu_mode_wkup_rst, + pmu_mode_pll_pd = 4, + pmu_mode_pwr_off, + pmu_mode_pmu_use_if, + pmu_mode_pmu_alive_use_if, + pmu_mode_osc_dis = 8, + pmu_mode_input_clamp, + pmu_mode_sref_enter, + pmu_mode_ddrc_gt, + pmu_mode_ddrio_ret = 12, + pmu_mode_ddrio_ret_deq, + pmu_mode_clr_pmu, + pmu_mode_clr_alive, + pmu_mode_clr_bus = 16, + pmu_mode_clr_dma, + pmu_mode_clr_msch, + pmu_mode_clr_peri, + pmu_mode_clr_video = 20, + pmu_mode_clr_vio, + pmu_mode_clr_gpu, + pmu_mode_clr_mcu, + pmu_mode_clr_cxcs = 24, + pmu_mode_clr_cci400, + pmu_mode_res1, + pmu_mode_res2, + pmu_mode_res3 = 28, + pmu_mode_mclst +}; + +enum pmu_core_power_st { + clst_l_cpu_wfe = 2, + clst_l_cpu_wfi = 6, + clst_b_l2_flsh_done = 10, + clst_b_l2_wfi = 11, + clst_b_cpu_wfe = 12, + clst_b_cpu_wfi = 16, + mcu_sleeping = 20, +}; + +enum pmu_sft_con { + pmu_sft_acinactm_clst_b = 5, + pmu_sft_l2flsh_clst_b, + pmu_sft_glbl_int_dis_b = 9, + pmu_sft_ddrio_ret_cfg = 11, +}; + +enum pmu_wkup_cfg2 { + pmu_cluster_l_wkup_en = 0, + pmu_cluster_b_wkup_en, + pmu_gpio_wkup_en, + pmu_sdio_wkup_en, + pmu_sdmmc_wkup_en, + pmu_sim_wkup_en, + pmu_timer_wkup_en, + pmu_usbdev_wkup_en, + pmu_sft_wkup_en, + pmu_wdt_mcu_wkup_en, + pmu_timeout_wkup_en, +}; + +enum pmu_bus_idle_st { + pmu_idle_ack_cluster_l = 0, + pmu_idle_ack_cluster_b, + pmu_idle_ack_gpu, + pmu_idle_ack_core, + pmu_idle_ack_bus, + pmu_idle_ack_dma, + pmu_idle_ack_peri, + pmu_idle_ack_video, + pmu_idle_ack_vio, + pmu_idle_ack_cci = 10, + pmu_idle_ack_msch, + pmu_idle_ack_alive, + pmu_idle_ack_pmu, + pmu_idle_ack_cxcs, + pmu_idle_ack_cci400, + pmu_inactive_cluster_l, + pmu_inactive_cluster_b, + pmu_idle_gpu, + pmu_idle_core, + pmu_idle_bus, + pmu_idle_dma, + pmu_idle_peri, + pmu_idle_video, + pmu_idle_vio, + pmu_idle_cci = 26, + pmu_idle_msch, + pmu_idle_alive, + pmu_idle_pmu, + pmu_active_cxcs, + pmu_active_cci, +}; + +#define PM_PWRDM_CPUSB_MSK (0xf << 5) + +#define CKECK_WFE_MSK 0x1 +#define CKECK_WFI_MSK 0x10 +#define CKECK_WFEI_MSK 0x11 + +#define PD_CTR_LOOP 500 +#define CHK_CPU_LOOP 500 + +#define MAX_WAIT_CONUT 1000 + +#endif /* PMU_H */ diff --git a/plat/rockchip/rk3368/drivers/soc/soc.c b/plat/rockchip/rk3368/drivers/soc/soc.c new file mode 100644 index 0000000..7d51bb8 --- /dev/null +++ b/plat/rockchip/rk3368/drivers/soc/soc.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/mmio.h> + +#include <plat_private.h> +#include <rk3368_def.h> +#include <soc.h> + +static uint32_t plls_con[END_PLL_ID][4]; + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_rk_mmap[] = { + MAP_REGION_FLAT(CCI400_BASE, CCI400_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(STIME_BASE, STIME_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMU_BASE, PMU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART0_BASE, UART0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART1_BASE, UART1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART2_BASE, UART2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART3_BASE, UART3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART4_BASE, UART4_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CRU_BASE, CRU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PCTL_BASE, DDR_PCTL_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PHY_BASE, DDR_PHY_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GRF_BASE, GRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SISE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/* The RockChip power domain tree descriptor */ +const unsigned char rockchip_power_domain_tree_desc[] = { + /* No of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* No of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, + /* No of children for the second cluster node */ + PLATFORM_CLUSTER1_CORE_COUNT +}; + +void secure_timer_init(void) +{ + mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT0, 0xffffffff); + mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT1, 0xffffffff); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN); +} + +void sgrf_init(void) +{ + /* setting all configurable ip into no-secure */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SOC_CON_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), SGRF_SOC_CON7_BITS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7), SGRF_SOC_CON_NS); + + /* secure dma to no sesure */ + mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(0), SGRF_BUSDMAC_CON0_NS); + mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(1), SGRF_BUSDMAC_CON1_NS); + dsb(); + + /* rst dma1 */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), + RST_DMA1_MSK | (RST_DMA1_MSK << 16)); + /* rst dma2 */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), + RST_DMA2_MSK | (RST_DMA2_MSK << 16)); + + dsb(); + + /* release dma1 rst*/ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), (RST_DMA1_MSK << 16)); + /* release dma2 rst*/ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), (RST_DMA2_MSK << 16)); +} + +void plat_rockchip_soc_init(void) +{ + secure_timer_init(); + sgrf_init(); +} + +void regs_updata_bits(uintptr_t addr, uint32_t val, + uint32_t mask, uint32_t shift) +{ + uint32_t tmp, orig; + + orig = mmio_read_32(addr); + + tmp = orig & ~(mask << shift); + tmp |= (val & mask) << shift; + + if (tmp != orig) + mmio_write_32(addr, tmp); + dsb(); +} + +static void plls_suspend(uint32_t pll_id) +{ + plls_con[pll_id][0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0)); + plls_con[pll_id][1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1)); + plls_con[pll_id][2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2)); + plls_con[pll_id][3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3)); + + mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_BYPASS); +} + +static void pm_plls_suspend(void) +{ + plls_suspend(NPLL_ID); + plls_suspend(CPLL_ID); + plls_suspend(GPLL_ID); + plls_suspend(ABPLL_ID); + plls_suspend(ALPLL_ID); +} + +static inline void plls_resume(void) +{ + mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3), + plls_con[ABPLL_ID][3] | PLL_BYPASS_W_MSK); + mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3), + plls_con[ALPLL_ID][3] | PLL_BYPASS_W_MSK); + mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3), + plls_con[GPLL_ID][3] | PLL_BYPASS_W_MSK); + mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3), + plls_con[CPLL_ID][3] | PLL_BYPASS_W_MSK); + mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3), + plls_con[NPLL_ID][3] | PLL_BYPASS_W_MSK); +} + +void soc_sleep_config(void) +{ + int i = 0; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000); + pm_plls_suspend(); + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000); +} + +void pm_plls_resume(void) +{ + plls_resume(); + + mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3), + plls_con[ABPLL_ID][3] | PLLS_MODE_WMASK); + mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3), + plls_con[ALPLL_ID][3] | PLLS_MODE_WMASK); + mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3), + plls_con[GPLL_ID][3] | PLLS_MODE_WMASK); + mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3), + plls_con[CPLL_ID][3] | PLLS_MODE_WMASK); + mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3), + plls_con[NPLL_ID][3] | PLLS_MODE_WMASK); +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + uint32_t temp_val; + + mmio_write_32(CRU_BASE + PLL_CONS((GPLL_ID), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((CPLL_ID), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((NPLL_ID), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((ABPLL_ID), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((ALPLL_ID), 3), PLL_SLOW_BITS); + + temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON) | + PMU_RST_BY_SECOND_SFT; + + mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val); + mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8); + + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to excute valid codes. + */ + while (1) + ; +} diff --git a/plat/rockchip/rk3368/drivers/soc/soc.h b/plat/rockchip/rk3368/drivers/soc/soc.h new file mode 100644 index 0000000..6c7a01b --- /dev/null +++ b/plat/rockchip/rk3368/drivers/soc/soc.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +enum plls_id { + ABPLL_ID = 0, + ALPLL_ID, + DPLL_ID, + CPLL_ID, + GPLL_ID, + NPLL_ID, + END_PLL_ID, +}; + +/***************************************************************************** + * secure timer + *****************************************************************************/ +#define TIMER_LOADE_COUNT0 0x00 +#define TIMER_LOADE_COUNT1 0x04 +#define TIMER_CURRENT_VALUE0 0x08 +#define TIMER_CURRENT_VALUE1 0x0C +#define TIMER_CONTROL_REG 0x10 +#define TIMER_INTSTATUS 0x18 + +#define TIMER_EN 0x1 + +#define STIMER1_BASE (STIME_BASE + 0x20) + +#define CYCL_24M_CNT_US(us) (24 * us) +#define CYCL_24M_CNT_MS(ms) (ms * CYCL_24M_CNT_US(1000)) + +/***************************************************************************** + * sgrf reg, offset + *****************************************************************************/ +#define SGRF_SOC_CON(n) (0x0 + (n) * 4) +#define SGRF_BUSDMAC_CON(n) (0x100 + (n) * 4) + +#define SGRF_SOC_CON_NS 0xffff0000 + +/***************************************************************************** + * con6[2]pmusram is security. + * con6[6]stimer is security. + *****************************************************************************/ +#define PMUSRAM_S_SHIFT 2 +#define PMUSRAM_S 1 +#define STIMER_S_SHIFT 6 +#define STIMER_S 1 +#define SGRF_SOC_CON7_BITS ((0xffffu << 16) | \ + (PMUSRAM_S << PMUSRAM_S_SHIFT) | \ + (STIMER_S << STIMER_S_SHIFT)) + +#define SGRF_BUSDMAC_CON0_NS 0xfffcfff8 +#define SGRF_BUSDMAC_CON1_NS 0xffff0fff + +/* + * sgrf_soc_con1~2, mask and offset + */ +#define CPU_BOOT_ADDR_WMASK 0xffff0000 +#define CPU_BOOT_ADDR_ALIGN 16 + +/***************************************************************************** + * cru reg, offset + *****************************************************************************/ +#define CRU_SOFTRST_CON 0x300 +#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4)) +#define CRU_SOFTRSTS_CON_CNT 15 + +#define SOFTRST_DMA1 0x40004 +#define SOFTRST_DMA2 0x10001 + +#define RST_DMA1_MSK 0x4 +#define RST_DMA2_MSK 0x0 + +#define CRU_CLKSEL_CON 0x100 +#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4)) +#define CRU_CLKSEL_CON_CNT 56 + +#define CRU_CLKGATE_CON 0x200 +#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4)) +#define CRU_CLKGATES_CON_CNT 25 + +#define CRU_GLB_SRST_FST 0x280 +#define CRU_GLB_SRST_SND 0x284 +#define CRU_GLB_RST_CON 0x388 + +#define CRU_CONS_GATEID(i) (16 * (i)) +#define GATE_ID(reg, bit) ((reg * 16) + bit) + +#define PMU_RST_BY_SECOND_SFT (BIT(1) << 2) +#define PMU_RST_NOT_BY_SFT (BIT(1) << 2) + +/*************************************************************************** + * pll + ***************************************************************************/ +#define PLL_PWR_DN_MSK (0x1 << 1) +#define PLL_PWR_DN REG_WMSK_BITS(1, 1, 0x1) +#define PLL_PWR_ON REG_WMSK_BITS(0, 1, 0x1) +#define PLL_RESET REG_WMSK_BITS(1, 5, 0x1) +#define PLL_RESET_RESUME REG_WMSK_BITS(0, 5, 0x1) +#define PLL_BYPASS_MSK (0x1 << 0) +#define PLL_BYPASS_W_MSK (PLL_BYPASS_MSK << 16) +#define PLL_BYPASS REG_WMSK_BITS(1, 0, 0x1) +#define PLL_NO_BYPASS REG_WMSK_BITS(0, 0, 0x1) +#define PLL_MODE_SHIFT 8 +#define PLL_MODE_MSK 0x3 +#define PLLS_MODE_WMASK (PLL_MODE_MSK << (16 + PLL_MODE_SHIFT)) +#define PLL_SLOW 0x0 +#define PLL_NORM 0x1 +#define PLL_DEEP 0x2 +#define PLL_SLOW_BITS REG_WMSK_BITS(PLL_SLOW, 8, 0x3) +#define PLL_NORM_BITS REG_WMSK_BITS(PLL_NORM, 8, 0x3) +#define PLL_DEEP_BITS REG_WMSK_BITS(PLL_DEEP, 8, 0x3) + +#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4)) + +#define REG_W_MSK(bits_shift, msk) \ + ((msk) << ((bits_shift) + 16)) +#define REG_VAL_CLRBITS(val, bits_shift, msk) \ + (val & (~(msk << bits_shift))) +#define REG_SET_BITS(bits, bits_shift, msk) \ + (((bits) & (msk)) << (bits_shift)) +#define REG_WMSK_BITS(bits, bits_shift, msk) \ + (REG_W_MSK(bits_shift, msk) | \ + REG_SET_BITS(bits, bits_shift, msk)) + +#define regs_updata_bit_set(addr, shift) \ + regs_updata_bits((addr), 0x1, 0x1, (shift)) +#define regs_updata_bit_clr(addr, shift) \ + regs_updata_bits((addr), 0x0, 0x1, (shift)) + +void regs_updata_bits(uintptr_t addr, uint32_t val, + uint32_t mask, uint32_t shift); +void soc_sleep_config(void); +void pm_plls_resume(void); + +#endif /* SOC_H */ diff --git a/plat/rockchip/rk3368/include/plat.ld.S b/plat/rockchip/rk3368/include/plat.ld.S new file mode 100644 index 0000000..e9bb3a2 --- /dev/null +++ b/plat/rockchip/rk3368/include/plat.ld.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ROCKCHIP_PLAT_LD_S +#define ROCKCHIP_PLAT_LD_S + +MEMORY { + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE +} + +SECTIONS +{ + . = PMUSRAM_BASE; + + /* + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram + */ + .text_pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + *(.pmusram.entry) + __bl31_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl31_pmusram_text_end = .; + __bl31_pmusram_data_start = .; + *(.pmusram.data) + __bl31_pmusram_data_end = .; + + } >PMUSRAM +} + +#endif /* ROCKCHIP_PLAT_LD_S */ diff --git a/plat/rockchip/rk3368/include/plat_sip_calls.h b/plat/rockchip/rk3368/include/plat_sip_calls.h new file mode 100644 index 0000000..66c4868 --- /dev/null +++ b/plat/rockchip/rk3368/include/plat_sip_calls.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +#define RK_PLAT_SIP_NUM_CALLS 0 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/plat/rockchip/rk3368/include/platform_def.h b/plat/rockchip/rk3368/include/platform_def.h new file mode 100644 index 0000000..519a025 --- /dev/null +++ b/plat/rockchip/rk3368/include/platform_def.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <arch.h> +#include <lib/utils_def.h> +#include <plat/common/common_def.h> + +#include <rk3368_def.h> + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL1) +#define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +#define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x800 +#elif defined(IMAGE_BL32) +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_RK_CLST_TO_CPUID_SHIFT 6 + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +/* + * This macro defines the deepest retention state possible. A higher state + * id will represent an invalid or a power down state. + */ +#define PLAT_MAX_RET_STATE U(1) + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE U(2) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* TF text, ro, rw, Size: 1MB */ +#define TZRAM_BASE (0x0) +#define TZRAM_SIZE (0x100000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted RAM + */ +#define BL31_BASE (TZRAM_BASE + 0x40000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 20 + +/******************************************************************************* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + ******************************************************************************/ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Define GICD and GICC and GICR base + */ +#define PLAT_RK_GICD_BASE RK3368_GICD_BASE +#define PLAT_RK_GICC_BASE RK3368_GICC_BASE + +#define PLAT_RK_UART_BASE UART2_BASE +#define PLAT_RK_UART_CLOCK RK3368_UART_CLOCK +#define PLAT_RK_UART_BAUDRATE RK3368_BAUDRATE + +#define PLAT_RK_CCI_BASE CCI400_BASE + +#define PLAT_RK_PRIMARY_CPU 0x0 + +#define PSRAM_DO_DDR_RESUME 0 +#define PSRAM_CHECK_WAKEUP_CPU 0 + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/rockchip/rk3368/plat_sip_calls.c b/plat/rockchip/rk3368/plat_sip_calls.c new file mode 100644 index 0000000..5918d58 --- /dev/null +++ b/plat/rockchip/rk3368/plat_sip_calls.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <common/runtime_svc.h> +#include <lib/mmio.h> + +#include <plat_sip_calls.h> +#include <rockchip_sip_svc.h> + +uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk new file mode 100644 index 0000000..e6c62de --- /dev/null +++ b/plat/rockchip/rk3368/platform.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/arm/gic/v2/gicv2.mk + +RK_PLAT := plat/rockchip +RK_PLAT_SOC := ${RK_PLAT}/${PLAT} +RK_PLAT_COMMON := ${RK_PLAT}/common + +DISABLE_BIN_GENERATION := 1 + +PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/aarch64/ \ + -I${RK_PLAT_COMMON}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ + -I${RK_PLAT_SOC}/drivers/ddr/ \ + -I${RK_PLAT_SOC}/include/ + +RK_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + ${RK_PLAT}/common/rockchip_gicv2.c + +PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + plat/common/aarch64/crash_console_helpers.S \ + plat/common/plat_psci_common.c + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + +BL31_SOURCES += ${RK_GIC_SOURCES} \ + drivers/arm/cci/cci.c \ + drivers/ti/uart/aarch64/16550_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/cpus/aarch64/cortex_a53.S \ + ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ + ${RK_PLAT_COMMON}/bl31_plat_setup.c \ + ${RK_PLAT_COMMON}/params_setup.c \ + ${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S \ + ${RK_PLAT_COMMON}/plat_pm.c \ + ${RK_PLAT_COMMON}/plat_topology.c \ + ${RK_PLAT_COMMON}/aarch64/platform_common.c \ + ${RK_PLAT_COMMON}/rockchip_sip_svc.c \ + ${RK_PLAT_SOC}/plat_sip_calls.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c \ + ${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c \ + +include lib/coreboot/coreboot.mk +include lib/libfdt/libfdt.mk + +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +WORKAROUND_CVE_2017_5715 := 0 diff --git a/plat/rockchip/rk3368/rk3368_def.h b/plat/rockchip/rk3368/rk3368_def.h new file mode 100644 index 0000000..4b0fbab --- /dev/null +++ b/plat/rockchip/rk3368/rk3368_def.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RK3368_DEF_H +#define RK3368_DEF_H + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define CCI400_BASE 0xffb90000 +#define CCI400_SIZE 0x10000 + +#define GIC400_BASE 0xffb70000 +#define GIC400_SIZE 0x10000 + +#define STIME_BASE 0xff830000 +#define STIME_SIZE 0x10000 + +#define CRU_BASE 0xff760000 +#define CRU_SIZE 0x10000 + +#define GRF_BASE 0xff770000 +#define GRF_SIZE 0x10000 + +#define SGRF_BASE 0xff740000 +#define SGRF_SIZE 0x10000 + +#define PMU_BASE 0xff730000 +#define PMU_GRF_BASE 0xff738000 +#define PMU_SIZE 0x10000 + +#define RK_INTMEM_BASE 0xff8c0000 +#define RK_INTMEM_SIZE 0x10000 + +#define UART0_BASE 0xff180000 +#define UART0_SIZE 0x10000 + +#define UART1_BASE 0xff190000 +#define UART1_SIZE 0x10000 + +#define UART2_BASE 0xff690000 +#define UART2_SIZE 0x10000 + +#define UART3_BASE 0xff1b0000 +#define UART3_SIZE 0x10000 + +#define UART4_BASE 0xff1c0000 +#define UART4_SIZE 0x10000 + +#define CRU_BASE 0xff760000 + +#define PMUSRAM_BASE 0xff720000 +#define PMUSRAM_SIZE 0x10000 +#define PMUSRAM_RSIZE 0x1000 + +#define DDR_PCTL_BASE 0xff610000 +#define DDR_PCTL_SIZE 0x10000 + +#define DDR_PHY_BASE 0xff620000 +#define DDR_PHY_SIZE 0x10000 + +#define SERVICE_BUS_BASE 0xffac0000 +#define SERVICE_BUS_SISE 0x50000 + +#define COLD_BOOT_BASE 0xffff0000 +/************************************************************************** + * UART related constants + **************************************************************************/ +#define RK3368_BAUDRATE 115200 +#define RK3368_UART_CLOCK 24000000 + +/****************************************************************************** + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 24000000 + +/****************************************************************************** + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base rk_platform compatible GIC memory map */ +#define RK3368_GICD_BASE (GIC400_BASE + 0x1000) +#define RK3368_GICC_BASE (GIC400_BASE + 0x2000) +#define RK3368_GICR_BASE 0 /* no GICR in GIC-400 */ + +/***************************************************************************** + * CCI-400 related constants + ******************************************************************************/ +#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 3 +#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 4 + +/****************************************************************************** + * sgi, ppi + ******************************************************************************/ +#define RK_IRQ_SEC_PHY_TIMER 29 + +#define RK_IRQ_SEC_SGI_0 8 +#define RK_IRQ_SEC_SGI_1 9 +#define RK_IRQ_SEC_SGI_2 10 +#define RK_IRQ_SEC_SGI_3 11 +#define RK_IRQ_SEC_SGI_4 12 +#define RK_IRQ_SEC_SGI_5 13 +#define RK_IRQ_SEC_SGI_6 14 +#define RK_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 0 interrupts. + */ +#define PLAT_RK_GICV2_G0_IRQS \ + INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL) + +#endif /* RK3368_DEF_H */ |