diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.c b/plat/rockchip/rk3399/drivers/dram/dfs.c index 70d9423..e6d39a1 100644 --- a/plat/rockchip/rk3399/drivers/dram/dfs.c +++ b/plat/rockchip/rk3399/drivers/dram/dfs.c @@ -1964,9 +1964,6 @@ static void m0_configure_ddr(struct pll_div pll_div, uint32_t ddr_index) { - /* set PARAM to M0_FUNC_DRAM */ - mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_DRAM); - mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(pll_div.fbdiv)); mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON1, POSTDIV2(pll_div.postdiv2) | POSTDIV1(pll_div.postdiv1) | @@ -1976,6 +1973,7 @@ mmio_write_32(M0_PARAM_ADDR + PARAM_FREQ_SELECT, ddr_index << 4); dmbst(); + m0_configure_execute_addr(M0_BINCODE_BASE); } static uint32_t prepare_ddr_timing(uint32_t mhz) diff --git a/plat/rockchip/rk3399/drivers/m0/Makefile b/plat/rockchip/rk3399/drivers/m0/Makefile index f6bdbf2..79e09f0 100644 --- a/plat/rockchip/rk3399/drivers/m0/Makefile +++ b/plat/rockchip/rk3399/drivers/m0/Makefile @@ -12,6 +12,7 @@ # Build platform PLAT_M0 ?= rk3399m0 +PLAT_M0_PMU ?= rk3399m0pmu ifeq (${V},0) Q=@ @@ -26,11 +27,10 @@ -I../../include/shared/ # NOTE: Add C source files here -C_SOURCES := src/startup.c \ - src/main.c \ - src/suspend.c \ - src/dram.c \ +C_SOURCES_COMMON := src/startup.c +C_SOURCES := src/dram.c \ src/stopwatch.c +C_SOURCES_PMU := src/suspend.c # Flags definition COMMON_FLAGS := -g -mcpu=$(ARCH) -mthumb -Wall -O3 -nostdlib -mfloat-abi=soft @@ -54,12 +54,19 @@ $(notdir $(patsubst %.S,%.o,$(filter %.S,$(1)))) endef +SOURCES_COMMON := $(C_SOURCES_COMMON) SOURCES := $(C_SOURCES) +SOURCES_PMU := $(C_SOURCES_PMU) +OBJS_COMMON := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_COMMON))) OBJS := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES))) +OBJS_PMU := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_PMU))) LINKERFILE := $(BUILD)/$(PLAT_M0).ld MAPFILE := $(BUILD)/$(PLAT_M0).map +MAPFILE_PMU := $(BUILD)/$(PLAT_M0_PMU).map ELF := $(BUILD)/$(PLAT_M0).elf +ELF_PMU := $(BUILD)/$(PLAT_M0_PMU).elf BIN := $(BUILD)/$(PLAT_M0).bin +BIN_PMU := $(BUILD)/$(PLAT_M0_PMU).bin LINKERFILE_SRC := src/$(PLAT_M0).ld.S # Function definition related compilation @@ -92,18 +99,27 @@ $(and $(REMAIN),$(error Unexpected source files present: $(REMAIN))) endef -.DEFAULT_GOAL := $(BIN) +.PHONY: all +all: $(BIN) $(BIN_PMU) + +.DEFAULT_GOAL := all $(LINKERFILE): $(LINKERFILE_SRC) $(CC) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $< -include $(LINKERFILE).d -$(ELF) : $(OBJS) $(LINKERFILE) +$(ELF) : $(OBJS) $(OBJS_COMMON) $(LINKERFILE) @echo " LD $@" - $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) + $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON) -$(BIN) : $(ELF) +%.bin : %.elf @echo " BIN $@" $(Q)$(OC) -O binary $< $@ +$(ELF_PMU) : $(OBJS_COMMON) $(OBJS_PMU) $(LINKERFILE) + @echo " LD $@" + $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON) + +$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_COMMON),$(1))) $(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES),$(1))) +$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_PMU),$(1))) diff --git a/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h b/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h index 472cbc9..176af3a 100644 --- a/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h +++ b/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h @@ -25,8 +25,6 @@ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) -void handle_suspend(void); -void handle_dram(void); void stopwatch_init_usecs_expire(unsigned int usecs); int stopwatch_expired(void); void stopwatch_reset(void); diff --git a/plat/rockchip/rk3399/drivers/m0/src/dram.c b/plat/rockchip/rk3399/drivers/m0/src/dram.c index c6a9259..b939a96 100644 --- a/plat/rockchip/rk3399/drivers/m0/src/dram.c +++ b/plat/rockchip/rk3399/drivers/m0/src/dram.c @@ -55,7 +55,7 @@ mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_NORMAL_MODE)); } -void handle_dram(void) +__attribute__((noreturn)) void main(void) { mmio_setbits_32(PHY_REG(0, 927), (1 << 22)); mmio_setbits_32(PHY_REG(1, 927), (1 << 22)); @@ -76,4 +76,9 @@ deidle_port(); mmio_clrbits_32(PHY_REG(0, 927), (1 << 22)); mmio_clrbits_32(PHY_REG(1, 927), (1 << 22)); + + mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG); + + for (;;) + __asm__ volatile ("wfi"); } diff --git a/plat/rockchip/rk3399/drivers/m0/src/main.c b/plat/rockchip/rk3399/drivers/m0/src/main.c deleted file mode 100644 index 0ed818d..0000000 --- a/plat/rockchip/rk3399/drivers/m0/src/main.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include "rk3399_mcu.h" - -__attribute__((noreturn)) void main(void) -{ - switch (mmio_read_32(PARAM_ADDR + PARAM_M0_FUNC)) { - case M0_FUNC_SUSPEND: - handle_suspend(); - break; - case M0_FUNC_DRAM: - handle_dram(); - break; - default: - break; - } - - mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG); - - for (;;) - __asm__ volatile ("wfi"); -} diff --git a/plat/rockchip/rk3399/drivers/m0/src/startup.c b/plat/rockchip/rk3399/drivers/m0/src/startup.c index 68f5b2d..dba0313 100644 --- a/plat/rockchip/rk3399/drivers/m0/src/startup.c +++ b/plat/rockchip/rk3399/drivers/m0/src/startup.c @@ -7,7 +7,7 @@ #include "rk3399_mcu.h" /* Stack configuration */ -#define STACK_SIZE 0x00000100 +#define STACK_SIZE 0x00000040 __attribute__ ((section(".co_stack"))) unsigned long pstack[STACK_SIZE]; diff --git a/plat/rockchip/rk3399/drivers/m0/src/suspend.c b/plat/rockchip/rk3399/drivers/m0/src/suspend.c index af29a11..39dfd11 100644 --- a/plat/rockchip/rk3399/drivers/m0/src/suspend.c +++ b/plat/rockchip/rk3399/drivers/m0/src/suspend.c @@ -11,18 +11,52 @@ #define SCR_SLEEPDEEP_SHIFT (1 << 2) -void handle_suspend(void) +__attribute__((noreturn)) void main(void) { unsigned int status_value; + /* + * PMU sometimes doesn't clear power mode bit as it's supposed to due + * to a hardware bug. Make the M0 clear it manually to be sure, + * otherwise interrupts some cases with concurrent wake interrupts + * we stay asleep forever. + */ while (1) { status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST); if (status_value) { mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01); - return; + break; } } - /* m0 enter deep sleep mode */ - mmio_setbits_32(M0_SCR, SCR_SLEEPDEEP_SHIFT); + /* + * FSM power secquence is .. -> ST_INPUT_CLAMP(step.17) -> .. -> + * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP -> + * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> .., + * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by + * power or other single glitch, but WAKEUP_RESET need work with 24MHz, + * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance + * that glitch will affect SOC, and mess up SOC status, so we + * addressmap_shared software clamp between ST_INPUT_CLAMP and + * ST_WAKEUP_RESET_CLR to avoid this happen. + */ + while (1) { + status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST); + if (status_value >= 17) { + mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02); + break; + } + + } + + while (1) { + status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST); + if (status_value >= 26) { + mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02); + break; + } + } + + for (;;) + __asm__ volatile ("wfi"); } diff --git a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c index 61849e5..3f258b7 100644 --- a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c +++ b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c @@ -21,14 +21,6 @@ mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7)); mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), WMSK_BIT(12)); - /* set the execute address for M0 */ - mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3), - BITS_WITH_WMASK((M0_BINCODE_BASE >> 12) & 0xffff, - 0xffff, 0)); - mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7), - BITS_WITH_WMASK((M0_BINCODE_BASE >> 28) & 0xf, - 0xf, 0)); - /* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */ mmio_setbits_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, 0x02); @@ -46,6 +38,17 @@ mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, WMSK_BIT(5)); } +void m0_configure_execute_addr(uintptr_t addr) +{ + /* set the execute address for M0 */ + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3), + BITS_WITH_WMASK((addr >> 12) & 0xffff, + 0xffff, 0)); + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7), + BITS_WITH_WMASK((addr >> 28) & 0xf, + 0xf, 0)); +} + void m0_start(void) { /* enable clocks for M0 */ diff --git a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h index b313ec6..cb323c4 100644 --- a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h +++ b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h @@ -11,13 +11,18 @@ #define M0_BINCODE_BASE ((uintptr_t)rk3399m0_bin) #define M0_PARAM_ADDR (M0_BINCODE_BASE + PARAM_ADDR) +#define M0PMU_BINCODE_BASE ((uintptr_t)rk3399m0pmu_bin) /* pmu_fw.c */ extern char rk3399m0_bin[]; extern char rk3399m0_bin_end[]; +extern char rk3399m0pmu_bin[]; +extern char rk3399m0pmu_bin_end[]; + extern void m0_init(void); extern void m0_start(void); extern void m0_stop(void); extern void m0_wait_done(void); +extern void m0_configure_execute_addr(uintptr_t addr); #endif /* __M0_CTL_H__ */ diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index 014d404..e136bbc 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -1064,12 +1064,6 @@ } } -static void m0_configure_suspend(void) -{ - /* set PARAM to M0_FUNC_SUSPEND */ - mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_SUSPEND); -} - void sram_save(void) { size_t text_size = (char *)&__bl31_sram_text_real_end - @@ -1344,7 +1338,7 @@ set_pmu_rsthold(); sys_slp_config(); - m0_configure_suspend(); + m0_configure_execute_addr(M0PMU_BINCODE_BASE); m0_start(); pmu_sgrf_rst_hld(); diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c b/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c index d299116..a09ad21 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c @@ -5,9 +5,9 @@ */ /* convoluted way to make sure that the define is pasted just the right way */ -#define _INCBIN(file, sym) \ +#define _INCBIN(file, sym, sec) \ __asm__( \ - ".section .sram.incbin\n" \ + ".section " #sec "\n" \ ".global " #sym "\n" \ ".type " #sym ", %object\n" \ ".align 4\n" \ @@ -18,6 +18,7 @@ #sym "_end:\n" \ ) -#define INCBIN(file, sym) _INCBIN(file, sym) +#define INCBIN(file, sym, sec) _INCBIN(file, sym, sec) -INCBIN(RK3399M0FW, rk3399m0_bin); +INCBIN(RK3399M0FW, rk3399m0_bin, ".sram.incbin"); +INCBIN(RK3399M0PMUFW, rk3399m0pmu_bin, ".pmusram.incbin"); diff --git a/plat/rockchip/rk3399/include/plat.ld.S b/plat/rockchip/rk3399/include/plat.ld.S index 85f4dc3..528c150 100644 --- a/plat/rockchip/rk3399/include/plat.ld.S +++ b/plat/rockchip/rk3399/include/plat.ld.S @@ -77,14 +77,21 @@ ASSERT(. == ALIGN(64 * 1024), ".pmusram.entry request 64K aligned."); *(.pmusram.entry) + __bl31_pmusram_text_start = .; *(.pmusram.text) *(.pmusram.rodata) __bl31_pmusram_text_end = .; + + /* M0 start address request 4K align */ + . = ALIGN(4096); + __pmusram_incbin_start = .; + *(.pmusram.incbin) + __pmusram_incbin_end = .; + __bl31_pmusram_data_start = .; *(.pmusram.data) __bl31_pmusram_data_end = .; - } >PMUSRAM } diff --git a/plat/rockchip/rk3399/include/shared/m0_param.h b/plat/rockchip/rk3399/include/shared/m0_param.h index 3edbf89..044e797 100644 --- a/plat/rockchip/rk3399/include/shared/m0_param.h +++ b/plat/rockchip/rk3399/include/shared/m0_param.h @@ -7,13 +7,6 @@ #ifndef __M0_PARAM_H__ #define __M0_PARAM_H__ -#ifndef __LINKER__ -enum { - M0_FUNC_SUSPEND = 0, - M0_FUNC_DRAM = 1, -}; -#endif /* __LINKER__ */ - #define PARAM_ADDR 0xc0 #define PARAM_M0_FUNC 0x00 diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index 1997dfc..fc386f0 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -82,12 +82,15 @@ RK3399M0FW=${BUILD_M0}/${PLAT_M0}.bin $(eval $(call add_define,RK3399M0FW)) +RK3399M0PMUFW=${BUILD_M0}/${PLAT_M0}pmu.bin +$(eval $(call add_define,RK3399M0PMUFW)) + HDCPFW=${RK_PLAT_SOC}/drivers/dp/hdcp.bin $(eval $(call add_define,HDCPFW)) # CCACHE_EXTRAFILES is needed because ccache doesn't handle .incbin export CCACHE_EXTRAFILES -${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW) +${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW):$(RK3399M0PMUFW) ${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c: $(RK3399M0FW) ${BUILD_PLAT}/bl31/cdn_dp.o: CCACHE_EXTRAFILES=$(HDCPFW)