From 32e9fc1a325952738af33b2b3e73fd0448636034 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 24 May 2017 08:47:49 +0800 Subject: [PATCH] hikey: support BL2 BL2 is used to load BL31 and SCP_BL2. In HiKey platform, SCP_BL2 is the mcu firmware that is used to scale cpu frequency and switch low power mode. Change-Id: I1621aa65bea989fd125ee8502fd56ef72362bf97 Signed-off-by: Haojian Zhuang Signed-off-by: Dan Handley --- plat/hisilicon/hikey/hikey_bl2_setup.c | 315 ++++++ plat/hisilicon/hikey/hikey_ddr.c | 967 +++++++++++++++++++ plat/hisilicon/hikey/hisi_dvfs.c | 778 +++++++++++++++ plat/hisilicon/hikey/hisi_mcu.c | 203 ++++ plat/hisilicon/hikey/include/hisi_mcu.h | 16 + plat/hisilicon/hikey/include/hisi_sram_map.h | 327 +++++++ plat/hisilicon/hikey/platform.mk | 17 + 7 files changed, 2623 insertions(+) create mode 100644 plat/hisilicon/hikey/hikey_bl2_setup.c create mode 100644 plat/hisilicon/hikey/hikey_ddr.c create mode 100644 plat/hisilicon/hikey/hisi_dvfs.c create mode 100644 plat/hisilicon/hikey/hisi_mcu.c create mode 100644 plat/hisilicon/hikey/include/hisi_mcu.h create mode 100644 plat/hisilicon/hikey/include/hisi_sram_map.h diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c new file mode 100644 index 00000000..9e9909b9 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_bl2_setup.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hikey_def.h" +#include "hikey_private.h" + +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +#define BL2_RO_BASE (unsigned long)(&__RO_START__) +#define BL2_RO_LIMIT (unsigned long)(&__RO_END__) + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to + * page-aligned addresses. + */ +#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) +#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) + +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +typedef struct bl2_to_bl31_params_mem { + bl31_params_t bl31_params; + image_info_t bl31_image_info; + image_info_t bl32_image_info; + image_info_t bl33_image_info; + entry_point_info_t bl33_ep_info; + entry_point_info_t bl32_ep_info; + entry_point_info_t bl31_ep_info; +} bl2_to_bl31_params_mem_t; + +static bl2_to_bl31_params_mem_t bl31_params_mem; + +meminfo_t *bl2_plat_sec_mem_layout(void) +{ + return &bl2_tzram_layout; +} + +void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo) +{ + scp_bl2_meminfo->total_base = SCP_BL2_BASE; + scp_bl2_meminfo->total_size = SCP_BL2_SIZE; + scp_bl2_meminfo->free_base = SCP_BL2_BASE; + scp_bl2_meminfo->free_size = SCP_BL2_SIZE; +} + +int bl2_plat_handle_scp_bl2(struct image_info *scp_bl2_image_info) +{ + /* Enable MCU SRAM */ + hisi_mcu_enable_sram(); + + /* Load MCU binary into SRAM */ + hisi_mcu_load_image(scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + /* Let MCU running */ + hisi_mcu_start_run(); + + INFO("%s: MCU PC is at 0x%x\n", + __func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2)); + INFO("%s: AO_SC_PERIPH_CLKSTAT4 is 0x%x\n", + __func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4)); + return 0; +} + +bl31_params_t *bl2_plat_get_bl31_params(void) +{ + bl31_params_t *bl2_to_bl31_params = NULL; + + /* + * Initialise the memory for all the arguments that needs to + * be passed to BL3-1 + */ + memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t)); + + /* Assign memory for TF related information */ + bl2_to_bl31_params = &bl31_params_mem.bl31_params; + SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0); + + /* Fill BL3-1 related information */ + bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); + + /* Fill BL3-2 related information if it exists */ +#if BL32_BASE + bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP, + VERSION_1, 0); + bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); +#endif + + /* Fill BL3-3 related information */ + bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info, + PARAM_EP, VERSION_1, 0); + + /* BL3-3 expects to receive the primary CPU MPID (through x0) */ + bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr(); + + bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); + + return bl2_to_bl31_params; +} + +struct entry_point_info *bl2_plat_get_bl31_ep_info(void) +{ + return &bl31_params_mem.bl31_ep_info; +} + +void bl2_plat_set_bl31_ep_info(image_info_t *image, + entry_point_info_t *bl31_ep_info) +{ + SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE); + bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} + +void bl2_plat_set_bl33_ep_info(image_info_t *image, + entry_point_info_t *bl33_ep_info) +{ + unsigned long el_status; + unsigned int mode; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + if (el_status) + mode = MODE_EL2; + else + mode = MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE); +} + +void bl2_plat_flush_bl31_params(void) +{ + flush_dcache_range((unsigned long)&bl31_params_mem, + sizeof(bl2_to_bl31_params_mem_t)); +} + +void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo) +{ + bl33_meminfo->total_base = DDR_BASE; + bl33_meminfo->total_size = DDR_SIZE; + bl33_meminfo->free_base = DDR_BASE; + bl33_meminfo->free_size = DDR_SIZE; +} + +static void reset_dwmmc_clk(void) +{ + unsigned int data; + + /* disable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (data & PERI_CLK0_MMC0); + /* enable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & PERI_CLK0_MMC0)); + /* reset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0); + + /* bypass mmc0 clock phase */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL2); + data |= 3; + mmio_write_32(PERI_SC_PERIPH_CTRL2, data); + + /* disable low power */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL13); + data |= 1 << 3; + mmio_write_32(PERI_SC_PERIPH_CTRL13, data); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (!(data & PERI_RST0_MMC0)); + + /* unreset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (data & PERI_RST0_MMC0); +} + +static void hikey_boardid_init(void) +{ + u_register_t midr; + + midr = read_midr(); + mmio_write_32(MEMORY_AXI_CHIP_ADDR, midr); + INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR, + (unsigned int)midr); + + mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0); + mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b); + + mmio_write_32(ACPU_ARM64_FLAGA, 0x1234); + mmio_write_32(ACPU_ARM64_FLAGB, 0x5678); +} + +static void hikey_sd_init(void) +{ + /* switch pinmux to SD */ + mmio_write_32(IOMG_SD_CLK, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_CMD, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA0, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA1, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA2, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA3, IOMG_MUX_FUNC0); + + mmio_write_32(IOCG_SD_CLK, IOCG_INPUT_16MA); + mmio_write_32(IOCG_SD_CMD, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA0, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA1, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA2, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA3, IOCG_INPUT_12MA); + + /* set SD Card detect as nopull */ + mmio_write_32(IOCG_GPIO8, 0); +} + +static void hikey_jumper_init(void) +{ + /* set jumper detect as nopull */ + mmio_write_32(IOCG_GPIO24, 0); + /* set jumper detect as GPIO */ + mmio_write_32(IOMG_GPIO24, IOMG_MUX_FUNC0); +} + +void bl2_early_platform_setup(meminfo_t *mem_layout) +{ + dw_mmc_params_t params; + + /* Initialize the console to provide early debug support */ + console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; + + /* Clear SRAM since it'll be used by MCU right now. */ + memset((void *)SRAM_BASE, 0, SRAM_SIZE); + + sp804_timer_init(SP804_TIMER0_BASE, 10, 192); + dsb(); + hikey_ddr_init(); + + hikey_boardid_init(); + init_acpu_dvfs(); + hikey_sd_init(); + hikey_jumper_init(); + + reset_dwmmc_clk(); + memset(¶ms, 0, sizeof(dw_mmc_params_t)); + params.reg_base = DWMMC0_BASE; + params.desc_base = HIKEY_MMC_DESC_BASE; + params.desc_size = 1 << 20; + params.clk_rate = 24 * 1000 * 1000; + params.bus_width = EMMC_BUS_WIDTH_8; + params.flags = EMMC_FLAG_CMD23; + dw_mmc_init(¶ms); + + hikey_io_setup(); +} + +void bl2_plat_arch_setup(void) +{ + hikey_init_mmu_el1(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + BL2_RO_BASE, + BL2_RO_LIMIT, + BL2_COHERENT_RAM_BASE, + BL2_COHERENT_RAM_LIMIT); +} + +void bl2_platform_setup(void) +{ +} diff --git a/plat/hisilicon/hikey/hikey_ddr.c b/plat/hisilicon/hikey/hikey_ddr.c new file mode 100644 index 00000000..6328eb69 --- /dev/null +++ b/plat/hisilicon/hikey/hikey_ddr.c @@ -0,0 +1,967 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +enum { + DDR_FREQ_533M = 0, + DDR_FREQ_800M, +}; + +static void init_pll(void) +{ + unsigned int data; + + data = mmio_read_32((0xf7032000 + 0x000)); + data |= 0x1; + mmio_write_32((0xf7032000 + 0x000), data); + dsb(); + do { + data = mmio_read_32((0xf7032000 + 0x000)); + } while (!(data & (1 << 28))); + + data = mmio_read_32((0xf7800000 + 0x000)); + data &= ~0x007; + data |= 0x004; + mmio_write_32((0xf7800000 + 0x000), data); + dsb(); + do { + data = mmio_read_32((0xf7800000 + 0x014)); + data &= 0x007; + } while (data != 0x004); + + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101); + data = mmio_read_32(PERI_SC_PERIPH_STAT1); + mmio_write_32(0xf7032000 + 0x02c, 0x5110103e); + data = mmio_read_32(0xf7032000 + 0x050); + data |= 1 << 28; + mmio_write_32(0xf7032000 + 0x050, data); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101); + mdelay(1); + data = mmio_read_32(PERI_SC_PERIPH_STAT1); + NOTICE("syspll frequency:%dHz\n", data); +} + +static void init_freq(void) +{ + unsigned int data, tmp; + unsigned int cpuext_cfg, ddr_cfg; + + mmio_write_32((0xf7032000 + 0x374), 0x4a); + mmio_write_32((0xf7032000 + 0x368), 0xda); + mmio_write_32((0xf7032000 + 0x36c), 0x01); + mmio_write_32((0xf7032000 + 0x370), 0x01); + mmio_write_32((0xf7032000 + 0x360), 0x60); + mmio_write_32((0xf7032000 + 0x364), 0x60); + + mmio_write_32((0xf7032000 + 0x114), 0x1000); + + data = mmio_read_32((0xf7032000 + 0x110)); + data |= (3 << 12); + mmio_write_32((0xf7032000 + 0x110), data); + + data = mmio_read_32((0xf7032000 + 0x110)); + data |= (1 << 4); + mmio_write_32((0xf7032000 + 0x110), data); + + + data = mmio_read_32((0xf7032000 + 0x110)); + data &= ~0x7; + data |= 0x5; + mmio_write_32((0xf7032000 + 0x110), data); + dsb(); + mdelay(10); + + + do { + data = mmio_read_32((0xf6504000 + 0x008)); + data &= (3 << 20); + } while (data != (3 << 20)); + dsb(); + mdelay(10); + + + data = mmio_read_32((0xf6504000 + 0x054)); + data &= ~((1 << 0) | (1 << 11)); + mmio_write_32((0xf6504000 + 0x054), data); + mdelay(10); + + data = mmio_read_32((0xf7032000 + 0x104)); + data &= ~(3 << 8); + data |= (1 << 8); + mmio_write_32((0xf7032000 + 0x104), data); + + data = mmio_read_32((0xf7032000 + 0x100)); + data |= (1 << 0); + mmio_write_32((0xf7032000 + 0x100), data); + dsb(); + + do { + data = mmio_read_32((0xf7032000 + 0x100)); + data &= (1 << 2); + } while (data != (1 << 2)); + + data = mmio_read_32((0xf6504000 + 0x06c)); + data &= ~0xffff; + data |= 0x56; + mmio_write_32((0xf6504000 + 0x06c), data); + + data = mmio_read_32((0xf6504000 + 0x06c)); + data &= ~(0xffffff << 8); + data |= 0xc7a << 8; + mmio_write_32((0xf6504000 + 0x06c), data); + + data = mmio_read_32((0xf6504000 + 0x058)); + data &= ((1 << 13) - 1); + data |= 0xccb; + mmio_write_32((0xf6504000 + 0x058), data); + + mmio_write_32((0xf6504000 + 0x060), 0x1fff); + mmio_write_32((0xf6504000 + 0x064), 0x1ffffff); + mmio_write_32((0xf6504000 + 0x068), 0x7fffffff); + mmio_write_32((0xf6504000 + 0x05c), 0x1); + + data = mmio_read_32((0xf6504000 + 0x054)); + data &= ~(0xf << 12); + data |= 1 << 12; + mmio_write_32((0xf6504000 + 0x054), data); + dsb(); + + + data = mmio_read_32((0xf7032000 + 0x000)); + data &= ~(1 << 0); + mmio_write_32((0xf7032000 + 0x000), data); + + mmio_write_32((0xf7032000 + 0x004), 0x5110207d); + mmio_write_32((0xf7032000 + 0x134), 0x10000005); + data = mmio_read_32((0xf7032000 + 0x134)); + + + data = mmio_read_32((0xf7032000 + 0x000)); + data |= (1 << 0); + mmio_write_32((0xf7032000 + 0x000), data); + + mmio_write_32((0xf7032000 + 0x368), 0x100da); + data = mmio_read_32((0xf7032000 + 0x378)); + data &= ~((1 << 7) - 1); + data |= 0x6b; + mmio_write_32((0xf7032000 + 0x378), data); + dsb(); + do { + data = mmio_read_32((0xf7032000 + 0x378)); + tmp = data & 0x7f; + data = (data & (0x7f << 8)) >> 8; + if (data != tmp) + continue; + data = mmio_read_32((0xf7032000 + 0x37c)); + } while (!(data & 1)); + + data = mmio_read_32((0xf7032000 + 0x104)); + data &= ~((3 << 0) | + (3 << 8)); + cpuext_cfg = 1; + ddr_cfg = 1; + data |= cpuext_cfg | (ddr_cfg << 8); + mmio_write_32((0xf7032000 + 0x104), data); + dsb(); + + do { + data = mmio_read_32((0xf7032000 + 0x104)); + tmp = (data & (3 << 16)) >> 16; + if (cpuext_cfg != tmp) + continue; + tmp = (data & (3 << 24)) >> 24; + if (ddr_cfg != tmp) + continue; + data = mmio_read_32((0xf7032000 + 0x000)); + data &= 1 << 28; + } while (!data); + + data = mmio_read_32((0xf7032000 + 0x100)); + data &= ~(1 << 0); + mmio_write_32((0xf7032000 + 0x100), data); + dsb(); + do { + data = mmio_read_32((0xf7032000 + 0x100)); + data &= (1 << 1); + } while (data != (1 << 1)); + mdelay(1000); + + data = mmio_read_32((0xf6504000 + 0x054)); + data &= ~(1 << 28); + mmio_write_32((0xf6504000 + 0x054), data); + dsb(); + + data = mmio_read_32((0xf7032000 + 0x110)); + data &= ~((1 << 4) | + (3 << 12)); + mmio_write_32((0xf7032000 + 0x110), data); +} + +int cat_533mhz_800mhz(void) +{ + unsigned int data, i; + unsigned int bdl[5]; + + + data = mmio_read_32((0xf712c000 + 0x1c8)); + data &= 0xfffff0f0; + data |= 0x100f0f; + mmio_write_32((0xf712c000 + 0x1c8), data); + + for (i = 0; i < 0x20; i++) { + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + data = (i << 0x10) + i; + mmio_write_32((0xf712c000 + 0x140), data); + mmio_write_32((0xf712c000 + 0x144), data); + mmio_write_32((0xf712c000 + 0x148), data); + mmio_write_32((0xf712c000 + 0x14c), data); + mmio_write_32((0xf712c000 + 0x150), data); + + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xfff7ffff; + mmio_write_32((0xf712c000 + 0x070), data); + + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x801); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (!(data & 0x400)) { + mdelay(10); + return 0; + } + WARN("lpddr3 cat fail\n"); + data = mmio_read_32((0xf712c000 + 0x1d4)); + if ((data & 0x1f00) && ((data & 0x1f) == 0)) { + bdl[0] = mmio_read_32((0xf712c000 + 0x140)); + bdl[1] = mmio_read_32((0xf712c000 + 0x144)); + bdl[2] = mmio_read_32((0xf712c000 + 0x148)); + bdl[3] = mmio_read_32((0xf712c000 + 0x14c)); + bdl[4] = mmio_read_32((0xf712c000 + 0x150)); + if ((!(bdl[0] & 0x1f001f)) || (!(bdl[1] & 0x1f001f)) || + (!(bdl[2] & 0x1f001f)) || (!(bdl[3] & 0x1f001f)) || + (!(bdl[4] & 0x1f001f))) { + WARN("lpddr3 cat deskew error\n"); + if (i == 0x1f) { + WARN("addrnbdl is max\n"); + return -EINVAL; + } + mmio_write_32((0xf712c000 + 0x008), 0x400); + } else { + WARN("lpddr3 cat other error1\n"); + return -EINVAL; + } + } else { + WARN("lpddr3 cat other error2\n"); + return -EINVAL; + } + } + return -EINVAL; +} + +static void ddrx_rdet(void) +{ + unsigned int data, rdet, bdl[4]; + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= 0xf800ffff; + data |= 0x8f0000; + mmio_write_32((0xf712c000 + 0x0d0), data); + + data = mmio_read_32((0xf712c000 + 0x0dc)); + data &= 0xfffffff0; + data |= 0xf; + mmio_write_32((0xf712c000 + 0x0dc), data); + + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xfff7ffff; + mmio_write_32((0xf712c000 + 0x070), data); + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf0000000; + data |= 0x80000000; + mmio_write_32((0xf712c000 + 0x0d0), data); + + mmio_write_32((0xf712c000 + 0x004), 0x101); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (!(data & 1)); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x100) + WARN("rdet lbs fail\n"); + + bdl[0] = mmio_read_32((0xf712c000 + 0x22c)) & 0x7f; + bdl[1] = mmio_read_32((0xf712c000 + 0x2ac)) & 0x7f; + bdl[2] = mmio_read_32((0xf712c000 + 0x32c)) & 0x7f; + bdl[3] = mmio_read_32((0xf712c000 + 0x3ac)) & 0x7f; + do { + data = mmio_read_32((0xf712c000 + 0x22c)); + data &= ~0x7f; + data |= bdl[0]; + mmio_write_32((0xf712c000 + 0x22c), data); + data = mmio_read_32((0xf712c000 + 0x2ac)); + data &= ~0x7f; + data |= bdl[1]; + mmio_write_32((0xf712c000 + 0x2ac), data); + data = mmio_read_32((0xf712c000 + 0x32c)); + data &= ~0x7f; + data |= bdl[2]; + mmio_write_32((0xf712c000 + 0x32c), data); + data = mmio_read_32((0xf712c000 + 0x3ac)); + data &= ~0x7f; + data |= bdl[3]; + mmio_write_32((0xf712c000 + 0x3ac), data); + + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xfff7ffff; + mmio_write_32((0xf712c000 + 0x070), data); + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf0000000; + data |= 0x40000000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x101); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + rdet = data & 0x100; + if (rdet) { + INFO("rdet ds fail\n"); + mmio_write_32((0xf712c000 + 0x008), 0x100); + } + bdl[0]++; + bdl[1]++; + bdl[2]++; + bdl[3]++; + } while (rdet); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf0000000; + data |= 0x30000000; + mmio_write_32((0xf712c000 + 0x0d0), data); + + mmio_write_32((0xf712c000 + 0x004), 0x101); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x100) + INFO("rdet rbs av fail\n"); +} + +static void ddrx_wdet(void) +{ + unsigned int data, wdet, zero_bdl, dq[4]; + int i; + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf; + data |= 0xf; + mmio_write_32((0xf712c000 + 0x0d0), data); + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= ~0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf000; + data |= 0x8000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x201); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x200) + INFO("wdet lbs fail\n"); + + dq[0] = mmio_read_32((0xf712c000 + 0x234)) & 0x1f00; + dq[1] = mmio_read_32((0xf712c000 + 0x2b4)) & 0x1f00; + dq[2] = mmio_read_32((0xf712c000 + 0x334)) & 0x1f00; + dq[3] = mmio_read_32((0xf712c000 + 0x3b4)) & 0x1f00; + + do { + mmio_write_32((0xf712c000 + 0x234), dq[0]); + mmio_write_32((0xf712c000 + 0x2b4), dq[1]); + mmio_write_32((0xf712c000 + 0x334), dq[2]); + mmio_write_32((0xf712c000 + 0x3b4), dq[3]); + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= ~0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf000; + data |= 0x4000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x201); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + wdet = data & 0x200; + if (wdet) { + INFO("wdet ds fail\n"); + mmio_write_32((0xf712c000 + 0x008), 0x200); + } + mdelay(10); + + for (i = 0; i < 4; i++) { + data = mmio_read_32((0xf712c000 + 0x210 + i * 0x80)); + if ((!(data & 0x1f)) || (!(data & 0x1f00)) || + (!(data & 0x1f0000)) || (!(data & 0x1f000000))) + zero_bdl = 1; + data = mmio_read_32((0xf712c000 + 0x214 + i * 0x80)); + if ((!(data & 0x1f)) || (!(data & 0x1f00)) || + (!(data & 0x1f0000)) || (!(data & 0x1f000000))) + zero_bdl = 1; + data = mmio_read_32((0xf712c000 + 0x218 + i * 0x80)); + if (!(data & 0x1f)) + zero_bdl = 1; + if (zero_bdl) { + if (i == 0) + dq[0] = dq[0] - 0x100; + if (i == 1) + dq[1] = dq[1] - 0x100; + if (i == 2) + dq[2] = dq[2] - 0x100; + if (i == 3) + dq[3] = dq[3] - 0x100; + } + } + } while (wdet); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf000; + data |= 0x3000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x201); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x200) + INFO("wdet rbs av fail\n"); +} + +static void set_ddrc_533mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x3); + mmio_write_32((0xf7032000 + 0x5a8), 0x11111); + data = mmio_read_32((0xf7032000 + 0x104)); + data |= 0x100; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x30); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x6400000); + mmio_write_32((0xf712c000 + 0x258), 0x640); + mmio_write_32((0xf712c000 + 0x2d8), 0x640); + mmio_write_32((0xf712c000 + 0x358), 0x640); + mmio_write_32((0xf712c000 + 0x3d8), 0x640); + mmio_write_32((0xf712c000 + 0x018), 0x0); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0x9dd87855); + mmio_write_32((0xf712c000 + 0x034), 0xa7138bb); + mmio_write_32((0xf712c000 + 0x038), 0x20091477); + mmio_write_32((0xf712c000 + 0x03c), 0x84534e16); + mmio_write_32((0xf712c000 + 0x040), 0x3008817); + mmio_write_32((0xf712c000 + 0x064), 0x106c3); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x305; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 0x40000000; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= ~0x10; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= ~0x2000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0xd0420900); + + mmio_write_32((0xf7128000 + 0x040), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x140f); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + NOTICE("failed to init lpddr3 rank0 dram phy\n"); + return; + } + NOTICE("succeed to init lpddr3 rank0 dram phy\n"); +} + +static void set_ddrc_800mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x2); + mmio_write_32((0xf7032000 + 0x5a8), 0x1003); + data = mmio_read_32((0xf7032000 + 0x104)); + data &= 0xfffffcff; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x30); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x5400000); + mmio_write_32((0xf712c000 + 0x258), 0x540); + mmio_write_32((0xf712c000 + 0x2d8), 0x540); + mmio_write_32((0xf712c000 + 0x358), 0x540); + mmio_write_32((0xf712c000 + 0x3d8), 0x540); + mmio_write_32((0xf712c000 + 0x018), 0x0); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0xe663ab77); + mmio_write_32((0xf712c000 + 0x034), 0xea952db); + mmio_write_32((0xf712c000 + 0x038), 0x200d1cb1); + mmio_write_32((0xf712c000 + 0x03c), 0xc67d0721); + mmio_write_32((0xf712c000 + 0x040), 0x3008aa1); + mmio_write_32((0xf712c000 + 0x064), 0x11a43); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x507; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 0x40000000; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xffffffef; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= 0xffffdfff; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0xd0420900); + + mmio_write_32((0xf7128000 + 0x040), 0x2001); + mmio_write_32((0xf712c000 + 0x004), 0x140f); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + WARN("failed to init lpddr3 rank0 dram phy\n"); + return; + } +} + +static void ddrc_common_init(int ddr800) +{ + unsigned int data; + + mmio_write_32((0xf7120000 + 0x020), 0x1); + mmio_write_32((0xf7120000 + 0x100), 0x1700); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + mmio_write_32((0xf7121400 + 0x104), 0xf); + mmio_write_32((0xf7121800 + 0x104), 0xf); + mmio_write_32((0xf7121800 + 0x104), 0xf); + mmio_write_32((0xf7121c00 + 0x104), 0xf); + mmio_write_32((0xf7122000 + 0x104), 0xf); + mmio_write_32((0xf7128000 + 0x02c), 0x6); + mmio_write_32((0xf7128000 + 0x020), 0x1); + mmio_write_32((0xf7128000 + 0x028), 0x310201); + mmio_write_32((0xf712c000 + 0x1e4), 0xfe007600); + mmio_write_32((0xf7128000 + 0x01c), 0xaf001); + + + data = mmio_read_32((0xf7128000 + 0x280)); + data |= 1 << 7; + mmio_write_32((0xf7128000 + 0x280), data); + mmio_write_32((0xf7128000 + 0x244), 0x3); + + if (ddr800) + mmio_write_32((0xf7128000 + 0x240), 167 * 400000 / 1024); + else + mmio_write_32((0xf7128000 + 0x240), 167 * 533000 / 1024); + + data = mmio_read_32((0xf712c000 + 0x080)); + data &= 0xffff; + data |= 0x4002000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf7128000 + 0x000), 0x0); + do { + data = mmio_read_32((0xf7128000 + 0x294)); + } while (data & 1); + mmio_write_32((0xf7128000 + 0x000), 0x2); +} + + +static int dienum_det_and_rowcol_cfg(void) +{ + unsigned int data; + + mmio_write_32((0xf7128000 + 0x210), 0x87); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + data = mmio_read_32((0xf7128000 + 0x4a8)) & 0xfc; + switch (data) { + case 0x18: + mmio_write_32((0xf7128000 + 0x060), 0x132); + mmio_write_32((0xf7128000 + 0x064), 0x132); + mmio_write_32((0xf7120000 + 0x100), 0x1600); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + break; + case 0x1c: + mmio_write_32((0xf7128000 + 0x060), 0x142); + mmio_write_32((0xf7128000 + 0x064), 0x142); + mmio_write_32((0xf7120000 + 0x100), 0x1700); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + break; + case 0x58: + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7120000 + 0x100), 0x1700); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + break; + default: + break; + } + if (!data) + return -EINVAL; + return 0; +} + +static int detect_ddr_chip_info(void) +{ + unsigned int data, mr5, mr6, mr7; + + mmio_write_32((0xf7128000 + 0x210), 0x57); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + + data = mmio_read_32((0xf7128000 + 0x4a8)); + mr5 = data & 0xff; + switch (mr5) { + case 1: + INFO("Samsung DDR\n"); + break; + case 6: + INFO("Hynix DDR\n"); + break; + case 3: + INFO("Elpida DDR\n"); + break; + default: + INFO("DDR from other vendors\n"); + break; + } + + mmio_write_32((0xf7128000 + 0x210), 0x67); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + data = mmio_read_32((0xf7128000 + 0x4a8)); + mr6 = data & 0xff; + mmio_write_32((0xf7128000 + 0x210), 0x77); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + data = mmio_read_32((0xf7128000 + 0x4a8)); + mr7 = data & 0xff; + data = mr5 + (mr6 << 8) + (mr7 << 16); + return data; +} + +int lpddr3_freq_init(int freq) +{ + unsigned int data; + + if (freq == DDR_FREQ_800M) { + set_ddrc_800mhz(); + INFO("%s, set ddrc 800mhz\n", __func__); + } else { + set_ddrc_533mhz(); + INFO("%s, set ddrc 533mhz\n", __func__); + } + + mmio_write_32((0xf712c000 + 0x004), 0xf1); + if (freq == DDR_FREQ_800M) + mmio_write_32((0xf7128000 + 0x050), 0x100023); + else + mmio_write_32((0xf7128000 + 0x050), 0x100123); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + if (freq == DDR_FREQ_800M) { + mmio_write_32((0xf7128000 + 0x100), 0x755a9d12); + mmio_write_32((0xf7128000 + 0x104), 0x1753b055); + mmio_write_32((0xf7128000 + 0x108), 0x7401505f); + mmio_write_32((0xf7128000 + 0x10c), 0x578ca244); + mmio_write_32((0xf7128000 + 0x110), 0x10700000); + mmio_write_32((0xf7128000 + 0x114), 0x13141306); + } else { + mmio_write_32((0xf7128000 + 0x100), 0xb77b6718); + mmio_write_32((0xf7128000 + 0x104), 0x1e82a071); + mmio_write_32((0xf7128000 + 0x108), 0x9501c07e); + mmio_write_32((0xf7128000 + 0x10c), 0xaf50c255); + mmio_write_32((0xf7128000 + 0x110), 0x10b00000); + mmio_write_32((0xf7128000 + 0x114), 0x13181908); + } + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + NOTICE("fail to init ddr3 rank0\n"); + return -EFAULT; + } + INFO("init ddr3 rank0\n"); + ddrx_rdet(); + ddrx_wdet(); + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + return 0; +} + +static void init_ddr(int freq) +{ + unsigned int data; + int ret; + + + data = mmio_read_32((0xf7032000 + 0x030)); + data |= 1; + mmio_write_32((0xf7032000 + 0x030), data); + data = mmio_read_32((0xf7032000 + 0x010)); + data |= 1; + mmio_write_32((0xf7032000 + 0x010), data); + + udelay(100); + do { + data = mmio_read_32((0xf7032000 + 0x030)); + data &= 3 << 28; + } while (data != (3 << 28)); + do { + data = mmio_read_32((0xf7032000 + 0x010)); + data &= 3 << 28; + } while (data != (3 << 28)); + + ret = lpddr3_freq_init(freq); + if (ret) + return; +} + +static void init_ddrc_qos(void) +{ + unsigned int port, data; + + mmio_write_32((0xf7124000 + 0x088), 1); + + port = 0; + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x11111111); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x11111111); + mmio_write_32((0xf7120000 + 0x400 + 0 * 0x10), 0x001d0007); + + for (port = 3; port <= 4; port++) { + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x77777777); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x77777777); + } + + port = 1; + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567); + + mmio_write_32((0xf7124000 + 0x1f0), 0); + mmio_write_32((0xf7124000 + 0x0bc), 0x3020100); + mmio_write_32((0xf7124000 + 0x0d0), 0x3020100); + mmio_write_32((0xf7124000 + 0x1f4), 0x01000100); + mmio_write_32((0xf7124000 + 0x08c + 0 * 4), 0xd0670402); + mmio_write_32((0xf7124000 + 0x068 + 0 * 4), 0x31); + mmio_write_32((0xf7124000 + 0x000), 0x7); + + data = mmio_read_32((0xf7124000 + 0x09c)); + data &= ~0xff0000; + data |= 0x400000; + mmio_write_32((0xf7124000 + 0x09c), data); + data = mmio_read_32((0xf7124000 + 0x0ac)); + data &= ~0xff0000; + data |= 0x400000; + mmio_write_32((0xf7124000 + 0x0ac), data); + port = 2; + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567); + + + mmio_write_32((0xf7124000 + 0x09c), 0xff7fff); + mmio_write_32((0xf7124000 + 0x0a0), 0xff); + mmio_write_32((0xf7124000 + 0x0ac), 0xff7fff); + mmio_write_32((0xf7124000 + 0x0b0), 0xff); + mmio_write_32((0xf7124000 + 0x0bc), 0x3020100); + mmio_write_32((0xf7124000 + 0x0d0), 0x3020100); +} + +static void ddr_phy_reset(void) +{ + mmio_write_32(0xf7030340, 0xa000); + mmio_write_32(0xf7030344, 0xa000); +} + +void hikey_ddr_init(void) +{ + uint32_t data; + + init_pll(); + init_freq(); + + /* + * Init DDR with 533MHz. Otherwise, DDR initialization + * may fail on 800MHz on some boards. + */ + ddr_phy_reset(); + init_ddr(DDR_FREQ_533M); + /* Init DDR with 800MHz. */ + ddr_phy_reset(); + init_ddr(DDR_FREQ_800M); + + + ddrc_common_init(1); + dienum_det_and_rowcol_cfg(); + detect_ddr_chip_info(); + + data = mmio_read_32(0xf7032000 + 0x010); + data &= ~0x1; + mmio_write_32(0xf7032000 + 0x010, data); + data = mmio_read_32(0xf7032000 + 0x010); + + /* + * Test memory access. Do not use address 0x0 because the compiler + * may assume it is not a valid address and generate incorrect code + * (GCC 4.9.1 without -fno-delete-null-pointer-checks for instance). + */ + mmio_write_32(0x4, 0xa5a55a5a); + INFO("ddr test value:0x%x\n", mmio_read_32(0x4)); + init_ddrc_qos(); +} diff --git a/plat/hisilicon/hikey/hisi_dvfs.c b/plat/hisilicon/hikey/hisi_dvfs.c new file mode 100644 index 00000000..0d4f893b --- /dev/null +++ b/plat/hisilicon/hikey/hisi_dvfs.c @@ -0,0 +1,778 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ACPU_FREQ_MAX_NUM 5 +#define ACPU_OPP_NUM 7 + +#define ACPU_VALID_VOLTAGE_MAGIC (0x5A5AC5C5) + +#define ACPU_WAIT_TIMEOUT (200) +#define ACPU_WAIT_FOR_WFI_TIMOUT (2000) +#define ACPU_DFS_STATE_CNT (0x10000) + +struct acpu_dvfs_sram_stru { + unsigned int magic; + unsigned int support_freq_num; + unsigned int support_freq_max; + unsigned int start_prof; + unsigned int vol[ACPU_OPP_NUM]; +}; + +struct acpu_volt_cal_para { + unsigned int freq; + unsigned int ul_vol; + unsigned int dl_vol; + unsigned int core_ref_hpm; +}; + +struct ddr_volt_cal_para { + unsigned int freq; + unsigned int ul_vol; + unsigned int dl_vol; + unsigned int ddr_ref_hpm; +}; + +struct acpu_dvfs_opp_para { + unsigned int freq; + unsigned int acpu_clk_profile0; + unsigned int acpu_clk_profile1; + unsigned int acpu_vol_profile; + unsigned int acpu_pll_freq; + unsigned int acpu_pll_frac; +}; + +unsigned int efuse_acpu_freq[] = { + 1200000, 1250000, 1300000, 1350000, + 1400000, 1450000, 1500000, 1550000, + 1600000, 1650000, 1700000, 1750000, + 1800000, 1850000, 1900000, 1950000, +}; + +struct acpu_dvfs_opp_para hi6220_acpu_profile[] = { + { 208000, 0x61E5, 0x022, 0x3A, 0x5220102B, 0x05555555 }, + { 432000, 0x10A6, 0x121, 0x3A, 0x5120102D, 0x10000005 }, + { 729000, 0x2283, 0x100, 0x4A, 0x51101026, 0x10000005 }, + { 960000, 0x1211, 0x100, 0x5B, 0x51101032, 0x10000005 }, + { 1200000, 0x1211, 0x100, 0x6B, 0x5110207D, 0x10000005 }, + { 1400000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, + { 1500000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, +}; + +struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile; +struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf = + (struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; + +static inline void write_reg_mask(uintptr_t addr, + uint32_t val, uint32_t mask) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg = (reg & ~(mask)) | val; + mmio_write_32(addr, reg); +} + +static inline uint32_t read_reg_mask(uintptr_t addr, + uint32_t mask, uint32_t offset) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg &= (mask << offset); + return (reg >> offset); +} + +static int acpu_dvfs_syspll_cfg(unsigned int prof_id) +{ + uint32_t reg0 = 0; + uint32_t count = 0; + uint32_t clk_div_status = 0; + + /* + * step 1: + * - ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; + */ + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x3 << 12, 0x3 << 12); + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 4, 0x1 << 4); + + /* + * step 2: + * - ACPUSYSPLLCFG.acpu_syspll_div_cfg: + * 208MHz, set to 0x5; + * 500MHz, set to 0x2; + * other opps set to 0x1 + */ + if (prof_id == 0) + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x5 << 0, 0x7 << 0); + else if (prof_id == 1) + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x2 << 0, 0x7 << 0); + else + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 0, 0x7 << 0); + + /* + * step 3: + * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x3; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0 + * - ACPU_SC_VD_CTRL.tune_en_int = 0 + * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1 + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 + */ + clk_div_status = 0x3; + do { + reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, 20); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: clk div status timeout!\n", __func__); + return -1; + } + } while (clk_div_status != reg0); + + write_reg_mask(ACPU_SC_VD_CTRL, 0x0, (0x1 << 0) | (0x1 << 11)); + write_reg_mask(PMCTRL_ACPUCLKDIV, 0x1 << 8, 0x3 << 8); + write_reg_mask(PMCTRL_ACPUPLLSEL, 0x1 << 0, 0x1 << 0); + + return 0; +} + +static void acpu_dvfs_clk_div_cfg(unsigned int prof_id, + unsigned int *cpuext_cfg, + unsigned int *acpu_ddr_cfg) +{ + if (prof_id == 0) { + write_reg_mask(PMCTRL_ACPUCLKDIV, + (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), + (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); + *cpuext_cfg = 0x1; + *acpu_ddr_cfg = 0x1; + } else if (prof_id == 1) { + write_reg_mask(PMCTRL_ACPUCLKDIV, + (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), + (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); + *cpuext_cfg = 0x1; + *acpu_ddr_cfg = 0x1; + } else { + /* ddr has not been inited */ + write_reg_mask(PMCTRL_ACPUCLKDIV, + (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x0 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), + (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); + *cpuext_cfg = 0x1; + *acpu_ddr_cfg = 0x0; + } +} + +static int acpu_dvfs_freq_ascend(unsigned int cur_prof, unsigned int tar_prof) +{ + unsigned int reg0 = 0; + unsigned int reg1 = 0; + unsigned int reg2 = 0; + unsigned int count = 0; + unsigned int cpuext_cfg_val = 0; + unsigned int acpu_ddr_cfg_val = 0; + int ret = 0; + + /* + * step 1: + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; + * + * step 2: + * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x5 (208MHz) + * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x2 (500MHz) + * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x1 (Other OPPs) + * + * step 3: + * - ACPU_SC_CPU_STAT.clk_div_status_vd = 0x3; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x0; + * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1; + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 + */ + ret = acpu_dvfs_syspll_cfg(cur_prof); + if (ret) + return -1; + + /* + * step 4: + * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, + SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: syspll sw status timeout\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + /* Enable VD functionality if > 800MHz */ + if (acpu_dvfs_profile[tar_prof].freq > 800000) { + + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); + + /* + * step 5: + * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; + * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; + */ + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); + write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, + ACPU_SC_VD_MASK_PATTERN_VAL, + ACPU_SC_VD_MASK_PATTERN_MASK); + + /* + * step 6: + * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; + * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; + * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; + * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; + */ + mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); + + /* + * step 7: + * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; + * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; + * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; + * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; + * + * step 8: + * - ACPU_SC_VD_CTRL.tune = 0x7; + */ + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); + } + + /* step 9: ACPUPLLCTRL.acpupll_en_cfg = 0x0 */ + write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); + + /* step 10: set PMCTRL_ACPUPLLFREQ and PMCTRL_ACPUPLLFRAC */ + mmio_write_32(PMCTRL_ACPUPLLFREQ, + acpu_dvfs_profile[tar_prof].acpu_pll_freq); + mmio_write_32(PMCTRL_ACPUPLLFRAC, + acpu_dvfs_profile[tar_prof].acpu_pll_frac); + + /* + * step 11: + * - wait for 1us; + * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 + */ + count = 0; + while (count < ACPU_WAIT_TIMEOUT) + count++; + + write_reg_mask(PMCTRL_ACPUPLLCTRL, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); + + /* step 12: PMCTRL_ACPUVOLPMUADDR = 0x100da */ + mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); + + /* + * step 13: + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (208MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (500MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x20 (798MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1300MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1500MHz); + */ + write_reg_mask(PMCTRL_ACPUDESTVOL, + acpu_dvfs_profile[tar_prof].acpu_vol_profile, + ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); + + /* + * step 14: + * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol + * - Polling ACPUVOLTIMEOUT.acpu_vol_timeout == 0x1 + * - Config PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg + * - Config ACPUCLKDIV.cpuext_clk_div_cfg; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); + reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); + reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, + SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu destvol cfg timeout.\n", __func__); + return -1; + } + } while ((reg0 != reg1) || (reg2 != 0x1)); + + acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); + + /* + * step 15: + * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; + * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; + * - ACPUPLLCTRL.acpupll_timeout = 0x1; + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); + reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); + reg2 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, + SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu clk div cfg timeout.\n", __func__); + return -1; + } + } while ((reg1 != cpuext_cfg_val) || + (reg0 != acpu_ddr_cfg_val) || + (reg2 != 0x1)); + + write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, + 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); + + /* + * step 16: + * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; + * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; + * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, + SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu pll sw status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + if (acpu_dvfs_profile[tar_prof].freq > 800000) + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); + + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, + (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | + (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); + + return 0; +} + +static int acpu_dvfs_freq_descend(unsigned int cur_prof, unsigned int tar_prof) +{ + unsigned int reg0 = 0; + unsigned int reg1 = 0; + unsigned int reg2 = 0; + unsigned int count = 0; + unsigned int cpuext_cfg_val = 0; + unsigned int acpu_ddr_cfg_val = 0; + int ret = 0; + + ret = acpu_dvfs_syspll_cfg(tar_prof); + if (ret) + return -1; + + /* + * step 4: + * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 2); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: syspll sw status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + /* + * Step 5: + * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x0 + */ + write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, 0x1 << 0); + + /* + * step 6 + * - Config PMCTRL_ACPUPLLFREQ and ACPUPLLFRAC + */ + mmio_write_32(PMCTRL_ACPUPLLFREQ, acpu_dvfs_profile[tar_prof].acpu_pll_freq); + mmio_write_32(PMCTRL_ACPUPLLFRAC, acpu_dvfs_profile[tar_prof].acpu_pll_frac); + + /* + * step 7: + * - Wait 1us; + * - Config PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 + */ + count = 0; + while (count < ACPU_WAIT_TIMEOUT) + count++; + + write_reg_mask(PMCTRL_ACPUPLLCTRL, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); + + /* Enable VD functionality if > 800MHz */ + if (acpu_dvfs_profile[tar_prof].freq > 800000) { + + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); + + /* + * step 9: + * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; + * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; + */ + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); + write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, + ACPU_SC_VD_MASK_PATTERN_VAL, + ACPU_SC_VD_MASK_PATTERN_MASK); + + /* + * step 10: + * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; + * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; + * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; + * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; + */ + mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); + + /* + * step 11: + * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; + * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; + * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; + * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; + * + * step 12: + * - ACPU_SC_VD_CTRL.tune = 0x7; + */ + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); + } + + /* + * step 13: + * - Pollig PMCTRL_ACPUPLLCTRL.acpupll_timeout == 0x1; + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, + SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpupll timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, + 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); + + /* + * step 14: + * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; + * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; + * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, + SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpupll sw status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + if (acpu_dvfs_profile[tar_prof].freq > 800000) + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); + + /* + * step 15: + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; + */ + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, + (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | + (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); + + /* + * step 16: + * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, + ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: clk div status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x0); + + acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); + + /* + * step 17: + * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; + * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; + * - PMCTRL_ACPUVOLPMUADDR = 0x1006C; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); + reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu clk div cfg timeout.\n", __func__); + return -1; + } + } while ((reg0 != cpuext_cfg_val) || (reg1 != acpu_ddr_cfg_val)); + + mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); + + /* + * step 16: + * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; + * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; + * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; + */ + write_reg_mask(PMCTRL_ACPUDESTVOL, + acpu_dvfs_profile[tar_prof].acpu_vol_profile, + ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); + + /* + * step 19: + * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol + * - ACPUVOLTIMEOUT.acpu_vol_timeout = 0x1; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); + reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); + reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, + SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu destvol cfg timeout.\n", __func__); + return -1; + } + } while ((reg0 != reg1) || (reg2 != 0x1)); + + return 0; +} + +int acpu_dvfs_target(unsigned int curr_prof, unsigned int target_prof) +{ + int ret = 0; + + if (curr_prof == target_prof) { + INFO("%s: target_prof is equal curr_prof: is %d!\n", + __func__, curr_prof); + return 0; + } + + if ((curr_prof >= ACPU_FREQ_MAX_NUM) || + (target_prof >= ACPU_FREQ_MAX_NUM)) { + INFO("%s: invalid parameter %d %d\n", + __func__, curr_prof, target_prof); + return -1; + } + + if (target_prof > acpu_dvfs_sram_buf->support_freq_num) + target_prof = acpu_dvfs_sram_buf->support_freq_num; + + if (target_prof < curr_prof) + ret = acpu_dvfs_freq_descend(curr_prof, target_prof); + else if (target_prof > curr_prof) + ret = acpu_dvfs_freq_ascend(curr_prof, target_prof); + + if (ret) { + ERROR("%s: acpu_dvfs_target failed!\n", __func__); + return -1; + } + + /* Complete acpu dvfs setting and set magic number */ + acpu_dvfs_sram_buf->start_prof = target_prof; + acpu_dvfs_sram_buf->magic = ACPU_VALID_VOLTAGE_MAGIC; + + mmio_write_32(DDR_DFS_FREQ_ADDR, 800000); + return 0; +} + +static int acpu_dvfs_set_freq(void) +{ + unsigned int i; + unsigned int curr_prof; + unsigned int target_prof; + unsigned int max_freq = 0; + + max_freq = acpu_dvfs_sram_buf->support_freq_max; + + for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) { + + if (max_freq == hi6220_acpu_profile[i].freq) { + target_prof = i; + break; + } + } + + if (i == acpu_dvfs_sram_buf->support_freq_num) { + ERROR("%s: cannot found max freq profile\n", __func__); + return -1; + } + + curr_prof = 0; + target_prof = i; + + /* if max freq is 208MHz, do nothing */ + if (curr_prof == target_prof) + return 0; + + if (acpu_dvfs_target(curr_prof, target_prof)) { + ERROR("%s: set acpu freq failed!", __func__); + return -1; + } + + INFO("%s: support freq num is %d\n", + __func__, acpu_dvfs_sram_buf->support_freq_num); + INFO("%s: start prof is 0x%x\n", + __func__, acpu_dvfs_sram_buf->start_prof); + INFO("%s: magic is 0x%x\n", + __func__, acpu_dvfs_sram_buf->magic); + INFO("%s: voltage:\n", __func__); + for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) + INFO(" - %d: 0x%x\n", i, acpu_dvfs_sram_buf->vol[i]); + + NOTICE("%s: set acpu freq success!", __func__); + return 0; +} + +struct acpu_dvfs_volt_setting { + unsigned int magic; + unsigned int support_freq_num; + unsigned int support_freq_max; + unsigned int start_prof; + unsigned int vol[7]; + unsigned int hmp_dly_threshold[7]; +}; + +static void acpu_dvfs_volt_init(void) +{ + struct acpu_dvfs_volt_setting *volt; + + /* + * - set default voltage; + * - set pmu address; + * - set voltage up and down step; + * - set voltage stable time; + */ + mmio_write_32(PMCTRL_ACPUDFTVOL, 0x4a); + mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0xda); + mmio_write_32(PMCTRL_ACPUVOLUPSTEP, 0x1); + mmio_write_32(PMCTRL_ACPUVOLDNSTEP, 0x1); + mmio_write_32(PMCTRL_ACPUPMUVOLUPTIME, 0x60); + mmio_write_32(PMCTRL_ACPUPMUVOLDNTIME, 0x60); + mmio_write_32(PMCTRL_ACPUCLKOFFCFG, 0x1000); + + volt = (void *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; + volt->magic = 0x5a5ac5c5; + volt->support_freq_num = 5; + volt->support_freq_max = 1200000; + volt->start_prof = 4; + volt->vol[0] = 0x49; + volt->vol[1] = 0x49; + volt->vol[2] = 0x50; + volt->vol[3] = 0x60; + volt->vol[4] = 0x78; + volt->vol[5] = 0x78; + volt->vol[6] = 0x78; + + volt->hmp_dly_threshold[0] = 0x0; + volt->hmp_dly_threshold[1] = 0x0; + volt->hmp_dly_threshold[2] = 0x0; + volt->hmp_dly_threshold[3] = 0x0e8b0e45; + volt->hmp_dly_threshold[4] = 0x10691023; + volt->hmp_dly_threshold[5] = 0x10691023; + volt->hmp_dly_threshold[6] = 0x10691023; + + INFO("%s: success!\n", __func__); +} + +void init_acpu_dvfs(void) +{ + unsigned int i = 0; + + INFO("%s: pmic version %d\n", __func__, + mmio_read_8(HI6553_VERSION_REG)); + + /* init parameters */ + mmio_write_32(ACPU_CHIP_MAX_FREQ, efuse_acpu_freq[8]); + INFO("%s: ACPU_CHIP_MAX_FREQ=0x%x.\n", + __func__, mmio_read_32(ACPU_CHIP_MAX_FREQ)); + + /* set maximum support frequency to 1.2GHz */ + for (i = 0; i < ACPU_FREQ_MAX_NUM; i++) + acpu_dvfs_sram_buf->vol[i] = hi6220_acpu_profile[i].acpu_vol_profile; + + acpu_dvfs_sram_buf->support_freq_num = ACPU_FREQ_MAX_NUM; + acpu_dvfs_sram_buf->support_freq_max = 1200000; + + /* init acpu dvfs */ + acpu_dvfs_volt_init(); + acpu_dvfs_set_freq(); +} diff --git a/plat/hisilicon/hikey/hisi_mcu.c b/plat/hisilicon/hikey/hisi_mcu.c new file mode 100644 index 00000000..359b94d7 --- /dev/null +++ b/plat/hisilicon/hikey/hisi_mcu.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCU_SECTION_MAX 30 + +enum MCU_IMAGE_SEC_TYPE_ENUM { + MCU_IMAGE_SEC_TYPE_TEXT = 0, /* text section */ + MCU_IMAGE_SEC_TYPE_DATA, /* data section */ + MCU_IMAGE_SEC_TYPE_BUTT +}; + +enum MCU_IMAGE_SEC_LOAD_ENUM { + MCU_IMAGE_SEC_LOAD_STATIC = 0, + MCU_IMAGE_SEC_LOAD_DYNAMIC, + MCU_IMAGE_SEC_LOAD_BUFFER, + MCU_IMAGE_SEC_LOAD_MODEM_ENTRY, + MCU_IMAGE_SEC_LOAD_BUTT +}; + +struct mcu_image_sec { + unsigned short serial; + char type; + char load_attr; + uint32_t src_offset; /* offset in image */ + uint32_t dst_offset; /* offset in memory */ + uint32_t size; +}; + +struct mcu_image_head { + char time_stamp[24]; + uint32_t image_size; + uint32_t secs_num; + struct mcu_image_sec secs[MCU_SECTION_MAX]; +}; + +#define SOC_SRAM_M3_BASE_ADDR (0xF6000000) + +#define MCU_SRAM_SIZE (0x0000C000) +#define MCU_CACHE_SIZE (0x00004000) +#define MCU_CODE_SIZE (MCU_SRAM_SIZE - MCU_CACHE_SIZE) + +#define MCU_SYS_MEM_ADDR (0x05E00000) +#define MCU_SYS_MEM_SIZE (0x00100000) + +static uint32_t mcu2ap_addr(uint32_t mcu_addr) +{ + if (mcu_addr < MCU_CODE_SIZE) + return (mcu_addr + SOC_SRAM_M3_BASE_ADDR); + else if ((mcu_addr >= MCU_SRAM_SIZE) && + (mcu_addr < MCU_SRAM_SIZE + MCU_SYS_MEM_SIZE)) + return mcu_addr - MCU_SRAM_SIZE + MCU_SYS_MEM_ADDR; + else + return mcu_addr; +} + +static int is_binary_header_invalid(struct mcu_image_head *head, + unsigned int length) +{ + /* invalid cases */ + if ((head->image_size == 0) || + (head->image_size > length) || + (head->secs_num > MCU_SECTION_MAX) || + (head->secs_num == 0)) + return 1; + + return 0; +} + +static int is_binary_section_invalid(struct mcu_image_sec *sec, + struct mcu_image_head *head) +{ + unsigned long ap_dst_offset = 0; + + if ((sec->serial >= head->secs_num) || + (sec->src_offset + sec->size > head->image_size)) + return 1; + + if ((sec->type >= MCU_IMAGE_SEC_TYPE_BUTT) || + (sec->load_attr >= MCU_IMAGE_SEC_LOAD_BUTT)) + return 1; + + ap_dst_offset = mcu2ap_addr(sec->dst_offset); + if ((ap_dst_offset >= SOC_SRAM_M3_BASE_ADDR) && + (ap_dst_offset < SOC_SRAM_M3_BASE_ADDR + 0x20000 - sec->size)) + return 0; + else if ((ap_dst_offset >= MCU_SYS_MEM_ADDR) && + (ap_dst_offset < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE - sec->size)) + return 0; + else if ((ap_dst_offset >= 0xfff8e000) && + (ap_dst_offset < 0xfff91c00 - sec->size)) + return 0; + + ERROR("%s: mcu destination address invalid.\n", __func__); + ERROR("%s: number=%d, dst offset=%d size=%d\n", + __func__, sec->serial, sec->dst_offset, sec->size); + return 1; +} + +void hisi_mcu_enable_sram(void) +{ + mmio_write_32(AO_SC_PERIPH_CLKEN4, + AO_SC_PERIPH_CLKEN4_HCLK_IPC_S | + AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS); + + /* set register to enable dvfs which is used by mcu */ + mmio_write_32(PERI_SC_RESERVED8_ADDR, 0x0A001022); + + /* mcu mem is powered on, need de-assert reset */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, + AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N); + + /* enable mcu hclk */ + mmio_write_32(AO_SC_PERIPH_CLKEN4, + AO_SC_PERIPH_CLKEN4_HCLK_MCU | + AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP); +} + +void hisi_mcu_start_run(void) +{ + unsigned int val; + + /* set mcu ddr remap configuration */ + mmio_write_32(AO_SC_MCU_SUBSYS_CTRL2, MCU_SYS_MEM_ADDR); + + /* de-assert reset for mcu and to run */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, + AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N | + AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N | + AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N | + AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N); + + val = mmio_read_32(AO_SC_SYS_CTRL2); + mmio_write_32(AO_SC_SYS_CTRL2, + val | AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR); + + INFO("%s: AO_SC_SYS_CTRL2=%x\n", __func__, + mmio_read_32(AO_SC_SYS_CTRL2)); +} + +int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size) +{ + unsigned int i; + struct mcu_image_head *head; + char *buf; + + head = (struct mcu_image_head *)image_base; + if (is_binary_header_invalid(head, image_size)) { + ERROR("Invalid %s image header.\n", head->time_stamp); + return -1; + } + + buf = (char *)head; + for (i = 0; i < head->secs_num; i++) { + + int *src, *dst; + + /* check the sections */ + if (is_binary_section_invalid(&head->secs[i], head)) { + ERROR("Invalid mcu section.\n"); + return -1; + } + + /* check if the section is static-loaded */ + if (head->secs[i].load_attr != MCU_IMAGE_SEC_LOAD_STATIC) + continue; + + /* copy the sections */ + src = (int *)(intptr_t)(buf + head->secs[i].src_offset); + dst = (int *)(intptr_t)mcu2ap_addr(head->secs[i].dst_offset); + + memcpy((void *)dst, (void *)src, head->secs[i].size); + + INFO("%s: mcu sections %d:\n", __func__, i); + INFO("%s: src = 0x%x\n", + __func__, (unsigned int)(uintptr_t)src); + INFO("%s: dst = 0x%x\n", + __func__, (unsigned int)(uintptr_t)dst); + INFO("%s: size = %d\n", __func__, head->secs[i].size); + + INFO("%s: [SRC 0x%x] 0x%x 0x%x 0x%x 0x%x\n", + __func__, (unsigned int)(uintptr_t)src, + src[0], src[1], src[2], src[3]); + INFO("%s: [DST 0x%x] 0x%x 0x%x 0x%x 0x%x\n", + __func__, (unsigned int)(uintptr_t)dst, + dst[0], dst[1], dst[2], dst[3]); + } + + return 0; +} diff --git a/plat/hisilicon/hikey/include/hisi_mcu.h b/plat/hisilicon/hikey/include/hisi_mcu.h new file mode 100644 index 00000000..f5c6ed0d --- /dev/null +++ b/plat/hisilicon/hikey/include/hisi_mcu.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __HISI_MCU_H__ +#define __HISI_MCU_H__ + +#include + +extern void hisi_mcu_enable_sram(void); +extern void hisi_mcu_start_run(void); +extern int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size); + +#endif /* __HISI_MCU_H__ */ diff --git a/plat/hisilicon/hikey/include/hisi_sram_map.h b/plat/hisilicon/hikey/include/hisi_sram_map.h new file mode 100644 index 00000000..ed90c7bf --- /dev/null +++ b/plat/hisilicon/hikey/include/hisi_sram_map.h @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __HISI_SRAM_MAP_H__ +#define __HISI_SRAM_MAP_H__ + +/* + * SRAM Memory Region Layout + * + * +-----------------------+ + * | Low Power Mode | 7KB + * +-----------------------+ + * | Secure OS | 64KB + * +-----------------------+ + * | Software Flag | 1KB + * +-----------------------+ + * + */ + +#define SOC_SRAM_OFF_BASE_ADDR (0xFFF80000) + +/* PM Section: 7KB */ +#define SRAM_PM_ADDR (SOC_SRAM_OFF_BASE_ADDR) +#define SRAM_PM_SIZE (0x00001C00) + +/* TEE OS Section: 64KB */ +#define SRAM_TEEOS_ADDR (SRAM_PM_ADDR + SRAM_PM_SIZE) +#define SRAM_TEEOS_SIZE (0x00010000) + +/* General Use Section: 1KB */ +#define SRAM_GENERAL_ADDR (SRAM_TEEOS_ADDR + SRAM_TEEOS_SIZE) +#define SRAM_GENERAL_SIZE (0x00000400) + +/* + * General Usage Section Layout: + * + * +-----------------------+ + * | AP boot flag | 64B + * +-----------------------+ + * | DICC flag | 32B + * +-----------------------+ + * | Soft flag | 256B + * +-----------------------+ + * | Thermal flag | 128B + * +-----------------------+ + * | CSHELL | 4B + * +-----------------------+ + * | Uart Switching | 4B + * +-----------------------+ + * | ICC | 1024B + * +-----------------------+ + * | Memory Management | 1024B + * +-----------------------+ + * | IFC | 32B + * +-----------------------+ + * | HIFI | 32B + * +-----------------------+ + * | DDR capacity | 4B + * +-----------------------+ + * | Reserved | + * +-----------------------+ + * + */ + +/* App Core Boot Flags */ +#define MEMORY_AXI_ACPU_START_ADDR (SRAM_GENERAL_ADDR) +#define MEMORY_AXI_ACPU_START_SIZE (64) + +#define MEMORY_AXI_SRESET_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0000) +#define MEMORY_AXI_SECOND_CPU_BOOT_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0004) +#define MEMORY_AXI_READY_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0008) +#define MEMORY_AXI_FASTBOOT_ENTRY_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x000C) +#define MEMORY_AXI_PD_CHARGE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0010) +#define MEMORY_AXI_DBG_ALARM_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0014) +#define MEMORY_AXI_CHIP_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0018) +#define MEMORY_AXI_BOARD_TYPE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x001C) +#define MEMORY_AXI_BOARD_ID_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0020) +#define MEMORY_AXI_CHARGETYPE_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0024) +#define MEMORY_AXI_COLD_START_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0028) +#define MEMORY_AXI_ANDROID_REBOOT_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x002C) +#define MEMORY_AXI_ACPU_WDTRST_REBOOT_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0030) +#define MEMORY_AXI_ABNRST_BITMAP_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0034) +#define MEMORY_AXI_32K_CLK_TYPE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0038) +#define AXI_MODEM_PANIC_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x003C) +#define AXI_MODEM_PANIC_FLAG (0x68697369) +#define MEMORY_AXI_ACPU_END_ADDR (AXI_MODEM_PANIC_FLAG_ADDR + 4) + +/* DICC Flags */ +#define MEMORY_AXI_DICC_ADDR (MEMORY_AXI_ACPU_START_ADDR + MEMORY_AXI_ACPU_START_SIZE) +#define MEMORY_AXI_DICC_SIZE (32) + +#define MEMORY_AXI_SOFT_FLAG_ADDR (MEMORY_AXI_DICC_ADDR + MEMORY_AXI_DICC_SIZE) +#define MEMORY_AXI_SOFT_FLAG_SIZE (256) + +/* Thermal Flags */ +#define MEMORY_AXI_TEMP_PROTECT_ADDR (MEMORY_AXI_SOFT_FLAG_ADDR + MEMORY_AXI_SOFT_FLAG_SIZE) +#define MEMORY_AXI_TEMP_PROTECT_SIZE (128) + +/* CSHELL */ +#define MEMORY_AXI_USB_CSHELL_ADDR (MEMORY_AXI_TEMP_PROTECT_ADDR + MEMORY_AXI_TEMP_PROTECT_SIZE) +#define MEMORY_AXI_USB_CSHELL_SIZE (4) + +/* Uart and A/C Shell Switch Flags */ +#define MEMORY_AXI_UART_INOUT_ADDR (MEMORY_AXI_USB_CSHELL_ADDR + MEMORY_AXI_USB_CSHELL_SIZE) +#define MEMORY_AXI_UART_INOUT_SIZE (4) + +/* IFC Flags */ +#define MEMORY_AXI_IFC_ADDR (MEMORY_AXI_UART_INOUT_ADDR + MEMORY_AXI_UART_INOUT_SIZE) +#define MEMORY_AXI_IFC_SIZE (32) + +/* HIFI Data */ +#define MEMORY_AXI_HIFI_ADDR (MEMORY_AXI_IFC_ADDR + MEMORY_AXI_IFC_SIZE) +#define MEMORY_AXI_HIFI_SIZE (32) + +/* CONFIG Flags */ +#define MEMORY_AXI_CONFIG_ADDR (MEMORY_AXI_HIFI_ADDR + MEMORY_AXI_HIFI_SIZE) +#define MEMORY_AXI_CONFIG_SIZE (32) + +/* DDR Capacity Flags */ +#define MEMORY_AXI_DDR_CAPACITY_ADDR (MEMORY_AXI_CONFIG_ADDR + MEMORY_AXI_CONFIG_SIZE) +#define MEMORY_AXI_DDR_CAPACITY_SIZE (4) + +/* USB Shell Flags */ +#define MEMORY_AXI_USB_SHELL_FLAG_ADDR (MEMORY_AXI_DDR_CAPACITY_ADDR + MEMORY_AXI_DDR_CAPACITY_SIZE) +#define MEMORY_AXI_USB_SHELL_FLAG_SIZE (4) + +/* MCU WDT Switch Flag */ +#define MEMORY_AXI_MCU_WDT_FLAG_ADDR (MEMORY_AXI_USB_SHELL_FLAG_ADDR + MEMORY_AXI_USB_SHELL_FLAG_SIZE) +#define MEMORY_AXI_MCU_WDT_FLAG_SIZE (4) + +/* TLDSP Mailbox MNTN */ +#define SRAM_DSP_MNTN_INFO_ADDR (MEMORY_AXI_MCU_WDT_FLAG_ADDR + MEMORY_AXI_MCU_WDT_FLAG_SIZE) +#define SRAM_DSP_MNTN_SIZE (32) + +/* TLDSP ARM Mailbox Protect Flag */ +#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR (SRAM_DSP_MNTN_INFO_ADDR + SRAM_DSP_MNTN_SIZE) +#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE (4) + +/* RTT Sleep Flag */ +#define SRAM_RTT_SLEEP_FLAG_ADDR (SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR + SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE) +#define SRAM_RTT_SLEEP_FLAG_SIZE (32) + +/* LDSP Awake Flag */ +#define MEMORY_AXI_LDSP_AWAKE_ADDR (SRAM_RTT_SLEEP_FLAG_ADDR + SRAM_RTT_SLEEP_FLAG_SIZE) +#define MEMORY_AXI_LDSP_AWAKE_SIZE (4) + +#define NVUPDATE_SUCCESS 0x5555AAAA +#define NVUPDATE_FAILURE 0xAAAA5555 + +/* + * Low Power Mode Region + */ +#define PWRCTRL_ACPU_ASM_SPACE_ADDR (SRAM_PM_ADDR) +#define PWRCTRL_ACPU_ASM_SPACE_SIZE (SRAM_PM_SIZE) + +#define PWRCTRL_ACPU_ASM_MEM_BASE (PWRCTRL_ACPU_ASM_SPACE_ADDR) +#define PWRCTRL_ACPU_ASM_MEM_SIZE (PWRCTRL_ACPU_ASM_SPACE_SIZE) +#define PWRCTRL_ACPU_ASM_CODE_BASE (PWRCTRL_ACPU_ASM_MEM_BASE + 0x200) +#define PWRCTRL_ACPU_ASM_DATA_BASE (PWRCTRL_ACPU_ASM_MEM_BASE + 0xE00) +#define PWRCTRL_ACPU_ASM_DATA_SIZE (0xE00) + +#define PWRCTRL_ACPU_ASM_D_C0_ADDR (PWRCTRL_ACPU_ASM_DATA_BASE) +#define PWRCTRL_ACPU_ASM_D_C0_MMU_PARA_AD (PWRCTRL_ACPU_ASM_DATA_BASE + 0) +#define PWRCTRL_ACPU_ASM_D_ARM_PARA_AD (PWRCTRL_ACPU_ASM_DATA_BASE + 0x20) + +#define PWRCTRL_ACPU_ASM_D_COMM_ADDR (PWRCTRL_ACPU_ASM_DATA_BASE + 0x700) + +#define PWRCTRL_ACPU_REBOOT (PWRCTRL_ACPU_ASM_D_COMM_ADDR) +#define PWRCTRL_ACPU_REBOOT_SIZE (0x200) +#define PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR (PWRCTRL_ACPU_REBOOT + PWRCTRL_ACPU_REBOOT_SIZE) +#define PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE (4) +#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR (PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR + PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE) +#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE (4) +#define EXCH_A_CORE_POWRCTRL_CONV_ADDR (PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR + PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE) +#define EXCH_A_CORE_POWRCTRL_CONV_SIZE (4) + +/* + * Below region memory mapping is: + * 4 + 12 + 16 + 28 + 28 + 16 + 28 + 12 + 24 + 20 + 64 + + * 4 + 4 + 4 + 4 + 12 + 4 + 4 + 4 + 4 + 16 + 4 + 0x2BC + + * 24 + 20 + 12 + 16 + */ + +#define MEMORY_AXI_CPU_IDLE_ADDR (EXCH_A_CORE_POWRCTRL_CONV_ADDR + EXCH_A_CORE_POWRCTRL_CONV_SIZE) +#define MEMORY_AXI_CPU_IDLE_SIZE (4) + +#define MEMORY_AXI_CUR_FREQ_ADDR (MEMORY_AXI_CPU_IDLE_ADDR + MEMORY_AXI_CPU_IDLE_SIZE) +#define MEMORY_AXI_CUR_FREQ_SIZE (12) + +#define MEMORY_AXI_ACPU_FREQ_VOL_ADDR (MEMORY_AXI_CUR_FREQ_ADDR + MEMORY_AXI_CUR_FREQ_SIZE) +#define MEMORY_AXI_ACPU_FREQ_VOL_SIZE (16 + 28 + 28) + +#define MEMORY_AXI_DDR_FREQ_VOL_ADDR (MEMORY_AXI_ACPU_FREQ_VOL_ADDR + MEMORY_AXI_ACPU_FREQ_VOL_SIZE) +#define MEMORY_AXI_DDR_FREQ_VOL_SIZE (16 + 28) + +#define MEMORY_AXI_ACPU_FIQ_TEST_ADDR (MEMORY_AXI_DDR_FREQ_VOL_ADDR + MEMORY_AXI_DDR_FREQ_VOL_SIZE) +#define MEMORY_AXI_ACPU_FIQ_TEST_SIZE (12) + +#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR (MEMORY_AXI_ACPU_FIQ_TEST_ADDR + MEMORY_AXI_ACPU_FIQ_TEST_SIZE) +#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE (24) + +#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR (MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE) +#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE (20) + +#define MEMORY_FREQDUMP_ADDR (MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE) +#define MEMORY_FREQDUMP_SIZE (64) + +#define MEMORY_AXI_CCPU_LOG_ADDR (MEMORY_FREQDUMP_ADDR + MEMORY_FREQDUMP_SIZE) +#define MEMORY_AXI_CCPU_LOG_SIZE (4) + +#define MEMORY_AXI_MCU_LOG_ADDR (MEMORY_AXI_CCPU_LOG_ADDR + MEMORY_AXI_CCPU_LOG_SIZE) +#define MEMORY_AXI_MCU_LOG_SIZE (4) + +#define MEMORY_AXI_SEC_CORE_BOOT_ADDR (MEMORY_AXI_MCU_LOG_ADDR + MEMORY_AXI_MCU_LOG_SIZE) +#define MEMORY_AXI_SEC_CORE_BOOT_SIZE (4) + +#define MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR (MEMORY_AXI_SEC_CORE_BOOT_ADDR + MEMORY_AXI_SEC_CORE_BOOT_SIZE) +#define MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE (0x4) + +#define POLICY_AREA_RESERVED (MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR + MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE) +#define POLICY_AREA_RESERVED_SIZE (12) + +#define DDR_POLICY_VALID_MAGIC (POLICY_AREA_RESERVED + POLICY_AREA_RESERVED_SIZE) +#define DDR_POLICY_VALID_MAGIC_SIZE (4) + +#define DDR_POLICY_MAX_NUM (DDR_POLICY_VALID_MAGIC + DDR_POLICY_VALID_MAGIC_SIZE) +#define DDR_POLICY_MAX_NUM_SIZE (4) + +#define DDR_POLICY_SUPPORT_NUM (DDR_POLICY_MAX_NUM + DDR_POLICY_MAX_NUM_SIZE) +#define DDR_POLICY_SUPPORT_NUM_SIZE (4) + +#define DDR_POLICY_CUR_POLICY (DDR_POLICY_SUPPORT_NUM + DDR_POLICY_SUPPORT_NUM_SIZE) +#define DDR_POLICY_CUR_POLICY_SIZE (4) + +#define ACPU_POLICY_VALID_MAGIC (DDR_POLICY_CUR_POLICY + DDR_POLICY_CUR_POLICY_SIZE) +#define ACPU_POLICY_VALID_MAGIC_SIZE (4) + +#define ACPU_POLICY_MAX_NUM (ACPU_POLICY_VALID_MAGIC + ACPU_POLICY_VALID_MAGIC_SIZE) +#define ACPU_POLICY_MAX_NUM_SIZE (4) + +#define ACPU_POLICY_SUPPORT_NUM (ACPU_POLICY_MAX_NUM + ACPU_POLICY_MAX_NUM_SIZE) +#define ACPU_POLICY_SUPPORT_NUM_SIZE (4) + +#define ACPU_POLICY_CUR_POLICY (ACPU_POLICY_SUPPORT_NUM + ACPU_POLICY_SUPPORT_NUM_SIZE) +#define ACPU_POLICY_CUR_POLICY_SIZE (4) + +#define LPDDR_OPTION_ADDR (ACPU_POLICY_CUR_POLICY + ACPU_POLICY_CUR_POLICY_SIZE) +#define LPDDR_OPTION_SIZE (4) + +#define MEMORY_AXI_DDR_DDL_ADDR (LPDDR_OPTION_ADDR + LPDDR_OPTION_SIZE) +#define MEMORY_AXI_DDR_DDL_SIZE (0x2BC) + +#define DDR_TEST_DFS_ADDR (MEMORY_AXI_DDR_DDL_ADDR + MEMORY_AXI_DDR_DDL_SIZE) +#define DDR_TEST_DFS_ADDR_SIZE (4) + +#define DDR_TEST_DFS_TIMES_ADDR (DDR_TEST_DFS_ADDR + DDR_TEST_DFS_ADDR_SIZE) +#define DDR_TEST_DFS_TIMES_ADDR_SIZE (4) + +#define DDR_TEST_QOS_ADDR (DDR_TEST_DFS_TIMES_ADDR + DDR_TEST_DFS_TIMES_ADDR_SIZE) +#define DDR_TEST_QOS_ADDR_SIZE (4) + +#define DDR_TEST_FUN_ADDR (DDR_TEST_QOS_ADDR + DDR_TEST_QOS_ADDR_SIZE) +#define DDR_TEST_FUN_ADDR_SIZE (4) + +#define BOARD_TYPE_ADDR (DDR_TEST_FUN_ADDR + DDR_TEST_FUN_ADDR_SIZE) +#define BOARD_ADDR_SIZE (4) +#define DDR_DFS_FREQ_ADDR (BOARD_TYPE_ADDR + BOARD_ADDR_SIZE) +#define DDR_DFS_FREQ_SIZE (4) + +#define DDR_PASR_ADDR (DDR_DFS_FREQ_ADDR + DDR_DFS_FREQ_SIZE) +#define DDR_PASR_SIZE (20) + +#define ACPU_DFS_FREQ_ADDR (DDR_PASR_ADDR + DDR_PASR_SIZE) +#define ACPU_DFS_FREQ_ADDR_SIZE (12) + +#define ACPU_CHIP_MAX_FREQ (ACPU_DFS_FREQ_ADDR + ACPU_DFS_FREQ_ADDR_SIZE) +#define ACPU_CHIP_MAX_FREQ_SIZE (4) + +#define MEMORY_MEDPLL_STATE_ADDR (ACPU_CHIP_MAX_FREQ + ACPU_CHIP_MAX_FREQ_SIZE) +#define MEMORY_MEDPLL_STATE_SIZE (8) + +#define MEMORY_CCPU_LOAD_FLAG_ADDR (MEMORY_MEDPLL_STATE_ADDR + MEMORY_MEDPLL_STATE_SIZE) +#define MEMORY_CCPU_LOAD_FLAG_SIZE (4) + + +#define ACPU_CORE_BITS_ADDR (MEMORY_CCPU_LOAD_FLAG_ADDR + MEMORY_CCPU_LOAD_FLAG_SIZE) +#define ACPU_CORE_BITS_SIZE (4) + +#define ACPU_CLUSTER_IDLE_ADDR (ACPU_CORE_BITS_ADDR + ACPU_CORE_BITS_SIZE) +#define ACPU_CLUSTER_IDLE_SIZE (4) + +#define ACPU_A53_FLAGS_ADDR (ACPU_CLUSTER_IDLE_ADDR + ACPU_CLUSTER_IDLE_SIZE) +#define ACPU_A53_FLAGS_SIZE (4) + +#define ACPU_POWER_STATE_QOS_ADDR (ACPU_A53_FLAGS_ADDR+ACPU_A53_FLAGS_SIZE) +#define ACPU_POWER_STATE_QOS_SIZE (4) + +#define ACPU_UNLOCK_CORE_FLAGS_ADDR (ACPU_POWER_STATE_QOS_ADDR+ACPU_POWER_STATE_QOS_SIZE) +#define ACPU_UNLOCK_CORE_FLAGS_SIZE (8) + +#define ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR (ACPU_UNLOCK_CORE_FLAGS_ADDR + ACPU_UNLOCK_CORE_FLAGS_SIZE) +#define ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE (4) + +#define ACPU_CORE_POWERDOWN_FLAGS_ADDR (ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR + ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE) +#define ACPU_CORE_POWERDOWN_FLAGS_SIZE (4) + +#define ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR (ACPU_CORE_POWERDOWN_FLAGS_ADDR + ACPU_CORE_POWERDOWN_FLAGS_SIZE) +#define ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE (4) + +#define ACPU_ARM64_FLAGA (ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR + ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE) +#define ACPU_ARM64_FLAGA_SIZE (4) + +#define ACPU_ARM64_FLAGB (ACPU_ARM64_FLAGA + ACPU_ARM64_FLAGA_SIZE) +#define ACPU_ARM64_FLAGB_SIZE (4) + +#define MCU_EXCEPTION_FLAGS_ADDR (ACPU_ARM64_FLAGB + ACPU_ARM64_FLAGB_SIZE) +#define MCU_EXCEPTION_FLAGS_SIZE (4) + +#define ACPU_MASTER_CORE_STATE_ADDR (MCU_EXCEPTION_FLAGS_ADDR + MCU_EXCEPTION_FLAGS_SIZE) +#define ACPU_MASTER_CORE_STATE_SIZE (4) + +#define PWRCTRL_AXI_RESERVED_ADDR (ACPU_MASTER_CORE_STATE_ADDR + ACPU_MASTER_CORE_STATE_SIZE) + +#endif /* __HISI_SRAM_MAP_H__ */ diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk index 5aa9b158..9d8f94a7 100644 --- a/plat/hisilicon/hikey/platform.mk +++ b/plat/hisilicon/hikey/platform.mk @@ -6,6 +6,7 @@ CONSOLE_BASE := PL011_UART3_BASE CRASH_CONSOLE_BASE := PL011_UART3_BASE +PLAT_PARTITION_MAX_ENTRIES := 12 PLAT_PL061_MAX_GPIOS := 160 COLD_BOOT_SINGLE_CPU := 1 PROGRAMMABLE_RESET_ADDRESS := 1 @@ -14,6 +15,8 @@ PROGRAMMABLE_RESET_ADDRESS := 1 $(eval $(call add_define,CONSOLE_BASE)) $(eval $(call add_define,CRASH_CONSOLE_BASE)) $(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) +$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) +$(eval $(call FIP_ADD_IMG,SCP_BL2,--scp-fw)) ENABLE_PLAT_COMPAT := 0 @@ -41,3 +44,17 @@ BL1_SOURCES += bl1/tbbr/tbbr_img_desc.c \ plat/hisilicon/hikey/aarch64/hikey_helpers.S \ plat/hisilicon/hikey/hikey_bl1_setup.c \ plat/hisilicon/hikey/hikey_io_storage.c + +BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/emmc/emmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ + plat/hisilicon/hikey/aarch64/hikey_helpers.S \ + plat/hisilicon/hikey/hikey_bl2_setup.c \ + plat/hisilicon/hikey/hikey_ddr.c \ + plat/hisilicon/hikey/hikey_io_storage.c \ + plat/hisilicon/hikey/hisi_dvfs.c \ + plat/hisilicon/hikey/hisi_mcu.c -- 2.30.2