GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
#include <mv_ddr_if.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
/*
|
||||
* This function may modify the default DRAM parameters
|
||||
* based on information received from SPD or bootloader
|
||||
* configuration located on non volatile storage
|
||||
*/
|
||||
void plat_marvell_dram_update_topology(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* This struct provides the DRAM training code with
|
||||
* the appropriate board DRAM configuration
|
||||
*/
|
||||
static struct mv_ddr_topology_map board_topology_map = {
|
||||
/* FIXME: MISL board 2CS 4Gb x8 devices of micron - 2133P */
|
||||
DEBUG_LEVEL_ERROR,
|
||||
0x1, /* active interfaces */
|
||||
/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
|
||||
{ { { {0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0} },
|
||||
SPEED_BIN_DDR_2133P, /* speed_bin */
|
||||
MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
|
||||
MV_DDR_DIE_CAP_4GBIT, /* die capacity */
|
||||
MV_DDR_FREQ_SAR, /* frequency */
|
||||
0, 0, /* cas_l, cas_wl */
|
||||
MV_DDR_TEMP_LOW} }, /* temperature */
|
||||
MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
|
||||
MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
|
||||
NOT_COMBINED, /* ddr twin-die combined*/
|
||||
{ {0} }, /* raw spd data */
|
||||
{0}, /* timing parameters */
|
||||
{ /* electrical configuration */
|
||||
{ /* memory electrical configuration */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
|
||||
{
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
|
||||
MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
|
||||
},
|
||||
MV_DDR_DIC_RZQ_DIV7 /* dic */
|
||||
},
|
||||
{ /* phy electrical configuration */
|
||||
MV_DDR_OHM_30, /* data_drv_p */
|
||||
MV_DDR_OHM_30, /* data_drv_n */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_p */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_n */
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_p 1cs */
|
||||
MV_DDR_OHM_120 /* odt_p 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_n 1cs */
|
||||
MV_DDR_OHM_120 /* odt_n 2cs */
|
||||
},
|
||||
},
|
||||
{ /* mac electrical configuration */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
|
||||
MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
|
||||
{
|
||||
/* Return the board topology as defined in the board code */
|
||||
return &board_topology_map;
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <armada_common.h>
|
||||
|
||||
/*
|
||||
* If bootrom is currently at BLE there's no need to include the memory
|
||||
* maps structure at this point
|
||||
*/
|
||||
#include <mvebu_def.h>
|
||||
#ifndef IMAGE_BLE
|
||||
|
||||
/*****************************************************************************
|
||||
* AMB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win amb_memory_map[] = {
|
||||
/* CP0 SPI1 CS0 Direct Mode access */
|
||||
{0xf900, 0x1000000, AMB_SPI1_CS0_ID},
|
||||
};
|
||||
|
||||
int marvell_get_amb_memory_map(struct addr_map_win **win,
|
||||
uint32_t *size, uintptr_t base)
|
||||
{
|
||||
*win = amb_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(amb_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* IO_WIN Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win io_win_memory_map[] = {
|
||||
#ifndef IMAGE_BLE
|
||||
/* MCI 0 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
|
||||
/* MCI 1 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_io_win_gcr_target(int ap_index)
|
||||
{
|
||||
return PIDI_TID;
|
||||
}
|
||||
|
||||
int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = io_win_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(io_win_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef IMAGE_BLE
|
||||
/*****************************************************************************
|
||||
* IOB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win iob_memory_map[] = {
|
||||
/* PEX1_X1 window */
|
||||
{0x00000000f7000000, 0x1000000, PEX1_TID},
|
||||
/* PEX2_X1 window */
|
||||
{0x00000000f8000000, 0x1000000, PEX2_TID},
|
||||
{0x00000000c0000000, 0x30000000, PEX2_TID},
|
||||
{0x0000000800000000, 0x100000000, PEX2_TID},
|
||||
/* PEX0_X4 window */
|
||||
{0x00000000f6000000, 0x1000000, PEX0_TID},
|
||||
/* SPI1_CS0 (RUNIT) window */
|
||||
{0x00000000f9000000, 0x1000000, RUNIT_TID},
|
||||
};
|
||||
|
||||
int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
*win = iob_memory_map;
|
||||
*size = ARRAY_SIZE(iob_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* CCU Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win ccu_memory_map[] = { /* IO window */
|
||||
#ifdef IMAGE_BLE
|
||||
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
|
||||
#else
|
||||
#if LLC_SRAM
|
||||
/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
|
||||
* and changes the window target to SRAM_TID.
|
||||
*/
|
||||
{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
|
||||
#endif
|
||||
{0x00000000f2000000, 0xe000000, IO_0_TID},
|
||||
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
|
||||
{0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_ccu_gcr_target(int ap)
|
||||
{
|
||||
return DRAM_0_TID;
|
||||
}
|
||||
|
||||
int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = ccu_memory_map;
|
||||
*size = ARRAY_SIZE(ccu_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef IMAGE_BLE
|
||||
/*****************************************************************************
|
||||
* SKIP IMAGE Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
#if PLAT_RECOVERY_IMAGE_ENABLE
|
||||
struct skip_image skip_im = {
|
||||
.detection_method = GPIO,
|
||||
.info.gpio.num = 33,
|
||||
.info.gpio.button_state = HIGH,
|
||||
.info.test.cp_ap = CP,
|
||||
.info.test.cp_index = 0,
|
||||
};
|
||||
|
||||
void *plat_marvell_get_skip_image_data(void)
|
||||
{
|
||||
/* Return the skip_image configurations */
|
||||
return &skip_im;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MVEBU_DEF_H
|
||||
#define MVEBU_DEF_H
|
||||
|
||||
#include <a8k_plat_def.h>
|
||||
|
||||
#define CP_COUNT 1 /* A70x0 has single CP0 */
|
||||
|
||||
#endif /* MVEBU_DEF_H */
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (C) 2018 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
#
|
||||
|
||||
PCI_EP_SUPPORT := 0
|
||||
|
||||
CP_NUM := 1
|
||||
$(eval $(call add_define,CP_NUM))
|
||||
|
||||
DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
|
||||
|
||||
MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
|
||||
|
||||
BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
|
||||
include plat/marvell/armada/a8k/common/a8k_common.mk
|
||||
|
||||
include plat/marvell/armada/common/marvell_common.mk
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
#include <mv_ddr_if.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
/*
|
||||
* This function may modify the default DRAM parameters
|
||||
* based on information received from SPD or bootloader
|
||||
* configuration located on non volatile storage
|
||||
*/
|
||||
void plat_marvell_dram_update_topology(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* This struct provides the DRAM training code with
|
||||
* the appropriate board DRAM configuration
|
||||
*/
|
||||
static struct mv_ddr_topology_map board_topology_map = {
|
||||
/* FIXME: MISL board 2CS 8Gb x8 devices of micron - 2133P */
|
||||
DEBUG_LEVEL_ERROR,
|
||||
0x1, /* active interfaces */
|
||||
/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
|
||||
{ { { {0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0} },
|
||||
SPEED_BIN_DDR_2400T, /* speed_bin */
|
||||
MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
|
||||
MV_DDR_DIE_CAP_8GBIT, /* die capacity */
|
||||
MV_DDR_FREQ_SAR, /* frequency */
|
||||
0, 0, /* cas_l, cas_wl */
|
||||
MV_DDR_TEMP_LOW} }, /* temperature */
|
||||
MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
|
||||
MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
|
||||
NOT_COMBINED, /* ddr twin-die combined*/
|
||||
{ {0} }, /* raw spd data */
|
||||
{0}, /* timing parameters */
|
||||
{ /* electrical configuration */
|
||||
{ /* memory electrical configuration */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
|
||||
{
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
|
||||
MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
|
||||
},
|
||||
MV_DDR_DIC_RZQ_DIV7 /* dic */
|
||||
},
|
||||
{ /* phy electrical configuration */
|
||||
MV_DDR_OHM_30, /* data_drv_p */
|
||||
MV_DDR_OHM_30, /* data_drv_n */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_p */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_n */
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_p 1cs */
|
||||
MV_DDR_OHM_120 /* odt_p 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_n 1cs */
|
||||
MV_DDR_OHM_120 /* odt_n 2cs */
|
||||
},
|
||||
},
|
||||
{ /* mac electrical configuration */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
|
||||
MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
|
||||
{
|
||||
/* Return the board topology as defined in the board code */
|
||||
return &board_topology_map;
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <armada_common.h>
|
||||
|
||||
/*
|
||||
* If bootrom is currently at BLE there's no need to include the memory
|
||||
* maps structure at this point
|
||||
*/
|
||||
#include <mvebu_def.h>
|
||||
#ifndef IMAGE_BLE
|
||||
|
||||
/*****************************************************************************
|
||||
* AMB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win *amb_memory_map;
|
||||
|
||||
int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
*win = amb_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(amb_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* IO WIN Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win io_win_memory_map[] = {
|
||||
#ifndef IMAGE_BLE
|
||||
/* MCI 0 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
|
||||
/* MCI 1 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_io_win_gcr_target(int ap_index)
|
||||
{
|
||||
return PIDI_TID;
|
||||
}
|
||||
|
||||
int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = io_win_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(io_win_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef IMAGE_BLE
|
||||
/*****************************************************************************
|
||||
* IOB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win iob_memory_map[] = {
|
||||
/* PEX0_X4 window */
|
||||
{0x00000000f6000000, 0x6000000, PEX0_TID},
|
||||
{0x00000000c0000000, 0x30000000, PEX0_TID},
|
||||
{0x0000000800000000, 0x200000000, PEX0_TID},
|
||||
};
|
||||
|
||||
int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
*win = iob_memory_map;
|
||||
*size = ARRAY_SIZE(iob_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* CCU Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win ccu_memory_map[] = {
|
||||
#ifdef IMAGE_BLE
|
||||
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
|
||||
#else
|
||||
#if LLC_SRAM
|
||||
/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
|
||||
* and changes the window target to SRAM_TID.
|
||||
*/
|
||||
{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
|
||||
#endif
|
||||
{0x00000000f2000000, 0xe000000, IO_0_TID},
|
||||
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
|
||||
{0x0000000800000000, 0x200000000, IO_0_TID}, /* IO window */
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_ccu_gcr_target(int ap)
|
||||
{
|
||||
return DRAM_0_TID;
|
||||
}
|
||||
|
||||
int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = ccu_memory_map;
|
||||
*size = ARRAY_SIZE(ccu_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef IMAGE_BLE
|
||||
|
||||
struct pci_hw_cfg *plat_get_pcie_hw_data(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SKIP IMAGE Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
#if PLAT_RECOVERY_IMAGE_ENABLE
|
||||
struct skip_image skip_im = {
|
||||
.detection_method = GPIO,
|
||||
.info.gpio.num = 33,
|
||||
.info.gpio.button_state = HIGH,
|
||||
.info.test.cp_ap = CP,
|
||||
.info.test.cp_index = 0,
|
||||
};
|
||||
|
||||
void *plat_marvell_get_skip_image_data(void)
|
||||
{
|
||||
/* Return the skip_image configurations */
|
||||
return &skip_im;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MVEBU_DEF_H
|
||||
#define MVEBU_DEF_H
|
||||
|
||||
#include <a8k_plat_def.h>
|
||||
|
||||
#define CP_COUNT 1 /* A70x0 has single CP0 */
|
||||
|
||||
/***********************************************************************
|
||||
* Required platform porting definitions common to all
|
||||
* Management Compute SubSystems (MSS)
|
||||
***********************************************************************
|
||||
*/
|
||||
/*
|
||||
* Load address of SCP_BL2
|
||||
* SCP_BL2 is loaded to the same place as BL31.
|
||||
* Once SCP_BL2 is transferred to the SCP,
|
||||
* it is discarded and BL31 is loaded over the top.
|
||||
*/
|
||||
#ifdef SCP_IMAGE
|
||||
#define SCP_BL2_BASE BL31_BASE
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* MVEBU_DEF_H */
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (C) 2018 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
#
|
||||
|
||||
PCI_EP_SUPPORT := 0
|
||||
|
||||
CP_NUM := 1
|
||||
$(eval $(call add_define,CP_NUM))
|
||||
|
||||
DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
|
||||
|
||||
MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
|
||||
|
||||
BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
|
||||
include plat/marvell/armada/a8k/common/a8k_common.mk
|
||||
|
||||
include plat/marvell/armada/common/marvell_common.mk
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Sartura Ltd.
|
||||
* Copyright (C) 2021 Globalscale technologies, Inc.
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
#include <mv_ddr_if.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
/*
|
||||
* This function may modify the default DRAM parameters
|
||||
* based on information received from SPD or bootloader
|
||||
* configuration located on non volatile storage
|
||||
*/
|
||||
void plat_marvell_dram_update_topology(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* This struct provides the DRAM training code with
|
||||
* the appropriate board DRAM configuration
|
||||
*/
|
||||
#if DDR_TOPOLOGY == 0
|
||||
static struct mv_ddr_topology_map board_topology_map_2g = {
|
||||
/* 1CS 4Gb x4 devices of Samsung K4A4G085WF */
|
||||
DEBUG_LEVEL_ERROR,
|
||||
0x1, /* active interfaces */
|
||||
/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
|
||||
{ { { {0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0} },
|
||||
SPEED_BIN_DDR_2400R, /* speed_bin */
|
||||
MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
|
||||
MV_DDR_DIE_CAP_4GBIT, /* die capacity */
|
||||
MV_DDR_FREQ_SAR, /* frequency */
|
||||
0, 0, /* cas_l, cas_wl */
|
||||
MV_DDR_TEMP_LOW} }, /* temperature */
|
||||
BUS_MASK_32BIT, /* subphys mask */
|
||||
MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
|
||||
NOT_COMBINED, /* ddr twin-die combined*/
|
||||
{ {0} }, /* raw spd data */
|
||||
{0}, /* timing parameters */
|
||||
{ /* electrical configuration */
|
||||
{ /* memory electrical configuration */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
|
||||
{
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
|
||||
MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
|
||||
},
|
||||
MV_DDR_DIC_RZQ_DIV7 /* dic */
|
||||
},
|
||||
{ /* phy electrical configuration */
|
||||
MV_DDR_OHM_30, /* data_drv_p */
|
||||
MV_DDR_OHM_30, /* data_drv_n */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_p */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_n */
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_p 1cs */
|
||||
MV_DDR_OHM_120 /* odt_p 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_n 1cs */
|
||||
MV_DDR_OHM_120 /* odt_n 2cs */
|
||||
},
|
||||
},
|
||||
{ /* mac electrical configuration */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
|
||||
MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
|
||||
},
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if DDR_TOPOLOGY == 1
|
||||
static struct mv_ddr_topology_map board_topology_map_4g = {
|
||||
/* 1CS 8Gb x4 devices of Samsung K4A8G085WC-BCTD */
|
||||
DEBUG_LEVEL_ERROR,
|
||||
0x1, /* active interfaces */
|
||||
/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
|
||||
{ { { {0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0},
|
||||
{0x1, 0x2, 0, 0} },
|
||||
SPEED_BIN_DDR_2400R, /* speed_bin */
|
||||
MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
|
||||
MV_DDR_DIE_CAP_8GBIT, /* die capacity */
|
||||
MV_DDR_FREQ_SAR, /* frequency */
|
||||
0, 0, /* cas_l, cas_wl */
|
||||
MV_DDR_TEMP_LOW} }, /* temperature */
|
||||
BUS_MASK_32BIT, /* subphys mask */
|
||||
MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
|
||||
NOT_COMBINED, /* ddr twin-die combined*/
|
||||
{ {0} }, /* raw spd data */
|
||||
{0}, /* timing parameters */
|
||||
{ /* electrical configuration */
|
||||
{ /* memory electrical configuration */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
|
||||
{
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
|
||||
MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
|
||||
},
|
||||
MV_DDR_DIC_RZQ_DIV7 /* dic */
|
||||
},
|
||||
{ /* phy electrical configuration */
|
||||
MV_DDR_OHM_30, /* data_drv_p */
|
||||
MV_DDR_OHM_30, /* data_drv_n */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_p */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_n */
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_p 1cs */
|
||||
MV_DDR_OHM_120 /* odt_p 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_n 1cs */
|
||||
MV_DDR_OHM_120 /* odt_n 2cs */
|
||||
},
|
||||
},
|
||||
{ /* mac electrical configuration */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
|
||||
MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
|
||||
},
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if DDR_TOPOLOGY == 2
|
||||
static struct mv_ddr_topology_map board_topology_map_8g = {
|
||||
/* 2CS 8Gb x8 devices of Micron MT40A1G8WE-083E IT */
|
||||
DEBUG_LEVEL_ERROR,
|
||||
0x1, /* active interfaces */
|
||||
/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
|
||||
{ { { {0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0},
|
||||
{0x3, 0x2, 0, 0} },
|
||||
SPEED_BIN_DDR_2400R, /* speed_bin */
|
||||
MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
|
||||
MV_DDR_DIE_CAP_8GBIT, /* die capacity */
|
||||
MV_DDR_FREQ_SAR, /* frequency */
|
||||
0, 0, /* cas_l, cas_wl */
|
||||
MV_DDR_TEMP_LOW} }, /* temperature */
|
||||
BUS_MASK_32BIT, /* subphys mask */
|
||||
MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
|
||||
NOT_COMBINED, /* ddr twin-die combined*/
|
||||
{ {0} }, /* raw spd data */
|
||||
{0}, /* timing parameters */
|
||||
{ /* electrical configuration */
|
||||
{ /* memory electrical configuration */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
|
||||
{
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
|
||||
MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
|
||||
},
|
||||
MV_DDR_DIC_RZQ_DIV7 /* dic */
|
||||
},
|
||||
{ /* phy electrical configuration */
|
||||
MV_DDR_OHM_30, /* data_drv_p */
|
||||
MV_DDR_OHM_30, /* data_drv_n */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_p */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_n */
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_p 1cs */
|
||||
MV_DDR_OHM_120 /* odt_p 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_n 1cs */
|
||||
MV_DDR_OHM_120 /* odt_n 2cs */
|
||||
},
|
||||
},
|
||||
{ /* mac electrical configuration */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
|
||||
MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
|
||||
},
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
|
||||
{
|
||||
/* a70x0_mochabin board supports 3 DDR4 models (2G/1CS, 4G/1CS, 8G/2CS) */
|
||||
#if DDR_TOPOLOGY == 0
|
||||
return &board_topology_map_2g;
|
||||
#elif DDR_TOPOLOGY == 1
|
||||
return &board_topology_map_4g;
|
||||
#elif DDR_TOPOLOGY == 2
|
||||
return &board_topology_map_8g;
|
||||
#else
|
||||
#error "Unknown DDR topology"
|
||||
#endif
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Sartura Ltd.
|
||||
* Copyright (C) 2021 Globalscale technologies, Inc.
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <armada_common.h>
|
||||
|
||||
/*
|
||||
* If bootrom is currently at BLE there's no need to include the memory
|
||||
* maps structure at this point
|
||||
*/
|
||||
#include <mvebu_def.h>
|
||||
#ifndef IMAGE_BLE
|
||||
|
||||
/*****************************************************************************
|
||||
* AMB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win amb_memory_map[] = {
|
||||
/* CP0 SPI1 CS0 Direct Mode access */
|
||||
{0xf900, 0x1000000, AMB_SPI1_CS0_ID},
|
||||
};
|
||||
|
||||
int marvell_get_amb_memory_map(struct addr_map_win **win,
|
||||
uint32_t *size, uintptr_t base)
|
||||
{
|
||||
*win = amb_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(amb_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* IO_WIN Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win io_win_memory_map[] = {
|
||||
#ifndef IMAGE_BLE
|
||||
/* MCI 0 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
|
||||
/* MCI 1 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_io_win_gcr_target(int ap_index)
|
||||
{
|
||||
return PIDI_TID;
|
||||
}
|
||||
|
||||
int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = io_win_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(io_win_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef IMAGE_BLE
|
||||
/*****************************************************************************
|
||||
* IOB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win iob_memory_map[] = {
|
||||
/* PEX1_X1 window */
|
||||
{0x00000000f7000000, 0x1000000, PEX1_TID},
|
||||
/* PEX2_X1 window */
|
||||
{0x00000000f8000000, 0x1000000, PEX2_TID},
|
||||
{0x00000000c0000000, 0x30000000, PEX2_TID},
|
||||
{0x0000000800000000, 0x100000000, PEX2_TID},
|
||||
/* PEX0_X4 window */
|
||||
{0x00000000f6000000, 0x1000000, PEX0_TID},
|
||||
/* SPI1_CS0 (RUNIT) window */
|
||||
{0x00000000f9000000, 0x1000000, RUNIT_TID},
|
||||
};
|
||||
|
||||
int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
*win = iob_memory_map;
|
||||
*size = ARRAY_SIZE(iob_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* CCU Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win ccu_memory_map[] = { /* IO window */
|
||||
#ifdef IMAGE_BLE
|
||||
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
|
||||
#else
|
||||
#if LLC_SRAM
|
||||
/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
|
||||
* and changes the window target to SRAM_TID.
|
||||
*/
|
||||
{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
|
||||
#endif
|
||||
{0x00000000f2000000, 0xe000000, IO_0_TID},
|
||||
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
|
||||
{0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_ccu_gcr_target(int ap)
|
||||
{
|
||||
return DRAM_0_TID;
|
||||
}
|
||||
|
||||
int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = ccu_memory_map;
|
||||
*size = ARRAY_SIZE(ccu_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef IMAGE_BLE
|
||||
/*****************************************************************************
|
||||
* SKIP IMAGE Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
#if PLAT_RECOVERY_IMAGE_ENABLE
|
||||
void *plat_marvell_get_skip_image_data(void)
|
||||
{
|
||||
/* No recovery button on a70x0_mochabin board */
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Sartura Ltd.
|
||||
* Copyright (C) 2021 Globalscale technologies, Inc.
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef __PHY_PORTING_LAYER_H
|
||||
#define __PHY_PORTING_LAYER_H
|
||||
|
||||
#define MAX_LANE_NR 6
|
||||
|
||||
static const struct xfi_params
|
||||
xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
|
||||
/* AP0 */
|
||||
{
|
||||
/* CP 0 */
|
||||
{
|
||||
{ 0 }, /* Comphy0 */
|
||||
{ 0 }, /* Comphy1 */
|
||||
{ 0 }, /* Comphy2 */
|
||||
{ 0 }, /* Comphy3 */
|
||||
{ .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, .align90 = 0x60,
|
||||
.g1_dfe_res = 0x1, .g1_amp = 0x1c, .g1_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, .g1_tx_emph_en = 0x1,
|
||||
.g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
|
||||
.g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
|
||||
.valid = 1 }, /* Comphy4 */
|
||||
{ 0 }, /* Comphy5 */
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sata_params
|
||||
sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
|
||||
/* AP0 */
|
||||
{
|
||||
/* CP 0 */
|
||||
{
|
||||
{ 0 }, /* Comphy0 */
|
||||
{ 0 }, /* Comphy1 */
|
||||
{ .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
|
||||
.g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g2_emph_en = 0x1, .g3_emph_en = 0x1,
|
||||
.g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, .g3_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, .g3_tx_emph_en = 0x0,
|
||||
.g1_tx_emph = 0x1, .g2_tx_emph = 0x1, .g3_tx_emph = 0x1,
|
||||
.g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, .g3_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x61,
|
||||
.g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, .g3_rx_selmuff = 0x3,
|
||||
.g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, .g3_rx_selmufi = 0x3,
|
||||
.g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, .g3_rx_selmupf = 0x2,
|
||||
.g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, .g3_rx_selmupi = 0x2,
|
||||
.polarity_invert = COMPHY_POLARITY_NO_INVERT,
|
||||
.valid = 0x1
|
||||
}, /* Comphy2 */
|
||||
{ .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
|
||||
.g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g2_emph_en = 0x1, .g3_emph_en = 0x1,
|
||||
.g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, .g3_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, .g3_tx_emph_en = 0x0,
|
||||
.g1_tx_emph = 0x1, .g2_tx_emph = 0x1, .g3_tx_emph = 0x1,
|
||||
.g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, .g3_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x61,
|
||||
.g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, .g3_rx_selmuff = 0x3,
|
||||
.g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, .g3_rx_selmufi = 0x3,
|
||||
.g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, .g3_rx_selmupf = 0x2,
|
||||
.g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, .g3_rx_selmupi = 0x2,
|
||||
.polarity_invert = COMPHY_POLARITY_NO_INVERT,
|
||||
.valid = 0x1
|
||||
}, /* Comphy3 */
|
||||
{ 0 }, /* Comphy4 */
|
||||
{ 0 }, /* Comphy5 */
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb_params
|
||||
usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
|
||||
[0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = {
|
||||
.polarity_invert = COMPHY_POLARITY_NO_INVERT
|
||||
},
|
||||
};
|
||||
|
||||
#endif /* __PHY_PORTING_LAYER_H */
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MVEBU_DEF_H
|
||||
#define MVEBU_DEF_H
|
||||
|
||||
#include <a8k_plat_def.h>
|
||||
|
||||
#define CP_COUNT 1 /* A70x0 has single CP0 */
|
||||
|
||||
#endif /* MVEBU_DEF_H */
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (C) 2021 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
#
|
||||
|
||||
PCI_EP_SUPPORT := 0
|
||||
|
||||
CP_NUM := 1
|
||||
$(eval $(call add_define,CP_NUM))
|
||||
|
||||
DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
|
||||
|
||||
MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
|
||||
|
||||
BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
|
||||
include plat/marvell/armada/a8k/common/a8k_common.mk
|
||||
|
||||
include plat/marvell/armada/common/marvell_common.mk
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/mentor/mi2cv.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mv_ddr_if.h>
|
||||
#include <mvebu_def.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
#define MVEBU_AP_MPP_CTRL0_7_REG MVEBU_AP_MPP_REGS(0)
|
||||
#define MVEBU_AP_MPP_CTRL4_OFFS 16
|
||||
#define MVEBU_AP_MPP_CTRL5_OFFS 20
|
||||
#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA 0x3
|
||||
#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA 0x3
|
||||
|
||||
#define MVEBU_CP_MPP_CTRL37_OFFS 20
|
||||
#define MVEBU_CP_MPP_CTRL38_OFFS 24
|
||||
#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2
|
||||
#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2
|
||||
|
||||
#define MVEBU_MPP_CTRL_MASK 0xf
|
||||
|
||||
/*
|
||||
* This struct provides the DRAM training code with
|
||||
* the appropriate board DRAM configuration
|
||||
*/
|
||||
static struct mv_ddr_topology_map board_topology_map = {
|
||||
/* MISL board with 1CS 8Gb x4 devices of Micron 2400T */
|
||||
DEBUG_LEVEL_ERROR,
|
||||
0x1, /* active interfaces */
|
||||
/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
|
||||
{ { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0} },
|
||||
/* TODO: double check if the speed bin is 2400T */
|
||||
SPEED_BIN_DDR_2400T, /* speed_bin */
|
||||
MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
|
||||
MV_DDR_DIE_CAP_8GBIT, /* die capacity */
|
||||
MV_DDR_FREQ_SAR, /* frequency */
|
||||
0, 0, /* cas_l, cas_wl */
|
||||
MV_DDR_TEMP_LOW} }, /* temperature */
|
||||
#if DDR32
|
||||
MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
|
||||
#else
|
||||
MV_DDR_64BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
|
||||
#endif
|
||||
MV_DDR_CFG_SPD, /* ddr configuration data source */
|
||||
NOT_COMBINED, /* ddr twin-die combined*/
|
||||
{ {0} }, /* raw spd data */
|
||||
{0}, /* timing parameters */
|
||||
{ /* electrical configuration */
|
||||
{ /* memory electrical configuration */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
|
||||
{
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
|
||||
MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
|
||||
},
|
||||
MV_DDR_DIC_RZQ_DIV7 /* dic */
|
||||
},
|
||||
{ /* phy electrical configuration */
|
||||
MV_DDR_OHM_30, /* data_drv_p */
|
||||
MV_DDR_OHM_30, /* data_drv_n */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_p */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_n */
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_p 1cs */
|
||||
MV_DDR_OHM_120 /* odt_p 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_n 1cs */
|
||||
MV_DDR_OHM_120 /* odt_n 2cs */
|
||||
},
|
||||
},
|
||||
{ /* mac electrical configuration */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
|
||||
MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
|
||||
{
|
||||
/* Return the board topology as defined in the board code */
|
||||
return &board_topology_map;
|
||||
}
|
||||
|
||||
static void mpp_config(void)
|
||||
{
|
||||
uintptr_t reg;
|
||||
uint32_t val;
|
||||
|
||||
reg = MVEBU_CP_MPP_REGS(0, 4);
|
||||
/* configure CP0 MPP 37 and 38 to i2c */
|
||||
val = mmio_read_32(reg);
|
||||
val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
|
||||
(MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
|
||||
val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA <<
|
||||
MVEBU_CP_MPP_CTRL37_OFFS) |
|
||||
(MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA <<
|
||||
MVEBU_CP_MPP_CTRL38_OFFS);
|
||||
mmio_write_32(reg, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function may modify the default DRAM parameters
|
||||
* based on information received from SPD or bootloader
|
||||
* configuration located on non volatile storage
|
||||
*/
|
||||
void plat_marvell_dram_update_topology(void)
|
||||
{
|
||||
struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
|
||||
|
||||
INFO("Gathering DRAM information\n");
|
||||
|
||||
if (tm->cfg_src == MV_DDR_CFG_SPD) {
|
||||
/* configure MPPs to enable i2c */
|
||||
mpp_config();
|
||||
|
||||
/* initialize i2c */
|
||||
i2c_init((void *)MVEBU_CP0_I2C_BASE);
|
||||
|
||||
/* select SPD memory page 0 to access DRAM configuration */
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
|
||||
|
||||
/* read data from spd */
|
||||
i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
|
||||
sizeof(tm->spd_data.all_bytes));
|
||||
}
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <armada_common.h>
|
||||
|
||||
/*
|
||||
* If bootrom is currently at BLE there's no need to include the memory
|
||||
* maps structure at this point
|
||||
*/
|
||||
#include <mvebu_def.h>
|
||||
#ifndef IMAGE_BLE
|
||||
|
||||
/*****************************************************************************
|
||||
* AMB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win amb_memory_map[] = {
|
||||
/* CP1 SPI1 CS0 Direct Mode access */
|
||||
{0xf900, 0x1000000, AMB_SPI1_CS0_ID},
|
||||
};
|
||||
|
||||
int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
*win = amb_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(amb_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* IO WIN Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win io_win_memory_map[] = {
|
||||
/* CP1 (MCI0) internal regs */
|
||||
{0x00000000f4000000, 0x2000000, MCI_0_TID},
|
||||
#ifndef IMAGE_BLE
|
||||
/* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
|
||||
{0x00000000f9000000, 0x2000000, MCI_0_TID},
|
||||
/* PCIe1 on CP1*/
|
||||
{0x00000000fb000000, 0x1000000, MCI_0_TID},
|
||||
/* PCIe2 on CP1*/
|
||||
{0x00000000fc000000, 0x1000000, MCI_0_TID},
|
||||
/* MCI 0 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
|
||||
/* MCI 1 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_io_win_gcr_target(int ap_index)
|
||||
{
|
||||
return PIDI_TID;
|
||||
}
|
||||
|
||||
int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = io_win_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(io_win_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef IMAGE_BLE
|
||||
/*****************************************************************************
|
||||
* IOB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win iob_memory_map_cp0[] = {
|
||||
/* CP0 */
|
||||
/* PEX1_X1 window */
|
||||
{0x00000000f7000000, 0x1000000, PEX1_TID},
|
||||
/* PEX2_X1 window */
|
||||
{0x00000000f8000000, 0x1000000, PEX2_TID},
|
||||
/* PEX0_X4 window */
|
||||
{0x00000000f6000000, 0x1000000, PEX0_TID},
|
||||
{0x00000000c0000000, 0x30000000, PEX0_TID},
|
||||
{0x0000000800000000, 0x100000000, PEX0_TID},
|
||||
};
|
||||
|
||||
struct addr_map_win iob_memory_map_cp1[] = {
|
||||
/* CP1 */
|
||||
/* SPI1_CS0 (RUNIT) window */
|
||||
{0x00000000f9000000, 0x1000000, RUNIT_TID},
|
||||
/* PEX1_X1 window */
|
||||
{0x00000000fb000000, 0x1000000, PEX1_TID},
|
||||
/* PEX2_X1 window */
|
||||
{0x00000000fc000000, 0x1000000, PEX2_TID},
|
||||
/* PEX0_X4 window */
|
||||
{0x00000000fa000000, 0x1000000, PEX0_TID}
|
||||
};
|
||||
|
||||
int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
switch (base) {
|
||||
case MVEBU_CP_REGS_BASE(0):
|
||||
*win = iob_memory_map_cp0;
|
||||
*size = ARRAY_SIZE(iob_memory_map_cp0);
|
||||
return 0;
|
||||
case MVEBU_CP_REGS_BASE(1):
|
||||
*win = iob_memory_map_cp1;
|
||||
*size = ARRAY_SIZE(iob_memory_map_cp1);
|
||||
return 0;
|
||||
default:
|
||||
*size = 0;
|
||||
*win = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* CCU Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win ccu_memory_map[] = {
|
||||
#ifdef IMAGE_BLE
|
||||
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
|
||||
#else
|
||||
#if LLC_SRAM
|
||||
/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
|
||||
* and changes the window target to SRAM_TID.
|
||||
*/
|
||||
{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
|
||||
#endif
|
||||
{0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
|
||||
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
|
||||
{0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_ccu_gcr_target(int ap)
|
||||
{
|
||||
return DRAM_0_TID;
|
||||
}
|
||||
|
||||
int marvell_get_ccu_memory_map(int ap, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = ccu_memory_map;
|
||||
*size = ARRAY_SIZE(ccu_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef IMAGE_BLE
|
||||
/*****************************************************************************
|
||||
* SoC PM configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
/* CP GPIO should be used and the GPIOs should be within same GPIO register */
|
||||
struct power_off_method pm_cfg = {
|
||||
.type = PMIC_GPIO,
|
||||
.cfg.gpio.pin_count = 1,
|
||||
.cfg.gpio.info = {{0, 35} },
|
||||
.cfg.gpio.step_count = 7,
|
||||
.cfg.gpio.seq = {1, 0, 1, 0, 1, 0, 1},
|
||||
.cfg.gpio.delay_ms = 10,
|
||||
};
|
||||
|
||||
void *plat_marvell_get_pm_cfg(void)
|
||||
{
|
||||
/* Return the PM configurations */
|
||||
return &pm_cfg;
|
||||
}
|
||||
|
||||
/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */
|
||||
#else
|
||||
/*****************************************************************************
|
||||
* SKIP IMAGE Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
#if PLAT_RECOVERY_IMAGE_ENABLE
|
||||
struct skip_image skip_im = {
|
||||
.detection_method = GPIO,
|
||||
.info.gpio.num = 33,
|
||||
.info.gpio.button_state = HIGH,
|
||||
.info.test.cp_ap = CP,
|
||||
.info.test.cp_index = 0,
|
||||
};
|
||||
|
||||
void *plat_marvell_get_skip_image_data(void)
|
||||
{
|
||||
/* Return the skip_image configurations */
|
||||
return &skip_im;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef PHY_PORTING_LAYER_H
|
||||
#define PHY_PORTING_LAYER_H
|
||||
|
||||
#define MAX_LANE_NR 6
|
||||
|
||||
static const struct xfi_params
|
||||
xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
|
||||
/* AP0 */
|
||||
{
|
||||
/* CP 0 */
|
||||
{
|
||||
{ 0 }, /* Comphy0 */
|
||||
{ 0 }, /* Comphy1 */
|
||||
{ .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x5f,
|
||||
.g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
|
||||
.g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
|
||||
.g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
|
||||
.valid = 0x1 }, /* Comphy2 */
|
||||
{ 0 }, /* Comphy3 */
|
||||
{ .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x5f,
|
||||
.g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
|
||||
.g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
|
||||
.g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
|
||||
.valid = 0x1 }, /* Comphy4 */
|
||||
{ 0 }, /* Comphy5 */
|
||||
},
|
||||
|
||||
/* CP 1 */
|
||||
{
|
||||
{ 0 }, /* Comphy0 */
|
||||
{ 0 }, /* Comphy1 */
|
||||
{ .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x5f,
|
||||
.g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
|
||||
.g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
|
||||
.g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
|
||||
.valid = 0x1 }, /* Comphy2 */
|
||||
{ 0 }, /* Comphy3 */
|
||||
{ .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x5f,
|
||||
.g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
|
||||
.g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
|
||||
.g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
|
||||
.valid = 0x1 }, /* Comphy4 */
|
||||
{ 0 }, /* Comphy5 */
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sata_params
|
||||
sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
|
||||
/* AP0 */
|
||||
{
|
||||
/* CP 0 */
|
||||
{
|
||||
{ 0 }, /* Comphy0 */
|
||||
{ .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
|
||||
.g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g2_emph_en = 0x1,
|
||||
.g3_emph_en = 0x1,
|
||||
.g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1,
|
||||
.g3_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0,
|
||||
.g3_tx_emph_en = 0x0,
|
||||
.g1_tx_emph = 0x1, .g2_tx_emph = 0x1,
|
||||
.g3_tx_emph = 0x1,
|
||||
.g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4,
|
||||
.g3_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x61,
|
||||
.g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3,
|
||||
.g3_rx_selmuff = 0x3,
|
||||
.g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0,
|
||||
.g3_rx_selmufi = 0x3,
|
||||
.g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1,
|
||||
.g3_rx_selmupf = 0x2,
|
||||
.g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0,
|
||||
.g3_rx_selmupi = 0x2,
|
||||
.polarity_invert = COMPHY_POLARITY_NO_INVERT,
|
||||
.valid = 0x1
|
||||
}, /* Comphy1 */
|
||||
{ 0 }, /* Comphy2 */
|
||||
{ .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
|
||||
.g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g2_emph_en = 0x1,
|
||||
.g3_emph_en = 0x1,
|
||||
.g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1,
|
||||
.g3_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0,
|
||||
.g3_tx_emph_en = 0x0,
|
||||
.g1_tx_emph = 0x1, .g2_tx_emph = 0x1,
|
||||
.g3_tx_emph = 0x1,
|
||||
.g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4,
|
||||
.g3_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x61,
|
||||
.g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3,
|
||||
.g3_rx_selmuff = 0x3,
|
||||
.g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0,
|
||||
.g3_rx_selmufi = 0x3,
|
||||
.g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1,
|
||||
.g3_rx_selmupf = 0x2,
|
||||
.g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0,
|
||||
.g3_rx_selmupi = 0x2,
|
||||
.polarity_invert = COMPHY_POLARITY_NO_INVERT,
|
||||
.valid = 0x1
|
||||
}, /* Comphy3 */
|
||||
{ 0 }, /* Comphy4 */
|
||||
{ 0 }, /* Comphy5 */
|
||||
},
|
||||
|
||||
/* CP 1 */
|
||||
{
|
||||
{ 0 }, /* Comphy0 */
|
||||
{ .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
|
||||
.g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g2_emph_en = 0x1,
|
||||
.g3_emph_en = 0x1,
|
||||
.g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1,
|
||||
.g3_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0,
|
||||
.g3_tx_emph_en = 0x0,
|
||||
.g1_tx_emph = 0x1, .g2_tx_emph = 0x1,
|
||||
.g3_tx_emph = 0x1,
|
||||
.g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4,
|
||||
.g3_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x61,
|
||||
.g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3,
|
||||
.g3_rx_selmuff = 0x3,
|
||||
.g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0,
|
||||
.g3_rx_selmufi = 0x3,
|
||||
.g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1,
|
||||
.g3_rx_selmupf = 0x2,
|
||||
.g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0,
|
||||
.g3_rx_selmupi = 0x2,
|
||||
.polarity_invert = COMPHY_POLARITY_NO_INVERT,
|
||||
.valid = 0x1
|
||||
}, /* Comphy1 */
|
||||
{ 0 }, /* Comphy2 */
|
||||
{ .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
|
||||
.g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
|
||||
.g1_emph_en = 0x1, .g2_emph_en = 0x1,
|
||||
.g3_emph_en = 0x1,
|
||||
.g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1,
|
||||
.g3_tx_amp_adj = 0x1,
|
||||
.g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0,
|
||||
.g3_tx_emph_en = 0x0,
|
||||
.g1_tx_emph = 0x1, .g2_tx_emph = 0x1,
|
||||
.g3_tx_emph = 0x1,
|
||||
.g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4,
|
||||
.g3_ffe_cap_sel = 0xf,
|
||||
.align90 = 0x61,
|
||||
.g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3,
|
||||
.g3_rx_selmuff = 0x3,
|
||||
.g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0,
|
||||
.g3_rx_selmufi = 0x3,
|
||||
.g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1,
|
||||
.g3_rx_selmupf = 0x2,
|
||||
.g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0,
|
||||
.g3_rx_selmupi = 0x2,
|
||||
.polarity_invert = COMPHY_POLARITY_NO_INVERT,
|
||||
.valid = 0x1
|
||||
}, /* Comphy3 */
|
||||
{ 0 }, /* Comphy4 */
|
||||
{ 0 }, /* Comphy5 */
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb_params
|
||||
usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
|
||||
[0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = {
|
||||
.polarity_invert = COMPHY_POLARITY_NO_INVERT
|
||||
},
|
||||
};
|
||||
#endif /* PHY_PORTING_LAYER_H */
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MVEBU_DEF_H
|
||||
#define MVEBU_DEF_H
|
||||
|
||||
#include <a8k_plat_def.h>
|
||||
|
||||
#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */
|
||||
#define I2C_SPD_ADDR 0x53 /* Access SPD data */
|
||||
#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */
|
||||
|
||||
#endif /* MVEBU_DEF_H */
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (C) 2018 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
#
|
||||
|
||||
PCI_EP_SUPPORT := 0
|
||||
|
||||
CP_NUM := 2
|
||||
$(eval $(call add_define,CP_NUM))
|
||||
|
||||
DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg
|
||||
|
||||
MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
|
||||
|
||||
BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
|
||||
include plat/marvell/armada/a8k/common/a8k_common.mk
|
||||
|
||||
include plat/marvell/armada/common/marvell_common.mk
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/mentor/mi2cv.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mv_ddr_if.h>
|
||||
#include <mvebu_def.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
#define MVEBU_CP_MPP_CTRL37_OFFS 20
|
||||
#define MVEBU_CP_MPP_CTRL38_OFFS 24
|
||||
#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2
|
||||
#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2
|
||||
|
||||
#define MVEBU_MPP_CTRL_MASK 0xf
|
||||
|
||||
/*
|
||||
* This struct provides the DRAM training code with
|
||||
* the appropriate board DRAM configuration
|
||||
*/
|
||||
static struct mv_ddr_topology_map board_topology_map = {
|
||||
/* Board with 1CS 8Gb x4 devices of Micron 2400T */
|
||||
DEBUG_LEVEL_ERROR,
|
||||
0x1, /* active interfaces */
|
||||
/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
|
||||
{ { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0} },
|
||||
/* TODO: double check if the speed bin is 2400T */
|
||||
SPEED_BIN_DDR_2400T, /* speed_bin */
|
||||
MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
|
||||
MV_DDR_DIE_CAP_8GBIT, /* die capacity */
|
||||
MV_DDR_FREQ_SAR, /* frequency */
|
||||
0, 0, /* cas_l, cas_wl */
|
||||
MV_DDR_TEMP_LOW} }, /* temperature */
|
||||
MV_DDR_64BIT_BUS_MASK, /* subphys mask */
|
||||
MV_DDR_CFG_SPD, /* ddr configuration data source */
|
||||
NOT_COMBINED, /* ddr twin-die combined*/
|
||||
{ {0} }, /* raw spd data */
|
||||
{0}, /* timing parameters */
|
||||
{ /* electrical configuration */
|
||||
{ /* memory electrical configuration */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
|
||||
{
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
|
||||
MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
|
||||
},
|
||||
MV_DDR_DIC_RZQ_DIV7 /* dic */
|
||||
},
|
||||
{ /* phy electrical configuration */
|
||||
MV_DDR_OHM_30, /* data_drv_p */
|
||||
MV_DDR_OHM_30, /* data_drv_n */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_p */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_n */
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_p 1cs */
|
||||
MV_DDR_OHM_120 /* odt_p 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_n 1cs */
|
||||
MV_DDR_OHM_120 /* odt_n 2cs */
|
||||
},
|
||||
},
|
||||
{ /* mac electrical configuration */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
|
||||
MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
|
||||
{
|
||||
/* Return the board topology as defined in the board code */
|
||||
return &board_topology_map;
|
||||
}
|
||||
|
||||
static void mpp_config(void)
|
||||
{
|
||||
uint32_t val;
|
||||
uintptr_t reg = MVEBU_CP_MPP_REGS(0, 4);
|
||||
|
||||
/* configure CP0 MPP 37 and 38 to i2c */
|
||||
val = mmio_read_32(reg);
|
||||
val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
|
||||
(MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
|
||||
val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA << MVEBU_CP_MPP_CTRL37_OFFS) |
|
||||
(MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA << MVEBU_CP_MPP_CTRL38_OFFS);
|
||||
mmio_write_32(reg, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function may modify the default DRAM parameters
|
||||
* based on information received from SPD or bootloader
|
||||
* configuration located on non volatile storage
|
||||
*/
|
||||
void plat_marvell_dram_update_topology(void)
|
||||
{
|
||||
struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
|
||||
|
||||
INFO("Gathering DRAM information\n");
|
||||
|
||||
if (tm->cfg_src == MV_DDR_CFG_SPD) {
|
||||
/* configure MPPs to enable i2c */
|
||||
mpp_config();
|
||||
/* initialize the i2c */
|
||||
i2c_init((void *)MVEBU_CP0_I2C_BASE);
|
||||
/* select SPD memory page 0 to access DRAM configuration */
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
|
||||
/* read data from spd */
|
||||
i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
|
||||
sizeof(tm->spd_data.all_bytes));
|
||||
}
|
||||
}
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <armada_common.h>
|
||||
|
||||
/*
|
||||
* If bootrom is currently at BLE there's no need to include the memory
|
||||
* maps structure at this point
|
||||
*/
|
||||
#include <mvebu_def.h>
|
||||
#ifndef IMAGE_BLE
|
||||
|
||||
/*****************************************************************************
|
||||
* GPIO Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MPP_CONTROL_REGISTER 0xf2440018
|
||||
#define MPP_CONTROL_MPP_SEL_52_MASK 0xf0000
|
||||
#define GPIO_DATA_OUT1_REGISTER 0xf2440140
|
||||
#define GPIO_DATA_OUT_EN_CTRL1_REGISTER 0xf2440144
|
||||
#define GPIO52_MASK 0x100000
|
||||
|
||||
/* Reset PCIe via GPIO number 52 */
|
||||
int marvell_gpio_config(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = mmio_read_32(MPP_CONTROL_REGISTER);
|
||||
reg |= MPP_CONTROL_MPP_SEL_52_MASK;
|
||||
mmio_write_32(MPP_CONTROL_REGISTER, reg);
|
||||
|
||||
reg = mmio_read_32(GPIO_DATA_OUT1_REGISTER);
|
||||
reg |= GPIO52_MASK;
|
||||
mmio_write_32(GPIO_DATA_OUT1_REGISTER, reg);
|
||||
|
||||
reg = mmio_read_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER);
|
||||
reg &= ~GPIO52_MASK;
|
||||
mmio_write_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER, reg);
|
||||
udelay(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* AMB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win amb_memory_map[] = {
|
||||
/* CP1 SPI1 CS0 Direct Mode access */
|
||||
{0xf900, 0x1000000, AMB_SPI1_CS0_ID},
|
||||
};
|
||||
|
||||
int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
*win = amb_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(amb_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* IO WIN Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win io_win_memory_map[] = {
|
||||
/* CP1 (MCI0) internal regs */
|
||||
{0x00000000f4000000, 0x2000000, MCI_0_TID},
|
||||
#ifndef IMAGE_BLE
|
||||
/* PCIe0-2 and SPI1_CS0 (RUNIT) on CP1*/
|
||||
{0x00000000f9000000, 0x4000000, MCI_0_TID},
|
||||
/* MCI 0 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
|
||||
/* MCI 1 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_io_win_gcr_target(int ap_index)
|
||||
{
|
||||
return PIDI_TID;
|
||||
}
|
||||
|
||||
int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = io_win_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(io_win_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef IMAGE_BLE
|
||||
/*****************************************************************************
|
||||
* IOB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win iob_memory_map_cp0[] = {
|
||||
/* CP0 */
|
||||
/* PEX1_X1 window */
|
||||
{0x00000000f7000000, 0x1000000, PEX1_TID},
|
||||
/* PEX2_X1 window */
|
||||
{0x00000000f8000000, 0x1000000, PEX2_TID},
|
||||
/* PEX0_X4 window */
|
||||
{0x00000000f6000000, 0x1000000, PEX0_TID},
|
||||
{0x00000000c0000000, 0x30000000, PEX0_TID},
|
||||
{0x0000000800000000, 0x100000000, PEX0_TID},
|
||||
};
|
||||
|
||||
struct addr_map_win iob_memory_map_cp1[] = {
|
||||
/* CP1 */
|
||||
/* SPI1_CS0 (RUNIT) window */
|
||||
{0x00000000f9000000, 0x1000000, RUNIT_TID},
|
||||
/* PEX1_X1 window */
|
||||
{0x00000000fb000000, 0x1000000, PEX1_TID},
|
||||
/* PEX2_X1 window */
|
||||
{0x00000000fc000000, 0x1000000, PEX2_TID},
|
||||
/* PEX0_X4 window */
|
||||
{0x00000000fa000000, 0x1000000, PEX0_TID}
|
||||
};
|
||||
|
||||
int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
switch (base) {
|
||||
case MVEBU_CP_REGS_BASE(0):
|
||||
*win = iob_memory_map_cp0;
|
||||
*size = ARRAY_SIZE(iob_memory_map_cp0);
|
||||
return 0;
|
||||
case MVEBU_CP_REGS_BASE(1):
|
||||
*win = iob_memory_map_cp1;
|
||||
*size = ARRAY_SIZE(iob_memory_map_cp1);
|
||||
return 0;
|
||||
default:
|
||||
*size = 0;
|
||||
*win = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* CCU Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win ccu_memory_map[] = {
|
||||
#ifdef IMAGE_BLE
|
||||
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
|
||||
#else
|
||||
#if LLC_SRAM
|
||||
/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
|
||||
* and changes the window target to SRAM_TID.
|
||||
*/
|
||||
{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
|
||||
#endif
|
||||
{0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
|
||||
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
|
||||
{0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_ccu_gcr_target(int ap)
|
||||
{
|
||||
return DRAM_0_TID;
|
||||
}
|
||||
|
||||
int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = ccu_memory_map;
|
||||
*size = ARRAY_SIZE(ccu_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */
|
||||
|
||||
/*****************************************************************************
|
||||
* SKIP IMAGE Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
void *plat_marvell_get_skip_image_data(void)
|
||||
{
|
||||
/* No recovery button on A8k-MCBIN board */
|
||||
return NULL;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MVEBU_DEF_H
|
||||
#define MVEBU_DEF_H
|
||||
|
||||
#include <a8k_plat_def.h>
|
||||
|
||||
#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */
|
||||
#define I2C_SPD_ADDR 0x53 /* Access SPD data */
|
||||
#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */
|
||||
|
||||
#endif /* MVEBU_DEF_H */
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (C) 2018 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
#
|
||||
|
||||
PCI_EP_SUPPORT := 0
|
||||
|
||||
CP_NUM := 2
|
||||
$(eval $(call add_define,CP_NUM))
|
||||
|
||||
DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg
|
||||
|
||||
MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
|
||||
|
||||
BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
|
||||
include plat/marvell/armada/a8k/common/a8k_common.mk
|
||||
|
||||
include plat/marvell/armada/common/marvell_common.mk
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/mentor/mi2cv.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mv_ddr_if.h>
|
||||
#include <mvebu_def.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
#define MVEBU_AP_MPP_CTRL0_7_REG MVEBU_AP_MPP_REGS(0)
|
||||
#define MVEBU_AP_MPP_CTRL4_OFFS 16
|
||||
#define MVEBU_AP_MPP_CTRL5_OFFS 20
|
||||
#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA 0x3
|
||||
#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA 0x3
|
||||
|
||||
#define MVEBU_CP_MPP_CTRL37_OFFS 20
|
||||
#define MVEBU_CP_MPP_CTRL38_OFFS 24
|
||||
#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2
|
||||
#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2
|
||||
|
||||
#define MVEBU_MPP_CTRL_MASK 0xf
|
||||
|
||||
/*
|
||||
* This struct provides the DRAM training code with
|
||||
* the appropriate board DRAM configuration
|
||||
*/
|
||||
static struct mv_ddr_topology_map board_topology_map = {
|
||||
/* Board with 1CS 8Gb x4 devices of Micron 2400T */
|
||||
DEBUG_LEVEL_ERROR,
|
||||
0x1, /* active interfaces */
|
||||
/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
|
||||
{ { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0} },
|
||||
/* TODO: double check if the speed bin is 2400T */
|
||||
SPEED_BIN_DDR_2400T, /* speed_bin */
|
||||
MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
|
||||
MV_DDR_DIE_CAP_8GBIT, /* die capacity */
|
||||
MV_DDR_FREQ_SAR, /* frequency */
|
||||
0, 0, /* cas_l, cas_wl */
|
||||
MV_DDR_TEMP_LOW} }, /* temperature */
|
||||
MV_DDR_64BIT_BUS_MASK, /* subphys mask */
|
||||
MV_DDR_CFG_SPD, /* ddr configuration data source */
|
||||
NOT_COMBINED, /* ddr twin-die combined*/
|
||||
{ {0} }, /* raw spd data */
|
||||
{0}, /* timing parameters */
|
||||
{ /* electrical configuration */
|
||||
{ /* memory electrical configuration */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
|
||||
{
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
|
||||
MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
|
||||
MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
|
||||
},
|
||||
MV_DDR_DIC_RZQ_DIV7 /* dic */
|
||||
},
|
||||
{ /* phy electrical configuration */
|
||||
MV_DDR_OHM_30, /* data_drv_p */
|
||||
MV_DDR_OHM_30, /* data_drv_n */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_p */
|
||||
MV_DDR_OHM_30, /* ctrl_drv_n */
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_p 1cs */
|
||||
MV_DDR_OHM_120 /* odt_p 2cs */
|
||||
},
|
||||
{
|
||||
MV_DDR_OHM_60, /* odt_n 1cs */
|
||||
MV_DDR_OHM_120 /* odt_n 2cs */
|
||||
},
|
||||
},
|
||||
{ /* mac electrical configuration */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
|
||||
MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
|
||||
MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
|
||||
{
|
||||
/* Return the board topology as defined in the board code */
|
||||
return &board_topology_map;
|
||||
}
|
||||
|
||||
static void mpp_config(void)
|
||||
{
|
||||
uint32_t val;
|
||||
uintptr_t reg;
|
||||
|
||||
/* configure ap mmps 4, 5 to I2C */
|
||||
reg = MVEBU_AP_MPP_CTRL0_7_REG;
|
||||
|
||||
val = mmio_read_32(reg);
|
||||
val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL4_OFFS) |
|
||||
(MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL5_OFFS));
|
||||
val |= ((MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA << MVEBU_AP_MPP_CTRL4_OFFS) |
|
||||
(MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA << MVEBU_AP_MPP_CTRL5_OFFS));
|
||||
|
||||
mmio_write_32(reg, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function may modify the default DRAM parameters
|
||||
* based on information received from SPD or bootloader
|
||||
* configuration located on non volatile storage
|
||||
*/
|
||||
void plat_marvell_dram_update_topology(void)
|
||||
{
|
||||
struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
|
||||
|
||||
INFO("Gathering DRAM information\n");
|
||||
|
||||
if (tm->cfg_src == MV_DDR_CFG_SPD) {
|
||||
/* configure MPPs to enable i2c */
|
||||
mpp_config();
|
||||
/* initialize the MVEBU_AP_I2C_BASE I2C bus */
|
||||
i2c_init((void *)MVEBU_AP_I2C_BASE);
|
||||
/* select SPD memory page 0 to access DRAM configuration */
|
||||
i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
|
||||
/* read data from spd */
|
||||
i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
|
||||
sizeof(tm->spd_data.all_bytes));
|
||||
}
|
||||
}
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <armada_common.h>
|
||||
|
||||
/*
|
||||
* If bootrom is currently at BLE there's no need to include the memory
|
||||
* maps structure at this point
|
||||
*/
|
||||
#include <mvebu_def.h>
|
||||
#ifndef IMAGE_BLE
|
||||
|
||||
/*****************************************************************************
|
||||
* GPIO Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MPP_CONTROL_REGISTER 0xf2440018
|
||||
#define MPP_CONTROL_MPP_SEL_52_MASK 0xf0000
|
||||
#define GPIO_DATA_OUT1_REGISTER 0xf2440140
|
||||
#define GPIO_DATA_OUT_EN_CTRL1_REGISTER 0xf2440144
|
||||
#define GPIO52_MASK 0x100000
|
||||
|
||||
/* Reset PCIe via GPIO number 52 */
|
||||
int marvell_gpio_config(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = mmio_read_32(MPP_CONTROL_REGISTER);
|
||||
reg |= MPP_CONTROL_MPP_SEL_52_MASK;
|
||||
mmio_write_32(MPP_CONTROL_REGISTER, reg);
|
||||
|
||||
reg = mmio_read_32(GPIO_DATA_OUT1_REGISTER);
|
||||
reg |= GPIO52_MASK;
|
||||
mmio_write_32(GPIO_DATA_OUT1_REGISTER, reg);
|
||||
|
||||
reg = mmio_read_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER);
|
||||
reg &= ~GPIO52_MASK;
|
||||
mmio_write_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER, reg);
|
||||
udelay(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* AMB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win amb_memory_map[] = {
|
||||
/* CP1 SPI1 CS0 Direct Mode access */
|
||||
{0xf900, 0x1000000, AMB_SPI1_CS0_ID},
|
||||
};
|
||||
|
||||
int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
*win = amb_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(amb_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* IO WIN Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win io_win_memory_map[] = {
|
||||
/* CP1 (MCI0) internal regs */
|
||||
{0x00000000f4000000, 0x2000000, MCI_0_TID},
|
||||
#ifndef IMAGE_BLE
|
||||
/* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
|
||||
{0x00000000f9000000, 0x2000000, MCI_0_TID},
|
||||
/* PCIe1 on CP1*/
|
||||
{0x00000000fb000000, 0x1000000, MCI_0_TID},
|
||||
/* PCIe2 on CP1*/
|
||||
{0x00000000fc000000, 0x1000000, MCI_0_TID},
|
||||
/* MCI 0 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
|
||||
/* MCI 1 indirect window */
|
||||
{MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_io_win_gcr_target(int ap_index)
|
||||
{
|
||||
return PIDI_TID;
|
||||
}
|
||||
|
||||
int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = io_win_memory_map;
|
||||
if (*win == NULL)
|
||||
*size = 0;
|
||||
else
|
||||
*size = ARRAY_SIZE(io_win_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef IMAGE_BLE
|
||||
/*****************************************************************************
|
||||
* IOB Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win iob_memory_map_cp0[] = {
|
||||
/* CP0 */
|
||||
/* PEX1_X1 window */
|
||||
{0x00000000f7000000, 0x1000000, PEX1_TID},
|
||||
/* PEX2_X1 window */
|
||||
{0x00000000f8000000, 0x1000000, PEX2_TID},
|
||||
/* PEX0_X4 window */
|
||||
{0x00000000f6000000, 0x1000000, PEX0_TID},
|
||||
{0x00000000c0000000, 0x30000000, PEX0_TID},
|
||||
{0x0000000800000000, 0x100000000, PEX0_TID},
|
||||
};
|
||||
|
||||
struct addr_map_win iob_memory_map_cp1[] = {
|
||||
/* CP1 */
|
||||
/* SPI1_CS0 (RUNIT) window */
|
||||
{0x00000000f9000000, 0x1000000, RUNIT_TID},
|
||||
/* PEX1_X1 window */
|
||||
{0x00000000fb000000, 0x1000000, PEX1_TID},
|
||||
/* PEX2_X1 window */
|
||||
{0x00000000fc000000, 0x1000000, PEX2_TID},
|
||||
/* PEX0_X4 window */
|
||||
{0x00000000fa000000, 0x1000000, PEX0_TID}
|
||||
};
|
||||
|
||||
int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
|
||||
uintptr_t base)
|
||||
{
|
||||
switch (base) {
|
||||
case MVEBU_CP_REGS_BASE(0):
|
||||
*win = iob_memory_map_cp0;
|
||||
*size = ARRAY_SIZE(iob_memory_map_cp0);
|
||||
return 0;
|
||||
case MVEBU_CP_REGS_BASE(1):
|
||||
*win = iob_memory_map_cp1;
|
||||
*size = ARRAY_SIZE(iob_memory_map_cp1);
|
||||
return 0;
|
||||
default:
|
||||
*size = 0;
|
||||
*win = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* CCU Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
struct addr_map_win ccu_memory_map[] = {
|
||||
#ifdef IMAGE_BLE
|
||||
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
|
||||
#else
|
||||
#if LLC_SRAM
|
||||
{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
|
||||
#endif
|
||||
{0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
|
||||
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
|
||||
{0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t marvell_get_ccu_gcr_target(int ap)
|
||||
{
|
||||
return DRAM_0_TID;
|
||||
}
|
||||
|
||||
int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
|
||||
uint32_t *size)
|
||||
{
|
||||
*win = ccu_memory_map;
|
||||
*size = ARRAY_SIZE(ccu_memory_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */
|
||||
|
||||
/*****************************************************************************
|
||||
* SKIP IMAGE Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
void *plat_marvell_get_skip_image_data(void)
|
||||
{
|
||||
/* No recovery button on A8k-MCBIN board */
|
||||
return NULL;
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Sartura Ltd.
|
||||
* Author: Luka Kovacic <luka.kovacic@sartura.hr>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <armada_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/ti/uart/uart_16550.h>
|
||||
#include <drivers/console.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Platform specific power off functions
|
||||
* Power off PSU / Send command to power management MCU / ...
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
unsigned char add_xor_checksum(unsigned char *buf, unsigned char xor_len)
|
||||
{
|
||||
unsigned char xor_sum = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < xor_len; i++)
|
||||
xor_sum ^= buf[i];
|
||||
|
||||
return xor_sum;
|
||||
}
|
||||
|
||||
int system_power_off(void)
|
||||
{
|
||||
static console_t console;
|
||||
|
||||
/* WT61P803 MCU system_off_now command */
|
||||
unsigned char system_off_now[4] = { '@', 'C', '0' };
|
||||
int i, len;
|
||||
|
||||
len = sizeof(system_off_now);
|
||||
system_off_now[len - 1] = add_xor_checksum(system_off_now, len);
|
||||
|
||||
console_16550_register(PLAT_MARVELL_UART_BASE + 0x100,
|
||||
PLAT_MARVELL_UART_CLK_IN_HZ, 115200, &console);
|
||||
|
||||
/* Send system_off_now to console */
|
||||
for (i = 0; i < len; i++) {
|
||||
console.putc(system_off_now[i], &console);
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
console.flush(&console);
|
||||
(void)console_unregister(&console);
|
||||
|
||||
mdelay(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MVEBU_DEF_H
|
||||
#define MVEBU_DEF_H
|
||||
|
||||
#include <a8k_plat_def.h>
|
||||
|
||||
#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */
|
||||
#define I2C_SPD_ADDR 0x53 /* Access SPD data */
|
||||
#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */
|
||||
|
||||
#endif /* MVEBU_DEF_H */
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (C) 2018 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
#
|
||||
|
||||
PCI_EP_SUPPORT := 0
|
||||
|
||||
CP_NUM := 2
|
||||
$(eval $(call add_define,CP_NUM))
|
||||
|
||||
DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg
|
||||
|
||||
MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
|
||||
|
||||
BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
|
||||
include plat/marvell/armada/a8k/common/a8k_common.mk
|
||||
|
||||
include plat/marvell/armada/common/marvell_common.mk
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
#
|
||||
# Copyright (C) 2016 - 2020 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
|
||||
PLAT_FAMILY := a8k
|
||||
PLAT_INCLUDE_BASE := include/plat/marvell/armada/$(PLAT_FAMILY)
|
||||
PLAT_COMMON_BASE := plat/marvell/armada/a8k/common
|
||||
MARVELL_DRV_BASE := drivers/marvell
|
||||
MARVELL_COMMON_BASE := plat/marvell/armada/common
|
||||
|
||||
MARVELL_SVC_TEST := 0
|
||||
$(eval $(call add_define,MARVELL_SVC_TEST))
|
||||
|
||||
ERRATA_A72_859971 := 1
|
||||
|
||||
# Enable MSS support for a8k family
|
||||
MSS_SUPPORT := 1
|
||||
$(eval $(call add_define,MSS_SUPPORT))
|
||||
|
||||
# Disable EL3 cache for power management
|
||||
BL31_CACHE_DISABLE := 0
|
||||
$(eval $(call add_define,BL31_CACHE_DISABLE))
|
||||
|
||||
$(eval $(call add_define,PCI_EP_SUPPORT))
|
||||
$(eval $(call assert_boolean,PCI_EP_SUPPORT))
|
||||
|
||||
AP_NUM := 1
|
||||
$(eval $(call add_define,AP_NUM))
|
||||
|
||||
DOIMAGEPATH ?= tools/marvell/doimage
|
||||
DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
|
||||
|
||||
include plat/marvell/marvell.mk
|
||||
include tools/marvell/doimage/doimage.mk
|
||||
|
||||
ifeq (${MARVELL_SECURE_BOOT},1)
|
||||
DOIMAGE_SEC_FLAGS := -c $(DOIMAGE_SEC)
|
||||
DOIMAGE_LIBS_CHECK = \
|
||||
if ! [ -d "/usr/include/mbedtls" ]; then \
|
||||
echo "****************************************" >&2; \
|
||||
echo "Missing mbedTLS installation! " >&2; \
|
||||
echo "Please download it from \"tls.mbed.org\"" >&2; \
|
||||
echo "Alternatively on Debian/Ubuntu system install" >&2; \
|
||||
echo "\"libmbedtls-dev\" package" >&2; \
|
||||
echo "Make sure to use version 2.1.0 or later" >&2; \
|
||||
echo "****************************************" >&2; \
|
||||
exit 1; \
|
||||
else if ! [ -f "/usr/include/libconfig.h" ]; then \
|
||||
echo "********************************************************" >&2; \
|
||||
echo "Missing Libconfig installation!" >&2; \
|
||||
echo "Please download it from \"www.hyperrealm.com/libconfig/\"" >&2; \
|
||||
echo "Alternatively on Debian/Ubuntu system install packages" >&2; \
|
||||
echo "\"libconfig8\" and \"libconfig8-dev\"" >&2; \
|
||||
echo "********************************************************" >&2; \
|
||||
exit 1; \
|
||||
fi \
|
||||
fi
|
||||
else #MARVELL_SECURE_BOOT
|
||||
DOIMAGE_LIBS_CHECK =
|
||||
DOIMAGE_SEC_FLAGS =
|
||||
endif #MARVELL_SECURE_BOOT
|
||||
|
||||
ROM_BIN_EXT ?= $(BUILD_PLAT)/ble.bin
|
||||
DOIMAGE_FLAGS += -b $(ROM_BIN_EXT) $(NAND_DOIMAGE_FLAGS) $(DOIMAGE_SEC_FLAGS)
|
||||
|
||||
# Check whether to build system_power.c for the platform
|
||||
ifneq ("$(wildcard $(BOARD_DIR)/board/system_power.c)","")
|
||||
SYSTEM_POWER_SUPPORT = 1
|
||||
else
|
||||
SYSTEM_POWER_SUPPORT = 0
|
||||
endif
|
||||
|
||||
# This define specifies DDR type for BLE
|
||||
$(eval $(call add_define,CONFIG_DDR4))
|
||||
|
||||
# This define specifies DDR topology for BLE
|
||||
DDR_TOPOLOGY ?= 0
|
||||
$(eval $(call add_define,DDR_TOPOLOGY))
|
||||
|
||||
MARVELL_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
|
||||
drivers/arm/gic/v2/gicv2_main.c \
|
||||
drivers/arm/gic/v2/gicv2_helpers.c \
|
||||
plat/common/plat_gicv2.c
|
||||
|
||||
PLAT_INCLUDES += -I$(BOARD_DIR) \
|
||||
-I$(BOARD_DIR)/board \
|
||||
-I$(CURDIR)/drivers/marvell \
|
||||
-I$(PLAT_COMMON_BASE)/include \
|
||||
-I$(PLAT_INCLUDE_BASE)/common
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := $(PLAT_COMMON_BASE)/aarch64/a8k_common.c \
|
||||
drivers/ti/uart/aarch64/16550_console.S
|
||||
|
||||
ifndef BLE_PORTING_SOURCES
|
||||
BLE_PORTING_SOURCES := $(BOARD_DIR)/board/dram_port.c \
|
||||
$(BOARD_DIR)/board/marvell_plat_config.c
|
||||
endif
|
||||
|
||||
MARVELL_MOCHI_DRV += $(MARVELL_DRV_BASE)/mochi/cp110_setup.c
|
||||
|
||||
BLE_SOURCES := drivers/mentor/i2c/mi2cv.c \
|
||||
$(PLAT_COMMON_BASE)/plat_ble_setup.c \
|
||||
$(MARVELL_MOCHI_DRV) \
|
||||
$(PLAT_COMMON_BASE)/plat_pm.c \
|
||||
$(MARVELL_DRV_BASE)/ap807_clocks_init.c \
|
||||
$(MARVELL_DRV_BASE)/thermal.c \
|
||||
$(PLAT_COMMON_BASE)/plat_thermal.c \
|
||||
$(BLE_PORTING_SOURCES) \
|
||||
$(MARVELL_DRV_BASE)/ccu.c \
|
||||
$(MARVELL_DRV_BASE)/io_win.c
|
||||
|
||||
BL1_SOURCES += $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
|
||||
lib/cpus/aarch64/cortex_a72.S
|
||||
|
||||
MARVELL_DRV := $(MARVELL_DRV_BASE)/io_win.c \
|
||||
$(MARVELL_DRV_BASE)/iob.c \
|
||||
$(MARVELL_DRV_BASE)/mci.c \
|
||||
$(MARVELL_DRV_BASE)/amb_adec.c \
|
||||
$(MARVELL_DRV_BASE)/ccu.c \
|
||||
$(MARVELL_DRV_BASE)/cache_llc.c \
|
||||
$(MARVELL_DRV_BASE)/comphy/phy-comphy-cp110.c \
|
||||
$(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c \
|
||||
$(MARVELL_DRV_BASE)/secure_dfx_access/armada_thermal.c \
|
||||
$(MARVELL_DRV_BASE)/secure_dfx_access/misc_dfx.c \
|
||||
$(MARVELL_DRV_BASE)/ddr_phy_access.c \
|
||||
drivers/rambus/trng_ip_76.c
|
||||
|
||||
ifeq (${MSS_SUPPORT}, 1)
|
||||
MARVELL_DRV += $(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
|
||||
endif
|
||||
|
||||
ifndef BL31_PORTING_SOURCES
|
||||
BL31_PORTING_SOURCES := $(BOARD_DIR)/board/marvell_plat_config.c
|
||||
endif
|
||||
|
||||
ifeq ($(SYSTEM_POWER_SUPPORT),1)
|
||||
BL31_PORTING_SOURCES += $(BOARD_DIR)/board/system_power.c
|
||||
endif
|
||||
|
||||
BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \
|
||||
$(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
|
||||
$(PLAT_COMMON_BASE)/aarch64/plat_arch_config.c \
|
||||
$(PLAT_COMMON_BASE)/plat_pm.c \
|
||||
$(PLAT_COMMON_BASE)/plat_bl31_setup.c \
|
||||
$(MARVELL_COMMON_BASE)/marvell_gicv2.c \
|
||||
$(MARVELL_COMMON_BASE)/mrvl_sip_svc.c \
|
||||
$(MARVELL_COMMON_BASE)/marvell_ddr_info.c \
|
||||
$(BL31_PORTING_SOURCES) \
|
||||
$(MARVELL_DRV) \
|
||||
$(MARVELL_MOCHI_DRV) \
|
||||
$(MARVELL_GIC_SOURCES)
|
||||
|
||||
# Add trace functionality for PM
|
||||
BL31_SOURCES += $(PLAT_COMMON_BASE)/plat_pm_trace.c
|
||||
|
||||
|
||||
ifeq (${MSS_SUPPORT}, 1)
|
||||
# Force builds with BL2 image on a80x0 platforms
|
||||
ifndef SCP_BL2
|
||||
$(error "Error: SCP_BL2 image is mandatory for a8k family")
|
||||
endif
|
||||
|
||||
# MSS (SCP) build
|
||||
include $(PLAT_COMMON_BASE)/mss/mss_a8k.mk
|
||||
endif
|
||||
|
||||
# BLE (ROM context execution code, AKA binary extension)
|
||||
BLE_PATH ?= $(PLAT_COMMON_BASE)/ble
|
||||
|
||||
include ${BLE_PATH}/ble.mk
|
||||
$(eval $(call MAKE_BL,ble))
|
||||
|
||||
clean realclean distclean: mrvl_clean
|
||||
|
||||
.PHONY: mrvl_clean
|
||||
mrvl_clean:
|
||||
@echo " Doimage CLEAN"
|
||||
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${DOIMAGEPATH} clean
|
||||
|
||||
${DOIMAGETOOL}: FORCE
|
||||
@$(DOIMAGE_LIBS_CHECK)
|
||||
${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH}
|
||||
|
||||
${BUILD_PLAT}/${FLASH_IMAGE}: ${ROM_BIN_EXT} ${BUILD_PLAT}/${BOOT_IMAGE} ${DOIMAGETOOL}
|
||||
@${ECHO_BLANK_LINE}
|
||||
@echo "Building flash image"
|
||||
${Q}${DOIMAGETOOL} ${DOIMAGE_FLAGS} ${BUILD_PLAT}/${BOOT_IMAGE} ${BUILD_PLAT}/${FLASH_IMAGE}
|
||||
@${ECHO_BLANK_LINE}
|
||||
@echo "Built $@ successfully"
|
||||
@${ECHO_BLANK_LINE}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <plat_marvell.h>
|
||||
|
||||
|
||||
/* MMU entry for internal (register) space access */
|
||||
#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
|
||||
DEVICE0_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
/*
|
||||
* Table of regions for various BL stages to map using the MMU.
|
||||
*/
|
||||
#if IMAGE_BL1
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MARVELL_MAP_SECURE_RAM,
|
||||
MAP_DEVICE0,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#if IMAGE_BL2
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MARVELL_MAP_SECURE_RAM,
|
||||
MAP_DEVICE0,
|
||||
MARVELL_MAP_DRAM,
|
||||
#ifdef SPD_opteed
|
||||
MARVELL_MAP_OPTEE_CORE_MEM,
|
||||
MARVELL_OPTEE_PAGEABLE_LOAD_MEM,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if IMAGE_BL2U
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MARVELL_MAP_SECURE_RAM,
|
||||
MAP_DEVICE0,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if IMAGE_BLE
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MAP_DEVICE0,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if IMAGE_BL31
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MARVELL_MAP_SECURE_RAM,
|
||||
MAP_DEVICE0,
|
||||
MARVELL_MAP_DRAM,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#if IMAGE_BL32
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MARVELL_MAP_SECURE_RAM,
|
||||
MAP_DEVICE0,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
MARVELL_CASSERT_MMAP;
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/marvell/cache_llc.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#define CCU_HTC_ASET (MVEBU_CCU_BASE(MVEBU_AP0) + 0x264)
|
||||
#define MVEBU_IO_AFFINITY (0xF00)
|
||||
#define MVEBU_SF_REG (MVEBU_REGS_BASE + 0x40)
|
||||
#define MVEBU_SF_EN BIT(8)
|
||||
#define MVEBU_DFX_REG(cluster_id) (MVEBU_REGS_BASE + 0x6F82A0 + \
|
||||
(cluster_id) * 0x4)
|
||||
#define MVEBU_DFX_CLK_EN_POS 0x3
|
||||
#define MVEBU_DFX_CL0_CLK_OFFS 16
|
||||
#define MVEBU_DFX_CL0_CLK_MASK (0xF << MVEBU_DFX_CL0_CLK_OFFS)
|
||||
#define MVEBU_DFX_CL1_CLK_OFFS 8
|
||||
#define MVEBU_DFX_CL1_CLK_MASK (0xF << MVEBU_DFX_CL1_CLK_OFFS)
|
||||
|
||||
#ifdef MVEBU_SOC_AP807
|
||||
static void plat_enable_snoop_filter(void)
|
||||
{
|
||||
int cpu_id = plat_my_core_pos();
|
||||
|
||||
/* Snoop filter needs to be enabled once per cluster */
|
||||
if (cpu_id % 2)
|
||||
return;
|
||||
|
||||
mmio_setbits_32(MVEBU_SF_REG, MVEBU_SF_EN);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MVEBU_SOC_AP807
|
||||
static void plat_config_dfx_clock(void)
|
||||
{
|
||||
int cluster_id = plat_my_core_pos();
|
||||
uint32_t val;
|
||||
|
||||
/* DFX clock needs to be configured once per cluster */
|
||||
if ((cluster_id % PLAT_MAX_CPUS_PER_CLUSTER) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
val = mmio_read_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER));
|
||||
if (cluster_id == 0) {
|
||||
val &= ~MVEBU_DFX_CL0_CLK_MASK;
|
||||
val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL0_CLK_OFFS);
|
||||
} else {
|
||||
val &= ~MVEBU_DFX_CL1_CLK_MASK;
|
||||
val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL1_CLK_OFFS);
|
||||
}
|
||||
mmio_write_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER), val);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void plat_enable_affinity(void)
|
||||
{
|
||||
int cluster_id;
|
||||
int affinity;
|
||||
|
||||
/* set CPU Affinity */
|
||||
cluster_id = plat_my_core_pos() / PLAT_MARVELL_CLUSTER_CORE_COUNT;
|
||||
affinity = (MVEBU_IO_AFFINITY | (1 << cluster_id));
|
||||
mmio_write_32(CCU_HTC_ASET, affinity);
|
||||
|
||||
/* set barier */
|
||||
isb();
|
||||
}
|
||||
|
||||
void marvell_psci_arch_init(int die_index)
|
||||
{
|
||||
#if LLC_ENABLE
|
||||
/* check if LLC is in exclusive mode
|
||||
* as L2 is configured to UniqueClean eviction
|
||||
* (in a8k reset handler)
|
||||
*/
|
||||
if (llc_is_exclusive(0) == 0)
|
||||
ERROR("LLC should be configured to exclusice mode\n");
|
||||
#endif
|
||||
|
||||
/* Enable Affinity */
|
||||
plat_enable_affinity();
|
||||
|
||||
#ifdef MVEBU_SOC_AP807
|
||||
plat_enable_snoop_filter();
|
||||
#else
|
||||
plat_config_dfx_clock();
|
||||
#endif
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <platform_def.h>
|
||||
#include <marvell_pm.h>
|
||||
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl plat_reset_handler
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* This function performs any platform specific actions
|
||||
* needed for a secondary cpu after a cold reset. Right
|
||||
* now this is a stub function.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
mov x0, #0
|
||||
ret
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned long plat_get_my_entrypoint (void);
|
||||
*
|
||||
* Main job of this routine is to distinguish
|
||||
* between a cold and warm boot
|
||||
* For a cold boot, return 0.
|
||||
* For a warm boot, read the mailbox and return the address it contains.
|
||||
*
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
/* Read first word and compare it with magic num */
|
||||
mov_imm x0, PLAT_MARVELL_MAILBOX_BASE
|
||||
ldr x1, [x0]
|
||||
mov_imm x2, MVEBU_MAILBOX_MAGIC_NUM
|
||||
cmp x1, x2
|
||||
beq warm_boot /* If compare failed, return 0, i.e. cold boot */
|
||||
mov x0, #0
|
||||
ret
|
||||
warm_boot:
|
||||
mov_imm x1, MBOX_IDX_SEC_ADDR /* Get the jump address */
|
||||
subs x1, x1, #1
|
||||
mov x2, #(MBOX_IDX_SEC_ADDR * 8)
|
||||
lsl x3, x2, x1
|
||||
add x0, x0, x3
|
||||
ldr x0, [x0]
|
||||
ret
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
|
||||
cmp x0, #MVEBU_PRIMARY_CPU
|
||||
cset w0, eq
|
||||
ret
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_reset_handler (void);
|
||||
*
|
||||
* Platform specific configuration right after cpu is
|
||||
* is our of reset.
|
||||
*
|
||||
* The plat_reset_handler can clobber x0 - x18, x30.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_reset_handler
|
||||
/*
|
||||
* Note: the configurations below should be done before MMU,
|
||||
* I Cache and L2are enabled.
|
||||
* The reset handler is executed right after reset
|
||||
* and before Caches are enabled.
|
||||
*/
|
||||
|
||||
/* Enable L1/L2 ECC and Parity */
|
||||
mrs x5, s3_1_c11_c0_2 /* L2 Ctrl */
|
||||
orr x5, x5, #(1 << 21) /* Enable L1/L2 cache ECC & Parity */
|
||||
msr s3_1_c11_c0_2, x5 /* L2 Ctrl */
|
||||
|
||||
#if LLC_ENABLE
|
||||
/*
|
||||
* Enable L2 UniqueClean evictions
|
||||
* Note: this configuration assumes that LLC is configured
|
||||
* in exclusive mode.
|
||||
* Later on in the code this assumption will be validated
|
||||
*/
|
||||
mrs x5, s3_1_c15_c0_0 /* L2 Ctrl */
|
||||
orr x5, x5, #(1 << 14) /* Enable UniqueClean evictions with data */
|
||||
msr s3_1_c15_c0_0, x5 /* L2 Ctrl */
|
||||
#endif
|
||||
|
||||
/* Instruction Barrier to allow msr command completion */
|
||||
isb
|
||||
|
||||
ret
|
||||
endfunc plat_reset_handler
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
|
||||
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
|
||||
ENTRY(ble_main)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx): ORIGIN = BLE_BASE, LENGTH = BLE_LIMIT - BLE_BASE
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BLE_BASE;
|
||||
|
||||
ro . : {
|
||||
__RO_START__ = .;
|
||||
*ble_main.o(.entry*)
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
__RO_END_UNALIGNED__ = .;
|
||||
__RO_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark start of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_START__ = . ;
|
||||
|
||||
.data . : {
|
||||
__DATA_START__ = .;
|
||||
*(.data*)
|
||||
__DATA_END__ = .;
|
||||
} >RAM
|
||||
|
||||
stacks . (NOLOAD) : {
|
||||
__STACKS_START__ = .;
|
||||
*(tzfw_normal_stacks)
|
||||
__STACKS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
.bss : {
|
||||
__BSS_START__ = .;
|
||||
*(.bss*)
|
||||
__BSS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* Extend the BLE binary to the maximum size allocated for it in platform
|
||||
* definition files and prevent overlapping between BLE BSS section and
|
||||
* additional extensions that can follow the BLE in flash image preamble.
|
||||
* This situation happens for instance when secure extension is added to
|
||||
* the image preamble.
|
||||
*/
|
||||
.fill LOADADDR(.bss) + SIZEOF(.bss) : {
|
||||
FILL(0xDEADC0DE);
|
||||
. = ORIGIN(RAM) + LENGTH(RAM) - 1;
|
||||
BYTE(0x00)
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark end of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_END__ = .;
|
||||
__BLE_END__ = .;
|
||||
|
||||
__BSS_SIZE__ = SIZEOF(.bss);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# Copyright (C) 2018 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
|
||||
MV_DDR_LIB = $(BUILD_PLAT)/ble/mv_ddr_lib.a
|
||||
LIBC_LIB = $(BUILD_PLAT)/lib/libc.a
|
||||
BLE_LIBS = $(MV_DDR_LIB) $(LIBC_LIB)
|
||||
PLAT_MARVELL = plat/marvell/armada
|
||||
|
||||
BLE_SOURCES += $(BLE_PATH)/ble_main.c \
|
||||
$(BLE_PATH)/ble_mem.S \
|
||||
drivers/delay_timer/delay_timer.c \
|
||||
drivers/marvell/iob.c \
|
||||
$(PLAT_MARVELL)/common/aarch64/marvell_helpers.S \
|
||||
$(PLAT_MARVELL)/common/plat_delay_timer.c \
|
||||
$(PLAT_MARVELL)/common/marvell_console.c
|
||||
|
||||
MV_DDR_INCLUDES := -I$(CURDIR)/include \
|
||||
-I$(CURDIR)/include/arch/aarch64 \
|
||||
-I$(CURDIR)/include/lib/libc \
|
||||
-I$(CURDIR)/include/lib/libc/aarch64
|
||||
|
||||
BLE_LINKERFILE := $(BLE_PATH)/ble.ld.S
|
||||
|
||||
BLE_OBJS := $(addprefix $(BUILD_PLAT)/ble/,$(call SOURCES_TO_OBJS,$(BLE_SOURCES)))
|
||||
$(BLE_OBJS): PLAT_INCLUDES += -I$(MV_DDR_PATH)
|
||||
$(BLE_OBJS): $(MV_DDR_LIB)
|
||||
|
||||
$(MV_DDR_LIB): FORCE
|
||||
# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
|
||||
$(if $(value MV_DDR_PATH),,$(error "Platform '$(PLAT)' for BLE requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
|
||||
$(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
|
||||
$(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
|
||||
@+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(MV_DDR_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(BUILD_PLAT)/ble
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/console.h>
|
||||
|
||||
#include <marvell_plat_priv.h>
|
||||
#include <marvell_pm.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
#define BR_FLAG_SILENT 0x1
|
||||
#define SKIP_IMAGE_CODE 0xDEADB002
|
||||
|
||||
void mailbox_clean(void)
|
||||
{
|
||||
uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
|
||||
|
||||
memset(mailbox, 0, PLAT_MARVELL_MAILBOX_SIZE);
|
||||
}
|
||||
|
||||
int exec_ble_main(int bootrom_flags)
|
||||
{
|
||||
int skip = 0;
|
||||
uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
|
||||
|
||||
/*
|
||||
* In some situations, like boot from UART, bootrom will
|
||||
* request to avoid printing to console. in that case don't
|
||||
* initialize the console and prints will be ignored
|
||||
*/
|
||||
if ((bootrom_flags & BR_FLAG_SILENT) == 0)
|
||||
marvell_console_boot_init();
|
||||
|
||||
NOTICE("Starting binary extension\n");
|
||||
|
||||
/* initialize time (for delay functionality) */
|
||||
plat_delay_timer_init();
|
||||
|
||||
ble_plat_setup(&skip);
|
||||
|
||||
/* if there's skip image request, bootrom will load from the image
|
||||
* saved on the next address of the flash
|
||||
*/
|
||||
if (skip)
|
||||
return SKIP_IMAGE_CODE;
|
||||
|
||||
/*
|
||||
* Check if the mailbox magic number is stored at index MBOX_IDX_MAGIC
|
||||
* and the suspend to RAM magic number at index MBOX_IDX_SUSPEND_MAGIC.
|
||||
* If the above is true, this is the recovery from suspend to RAM state.
|
||||
* In such case the mailbox should remain intact, since it stores the
|
||||
* warm boot jump address to be used by the TF-A in BL31.
|
||||
* Othervise the mailbox should be cleaned from a garbage data.
|
||||
*/
|
||||
if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM ||
|
||||
mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE) {
|
||||
NOTICE("Cold boot\n");
|
||||
mailbox_clean();
|
||||
} else {
|
||||
void (*bootrom_exit)(void) =
|
||||
(void (*)(void))mailbox[MBOX_IDX_ROM_EXIT_ADDR];
|
||||
|
||||
INFO("Recovery...\n");
|
||||
/*
|
||||
* If this is recovery from suspend, two things has to be done:
|
||||
* 1. Define the DRAM region as executable memory for preparing
|
||||
* jump to TF-A
|
||||
* 2. Instead of returning control to the BootROM, invalidate
|
||||
* and flush caches, and continue execution at address stored
|
||||
* in the mailbox.
|
||||
* This should be done until the BootROM have a native support
|
||||
* for the system restore flow.
|
||||
*/
|
||||
marvell_ble_prepare_exit();
|
||||
bootrom_exit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* NOTE: don't notify this function, all code must be added to exec_ble_main
|
||||
* in order to keep the end of ble_main as a fixed address.
|
||||
*/
|
||||
int __attribute__ ((section(".entry"))) ble_main(int bootrom_flags)
|
||||
{
|
||||
volatile int ret;
|
||||
|
||||
ret = exec_ble_main(bootrom_flags);
|
||||
return ret;
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <marvell_def.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define PTE_NON_EXEC_OFF 54 /* XN - eXecute Never bit offset - see VMSAv8-64 */
|
||||
|
||||
.globl marvell_ble_prepare_exit
|
||||
|
||||
func marvell_ble_prepare_exit
|
||||
/*
|
||||
* Read the page table base and set the first page to be executable.
|
||||
* This is required for jumping to DRAM for further execution.
|
||||
*/
|
||||
mrs x0, ttbr0_el3
|
||||
ldr x1, [x0]
|
||||
mov x2, #1
|
||||
bic x1, x1, x2, lsl #PTE_NON_EXEC_OFF
|
||||
str x1, [x0]
|
||||
tlbi alle3
|
||||
dsb sy
|
||||
isb
|
||||
ret
|
||||
endfunc marvell_ble_prepare_exit
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef A8K_PLAT_DEF_H
|
||||
#define A8K_PLAT_DEF_H
|
||||
|
||||
#include <marvell_def.h>
|
||||
|
||||
#define MVEBU_PRIMARY_CPU 0x0
|
||||
#define MVEBU_AP0 0x0
|
||||
|
||||
/* APN806 revision ID */
|
||||
#define MVEBU_CSS_GWD_CTRL_IIDR2_REG (MVEBU_REGS_BASE + 0x610FCC)
|
||||
#define GWD_IIDR2_REV_ID_OFFSET 12
|
||||
#define GWD_IIDR2_REV_ID_MASK 0xF
|
||||
#define GWD_IIDR2_CHIP_ID_OFFSET 20
|
||||
#define GWD_IIDR2_CHIP_ID_MASK (0xFFFu << GWD_IIDR2_CHIP_ID_OFFSET)
|
||||
|
||||
#define CHIP_ID_AP806 0x806
|
||||
#define CHIP_ID_AP807 0x807
|
||||
|
||||
#define COUNTER_FREQUENCY 25000000
|
||||
|
||||
#define MVEBU_REGS_BASE 0xF0000000
|
||||
#define MVEBU_REGS_BASE_MASK 0xF0000000
|
||||
#define MVEBU_REGS_BASE_AP(ap) MVEBU_REGS_BASE
|
||||
#define MVEBU_AP_IO_BASE(ap) 0xF2000000
|
||||
#define MVEBU_CP_OFFSET 0x2000000
|
||||
#define MVEBU_CP_REGS_BASE(cp_index) (MVEBU_AP_IO_BASE(0) + \
|
||||
(cp_index) * MVEBU_CP_OFFSET)
|
||||
#define MVEBU_RFU_BASE (MVEBU_REGS_BASE + 0x6F0000)
|
||||
#define MVEBU_IO_WIN_BASE(ap_index) (MVEBU_RFU_BASE)
|
||||
#define MVEBU_IO_WIN_GCR_OFFSET (0x70)
|
||||
#define MVEBU_IO_WIN_MAX_WINS (7)
|
||||
|
||||
/* Misc SoC configurations Base */
|
||||
#define MVEBU_MISC_SOC_BASE (MVEBU_REGS_BASE + 0x6F4300)
|
||||
|
||||
#define MVEBU_CCU_BASE(ap_index) (MVEBU_REGS_BASE + 0x4000)
|
||||
#define MVEBU_CCU_MAX_WINS (8)
|
||||
|
||||
#define MVEBU_LLC_BASE(ap_index) (MVEBU_REGS_BASE + 0x8000)
|
||||
#define MVEBU_DRAM_MAC_BASE (MVEBU_REGS_BASE + 0x20000)
|
||||
#define MVEBU_DRAM_PHY_BASE (MVEBU_REGS_BASE + 0x20000)
|
||||
#define MVEBU_SMMU_BASE (MVEBU_REGS_BASE + 0x100000)
|
||||
#define MVEBU_CP_MPP_REGS(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \
|
||||
0x440000 + ((n) << 2))
|
||||
#define MVEBU_PM_MPP_REGS(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \
|
||||
0x440000 + ((n / 8) << 2))
|
||||
#define MVEBU_CP_GPIO_DATA_OUT(cp_index, n) \
|
||||
(MVEBU_CP_REGS_BASE(cp_index) + \
|
||||
0x440100 + ((n > 31) ? 0x40 : 0x00))
|
||||
#define MVEBU_CP_GPIO_DATA_OUT_EN(cp_index, n) \
|
||||
(MVEBU_CP_REGS_BASE(cp_index) + \
|
||||
0x440104 + ((n > 31) ? 0x40 : 0x00))
|
||||
#define MVEBU_CP_GPIO_DATA_IN(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \
|
||||
0x440110 + ((n > 31) ? 0x40 : 0x00))
|
||||
#define MVEBU_AP_MPP_REGS(n) (MVEBU_RFU_BASE + 0x4000 + ((n) << 2))
|
||||
#define MVEBU_AP_GPIO_REGS (MVEBU_RFU_BASE + 0x5040)
|
||||
#define MVEBU_AP_GPIO_DATA_IN (MVEBU_AP_GPIO_REGS + 0x10)
|
||||
#define MVEBU_AP_I2C_BASE (MVEBU_REGS_BASE + 0x511000)
|
||||
#define MVEBU_CP0_I2C_BASE (MVEBU_CP_REGS_BASE(0) + 0x701000)
|
||||
#define MVEBU_AP_GEN_MGMT_BASE (MVEBU_RFU_BASE + 0x8000)
|
||||
#define MVEBU_AP_EXT_TSEN_BASE (MVEBU_AP_GEN_MGMT_BASE + 0x84)
|
||||
|
||||
#define MVEBU_AP_MC_TRUSTZONE_REG_LOW(ap, win) (MVEBU_REGS_BASE_AP(ap) + \
|
||||
0x20080 + ((win) * 0x8))
|
||||
#define MVEBU_AP_MC_TRUSTZONE_REG_HIGH(ap, win) (MVEBU_REGS_BASE_AP(ap) + \
|
||||
0x20084 + ((win) * 0x8))
|
||||
|
||||
/* MCI indirect access definitions */
|
||||
#define MCI_MAX_UNIT_ID 2
|
||||
/* SoC RFU / IHBx4 Control */
|
||||
#define MCIX4_REG_START_ADDRESS_REG(unit_id) (MVEBU_RFU_BASE + \
|
||||
0x4218 + (unit_id * 0x20))
|
||||
#define MCI_REMAP_OFF_SHIFT 8
|
||||
|
||||
#define MVEBU_MCI_REG_BASE_REMAP(index) (0xFD000000 + \
|
||||
((index) * 0x1000000))
|
||||
|
||||
#define MVEBU_PCIE_X4_MAC_BASE(x) (MVEBU_CP_REGS_BASE(x) + 0x600000)
|
||||
#define MVEBU_COMPHY_BASE(x) (MVEBU_CP_REGS_BASE(x) + 0x441000)
|
||||
#define MVEBU_HPIPE_BASE(x) (MVEBU_CP_REGS_BASE(x) + 0x120000)
|
||||
#define MVEBU_CP_DFX_OFFSET (0x400200)
|
||||
|
||||
/*****************************************************************************
|
||||
* MVEBU memory map related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
/* Aggregate of all devices in the first GB */
|
||||
#define DEVICE0_BASE MVEBU_REGS_BASE
|
||||
#define DEVICE0_SIZE 0x10000000
|
||||
|
||||
/*****************************************************************************
|
||||
* GIC-400 & interrupt handling related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
/* Base MVEBU compatible GIC memory map */
|
||||
#define MVEBU_GICD_BASE 0x210000
|
||||
#define MVEBU_GICC_BASE 0x220000
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* AXI Configuration
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_AXI_ATTR_ARCACHE_OFFSET 4
|
||||
#define MVEBU_AXI_ATTR_ARCACHE_MASK (0xF << \
|
||||
MVEBU_AXI_ATTR_ARCACHE_OFFSET)
|
||||
#define MVEBU_AXI_ATTR_ARDOMAIN_OFFSET 12
|
||||
#define MVEBU_AXI_ATTR_ARDOMAIN_MASK (0x3 << \
|
||||
MVEBU_AXI_ATTR_ARDOMAIN_OFFSET)
|
||||
#define MVEBU_AXI_ATTR_AWCACHE_OFFSET 20
|
||||
#define MVEBU_AXI_ATTR_AWCACHE_MASK (0xF << \
|
||||
MVEBU_AXI_ATTR_AWCACHE_OFFSET)
|
||||
#define MVEBU_AXI_ATTR_AWDOMAIN_OFFSET 28
|
||||
#define MVEBU_AXI_ATTR_AWDOMAIN_MASK (0x3 << \
|
||||
MVEBU_AXI_ATTR_AWDOMAIN_OFFSET)
|
||||
|
||||
/* SATA MBUS to AXI configuration */
|
||||
#define MVEBU_SATA_M2A_AXI_ARCACHE_OFFSET 1
|
||||
#define MVEBU_SATA_M2A_AXI_ARCACHE_MASK (0xF << \
|
||||
MVEBU_SATA_M2A_AXI_ARCACHE_OFFSET)
|
||||
#define MVEBU_SATA_M2A_AXI_AWCACHE_OFFSET 5
|
||||
#define MVEBU_SATA_M2A_AXI_AWCACHE_MASK (0xF << \
|
||||
MVEBU_SATA_M2A_AXI_AWCACHE_OFFSET)
|
||||
|
||||
/* ARM cache attributes */
|
||||
#define CACHE_ATTR_BUFFERABLE 0x1
|
||||
#define CACHE_ATTR_CACHEABLE 0x2
|
||||
#define CACHE_ATTR_READ_ALLOC 0x4
|
||||
#define CACHE_ATTR_WRITE_ALLOC 0x8
|
||||
/* Domain */
|
||||
#define DOMAIN_NON_SHAREABLE 0x0
|
||||
#define DOMAIN_INNER_SHAREABLE 0x1
|
||||
#define DOMAIN_OUTER_SHAREABLE 0x2
|
||||
#define DOMAIN_SYSTEM_SHAREABLE 0x3
|
||||
|
||||
/************************************************************************
|
||||
* Required platform porting definitions common to all
|
||||
* Management Compute SubSystems (MSS)
|
||||
************************************************************************
|
||||
*/
|
||||
/*
|
||||
* Load address of SCP_BL2
|
||||
* SCP_BL2 is loaded to the same place as BL31.
|
||||
* Once SCP_BL2 is transferred to the SCP,
|
||||
* it is discarded and BL31 is loaded over the top.
|
||||
*/
|
||||
#ifdef SCP_IMAGE
|
||||
#define SCP_BL2_BASE BL31_BASE
|
||||
#define SCP_BL2_SIZE BL31_LIMIT
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
enum ap806_sar_target_dev {
|
||||
SAR_PIDI_MCIX2 = 0x0,
|
||||
SAR_MCIX4 = 0x1,
|
||||
SAR_SPI = 0x2,
|
||||
SAR_SD = 0x3,
|
||||
SAR_PIDI_MCIX2_BD = 0x4, /* BootRom disabled */
|
||||
SAR_MCIX4_DB = 0x5, /* BootRom disabled */
|
||||
SAR_SPI_DB = 0x6, /* BootRom disabled */
|
||||
SAR_EMMC = 0x7
|
||||
};
|
||||
|
||||
enum io_win_target_ids {
|
||||
MCI_0_TID = 0x0,
|
||||
MCI_1_TID = 0x1,
|
||||
MCI_2_TID = 0x2,
|
||||
PIDI_TID = 0x3,
|
||||
SPI_TID = 0x4,
|
||||
STM_TID = 0x5,
|
||||
BOOTROM_TID = 0x6,
|
||||
IO_WIN_MAX_TID
|
||||
};
|
||||
|
||||
enum ccu_target_ids {
|
||||
IO_0_TID = 0x00,
|
||||
DRAM_0_TID = 0x03,
|
||||
IO_1_TID = 0x0F,
|
||||
CFG_REG_TID = 0x10,
|
||||
RAR_TID = 0x20,
|
||||
SRAM_TID = 0x40,
|
||||
DRAM_1_TID = 0xC0,
|
||||
CCU_MAX_TID,
|
||||
INVALID_TID = 0xFF
|
||||
};
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* A8K_PLAT_DEF_H */
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#define DRAM_MAX_IFACE 1
|
||||
#define DRAM_CH0_MMAP_LOW_OFFSET 0x20200
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
/* This driver provides I2C support for Marvell A8K and compatible SoCs */
|
||||
|
||||
#ifndef MENTOR_I2C_PLAT_H
|
||||
#define MENTOR_I2C_PLAT_H
|
||||
|
||||
#define CONFIG_SYS_TCLK 250000000
|
||||
#define CONFIG_SYS_I2C_SPEED 100000
|
||||
#define CONFIG_SYS_I2C_SLAVE 0x0
|
||||
|
||||
#define I2C_CAN_UNSTUCK
|
||||
|
||||
struct mentor_i2c_regs {
|
||||
uint32_t slave_address;
|
||||
uint32_t data;
|
||||
uint32_t control;
|
||||
union {
|
||||
uint32_t status; /* when reading */
|
||||
uint32_t baudrate; /* when writing */
|
||||
};
|
||||
uint32_t xtnd_slave_addr;
|
||||
uint32_t reserved[2];
|
||||
uint32_t soft_reset;
|
||||
uint8_t reserved2[0xa0 - 0x20];
|
||||
uint32_t unstuck;
|
||||
};
|
||||
|
||||
#endif /* MENTOR_I2C_PLAT_H */
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef PLAT_MACROS_S
|
||||
#define PLAT_MACROS_S
|
||||
|
||||
#include <marvell_macros.S>
|
||||
|
||||
/*
|
||||
* Required platform porting macros
|
||||
* (Provided by included headers)
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
.endm
|
||||
|
||||
#endif /* PLAT_MACROS_S */
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <stdio.h>
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#include <common/interrupt_props.h>
|
||||
#include <drivers/arm/gic_common.h>
|
||||
|
||||
#include <board_marvell_def.h>
|
||||
#include <mvebu_def.h>
|
||||
|
||||
/*
|
||||
* Most platform porting definitions provided by included headers
|
||||
*/
|
||||
|
||||
/*
|
||||
* DRAM Memory layout:
|
||||
* +-----------------------+
|
||||
* : :
|
||||
* : Linux :
|
||||
* 0x04X00000-->+-----------------------+
|
||||
* | BL3-3(u-boot) |>>}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
* |-----------------------| } |
|
||||
* | BL3-[0,1, 2] | }---------------------------------> |
|
||||
* |-----------------------| } || |
|
||||
* | BL2 | }->FIP (loaded by || |
|
||||
* |-----------------------| } BootROM to DRAM) || |
|
||||
* | FIP_TOC | } || |
|
||||
* 0x04120000-->|-----------------------| || |
|
||||
* | BL1 (RO) | || |
|
||||
* 0x04100000-->+-----------------------+ || |
|
||||
* : : || |
|
||||
* : Trusted SRAM section : \/ |
|
||||
* 0x04040000-->+-----------------------+ Replaced by BL2 +----------------+ |
|
||||
* | BL1 (RW) | <<<<<<<<<<<<<<<< | BL3-1 NOBITS | |
|
||||
* 0x04037000-->|-----------------------| <<<<<<<<<<<<<<<< |----------------| |
|
||||
* | | <<<<<<<<<<<<<<<< | BL3-1 PROGBITS | |
|
||||
* 0x04023000-->|-----------------------| +----------------+ |
|
||||
* | BL2 | |
|
||||
* |-----------------------| |
|
||||
* | | |
|
||||
* 0x04001000-->|-----------------------| |
|
||||
* | Shared | |
|
||||
* 0x04000000-->+-----------------------+ |
|
||||
* : : |
|
||||
* : Linux : |
|
||||
* : : |
|
||||
* |-----------------------| |
|
||||
* | | U-Boot(BL3-3) Loaded by BL2 |
|
||||
* | U-Boot | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
* 0x00000000-->+-----------------------+
|
||||
*
|
||||
* Trusted SRAM section 0x4000000..0x4200000:
|
||||
* ----------------------------------------
|
||||
* SRAM_BASE = 0x4001000
|
||||
* BL2_BASE = 0x4006000
|
||||
* BL2_LIMIT = BL31_BASE
|
||||
* BL31_BASE = 0x4023000 = (64MB + 256KB - 0x1D000)
|
||||
* BL31_PROGBITS_LIMIT = BL1_RW_BASE
|
||||
* BL1_RW_BASE = 0x4037000 = (64MB + 256KB - 0x9000)
|
||||
* BL1_RW_LIMIT = BL31_LIMIT = 0x4040000
|
||||
*
|
||||
*
|
||||
* PLAT_MARVELL_FIP_BASE = 0x4120000
|
||||
*/
|
||||
|
||||
#define PLAT_MARVELL_SRAM_BASE 0xFFE1C048
|
||||
#define PLAT_MARVELL_SRAM_END 0xFFE78000
|
||||
|
||||
#define PLAT_MARVELL_ATF_BASE 0x4000000
|
||||
#define PLAT_MARVELL_ATF_LOAD_ADDR (PLAT_MARVELL_ATF_BASE + \
|
||||
0x100000)
|
||||
|
||||
#define PLAT_MARVELL_FIP_BASE (PLAT_MARVELL_ATF_LOAD_ADDR + \
|
||||
0x20000)
|
||||
#define PLAT_MARVELL_FIP_MAX_SIZE 0x4000000
|
||||
|
||||
#define PLAT_MARVELL_NORTHB_COUNT 1
|
||||
|
||||
#define PLAT_MARVELL_CLUSTER_COUNT U(2)
|
||||
#define PLAT_MARVELL_CLUSTER_CORE_COUNT U(2)
|
||||
|
||||
#define PLAT_MARVELL_CORE_COUNT (PLAT_MARVELL_CLUSTER_COUNT * \
|
||||
PLAT_MARVELL_CLUSTER_CORE_COUNT)
|
||||
|
||||
#define PLAT_MAX_CPUS_PER_CLUSTER PLAT_MARVELL_CLUSTER_CORE_COUNT
|
||||
|
||||
/* Part of DRAM that is used as Trusted ROM */
|
||||
#define PLAT_MARVELL_TRUSTED_ROM_BASE PLAT_MARVELL_ATF_LOAD_ADDR
|
||||
/* 4 MB for FIP image */
|
||||
#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x00400000
|
||||
/* Reserve 12MB for SCP (Secure PayLoad) Trusted RAM
|
||||
* OP-TEE 4MB SHMEM follows this region
|
||||
*/
|
||||
#define PLAT_MARVELL_TRUSTED_RAM_BASE 0x04400000
|
||||
#define PLAT_MARVELL_TRUSTED_RAM_SIZE 0x00C00000 /* 12 MB DRAM */
|
||||
|
||||
#define PLAT_MARVELL_LLC_SRAM_BASE 0x05400000
|
||||
#define PLAT_MARVELL_LLC_SRAM_SIZE 0x00100000 /* 1 MB SRAM */
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
|
||||
* plus a little space for growth.
|
||||
*/
|
||||
#define PLAT_MARVELL_MAX_BL1_RW_SIZE 0xA000
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
|
||||
* little space for growth.
|
||||
*/
|
||||
#define PLAT_MARVELL_MAX_BL2_SIZE 0xF000
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
|
||||
* little space for growth.
|
||||
*/
|
||||
#define PLAT_MARVEL_MAX_BL31_SIZE 0x5D000
|
||||
|
||||
#define PLAT_MARVELL_CPU_ENTRY_ADDR BL1_RO_BASE
|
||||
|
||||
/* GIC related definitions */
|
||||
#define PLAT_MARVELL_GICD_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE)
|
||||
#define PLAT_MARVELL_GICC_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE)
|
||||
|
||||
#define PLAT_MARVELL_G0_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_PIC0, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL)
|
||||
|
||||
#define PLAT_MARVELL_G1S_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL)
|
||||
|
||||
#define PLAT_MARVELL_SHARED_RAM_CACHED 1
|
||||
|
||||
/*
|
||||
* Load address of BL3-3 for this platform port
|
||||
*/
|
||||
#define PLAT_MARVELL_NS_IMAGE_OFFSET 0x0
|
||||
|
||||
/* System Reference Clock*/
|
||||
#define PLAT_REF_CLK_IN_HZ COUNTER_FREQUENCY
|
||||
|
||||
/*
|
||||
* PL011 related constants
|
||||
*/
|
||||
#define PLAT_MARVELL_UART_BASE (MVEBU_REGS_BASE + 0x512000)
|
||||
#define PLAT_MARVELL_UART_CLK_IN_HZ 200000000
|
||||
|
||||
/* Recovery image enable */
|
||||
#define PLAT_RECOVERY_IMAGE_ENABLE 0
|
||||
|
||||
/* Required platform porting definitions */
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
|
||||
|
||||
/* System timer related constants */
|
||||
#define PLAT_MARVELL_NSTIMER_FRAME_ID 1
|
||||
|
||||
/* Mailbox base address (note the lower memory space
|
||||
* is reserved for BLE data)
|
||||
*/
|
||||
#define PLAT_MARVELL_MAILBOX_BASE (MARVELL_SHARED_RAM_BASE \
|
||||
+ 0x400)
|
||||
#define PLAT_MARVELL_MAILBOX_SIZE 0x100
|
||||
#define PLAT_MARVELL_MAILBOX_MAGIC_NUM 0x6D72766C /* mrvl */
|
||||
|
||||
/* Securities */
|
||||
#define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER
|
||||
|
||||
#define MVEBU_PMU_IRQ_WA
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2018 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
#
|
||||
|
||||
PLAT_MARVELL := plat/marvell/armada
|
||||
A8K_MSS_SOURCE := $(PLAT_MARVELL)/a8k/common/mss
|
||||
|
||||
BL2_SOURCES += $(A8K_MSS_SOURCE)/mss_bl2_setup.c \
|
||||
$(MARVELL_MOCHI_DRV)
|
||||
|
||||
BL31_SOURCES += $(A8K_MSS_SOURCE)/mss_pm_ipc.c \
|
||||
$(A8K_MSS_SOURCE)/mss_bl31_setup.c
|
||||
|
||||
PLAT_INCLUDES += -I$(A8K_MSS_SOURCE)
|
||||
|
||||
ifneq (${SCP_BL2},)
|
||||
# This define is used to inidcate the SCP image is present
|
||||
$(eval $(call add_define,SCP_IMAGE))
|
||||
endif
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/marvell/ccu.h>
|
||||
#include <drivers/marvell/mochi/ap_setup.h>
|
||||
#include <drivers/marvell/mochi/cp110_setup.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <armada_common.h>
|
||||
#include <marvell_plat_priv.h> /* timer functionality */
|
||||
#include "mss_defs.h"
|
||||
#include "mss_scp_bootloader.h"
|
||||
|
||||
/* MSS windows configuration */
|
||||
#define MSS_AEBR(base) (base + 0x160)
|
||||
#define MSS_AIBR(base) (base + 0x164)
|
||||
#define MSS_AEBR_MASK 0xFFF
|
||||
#define MSS_AIBR_MASK 0xFFF
|
||||
|
||||
#define MSS_EXTERNAL_SPACE 0x50000000
|
||||
#define MSS_EXTERNAL_ACCESS_BIT 28
|
||||
#define MSS_EXTERNAL_ADDR_MASK 0xfffffff
|
||||
#define MSS_INTERNAL_ACCESS_BIT 28
|
||||
|
||||
struct addr_map_win ccu_mem_map[] = {
|
||||
{MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID}
|
||||
};
|
||||
|
||||
/* Since the scp_bl2 image can contain firmware for cp1 and cp0 coprocessors,
|
||||
* the access to cp0 and cp1 need to be provided. More precisely it is
|
||||
* required to:
|
||||
* - get the information about device id which is stored in CP0 registers
|
||||
* (to distinguish between cases where we have cp0 and cp1 or standalone cp0)
|
||||
* - get the access to cp which is needed for loading fw for cp0/cp1
|
||||
* coprocessors
|
||||
* This function configures ccu windows accordingly.
|
||||
*
|
||||
* Note: there is no need to restore previous ccu configuration, since in next
|
||||
* phase (BL31) the init_ccu will be called (via apn806_init/
|
||||
* bl31_plat_arch_setu) and therefore the ccu configuration will be overwritten.
|
||||
*/
|
||||
static int bl2_plat_mmap_init(void)
|
||||
{
|
||||
int cfg_num, win_id, cfg_idx, cp;
|
||||
|
||||
cfg_num = ARRAY_SIZE(ccu_mem_map);
|
||||
|
||||
/* CCU window-0 should not be counted - it's already used */
|
||||
if (cfg_num > (MVEBU_CCU_MAX_WINS - 1)) {
|
||||
ERROR("BL2: %s: trying to open too many windows\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Enable required CCU windows
|
||||
* Do not touch CCU window 0,
|
||||
* it's used for the internal registers access
|
||||
*/
|
||||
for (cfg_idx = 0, win_id = 1;
|
||||
(win_id < MVEBU_CCU_MAX_WINS) && (cfg_idx < cfg_num); win_id++) {
|
||||
/* Skip already enabled CCU windows */
|
||||
if (ccu_is_win_enabled(MVEBU_AP0, win_id))
|
||||
continue;
|
||||
/* Enable required CCU windows */
|
||||
ccu_win_check(&ccu_mem_map[cfg_idx]);
|
||||
ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id);
|
||||
cfg_idx++;
|
||||
}
|
||||
|
||||
/* Config address for each cp other than cp0 */
|
||||
for (cp = 1; cp < CP_COUNT; cp++)
|
||||
update_cp110_default_win(cp);
|
||||
|
||||
/* There is need to configure IO_WIN windows again to overwrite
|
||||
* temporary configuration done during update_cp110_default_win
|
||||
*/
|
||||
init_io_win(MVEBU_AP0);
|
||||
|
||||
/* Open AMB bridge required for MG access */
|
||||
for (cp = 0; cp < CP_COUNT; cp++)
|
||||
cp110_amb_init(MVEBU_CP_REGS_BASE(cp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
|
||||
* Return 0 on success, -1 otherwise.
|
||||
*****************************************************************************
|
||||
*/
|
||||
int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
|
||||
|
||||
/* initialize time (for delay functionality) */
|
||||
plat_delay_timer_init();
|
||||
|
||||
ret = bl2_plat_mmap_init();
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base,
|
||||
scp_bl2_image_info->image_size);
|
||||
|
||||
if (ret == 0)
|
||||
INFO("BL2: SCP_BL2 transferred to SCP\n");
|
||||
else
|
||||
ERROR("BL2: SCP_BL2 transfer failure\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
|
||||
{
|
||||
return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET;
|
||||
}
|
||||
|
||||
uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx)
|
||||
{
|
||||
return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET;
|
||||
}
|
||||
|
||||
uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
|
||||
{
|
||||
return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET;
|
||||
}
|
||||
|
||||
uint32_t bl2_plat_get_cp_count(int ap_idx)
|
||||
{
|
||||
uint32_t revision = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
|
||||
/* A8040: two CPs.
|
||||
* A7040: one CP.
|
||||
*/
|
||||
if (revision == MVEBU_80X0_DEV_ID ||
|
||||
revision == MVEBU_80X0_CP115_DEV_ID)
|
||||
return 2;
|
||||
else if (revision == MVEBU_CN9130_DEV_ID)
|
||||
return CP_COUNT;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t bl2_plat_get_ap_count(void)
|
||||
{
|
||||
/* A8040 and A7040 have only one AP */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bl2_plat_configure_mss_windows(uintptr_t mss_regs)
|
||||
{
|
||||
/* set AXI External and Internal Address Bus extension */
|
||||
mmio_write_32(MSS_AEBR(mss_regs),
|
||||
((0x0 >> MSS_EXTERNAL_ACCESS_BIT) & MSS_AEBR_MASK));
|
||||
mmio_write_32(MSS_AIBR(mss_regs),
|
||||
((mss_regs >> MSS_INTERNAL_ACCESS_BIT) & MSS_AIBR_MASK));
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <armada_common.h>
|
||||
|
||||
#include "mss_defs.h"
|
||||
|
||||
void mss_start_cp_cm3(int cp)
|
||||
{
|
||||
uint32_t magic;
|
||||
uintptr_t sram = MVEBU_CP_REGS_BASE(cp) + MSS_CP_SRAM_OFFSET;
|
||||
uintptr_t regs = MVEBU_CP_REGS_BASE(cp) + MSS_CP_REGS_OFFSET;
|
||||
|
||||
magic = mmio_read_32(sram);
|
||||
|
||||
/* Make sure the FW was loaded */
|
||||
if (magic != MSS_FW_READY_MAGIC) {
|
||||
return;
|
||||
}
|
||||
|
||||
NOTICE("Starting CP%d MSS CPU\n", cp);
|
||||
/* remove the magic */
|
||||
mmio_write_32(sram, 0);
|
||||
/* Release M3 from reset */
|
||||
mmio_write_32(MSS_M3_RSTCR(regs),
|
||||
(MSS_M3_RSTCR_RST_OFF << MSS_M3_RSTCR_RST_OFFSET));
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MSS_DEFS_H
|
||||
#define MSS_DEFS_H
|
||||
|
||||
#define MSS_DMA_SRCBR(base) (base + 0xC0)
|
||||
#define MSS_DMA_DSTBR(base) (base + 0xC4)
|
||||
#define MSS_DMA_CTRLR(base) (base + 0xC8)
|
||||
#define MSS_M3_RSTCR(base) (base + 0xFC)
|
||||
|
||||
#define MSS_DMA_CTRLR_SIZE_OFFSET (0)
|
||||
#define MSS_DMA_CTRLR_REQ_OFFSET (15)
|
||||
#define MSS_DMA_CTRLR_REQ_SET (1)
|
||||
#define MSS_DMA_CTRLR_ACK_OFFSET (12)
|
||||
#define MSS_DMA_CTRLR_ACK_MASK (0x1)
|
||||
#define MSS_DMA_CTRLR_ACK_READY (1)
|
||||
#define MSS_M3_RSTCR_RST_OFFSET (0)
|
||||
#define MSS_M3_RSTCR_RST_OFF (1)
|
||||
|
||||
#define MSS_FW_READY_MAGIC 0x46575144 /* FWRD */
|
||||
|
||||
#define MSS_AP_REGS_OFFSET 0x00580000
|
||||
#define MSS_CP_SRAM_OFFSET 0x00220000
|
||||
#define MSS_CP_REGS_OFFSET 0x00280000
|
||||
|
||||
void mss_start_cp_cm3(int cp);
|
||||
|
||||
#endif /* MSS_DEFS_H */
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mss_pm_ipc.h>
|
||||
|
||||
/*
|
||||
* SISR is 32 bit interrupt register representing 32 interrupts
|
||||
*
|
||||
* +======+=============+=============+
|
||||
* + Bits + 31 + 30 - 00 +
|
||||
* +======+=============+=============+
|
||||
* + Desc + MSS Msg Int + Reserved +
|
||||
* +======+=============+=============+
|
||||
*/
|
||||
#define MSS_SISR (MVEBU_REGS_BASE + 0x5800D0)
|
||||
#define MSS_SISTR (MVEBU_REGS_BASE + 0x5800D8)
|
||||
|
||||
#define MSS_MSG_INT_MASK (0x80000000)
|
||||
#define MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110)
|
||||
#define MSS_TRIGGER_TIMEOUT (2000)
|
||||
|
||||
/*****************************************************************************
|
||||
* mss_pm_ipc_msg_send
|
||||
*
|
||||
* DESCRIPTION: create and transmit IPC message
|
||||
*****************************************************************************
|
||||
*/
|
||||
int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id,
|
||||
const psci_power_state_t *target_state)
|
||||
{
|
||||
/* Transmit IPC message */
|
||||
#ifndef DISABLE_CLUSTER_LEVEL
|
||||
mv_pm_ipc_msg_tx(channel_id, msg_id,
|
||||
(unsigned int)target_state->pwr_domain_state[
|
||||
MPIDR_AFFLVL1]);
|
||||
#else
|
||||
mv_pm_ipc_msg_tx(channel_id, msg_id, 0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* mss_pm_ipc_msg_trigger
|
||||
*
|
||||
* DESCRIPTION: Trigger IPC message interrupt to MSS
|
||||
*****************************************************************************
|
||||
*/
|
||||
int mss_pm_ipc_msg_trigger(void)
|
||||
{
|
||||
unsigned int timeout;
|
||||
unsigned int t_end;
|
||||
unsigned int t_start = mmio_read_32(MSS_TIMER_BASE);
|
||||
|
||||
mmio_write_32(MSS_SISR, MSS_MSG_INT_MASK);
|
||||
|
||||
do {
|
||||
/* wait while SCP process incoming interrupt */
|
||||
if (mmio_read_32(MSS_SISTR) != MSS_MSG_INT_MASK)
|
||||
break;
|
||||
|
||||
/* check timeout */
|
||||
t_end = mmio_read_32(MSS_TIMER_BASE);
|
||||
|
||||
timeout = ((t_start > t_end) ?
|
||||
(t_start - t_end) : (t_end - t_start));
|
||||
if (timeout > MSS_TRIGGER_TIMEOUT) {
|
||||
ERROR("PM MSG Trigger Timeout\n");
|
||||
break;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MSS_PM_IPC_H
|
||||
#define MSS_PM_IPC_H
|
||||
|
||||
#include <mss_ipc_drv.h>
|
||||
|
||||
/* Currently MSS does not support Cluster level Power Down */
|
||||
#define DISABLE_CLUSTER_LEVEL
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* mss_pm_ipc_msg_send
|
||||
*
|
||||
* DESCRIPTION: create and transmit IPC message
|
||||
*****************************************************************************
|
||||
*/
|
||||
int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id,
|
||||
const psci_power_state_t *target_state);
|
||||
|
||||
/*****************************************************************************
|
||||
* mss_pm_ipc_msg_trigger
|
||||
*
|
||||
* DESCRIPTION: Trigger IPC message interrupt to MSS
|
||||
*****************************************************************************
|
||||
*/
|
||||
int mss_pm_ipc_msg_trigger(void);
|
||||
|
||||
|
||||
#endif /* MSS_PM_IPC_H */
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <plat_marvell.h>
|
||||
|
||||
void marvell_bl1_setup_mpps(void)
|
||||
{
|
||||
/* Enable UART MPPs.
|
||||
** In a normal system, this is done by Bootrom.
|
||||
*/
|
||||
mmio_write_32(MVEBU_AP_MPP_REGS(1), 0x3000);
|
||||
mmio_write_32(MVEBU_AP_MPP_REGS(2), 0x3000);
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/marvell/mci.h>
|
||||
#include <drivers/marvell/mochi/ap_setup.h>
|
||||
#include <drivers/marvell/mochi/cp110_setup.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <armada_common.h>
|
||||
#include <marvell_plat_priv.h>
|
||||
#include <marvell_pm.h>
|
||||
#include <mc_trustzone/mc_trustzone.h>
|
||||
#include <plat_marvell.h>
|
||||
#if MSS_SUPPORT
|
||||
#include <mss_ipc_drv.h>
|
||||
#include <mss_mem.h>
|
||||
#include <mss_defs.h>
|
||||
#endif
|
||||
|
||||
/* In Armada-8k family AP806/AP807, CP0 connected to PIDI
|
||||
* and CP1 connected to IHB via MCI #0
|
||||
*/
|
||||
#define MVEBU_MCI0 0
|
||||
|
||||
static _Bool pm_fw_running;
|
||||
|
||||
/* Set a weak stub for platforms that don't need to configure GPIO */
|
||||
#pragma weak marvell_gpio_config
|
||||
int marvell_gpio_config(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void marvell_bl31_mpp_init(int cp)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* need to do for CP#0 only */
|
||||
if (cp)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* Enable CP0 I2C MPPs (MPP: 37-38)
|
||||
* U-Boot rely on proper MPP settings for I2C EEPROM usage
|
||||
* (only for CP0)
|
||||
*/
|
||||
reg = mmio_read_32(MVEBU_CP_MPP_REGS(0, 4));
|
||||
mmio_write_32(MVEBU_CP_MPP_REGS(0, 4), reg | 0x2200000);
|
||||
}
|
||||
|
||||
#if MSS_SUPPORT
|
||||
void marvell_bl31_mss_init(void)
|
||||
{
|
||||
struct mss_pm_ctrl_block *mss_pm_crtl =
|
||||
(struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE;
|
||||
|
||||
/* Check that the image was loaded successfully */
|
||||
if (mss_pm_crtl->handshake != HOST_ACKNOWLEDGMENT) {
|
||||
NOTICE("MSS PM is not supported in this build\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we got here it means that the PM firmware is running */
|
||||
pm_fw_running = 1;
|
||||
|
||||
INFO("MSS IPC init\n");
|
||||
|
||||
if (mss_pm_crtl->ipc_state == IPC_INITIALIZED)
|
||||
mv_pm_ipc_init(mss_pm_crtl->ipc_base_address | MVEBU_REGS_BASE);
|
||||
}
|
||||
#endif
|
||||
|
||||
_Bool is_pm_fw_running(void)
|
||||
{
|
||||
return pm_fw_running;
|
||||
}
|
||||
|
||||
/* For TrusTzone we treat the "target" field of addr_map_win
|
||||
* struct as attribute
|
||||
*/
|
||||
static const struct addr_map_win tz_map[] = {
|
||||
{PLAT_MARVELL_ATF_BASE, 0x200000, TZ_PERM_ABORT}
|
||||
};
|
||||
|
||||
/* Configure MC TrustZone regions */
|
||||
static void marvell_bl31_security_setup(void)
|
||||
{
|
||||
int tz_nr, win_id;
|
||||
|
||||
tz_nr = ARRAY_SIZE(tz_map);
|
||||
|
||||
for (win_id = 0; win_id < tz_nr; win_id++)
|
||||
tz_enable_win(MVEBU_AP0, tz_map, win_id);
|
||||
}
|
||||
|
||||
/* This function overruns the same function in marvell_bl31_setup.c */
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
int cp;
|
||||
uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
|
||||
|
||||
/* initialize the timer for mdelay/udelay functionality */
|
||||
plat_delay_timer_init();
|
||||
|
||||
/* configure apn806 */
|
||||
ap_init();
|
||||
|
||||
/* In marvell_bl31_plat_arch_setup, el3 mmu is configured.
|
||||
* el3 mmu configuration MUST be called after apn806_init, if not,
|
||||
* this will cause an hang in init_io_win
|
||||
* (after setting the IO windows GCR values).
|
||||
*/
|
||||
if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM ||
|
||||
mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE)
|
||||
marvell_bl31_plat_arch_setup();
|
||||
|
||||
for (cp = 0; cp < CP_COUNT; cp++) {
|
||||
cp110_init(MVEBU_CP_REGS_BASE(cp),
|
||||
STREAM_ID_BASE + (cp * MAX_STREAM_ID_PER_CP));
|
||||
|
||||
marvell_bl31_mpp_init(cp);
|
||||
|
||||
#if MSS_SUPPORT
|
||||
/* Release CP MSS CPU from reset once the CP init is done */
|
||||
mss_start_cp_cm3(cp);
|
||||
#endif
|
||||
}
|
||||
|
||||
for (cp = 1; cp < CP_COUNT; cp++)
|
||||
mci_link_tune(cp - 1);
|
||||
|
||||
#if MSS_SUPPORT
|
||||
/* initialize IPC between MSS and ATF */
|
||||
if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM ||
|
||||
mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE)
|
||||
marvell_bl31_mss_init();
|
||||
#endif
|
||||
/* Configure GPIO */
|
||||
marvell_gpio_config();
|
||||
|
||||
marvell_bl31_security_setup();
|
||||
}
|
||||
+765
@@ -0,0 +1,765 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/marvell/ap807_clocks_init.h>
|
||||
#include <drivers/marvell/aro.h>
|
||||
#include <drivers/marvell/ccu.h>
|
||||
#include <drivers/marvell/io_win.h>
|
||||
#include <drivers/marvell/mochi/ap_setup.h>
|
||||
#include <drivers/marvell/mochi/cp110_setup.h>
|
||||
|
||||
#include <armada_common.h>
|
||||
#include <efuse_def.h>
|
||||
#include <mv_ddr_if.h>
|
||||
#include <mvebu_def.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
/* Register for skip image use */
|
||||
#define SCRATCH_PAD_REG2 0xF06F00A8
|
||||
#define SCRATCH_PAD_SKIP_VAL 0x01
|
||||
#define NUM_OF_GPIO_PER_REG 32
|
||||
|
||||
#define MMAP_SAVE_AND_CONFIG 0
|
||||
#define MMAP_RESTORE_SAVED 1
|
||||
|
||||
/* SAR clock settings */
|
||||
#define MVEBU_AP_SAR_REG_BASE(r) (MVEBU_AP_GEN_MGMT_BASE + 0x200 +\
|
||||
((r) << 2))
|
||||
|
||||
#define SAR_CLOCK_FREQ_MODE_OFFSET (0)
|
||||
#define SAR_CLOCK_FREQ_MODE_MASK (0x1f << SAR_CLOCK_FREQ_MODE_OFFSET)
|
||||
#define SAR_PIDI_LOW_SPEED_OFFSET (20)
|
||||
#define SAR_PIDI_LOW_SPEED_MASK (1 << SAR_PIDI_LOW_SPEED_OFFSET)
|
||||
#define SAR_PIDI_LOW_SPEED_SHIFT (15)
|
||||
#define SAR_PIDI_LOW_SPEED_SET (1 << SAR_PIDI_LOW_SPEED_SHIFT)
|
||||
|
||||
#define FREQ_MODE_AP_SAR_REG_NUM (0)
|
||||
#define SAR_CLOCK_FREQ_MODE(v) (((v) & SAR_CLOCK_FREQ_MODE_MASK) >> \
|
||||
SAR_CLOCK_FREQ_MODE_OFFSET)
|
||||
|
||||
#define AVS_I2C_EEPROM_ADDR 0x57 /* EEPROM */
|
||||
#define AVS_EN_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x130)
|
||||
#define AVS_ENABLE_OFFSET (0)
|
||||
#define AVS_SOFT_RESET_OFFSET (2)
|
||||
#define AVS_TARGET_DELTA_OFFSET (21)
|
||||
|
||||
#ifndef MVEBU_SOC_AP807
|
||||
/* AP806 SVC bits */
|
||||
#define AVS_LOW_VDD_LIMIT_OFFSET (4)
|
||||
#define AVS_HIGH_VDD_LIMIT_OFFSET (12)
|
||||
#define AVS_VDD_LOW_LIMIT_MASK (0xFF << AVS_LOW_VDD_LIMIT_OFFSET)
|
||||
#define AVS_VDD_HIGH_LIMIT_MASK (0xFF << AVS_HIGH_VDD_LIMIT_OFFSET)
|
||||
#else
|
||||
/* AP807 SVC bits */
|
||||
#define AVS_LOW_VDD_LIMIT_OFFSET (3)
|
||||
#define AVS_HIGH_VDD_LIMIT_OFFSET (13)
|
||||
#define AVS_VDD_LOW_LIMIT_MASK (0x3FF << AVS_LOW_VDD_LIMIT_OFFSET)
|
||||
#define AVS_VDD_HIGH_LIMIT_MASK (0x3FF << AVS_HIGH_VDD_LIMIT_OFFSET)
|
||||
#endif
|
||||
|
||||
/* VDD limit is 0.9V for A70x0 @ CPU frequency < 1600MHz */
|
||||
#define AVS_A7K_LOW_CLK_VALUE ((0x80 << AVS_TARGET_DELTA_OFFSET) | \
|
||||
(0x1A << AVS_HIGH_VDD_LIMIT_OFFSET) | \
|
||||
(0x1A << AVS_LOW_VDD_LIMIT_OFFSET) | \
|
||||
(0x1 << AVS_SOFT_RESET_OFFSET) | \
|
||||
(0x1 << AVS_ENABLE_OFFSET))
|
||||
/* VDD limit is 1.0V for all A80x0 devices */
|
||||
#define AVS_A8K_CLK_VALUE ((0x80 << AVS_TARGET_DELTA_OFFSET) | \
|
||||
(0x24 << AVS_HIGH_VDD_LIMIT_OFFSET) | \
|
||||
(0x24 << AVS_LOW_VDD_LIMIT_OFFSET) | \
|
||||
(0x1 << AVS_SOFT_RESET_OFFSET) | \
|
||||
(0x1 << AVS_ENABLE_OFFSET))
|
||||
|
||||
/* VDD is 0.88V for 2GHz clock on CN913x devices */
|
||||
#define AVS_AP807_CLK_VALUE ((0x80UL << 24) | \
|
||||
(0x2dc << 13) | \
|
||||
(0x2dc << 3) | \
|
||||
(0x1 << AVS_SOFT_RESET_OFFSET) | \
|
||||
(0x1 << AVS_ENABLE_OFFSET))
|
||||
|
||||
/*
|
||||
* - Identification information in the LD-0 eFuse:
|
||||
* DRO: LD0[74:65] - Not used by the SW
|
||||
* Revision: LD0[78:75] - Not used by the SW
|
||||
* Bin: LD0[80:79] - Not used by the SW
|
||||
* SW Revision: LD0[115:113]
|
||||
* Cluster 1 PWR: LD0[193] - if set to 1, power down CPU Cluster-1
|
||||
* resulting in 2 CPUs active only (7020)
|
||||
*/
|
||||
/* Offsets for 2 efuse fields combined into single 64-bit value [125:63] */
|
||||
#define EFUSE_AP_LD0_DRO_OFFS 2 /* LD0[74:65] */
|
||||
#define EFUSE_AP_LD0_DRO_MASK 0x3FF
|
||||
#define EFUSE_AP_LD0_REVID_OFFS 12 /* LD0[78:75] */
|
||||
#define EFUSE_AP_LD0_REVID_MASK 0xF
|
||||
#define EFUSE_AP_LD0_BIN_OFFS 16 /* LD0[80:79] */
|
||||
#define EFUSE_AP_LD0_BIN_MASK 0x3
|
||||
#define EFUSE_AP_LD0_SWREV_MASK 0x7
|
||||
|
||||
#ifndef MVEBU_SOC_AP807
|
||||
/* AP806 AVS work points in the LD0 eFuse
|
||||
* SVC1 work point: LD0[88:81]
|
||||
* SVC2 work point: LD0[96:89]
|
||||
* SVC3 work point: LD0[104:97]
|
||||
* SVC4 work point: LD0[112:105]
|
||||
*/
|
||||
#define EFUSE_AP_LD0_SVC1_OFFS 18 /* LD0[88:81] */
|
||||
#define EFUSE_AP_LD0_SVC2_OFFS 26 /* LD0[96:89] */
|
||||
#define EFUSE_AP_LD0_SVC3_OFFS 34 /* LD0[104:97] */
|
||||
#define EFUSE_AP_LD0_WP_MASK 0xFF
|
||||
#define EFUSE_AP_LD0_SWREV_OFFS 50 /* LD0[115:113] */
|
||||
#else
|
||||
/* AP807 AVS work points in the LD0 eFuse
|
||||
* SVC1 work point: LD0[91:81]
|
||||
* SVC2 work point: LD0[102:92]
|
||||
* SVC3 work point: LD0[113:103]
|
||||
*/
|
||||
#define EFUSE_AP_LD0_SVC1_OFFS 18 /* LD0[91:81] */
|
||||
#define EFUSE_AP_LD0_SVC2_OFFS 29 /* LD0[102:92] */
|
||||
#define EFUSE_AP_LD0_SVC3_OFFS 40 /* LD0[113:103] */
|
||||
#define EFUSE_AP_LD0_WP_MASK 0x7FF /* 10 data,1 parity */
|
||||
#define EFUSE_AP_LD0_SWREV_OFFS 51 /* LD0[116:114] */
|
||||
#endif
|
||||
|
||||
#define EFUSE_AP_LD0_SVC4_OFFS 42 /* LD0[112:105] */
|
||||
|
||||
#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS 4
|
||||
|
||||
#if MARVELL_SVC_TEST
|
||||
#define MVEBU_CP_MPP_CTRL37_OFFS 20
|
||||
#define MVEBU_CP_MPP_CTRL38_OFFS 24
|
||||
#define MVEBU_CP_MPP_I2C_FUNC 2
|
||||
#define MVEBU_MPP_CTRL_MASK 0xf
|
||||
#endif
|
||||
|
||||
/* Return the AP revision of the chip */
|
||||
static unsigned int ble_get_ap_type(void)
|
||||
{
|
||||
unsigned int chip_rev_id;
|
||||
|
||||
chip_rev_id = mmio_read_32(MVEBU_CSS_GWD_CTRL_IIDR2_REG);
|
||||
chip_rev_id = ((chip_rev_id & GWD_IIDR2_CHIP_ID_MASK) >>
|
||||
GWD_IIDR2_CHIP_ID_OFFSET);
|
||||
|
||||
return chip_rev_id;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* The routine allows to save the CCU and IO windows configuration during DRAM
|
||||
* setup and restore them afterwards before exiting the BLE stage.
|
||||
* Such window configuration is required since not all default settings coming
|
||||
* from the HW and the BootROM allow access to peripherals connected to
|
||||
* all available CPn components.
|
||||
* For instance, when the boot device is located on CP0, the IO window to CP1
|
||||
* is not opened automatically by the HW and if the DRAM SPD is located on CP1
|
||||
* i2c channel, it cannot be read at BLE stage.
|
||||
* Therefore the DRAM init procedure have to provide access to all available
|
||||
* CPn peripherals during the BLE stage by setting the CCU IO window to all
|
||||
* CPnph addresses and by enabling the IO windows accordingly.
|
||||
* Additionally this function configures the CCU GCR to DRAM, which allows
|
||||
* usage or more than 4GB DRAM as it configured by the default CCU DRAM window.
|
||||
*
|
||||
* IN:
|
||||
* MMAP_SAVE_AND_CONFIG - save the existing configuration and update it
|
||||
* MMAP_RESTORE_SAVED - restore saved configuration
|
||||
* OUT:
|
||||
* NONE
|
||||
****************************************************************************
|
||||
*/
|
||||
static void ble_plat_mmap_config(int restore)
|
||||
{
|
||||
if (restore == MMAP_RESTORE_SAVED) {
|
||||
/* Restore all orig. settings that were modified by BLE stage */
|
||||
ccu_restore_win_all(MVEBU_AP0);
|
||||
/* Restore CCU */
|
||||
iow_restore_win_all(MVEBU_AP0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store original values */
|
||||
ccu_save_win_all(MVEBU_AP0);
|
||||
/* Save CCU */
|
||||
iow_save_win_all(MVEBU_AP0);
|
||||
|
||||
init_ccu(MVEBU_AP0);
|
||||
/* The configuration saved, now all the changes can be done */
|
||||
init_io_win(MVEBU_AP0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Setup Adaptive Voltage Switching - this is required for some platforms
|
||||
****************************************************************************
|
||||
*/
|
||||
#if !MARVELL_SVC_TEST
|
||||
static void ble_plat_avs_config(void)
|
||||
{
|
||||
uint32_t freq_mode, device_id;
|
||||
uint32_t avs_val = 0;
|
||||
|
||||
freq_mode =
|
||||
SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
|
||||
FREQ_MODE_AP_SAR_REG_NUM)));
|
||||
/* Check which SoC is running and act accordingly */
|
||||
if (ble_get_ap_type() == CHIP_ID_AP807) {
|
||||
|
||||
avs_val = AVS_AP807_CLK_VALUE;
|
||||
|
||||
} else {
|
||||
/* Check which SoC is running and act accordingly */
|
||||
device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
|
||||
switch (device_id) {
|
||||
case MVEBU_80X0_DEV_ID:
|
||||
case MVEBU_80X0_CP115_DEV_ID:
|
||||
/* Always fix the default AVS value on A80x0 */
|
||||
avs_val = AVS_A8K_CLK_VALUE;
|
||||
break;
|
||||
case MVEBU_70X0_DEV_ID:
|
||||
case MVEBU_70X0_CP115_DEV_ID:
|
||||
/* Fix AVS for CPU clocks lower than 1600MHz on A70x0 */
|
||||
if ((freq_mode > CPU_1600_DDR_900_RCLK_900_2) &&
|
||||
(freq_mode < CPU_DDR_RCLK_INVALID))
|
||||
avs_val = AVS_A7K_LOW_CLK_VALUE;
|
||||
break;
|
||||
default:
|
||||
ERROR("Unsupported Device ID 0x%x\n", device_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (avs_val) {
|
||||
VERBOSE("AVS: Setting AVS CTRL to 0x%x\n", avs_val);
|
||||
mmio_write_32(AVS_EN_CTRL_REG, avs_val);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* Update or override current AVS work point value using data stored in EEPROM
|
||||
* This is only required by QA/validation flows and activated by
|
||||
* MARVELL_SVC_TEST flag.
|
||||
*
|
||||
* The function is expected to be called twice.
|
||||
*
|
||||
* First time with AVS value of 0 for testing if the EEPROM requests completely
|
||||
* override the AVS value and bypass the eFuse test
|
||||
*
|
||||
* Second time - with non-zero AVS value obtained from eFuses as an input.
|
||||
* In this case the EEPROM may contain AVS correction value (either positive
|
||||
* or negative) that is added to the input AVS value and returned back for
|
||||
* further processing.
|
||||
******************************************************************************
|
||||
*/
|
||||
static uint32_t avs_update_from_eeprom(uint32_t avs_workpoint)
|
||||
{
|
||||
uint32_t new_wp = avs_workpoint;
|
||||
#if MARVELL_SVC_TEST
|
||||
/* ---------------------------------------------------------------------
|
||||
* EEPROM | Data description (avs_step)
|
||||
* address |
|
||||
* ---------------------------------------------------------------------
|
||||
* 0x120 | AVS workpoint correction value
|
||||
* | if not 0 and not 0xff, correct the AVS taken from eFuse
|
||||
* | by the number of steps indicated by bit[6:0]
|
||||
* | bit[7] defines correction direction.
|
||||
* | If bit[7]=1, add the value from bit[6:0] to AVS workpoint,
|
||||
* | othervise substruct this value from AVS workpoint.
|
||||
* ---------------------------------------------------------------------
|
||||
* 0x121 | AVS workpoint override value
|
||||
* | Override the AVS workpoint with the value stored in this
|
||||
* | byte. When running on AP806, the AVS workpoint is 7 bits
|
||||
* | wide and override value is valid when bit[6:0] holds
|
||||
* | value greater than zero and smaller than 0x33.
|
||||
* | When running on AP807, the AVS workpoint is 10 bits wide.
|
||||
* | Additional 2 MSB bits are supplied by EEPROM byte 0x122.
|
||||
* | AVS override value is valid when byte @ 0x121 and bit[1:0]
|
||||
* | of byte @ 0x122 combined have non-zero value.
|
||||
* ---------------------------------------------------------------------
|
||||
* 0x122 | Extended AVS workpoint override value
|
||||
* | Valid only for AP807 platforms and must be less than 0x4
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
static uint8_t avs_step[3] = {0};
|
||||
uintptr_t reg;
|
||||
uint32_t val;
|
||||
unsigned int ap_type = ble_get_ap_type();
|
||||
|
||||
/* Always happens on second call to this function */
|
||||
if (avs_workpoint != 0) {
|
||||
/* Get correction steps from the EEPROM */
|
||||
if ((avs_step[0] != 0) && (avs_step[0] != 0xff)) {
|
||||
NOTICE("AVS request to step %s by 0x%x from old 0x%x\n",
|
||||
avs_step[0] & 0x80 ? "DOWN" : "UP",
|
||||
avs_step[0] & 0x7f, new_wp);
|
||||
if (avs_step[0] & 0x80)
|
||||
new_wp -= avs_step[0] & 0x7f;
|
||||
else
|
||||
new_wp += avs_step[0] & 0x7f;
|
||||
}
|
||||
|
||||
return new_wp;
|
||||
}
|
||||
|
||||
/* AVS values are located in EEPROM
|
||||
* at CP0 i2c bus #0, device 0x57 offset 0x120
|
||||
* The SDA and SCK pins of CP0 i2c-0: MPP[38:37], i2c function 0x2.
|
||||
*/
|
||||
reg = MVEBU_CP_MPP_REGS(0, 4);
|
||||
val = mmio_read_32(reg);
|
||||
val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
|
||||
(MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
|
||||
val |= (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL37_OFFS) |
|
||||
(MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL38_OFFS);
|
||||
mmio_write_32(reg, val);
|
||||
|
||||
/* Init CP0 i2c-0 */
|
||||
i2c_init((void *)(MVEBU_CP0_I2C_BASE));
|
||||
|
||||
/* Read EEPROM only once at the fist call! */
|
||||
i2c_read(AVS_I2C_EEPROM_ADDR, 0x120, 2, avs_step, 3);
|
||||
NOTICE("== SVC test build ==\n");
|
||||
NOTICE("EEPROM holds values 0x%x, 0x%x and 0x%x\n",
|
||||
avs_step[0], avs_step[1], avs_step[2]);
|
||||
|
||||
/* Override the AVS value? */
|
||||
if ((ap_type != CHIP_ID_AP807) && (avs_step[1] < 0x33)) {
|
||||
/* AP806 - AVS is 7 bits */
|
||||
new_wp = avs_step[1];
|
||||
|
||||
} else if (ap_type == CHIP_ID_AP807 && (avs_step[2] < 0x4)) {
|
||||
/* AP807 - AVS is 10 bits */
|
||||
new_wp = avs_step[2];
|
||||
new_wp <<= 8;
|
||||
new_wp |= avs_step[1];
|
||||
}
|
||||
|
||||
if (new_wp == 0)
|
||||
NOTICE("Ignore BAD AVS Override value in EEPROM!\n");
|
||||
else
|
||||
NOTICE("Override AVS by EEPROM value 0x%x\n", new_wp);
|
||||
#endif /* MARVELL_SVC_TEST */
|
||||
return new_wp;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* SVC flow - v0.10
|
||||
* The feature is intended to configure AVS value according to eFuse values
|
||||
* that are burned individually for each SoC during the test process.
|
||||
* Primary AVS value is stored in HD efuse and processed on power on
|
||||
* by the HW engine
|
||||
* Secondary AVS value is located in LD efuse and contains 4 work points for
|
||||
* various CPU frequencies.
|
||||
* The Secondary AVS value is only taken into account if the SW Revision stored
|
||||
* in the efuse is greater than 0 and the CPU is running in a certain speed.
|
||||
****************************************************************************
|
||||
*/
|
||||
static void ble_plat_svc_config(void)
|
||||
{
|
||||
uint32_t reg_val, avs_workpoint, freq_pidi_mode;
|
||||
uint64_t efuse;
|
||||
uint32_t device_id, single_cluster;
|
||||
uint16_t svc[4], perr[4], i, sw_ver;
|
||||
uint8_t avs_data_bits, min_sw_ver, svc_fields;
|
||||
unsigned int ap_type;
|
||||
|
||||
/* Get test EERPOM data */
|
||||
avs_workpoint = avs_update_from_eeprom(0);
|
||||
if (avs_workpoint)
|
||||
goto set_aws_wp;
|
||||
|
||||
/* Set access to LD0 */
|
||||
reg_val = mmio_read_32(MVEBU_AP_EFUSE_SRV_CTRL_REG);
|
||||
reg_val &= ~EFUSE_SRV_CTRL_LD_SELECT_MASK;
|
||||
mmio_write_32(MVEBU_AP_EFUSE_SRV_CTRL_REG, reg_val);
|
||||
|
||||
/* Obtain the value of LD0[125:63] */
|
||||
efuse = mmio_read_32(MVEBU_AP_LDX_125_95_EFUSE_OFFS);
|
||||
efuse <<= 32;
|
||||
efuse |= mmio_read_32(MVEBU_AP_LDX_94_63_EFUSE_OFFS);
|
||||
|
||||
/* SW Revision:
|
||||
* Starting from SW revision 1 the SVC flow is supported.
|
||||
* SW version 0 (efuse not programmed) should follow the
|
||||
* regular AVS update flow.
|
||||
*/
|
||||
sw_ver = (efuse >> EFUSE_AP_LD0_SWREV_OFFS) & EFUSE_AP_LD0_SWREV_MASK;
|
||||
if (sw_ver < 1) {
|
||||
NOTICE("SVC: SW Revision 0x%x. SVC is not supported\n", sw_ver);
|
||||
#if MARVELL_SVC_TEST
|
||||
NOTICE("SVC_TEST: AVS bypassed\n");
|
||||
|
||||
#else
|
||||
ble_plat_avs_config();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Frequency mode from SAR */
|
||||
freq_pidi_mode = SAR_CLOCK_FREQ_MODE(
|
||||
mmio_read_32(
|
||||
MVEBU_AP_SAR_REG_BASE(
|
||||
FREQ_MODE_AP_SAR_REG_NUM)));
|
||||
|
||||
/* Decode all SVC work points */
|
||||
svc[0] = (efuse >> EFUSE_AP_LD0_SVC1_OFFS) & EFUSE_AP_LD0_WP_MASK;
|
||||
svc[1] = (efuse >> EFUSE_AP_LD0_SVC2_OFFS) & EFUSE_AP_LD0_WP_MASK;
|
||||
svc[2] = (efuse >> EFUSE_AP_LD0_SVC3_OFFS) & EFUSE_AP_LD0_WP_MASK;
|
||||
|
||||
/* Fetch AP type to distinguish between AP806 and AP807 */
|
||||
ap_type = ble_get_ap_type();
|
||||
|
||||
if (ap_type != CHIP_ID_AP807) {
|
||||
svc[3] = (efuse >> EFUSE_AP_LD0_SVC4_OFFS)
|
||||
& EFUSE_AP_LD0_WP_MASK;
|
||||
INFO("SVC: Efuse WP: [0]=0x%x, [1]=0x%x, [2]=0x%x, [3]=0x%x\n",
|
||||
svc[0], svc[1], svc[2], svc[3]);
|
||||
avs_data_bits = 7;
|
||||
min_sw_ver = 2; /* parity check from sw revision 2 */
|
||||
svc_fields = 4;
|
||||
} else {
|
||||
INFO("SVC: Efuse WP: [0]=0x%x, [1]=0x%x, [2]=0x%x\n",
|
||||
svc[0], svc[1], svc[2]);
|
||||
avs_data_bits = 10;
|
||||
min_sw_ver = 1; /* parity check required from sw revision 1 */
|
||||
svc_fields = 3;
|
||||
}
|
||||
|
||||
/* Validate parity of SVC workpoint values */
|
||||
for (i = 0; i < svc_fields; i++) {
|
||||
uint8_t parity, bit;
|
||||
perr[i] = 0;
|
||||
|
||||
for (bit = 1, parity = (svc[i] & 1); bit < avs_data_bits; bit++)
|
||||
parity ^= (svc[i] >> bit) & 1;
|
||||
|
||||
/* From SW version 1 or 2 (AP806/AP807), check parity */
|
||||
if ((sw_ver >= min_sw_ver) &&
|
||||
(parity != ((svc[i] >> avs_data_bits) & 1)))
|
||||
perr[i] = 1; /* register the error */
|
||||
}
|
||||
|
||||
single_cluster = mmio_read_32(MVEBU_AP_LDX_220_189_EFUSE_OFFS);
|
||||
single_cluster = (single_cluster >> EFUSE_AP_LD0_CLUSTER_DOWN_OFFS) & 1;
|
||||
|
||||
device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
|
||||
if (device_id == MVEBU_80X0_DEV_ID ||
|
||||
device_id == MVEBU_80X0_CP115_DEV_ID) {
|
||||
/* A8040/A8020 */
|
||||
NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
|
||||
single_cluster == 0 ? "8040" : "8020", freq_pidi_mode);
|
||||
switch (freq_pidi_mode) {
|
||||
case CPU_1800_DDR_1050_RCLK_1050:
|
||||
if (perr[1])
|
||||
goto perror;
|
||||
avs_workpoint = svc[1];
|
||||
break;
|
||||
case CPU_1600_DDR_1050_RCLK_1050:
|
||||
case CPU_1600_DDR_900_RCLK_900_2:
|
||||
if (perr[2])
|
||||
goto perror;
|
||||
avs_workpoint = svc[2];
|
||||
break;
|
||||
case CPU_1300_DDR_800_RCLK_800:
|
||||
case CPU_1300_DDR_650_RCLK_650:
|
||||
if (perr[3])
|
||||
goto perror;
|
||||
avs_workpoint = svc[3];
|
||||
break;
|
||||
case CPU_2000_DDR_1200_RCLK_1200:
|
||||
case CPU_2000_DDR_1050_RCLK_1050:
|
||||
default:
|
||||
if (perr[0])
|
||||
goto perror;
|
||||
avs_workpoint = svc[0];
|
||||
break;
|
||||
}
|
||||
} else if (device_id == MVEBU_70X0_DEV_ID ||
|
||||
device_id == MVEBU_70X0_CP115_DEV_ID) {
|
||||
/* A7040/A7020/A6040 */
|
||||
NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
|
||||
single_cluster == 0 ? "7040" : "7020", freq_pidi_mode);
|
||||
switch (freq_pidi_mode) {
|
||||
case CPU_1400_DDR_800_RCLK_800:
|
||||
if (single_cluster) {/* 7020 */
|
||||
if (perr[1])
|
||||
goto perror;
|
||||
avs_workpoint = svc[1];
|
||||
} else {
|
||||
if (perr[0])
|
||||
goto perror;
|
||||
avs_workpoint = svc[0];
|
||||
}
|
||||
break;
|
||||
case CPU_1200_DDR_800_RCLK_800:
|
||||
if (single_cluster) {/* 7020 */
|
||||
if (perr[2])
|
||||
goto perror;
|
||||
avs_workpoint = svc[2];
|
||||
} else {
|
||||
if (perr[1])
|
||||
goto perror;
|
||||
avs_workpoint = svc[1];
|
||||
}
|
||||
break;
|
||||
case CPU_800_DDR_800_RCLK_800:
|
||||
case CPU_1000_DDR_800_RCLK_800:
|
||||
if (single_cluster) {/* 7020 */
|
||||
if (perr[3])
|
||||
goto perror;
|
||||
avs_workpoint = svc[3];
|
||||
} else {
|
||||
if (perr[2])
|
||||
goto perror;
|
||||
avs_workpoint = svc[2];
|
||||
}
|
||||
break;
|
||||
case CPU_600_DDR_800_RCLK_800:
|
||||
if (perr[3])
|
||||
goto perror;
|
||||
avs_workpoint = svc[3]; /* Same for 6040 and 7020 */
|
||||
break;
|
||||
case CPU_1600_DDR_800_RCLK_800: /* 7020 only */
|
||||
default:
|
||||
if (single_cluster) {/* 7020 */
|
||||
if (perr[0])
|
||||
goto perror;
|
||||
avs_workpoint = svc[0];
|
||||
} else {
|
||||
#if MARVELL_SVC_TEST
|
||||
reg_val = mmio_read_32(AVS_EN_CTRL_REG);
|
||||
avs_workpoint = (reg_val &
|
||||
AVS_VDD_LOW_LIMIT_MASK) >>
|
||||
AVS_LOW_VDD_LIMIT_OFFSET;
|
||||
NOTICE("7040 1600Mhz, avs = 0x%x\n",
|
||||
avs_workpoint);
|
||||
#else
|
||||
NOTICE("SVC: AVS work point not changed\n");
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (device_id == MVEBU_3900_DEV_ID) {
|
||||
NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
|
||||
"3900", freq_pidi_mode);
|
||||
switch (freq_pidi_mode) {
|
||||
case CPU_1600_DDR_1200_RCLK_1200:
|
||||
if (perr[0])
|
||||
goto perror;
|
||||
avs_workpoint = svc[0];
|
||||
break;
|
||||
case CPU_1300_DDR_800_RCLK_800:
|
||||
if (perr[1])
|
||||
goto perror;
|
||||
avs_workpoint = svc[1];
|
||||
break;
|
||||
default:
|
||||
if (perr[0])
|
||||
goto perror;
|
||||
avs_workpoint = svc[0];
|
||||
break;
|
||||
}
|
||||
} else if (device_id == MVEBU_CN9130_DEV_ID) {
|
||||
NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
|
||||
"CN913x", freq_pidi_mode);
|
||||
switch (freq_pidi_mode) {
|
||||
case CPU_2200_DDR_1200_RCLK_1200:
|
||||
if (perr[0])
|
||||
goto perror;
|
||||
avs_workpoint = svc[0];
|
||||
break;
|
||||
case CPU_2000_DDR_1200_RCLK_1200:
|
||||
if (perr[1])
|
||||
goto perror;
|
||||
avs_workpoint = svc[1];
|
||||
break;
|
||||
case CPU_1600_DDR_1200_RCLK_1200:
|
||||
if (perr[2])
|
||||
goto perror;
|
||||
avs_workpoint = svc[2];
|
||||
break;
|
||||
default:
|
||||
ERROR("SVC: Unsupported Frequency 0x%x\n",
|
||||
freq_pidi_mode);
|
||||
return;
|
||||
|
||||
}
|
||||
} else {
|
||||
ERROR("SVC: Unsupported Device ID 0x%x\n", device_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set AVS control if needed */
|
||||
if (avs_workpoint == 0) {
|
||||
ERROR("SVC: You are using a frequency setup which is\n");
|
||||
ERROR("Not supported by this device\n");
|
||||
ERROR("This may result in malfunction of the device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove parity bit */
|
||||
if (ap_type != CHIP_ID_AP807)
|
||||
avs_workpoint &= 0x7F;
|
||||
else
|
||||
avs_workpoint &= 0x3FF;
|
||||
|
||||
/* Update WP from EEPROM if needed */
|
||||
avs_workpoint = avs_update_from_eeprom(avs_workpoint);
|
||||
|
||||
set_aws_wp:
|
||||
reg_val = mmio_read_32(AVS_EN_CTRL_REG);
|
||||
NOTICE("SVC: AVS work point changed from 0x%x to 0x%x\n",
|
||||
(reg_val & AVS_VDD_LOW_LIMIT_MASK) >> AVS_LOW_VDD_LIMIT_OFFSET,
|
||||
avs_workpoint);
|
||||
reg_val &= ~(AVS_VDD_LOW_LIMIT_MASK | AVS_VDD_HIGH_LIMIT_MASK);
|
||||
reg_val |= 0x1 << AVS_ENABLE_OFFSET;
|
||||
reg_val |= avs_workpoint << AVS_HIGH_VDD_LIMIT_OFFSET;
|
||||
reg_val |= avs_workpoint << AVS_LOW_VDD_LIMIT_OFFSET;
|
||||
mmio_write_32(AVS_EN_CTRL_REG, reg_val);
|
||||
return;
|
||||
|
||||
perror:
|
||||
ERROR("Failed SVC WP[%d] parity check!\n", i);
|
||||
ERROR("Ignoring the WP values\n");
|
||||
}
|
||||
|
||||
#if PLAT_RECOVERY_IMAGE_ENABLE
|
||||
static int ble_skip_image_i2c(struct skip_image *skip_im)
|
||||
{
|
||||
ERROR("skipping image using i2c is not supported\n");
|
||||
/* not supported */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ble_skip_image_other(struct skip_image *skip_im)
|
||||
{
|
||||
ERROR("implementation missing for skip image request\n");
|
||||
/* not supported, make your own implementation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ble_skip_image_gpio(struct skip_image *skip_im)
|
||||
{
|
||||
unsigned int val;
|
||||
unsigned int mpp_address = 0;
|
||||
unsigned int offset = 0;
|
||||
|
||||
switch (skip_im->info.test.cp_ap) {
|
||||
case(CP):
|
||||
mpp_address = MVEBU_CP_GPIO_DATA_IN(skip_im->info.test.cp_index,
|
||||
skip_im->info.gpio.num);
|
||||
if (skip_im->info.gpio.num > NUM_OF_GPIO_PER_REG)
|
||||
offset = skip_im->info.gpio.num - NUM_OF_GPIO_PER_REG;
|
||||
else
|
||||
offset = skip_im->info.gpio.num;
|
||||
break;
|
||||
case(AP):
|
||||
mpp_address = MVEBU_AP_GPIO_DATA_IN;
|
||||
offset = skip_im->info.gpio.num;
|
||||
break;
|
||||
}
|
||||
|
||||
val = mmio_read_32(mpp_address);
|
||||
val &= (1 << offset);
|
||||
if ((!val && skip_im->info.gpio.button_state == HIGH) ||
|
||||
(val && skip_im->info.gpio.button_state == LOW)) {
|
||||
mmio_write_32(SCRATCH_PAD_REG2, SCRATCH_PAD_SKIP_VAL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks if there's a skip image request:
|
||||
* return values:
|
||||
* 1: (true) images request been made.
|
||||
* 0: (false) no image request been made.
|
||||
*/
|
||||
static int ble_skip_current_image(void)
|
||||
{
|
||||
struct skip_image *skip_im;
|
||||
|
||||
/*fetching skip image info*/
|
||||
skip_im = (struct skip_image *)plat_marvell_get_skip_image_data();
|
||||
|
||||
if (skip_im == NULL)
|
||||
return 0;
|
||||
|
||||
/* check if skipping image request has already been made */
|
||||
if (mmio_read_32(SCRATCH_PAD_REG2) == SCRATCH_PAD_SKIP_VAL)
|
||||
return 0;
|
||||
|
||||
switch (skip_im->detection_method) {
|
||||
case GPIO:
|
||||
return ble_skip_image_gpio(skip_im);
|
||||
case I2C:
|
||||
return ble_skip_image_i2c(skip_im);
|
||||
case USER_DEFINED:
|
||||
return ble_skip_image_other(skip_im);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int ble_plat_setup(int *skip)
|
||||
{
|
||||
int ret, cp;
|
||||
unsigned int freq_mode;
|
||||
|
||||
/* Power down unused CPUs */
|
||||
plat_marvell_early_cpu_powerdown();
|
||||
|
||||
/*
|
||||
* Save the current CCU configuration and make required changes:
|
||||
* - Allow access to DRAM larger than 4GB
|
||||
* - Open memory access to all CPn peripherals
|
||||
*/
|
||||
ble_plat_mmap_config(MMAP_SAVE_AND_CONFIG);
|
||||
|
||||
#if PLAT_RECOVERY_IMAGE_ENABLE
|
||||
/* Check if there's a skip request to bootRom recovery Image */
|
||||
if (ble_skip_current_image()) {
|
||||
/* close memory access to all CPn peripherals. */
|
||||
ble_plat_mmap_config(MMAP_RESTORE_SAVED);
|
||||
*skip = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/* Do required CP-110 setups for BLE stage */
|
||||
cp110_ble_init(MVEBU_CP_REGS_BASE(0));
|
||||
|
||||
/* Config address for each cp other than cp0 */
|
||||
for (cp = 1; cp < CP_COUNT; cp++)
|
||||
update_cp110_default_win(cp);
|
||||
|
||||
/* Setup AVS */
|
||||
ble_plat_svc_config();
|
||||
|
||||
/* read clk option from sampled-at-reset register */
|
||||
freq_mode =
|
||||
SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
|
||||
FREQ_MODE_AP_SAR_REG_NUM)));
|
||||
|
||||
/* work with PLL clock driver in AP807 */
|
||||
if (ble_get_ap_type() == CHIP_ID_AP807)
|
||||
ap807_clocks_init(freq_mode);
|
||||
|
||||
/* Do required AP setups for BLE stage */
|
||||
ap_ble_init();
|
||||
|
||||
/* Update DRAM topology (scan DIMM SPDs) */
|
||||
plat_marvell_dram_update_topology();
|
||||
|
||||
/* Kick it in */
|
||||
ret = dram_init();
|
||||
|
||||
/* Restore the original CCU configuration before exit from BLE */
|
||||
ble_plat_mmap_config(MMAP_RESTORE_SAVED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
+853
@@ -0,0 +1,853 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/marvell/cache_llc.h>
|
||||
#include <lib/bakery_lock.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <armada_common.h>
|
||||
#include <marvell_pm.h>
|
||||
#if MSS_SUPPORT
|
||||
#include <mss_pm_ipc.h>
|
||||
#endif
|
||||
#include <plat_marvell.h>
|
||||
#include <plat_pm_trace.h>
|
||||
|
||||
#define MVEBU_PRIVATE_UID_REG 0x30
|
||||
#define MVEBU_RFU_GLOBL_SW_RST 0x84
|
||||
#define MVEBU_CCU_RVBAR(cpu) (MVEBU_REGS_BASE + 0x640 + (cpu * 4))
|
||||
#define MVEBU_CCU_CPU_UN_RESET(cpu) (MVEBU_REGS_BASE + 0x650 + (cpu * 4))
|
||||
|
||||
#define MPIDR_CPU_GET(mpidr) ((mpidr) & MPIDR_CPU_MASK)
|
||||
#define MPIDR_CLUSTER_GET(mpidr) MPIDR_AFFLVL1_VAL((mpidr))
|
||||
|
||||
#define MVEBU_GPIO_MASK(index) (1 << (index % 32))
|
||||
#define MVEBU_MPP_MASK(index) (0xF << (4 * (index % 8)))
|
||||
#define MVEBU_GPIO_VALUE(index, value) (value << (index % 32))
|
||||
|
||||
#define MVEBU_USER_CMD_0_REG (MVEBU_DRAM_MAC_BASE + 0x20)
|
||||
#define MVEBU_USER_CMD_CH0_OFFSET 28
|
||||
#define MVEBU_USER_CMD_CH0_MASK (1 << MVEBU_USER_CMD_CH0_OFFSET)
|
||||
#define MVEBU_USER_CMD_CH0_EN (1 << MVEBU_USER_CMD_CH0_OFFSET)
|
||||
#define MVEBU_USER_CMD_CS_OFFSET 24
|
||||
#define MVEBU_USER_CMD_CS_MASK (0xF << MVEBU_USER_CMD_CS_OFFSET)
|
||||
#define MVEBU_USER_CMD_CS_ALL (0xF << MVEBU_USER_CMD_CS_OFFSET)
|
||||
#define MVEBU_USER_CMD_SR_OFFSET 6
|
||||
#define MVEBU_USER_CMD_SR_MASK (0x3 << MVEBU_USER_CMD_SR_OFFSET)
|
||||
#define MVEBU_USER_CMD_SR_ENTER (0x1 << MVEBU_USER_CMD_SR_OFFSET)
|
||||
#define MVEBU_MC_PWR_CTRL_REG (MVEBU_DRAM_MAC_BASE + 0x54)
|
||||
#define MVEBU_MC_AC_ON_DLY_OFFSET 8
|
||||
#define MVEBU_MC_AC_ON_DLY_MASK (0xF << MVEBU_MC_AC_ON_DLY_OFFSET)
|
||||
#define MVEBU_MC_AC_ON_DLY_DEF_VAR (8 << MVEBU_MC_AC_ON_DLY_OFFSET)
|
||||
#define MVEBU_MC_AC_OFF_DLY_OFFSET 4
|
||||
#define MVEBU_MC_AC_OFF_DLY_MASK (0xF << MVEBU_MC_AC_OFF_DLY_OFFSET)
|
||||
#define MVEBU_MC_AC_OFF_DLY_DEF_VAR (0xC << MVEBU_MC_AC_OFF_DLY_OFFSET)
|
||||
#define MVEBU_MC_PHY_AUTO_OFF_OFFSET 0
|
||||
#define MVEBU_MC_PHY_AUTO_OFF_MASK (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET)
|
||||
#define MVEBU_MC_PHY_AUTO_OFF_EN (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET)
|
||||
|
||||
/* this lock synchronize AP multiple cores execution with MSS */
|
||||
DEFINE_BAKERY_LOCK(pm_sys_lock);
|
||||
|
||||
/* Weak definitions may be overridden in specific board */
|
||||
#pragma weak plat_marvell_get_pm_cfg
|
||||
|
||||
/* AP806 CPU power down /power up definitions */
|
||||
enum CPU_ID {
|
||||
CPU0,
|
||||
CPU1,
|
||||
CPU2,
|
||||
CPU3
|
||||
};
|
||||
|
||||
#define REG_WR_VALIDATE_TIMEOUT (2000)
|
||||
|
||||
#define FEATURE_DISABLE_STATUS_REG \
|
||||
(MVEBU_REGS_BASE + 0x6F8230)
|
||||
#define FEATURE_DISABLE_STATUS_CPU_CLUSTER_OFFSET 4
|
||||
#define FEATURE_DISABLE_STATUS_CPU_CLUSTER_MASK \
|
||||
(0x1 << FEATURE_DISABLE_STATUS_CPU_CLUSTER_OFFSET)
|
||||
|
||||
#ifdef MVEBU_SOC_AP807
|
||||
#define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 1
|
||||
#define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 0
|
||||
#else
|
||||
#define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 0
|
||||
#define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 31
|
||||
#endif
|
||||
|
||||
#define PWRC_CPUN_CR_REG(cpu_id) \
|
||||
(MVEBU_REGS_BASE + 0x680000 + (cpu_id * 0x10))
|
||||
#define PWRC_CPUN_CR_PWR_DN_RQ_MASK \
|
||||
(0x1 << PWRC_CPUN_CR_PWR_DN_RQ_OFFSET)
|
||||
#define PWRC_CPUN_CR_ISO_ENABLE_OFFSET 16
|
||||
#define PWRC_CPUN_CR_ISO_ENABLE_MASK \
|
||||
(0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)
|
||||
#define PWRC_CPUN_CR_LDO_BYPASS_RDY_MASK \
|
||||
(0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET)
|
||||
|
||||
#define CCU_B_PRCRN_REG(cpu_id) \
|
||||
(MVEBU_REGS_BASE + 0x1A50 + \
|
||||
((cpu_id / 2) * (0x400)) + ((cpu_id % 2) * 4))
|
||||
#define CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET 0
|
||||
#define CCU_B_PRCRN_CPUPORESET_STATIC_MASK \
|
||||
(0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET)
|
||||
|
||||
/* power switch fingers */
|
||||
#define AP807_PWRC_LDO_CR0_REG \
|
||||
(MVEBU_REGS_BASE + 0x680000 + 0x100)
|
||||
#define AP807_PWRC_LDO_CR0_OFFSET 16
|
||||
#define AP807_PWRC_LDO_CR0_MASK \
|
||||
(0xff << AP807_PWRC_LDO_CR0_OFFSET)
|
||||
#define AP807_PWRC_LDO_CR0_VAL 0xfc
|
||||
|
||||
/*
|
||||
* Power down CPU:
|
||||
* Used to reduce power consumption, and avoid SoC unnecessary temperature rise.
|
||||
*/
|
||||
static int plat_marvell_cpu_powerdown(int cpu_id)
|
||||
{
|
||||
uint32_t reg_val;
|
||||
int exit_loop = REG_WR_VALIDATE_TIMEOUT;
|
||||
|
||||
INFO("Powering down CPU%d\n", cpu_id);
|
||||
|
||||
/* 1. Isolation enable */
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
reg_val |= 0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET;
|
||||
mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
|
||||
|
||||
/* 2. Read and check Isolation enabled - verify bit set to 1 */
|
||||
do {
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
exit_loop--;
|
||||
} while (!(reg_val & (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)) &&
|
||||
exit_loop > 0);
|
||||
|
||||
/* 3. Switch off CPU power */
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
reg_val &= ~PWRC_CPUN_CR_PWR_DN_RQ_MASK;
|
||||
mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
|
||||
|
||||
/* 4. Read and check Switch Off - verify bit set to 0 */
|
||||
exit_loop = REG_WR_VALIDATE_TIMEOUT;
|
||||
do {
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
exit_loop--;
|
||||
} while (reg_val & PWRC_CPUN_CR_PWR_DN_RQ_MASK && exit_loop > 0);
|
||||
|
||||
if (exit_loop <= 0)
|
||||
goto cpu_poweroff_error;
|
||||
|
||||
/* 5. De-Assert power ready */
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
reg_val &= ~PWRC_CPUN_CR_LDO_BYPASS_RDY_MASK;
|
||||
mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
|
||||
|
||||
/* 6. Assert CPU POR reset */
|
||||
reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id));
|
||||
reg_val &= ~CCU_B_PRCRN_CPUPORESET_STATIC_MASK;
|
||||
mmio_write_32(CCU_B_PRCRN_REG(cpu_id), reg_val);
|
||||
|
||||
/* 7. Read and poll on Validate the CPU is out of reset */
|
||||
exit_loop = REG_WR_VALIDATE_TIMEOUT;
|
||||
do {
|
||||
reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id));
|
||||
exit_loop--;
|
||||
} while (reg_val & CCU_B_PRCRN_CPUPORESET_STATIC_MASK && exit_loop > 0);
|
||||
|
||||
if (exit_loop <= 0)
|
||||
goto cpu_poweroff_error;
|
||||
|
||||
INFO("Successfully powered down CPU%d\n", cpu_id);
|
||||
|
||||
return 0;
|
||||
|
||||
cpu_poweroff_error:
|
||||
ERROR("ERROR: Can't power down CPU%d\n", cpu_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power down CPUs 1-3 at early boot stage,
|
||||
* to reduce power consumption and SoC temperature.
|
||||
* This is triggered by BLE prior to DDR initialization.
|
||||
*
|
||||
* Note:
|
||||
* All CPUs will be powered up by plat_marvell_cpu_powerup on Linux boot stage,
|
||||
* which is triggered by PSCI ops (pwr_domain_on).
|
||||
*/
|
||||
int plat_marvell_early_cpu_powerdown(void)
|
||||
{
|
||||
uint32_t cpu_cluster_status =
|
||||
mmio_read_32(FEATURE_DISABLE_STATUS_REG) &
|
||||
FEATURE_DISABLE_STATUS_CPU_CLUSTER_MASK;
|
||||
/* if cpu_cluster_status bit is set,
|
||||
* that means we have only single cluster
|
||||
*/
|
||||
int cluster_count = cpu_cluster_status ? 1 : 2;
|
||||
|
||||
INFO("Powering off unused CPUs\n");
|
||||
|
||||
/* CPU1 is in AP806 cluster-0, which always exists, so power it down */
|
||||
if (plat_marvell_cpu_powerdown(CPU1) == -1)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* CPU2-3 are in AP806 2nd cluster (cluster-1),
|
||||
* which doesn't exists in dual-core systems.
|
||||
* so need to check if we have dual-core (single cluster)
|
||||
* or quad-code (2 clusters)
|
||||
*/
|
||||
if (cluster_count == 2) {
|
||||
/* CPU2-3 are part of 2nd cluster */
|
||||
if (plat_marvell_cpu_powerdown(CPU2) == -1)
|
||||
return -1;
|
||||
if (plat_marvell_cpu_powerdown(CPU3) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power up CPU - part of Linux boot stage
|
||||
*/
|
||||
static int plat_marvell_cpu_powerup(u_register_t mpidr)
|
||||
{
|
||||
uint32_t reg_val;
|
||||
int cpu_id = MPIDR_CPU_GET(mpidr),
|
||||
cluster = MPIDR_CLUSTER_GET(mpidr);
|
||||
int exit_loop = REG_WR_VALIDATE_TIMEOUT;
|
||||
|
||||
/* calculate absolute CPU ID */
|
||||
cpu_id = cluster * PLAT_MARVELL_CLUSTER_CORE_COUNT + cpu_id;
|
||||
|
||||
INFO("Powering on CPU%d\n", cpu_id);
|
||||
|
||||
#ifdef MVEBU_SOC_AP807
|
||||
/* Activate 2 power switch fingers */
|
||||
reg_val = mmio_read_32(AP807_PWRC_LDO_CR0_REG);
|
||||
reg_val &= ~(AP807_PWRC_LDO_CR0_MASK);
|
||||
reg_val |= (AP807_PWRC_LDO_CR0_VAL << AP807_PWRC_LDO_CR0_OFFSET);
|
||||
mmio_write_32(AP807_PWRC_LDO_CR0_REG, reg_val);
|
||||
udelay(100);
|
||||
#endif
|
||||
|
||||
/* 1. Switch CPU power ON */
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
reg_val |= 0x1 << PWRC_CPUN_CR_PWR_DN_RQ_OFFSET;
|
||||
mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
|
||||
|
||||
/* 2. Wait for CPU on, up to 100 uSec: */
|
||||
udelay(100);
|
||||
|
||||
/* 3. Assert power ready */
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
reg_val |= 0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET;
|
||||
mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
|
||||
|
||||
/* 4. Read & Validate power ready
|
||||
* used in order to generate 16 Host CPU cycles
|
||||
*/
|
||||
do {
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
exit_loop--;
|
||||
} while (!(reg_val & (0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET)) &&
|
||||
exit_loop > 0);
|
||||
|
||||
if (exit_loop <= 0)
|
||||
goto cpu_poweron_error;
|
||||
|
||||
/* 5. Isolation disable */
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
reg_val &= ~PWRC_CPUN_CR_ISO_ENABLE_MASK;
|
||||
mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
|
||||
|
||||
/* 6. Read and check Isolation enabled - verify bit set to 1 */
|
||||
exit_loop = REG_WR_VALIDATE_TIMEOUT;
|
||||
do {
|
||||
reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
|
||||
exit_loop--;
|
||||
} while ((reg_val & (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)) &&
|
||||
exit_loop > 0);
|
||||
|
||||
/* 7. De Assert CPU POR reset & Core reset */
|
||||
reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id));
|
||||
reg_val |= 0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET;
|
||||
mmio_write_32(CCU_B_PRCRN_REG(cpu_id), reg_val);
|
||||
|
||||
/* 8. Read & Validate CPU POR reset */
|
||||
exit_loop = REG_WR_VALIDATE_TIMEOUT;
|
||||
do {
|
||||
reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id));
|
||||
exit_loop--;
|
||||
} while (!(reg_val & (0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET)) &&
|
||||
exit_loop > 0);
|
||||
|
||||
if (exit_loop <= 0)
|
||||
goto cpu_poweron_error;
|
||||
|
||||
INFO("Successfully powered on CPU%d\n", cpu_id);
|
||||
|
||||
return 0;
|
||||
|
||||
cpu_poweron_error:
|
||||
ERROR("ERROR: Can't power up CPU%d\n", cpu_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int plat_marvell_cpu_on(u_register_t mpidr)
|
||||
{
|
||||
int cpu_id;
|
||||
int cluster;
|
||||
|
||||
/* Set barierr */
|
||||
dsbsy();
|
||||
|
||||
/* Get cpu number - use CPU ID */
|
||||
cpu_id = MPIDR_CPU_GET(mpidr);
|
||||
|
||||
/* Get cluster number - use affinity level 1 */
|
||||
cluster = MPIDR_CLUSTER_GET(mpidr);
|
||||
|
||||
/* Set CPU private UID */
|
||||
mmio_write_32(MVEBU_REGS_BASE + MVEBU_PRIVATE_UID_REG, cluster + 0x4);
|
||||
|
||||
/* Set the cpu start address to BL1 entry point (align to 0x10000) */
|
||||
mmio_write_32(MVEBU_CCU_RVBAR(cpu_id),
|
||||
PLAT_MARVELL_CPU_ENTRY_ADDR >> 16);
|
||||
|
||||
/* Get the cpu out of reset */
|
||||
mmio_write_32(MVEBU_CCU_CPU_UN_RESET(cpu_id), 0x10001);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A8K handler called to check the validity of the power state
|
||||
* parameter.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static int a8k_validate_power_state(unsigned int power_state,
|
||||
psci_power_state_t *req_state)
|
||||
{
|
||||
int pstate = psci_get_pstate_type(power_state);
|
||||
int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
|
||||
int i;
|
||||
|
||||
if (pwr_lvl > PLAT_MAX_PWR_LVL)
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
/* Sanity check the requested state */
|
||||
if (pstate == PSTATE_TYPE_STANDBY) {
|
||||
/*
|
||||
* It's possible to enter standby only on power level 0
|
||||
* Ignore any other power level.
|
||||
*/
|
||||
if (pwr_lvl != MARVELL_PWR_LVL0)
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
req_state->pwr_domain_state[MARVELL_PWR_LVL0] =
|
||||
MARVELL_LOCAL_STATE_RET;
|
||||
} else {
|
||||
for (i = MARVELL_PWR_LVL0; i <= pwr_lvl; i++)
|
||||
req_state->pwr_domain_state[i] =
|
||||
MARVELL_LOCAL_STATE_OFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* We expect the 'state id' to be zero.
|
||||
*/
|
||||
if (psci_get_pstate_id(power_state))
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A8K handler called when a CPU is about to enter standby.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static void a8k_cpu_standby(plat_local_state_t cpu_state)
|
||||
{
|
||||
if (!is_pm_fw_running()) {
|
||||
ERROR("%s: needs to be implemented\n", __func__);
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A8K handler called when a power domain is about to be turned on. The
|
||||
* mpidr determines the CPU to be turned on.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static int a8k_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
/* Power up CPU (CPUs 1-3 are powered off at start of BLE) */
|
||||
plat_marvell_cpu_powerup(mpidr);
|
||||
|
||||
#if MSS_SUPPORT
|
||||
if (is_pm_fw_running()) {
|
||||
unsigned int target =
|
||||
((mpidr & 0xFF) + (((mpidr >> 8) & 0xFF) * 2));
|
||||
|
||||
/*
|
||||
* pm system synchronization - used to synchronize
|
||||
* multiple core access to MSS
|
||||
*/
|
||||
bakery_lock_get(&pm_sys_lock);
|
||||
|
||||
/* send CPU ON IPC Message to MSS */
|
||||
mss_pm_ipc_msg_send(target, PM_IPC_MSG_CPU_ON, 0);
|
||||
|
||||
/* trigger IPC message to MSS */
|
||||
mss_pm_ipc_msg_trigger();
|
||||
|
||||
/* pm system synchronization */
|
||||
bakery_lock_release(&pm_sys_lock);
|
||||
|
||||
/* trace message */
|
||||
PM_TRACE(TRACE_PWR_DOMAIN_ON | target);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* proprietary CPU ON exection flow */
|
||||
plat_marvell_cpu_on(mpidr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A8K handler called to validate the entry point.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static int a8k_validate_ns_entrypoint(uintptr_t entrypoint)
|
||||
{
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A8K handler called when a power domain is about to be turned off. The
|
||||
* target_state encodes the power state that each level should transition to.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static void a8k_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
#if MSS_SUPPORT
|
||||
if (is_pm_fw_running()) {
|
||||
unsigned int idx = plat_my_core_pos();
|
||||
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
/* pm system synchronization - used to synchronize multiple
|
||||
* core access to MSS
|
||||
*/
|
||||
bakery_lock_get(&pm_sys_lock);
|
||||
|
||||
/* send CPU OFF IPC Message to MSS */
|
||||
mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_OFF, target_state);
|
||||
|
||||
/* trigger IPC message to MSS */
|
||||
mss_pm_ipc_msg_trigger();
|
||||
|
||||
/* pm system synchronization */
|
||||
bakery_lock_release(&pm_sys_lock);
|
||||
|
||||
/* trace message */
|
||||
PM_TRACE(TRACE_PWR_DOMAIN_OFF);
|
||||
} else {
|
||||
INFO("%s: is not supported without SCP\n", __func__);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get PM config to power off the SoC */
|
||||
void *plat_marvell_get_pm_cfg(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function should be called on restore from
|
||||
* "suspend to RAM" state when the execution flow
|
||||
* has to bypass BootROM image to RAM copy and speed up
|
||||
* the system recovery
|
||||
*
|
||||
*/
|
||||
static void plat_marvell_exit_bootrom(void)
|
||||
{
|
||||
marvell_exit_bootrom(PLAT_MARVELL_TRUSTED_ROM_BASE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare for the power off of the system via GPIO
|
||||
*/
|
||||
static void plat_marvell_power_off_gpio(struct power_off_method *pm_cfg,
|
||||
register_t *gpio_addr,
|
||||
register_t *gpio_data)
|
||||
{
|
||||
unsigned int gpio;
|
||||
unsigned int idx;
|
||||
unsigned int shift;
|
||||
unsigned int reg;
|
||||
unsigned int addr;
|
||||
gpio_info_t *info;
|
||||
unsigned int tog_bits;
|
||||
|
||||
assert((pm_cfg->cfg.gpio.pin_count < PMIC_GPIO_MAX_NUMBER) &&
|
||||
(pm_cfg->cfg.gpio.step_count < PMIC_GPIO_MAX_TOGGLE_STEP));
|
||||
|
||||
/* Prepare GPIOs for PMIC */
|
||||
for (gpio = 0; gpio < pm_cfg->cfg.gpio.pin_count; gpio++) {
|
||||
info = &pm_cfg->cfg.gpio.info[gpio];
|
||||
/* Set PMIC GPIO to output mode */
|
||||
reg = mmio_read_32(MVEBU_CP_GPIO_DATA_OUT_EN(
|
||||
info->cp_index, info->gpio_index));
|
||||
mmio_write_32(MVEBU_CP_GPIO_DATA_OUT_EN(
|
||||
info->cp_index, info->gpio_index),
|
||||
reg & ~MVEBU_GPIO_MASK(info->gpio_index));
|
||||
|
||||
/* Set the appropriate MPP to GPIO mode */
|
||||
reg = mmio_read_32(MVEBU_PM_MPP_REGS(info->cp_index,
|
||||
info->gpio_index));
|
||||
mmio_write_32(MVEBU_PM_MPP_REGS(info->cp_index,
|
||||
info->gpio_index),
|
||||
reg & ~MVEBU_MPP_MASK(info->gpio_index));
|
||||
}
|
||||
|
||||
/* Wait for MPP & GPIO pre-configurations done */
|
||||
mdelay(pm_cfg->cfg.gpio.delay_ms);
|
||||
|
||||
/* Toggle the GPIO values, and leave final step to be triggered
|
||||
* after DDR self-refresh is enabled
|
||||
*/
|
||||
for (idx = 0; idx < pm_cfg->cfg.gpio.step_count; idx++) {
|
||||
tog_bits = pm_cfg->cfg.gpio.seq[idx];
|
||||
|
||||
/* The GPIOs must be within same GPIO register,
|
||||
* thus could get the original value by first GPIO
|
||||
*/
|
||||
info = &pm_cfg->cfg.gpio.info[0];
|
||||
reg = mmio_read_32(MVEBU_CP_GPIO_DATA_OUT(
|
||||
info->cp_index, info->gpio_index));
|
||||
addr = MVEBU_CP_GPIO_DATA_OUT(info->cp_index, info->gpio_index);
|
||||
|
||||
for (gpio = 0; gpio < pm_cfg->cfg.gpio.pin_count; gpio++) {
|
||||
shift = pm_cfg->cfg.gpio.info[gpio].gpio_index % 32;
|
||||
if (GPIO_LOW == (tog_bits & (1 << gpio)))
|
||||
reg &= ~(1 << shift);
|
||||
else
|
||||
reg |= (1 << shift);
|
||||
}
|
||||
|
||||
/* Set the GPIO register, for last step just store
|
||||
* register address and values to system registers
|
||||
*/
|
||||
if (idx < pm_cfg->cfg.gpio.step_count - 1) {
|
||||
mmio_write_32(MVEBU_CP_GPIO_DATA_OUT(
|
||||
info->cp_index, info->gpio_index), reg);
|
||||
mdelay(pm_cfg->cfg.gpio.delay_ms);
|
||||
} else {
|
||||
/* Save GPIO register and address values for
|
||||
* finishing the power down operation later
|
||||
*/
|
||||
*gpio_addr = addr;
|
||||
*gpio_data = reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare for the power off of the system
|
||||
*/
|
||||
static void plat_marvell_power_off_prepare(struct power_off_method *pm_cfg,
|
||||
register_t *addr, register_t *data)
|
||||
{
|
||||
switch (pm_cfg->type) {
|
||||
case PMIC_GPIO:
|
||||
plat_marvell_power_off_gpio(pm_cfg, addr, data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A8K handler called when a power domain is about to be suspended. The
|
||||
* target_state encodes the power state that each level should transition to.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static void a8k_pwr_domain_suspend(const psci_power_state_t *target_state)
|
||||
{
|
||||
#if MSS_SUPPORT
|
||||
if (is_pm_fw_running()) {
|
||||
unsigned int idx;
|
||||
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
idx = plat_my_core_pos();
|
||||
|
||||
/* pm system synchronization - used to synchronize multiple
|
||||
* core access to MSS
|
||||
*/
|
||||
bakery_lock_get(&pm_sys_lock);
|
||||
|
||||
/* send CPU Suspend IPC Message to MSS */
|
||||
mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_SUSPEND, target_state);
|
||||
|
||||
/* trigger IPC message to MSS */
|
||||
mss_pm_ipc_msg_trigger();
|
||||
|
||||
/* pm system synchronization */
|
||||
bakery_lock_release(&pm_sys_lock);
|
||||
|
||||
/* trace message */
|
||||
PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
|
||||
|
||||
INFO("Suspending to RAM\n");
|
||||
|
||||
marvell_console_runtime_end();
|
||||
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
mailbox[MBOX_IDX_SUSPEND_MAGIC] = MVEBU_MAILBOX_SUSPEND_STATE;
|
||||
mailbox[MBOX_IDX_ROM_EXIT_ADDR] = (uintptr_t)&plat_marvell_exit_bootrom;
|
||||
|
||||
#if PLAT_MARVELL_SHARED_RAM_CACHED
|
||||
flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
|
||||
MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
|
||||
2 * sizeof(uintptr_t));
|
||||
#endif
|
||||
/* Flush and disable LLC before going off-power */
|
||||
llc_disable(0);
|
||||
|
||||
isb();
|
||||
/*
|
||||
* Do not halt here!
|
||||
* The function must return for allowing the caller function
|
||||
* psci_power_up_finish() to do the proper context saving and
|
||||
* to release the CPU lock.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A8K handler called when a power domain has just been powered on after
|
||||
* being turned off earlier. The target_state encodes the low power state that
|
||||
* each level has woken up from.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static void a8k_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
/* arch specific configuration */
|
||||
marvell_psci_arch_init(0);
|
||||
|
||||
/* Interrupt initialization */
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
|
||||
if (is_pm_fw_running()) {
|
||||
/* trace message */
|
||||
PM_TRACE(TRACE_PWR_DOMAIN_ON_FINISH);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A8K handler called when a power domain has just been powered on after
|
||||
* having been suspended earlier. The target_state encodes the low power state
|
||||
* that each level has woken up from.
|
||||
* TODO: At the moment we reuse the on finisher and reinitialize the secure
|
||||
* context. Need to implement a separate suspend finisher.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static void a8k_pwr_domain_suspend_finish(
|
||||
const psci_power_state_t *target_state)
|
||||
{
|
||||
if (is_pm_fw_running()) {
|
||||
/* arch specific configuration */
|
||||
marvell_psci_arch_init(0);
|
||||
|
||||
/* Interrupt initialization */
|
||||
gicv2_cpuif_enable();
|
||||
|
||||
/* trace message */
|
||||
PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND_FINISH);
|
||||
} else {
|
||||
uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
|
||||
|
||||
/* Only primary CPU requres platform init */
|
||||
if (!plat_my_core_pos()) {
|
||||
/* Initialize the console to provide
|
||||
* early debug support
|
||||
*/
|
||||
marvell_console_runtime_init();
|
||||
|
||||
bl31_plat_arch_setup();
|
||||
marvell_bl31_platform_setup();
|
||||
/*
|
||||
* Remove suspend to RAM marker from the mailbox
|
||||
* for treating a regular reset as a cold boot
|
||||
*/
|
||||
mailbox[MBOX_IDX_SUSPEND_MAGIC] = 0;
|
||||
mailbox[MBOX_IDX_ROM_EXIT_ADDR] = 0;
|
||||
#if PLAT_MARVELL_SHARED_RAM_CACHED
|
||||
flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
|
||||
MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
|
||||
2 * sizeof(uintptr_t));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND`
|
||||
* call to get the `power_state` parameter. This allows the platform to encode
|
||||
* the appropriate State-ID field within the `power_state` parameter which can
|
||||
* be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static void a8k_get_sys_suspend_power_state(psci_power_state_t *req_state)
|
||||
{
|
||||
/* lower affinities use PLAT_MAX_OFF_STATE */
|
||||
for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
|
||||
req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
|
||||
}
|
||||
|
||||
static void
|
||||
__dead2 a8k_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
|
||||
{
|
||||
struct power_off_method *pm_cfg;
|
||||
unsigned int srcmd;
|
||||
unsigned int sdram_reg;
|
||||
register_t gpio_data = 0, gpio_addr = 0;
|
||||
|
||||
if (is_pm_fw_running()) {
|
||||
psci_power_down_wfi();
|
||||
panic();
|
||||
}
|
||||
|
||||
pm_cfg = (struct power_off_method *)plat_marvell_get_pm_cfg();
|
||||
|
||||
/* Prepare for power off */
|
||||
plat_marvell_power_off_prepare(pm_cfg, &gpio_addr, &gpio_data);
|
||||
|
||||
/* First step to enable DDR self-refresh
|
||||
* to keep the data during suspend
|
||||
*/
|
||||
mmio_write_32(MVEBU_MC_PWR_CTRL_REG, 0x8C1);
|
||||
|
||||
/* Save DDR self-refresh second step register
|
||||
* and value to be issued later
|
||||
*/
|
||||
sdram_reg = MVEBU_USER_CMD_0_REG;
|
||||
srcmd = mmio_read_32(sdram_reg);
|
||||
srcmd &= ~(MVEBU_USER_CMD_CH0_MASK | MVEBU_USER_CMD_CS_MASK |
|
||||
MVEBU_USER_CMD_SR_MASK);
|
||||
srcmd |= (MVEBU_USER_CMD_CH0_EN | MVEBU_USER_CMD_CS_ALL |
|
||||
MVEBU_USER_CMD_SR_ENTER);
|
||||
|
||||
/*
|
||||
* Wait for DRAM is done using registers access only.
|
||||
* At this stage any access to DRAM (procedure call) will
|
||||
* release it from the self-refresh mode
|
||||
*/
|
||||
__asm__ volatile (
|
||||
/* Align to a cache line */
|
||||
" .balign 64\n\t"
|
||||
|
||||
/* Enter self refresh */
|
||||
" str %[srcmd], [%[sdram_reg]]\n\t"
|
||||
|
||||
/*
|
||||
* Wait 100 cycles for DDR to enter self refresh, by
|
||||
* doing 50 times two instructions.
|
||||
*/
|
||||
" mov x1, #50\n\t"
|
||||
"1: subs x1, x1, #1\n\t"
|
||||
" bne 1b\n\t"
|
||||
|
||||
/* Issue the command to trigger the SoC power off */
|
||||
" str %[gpio_data], [%[gpio_addr]]\n\t"
|
||||
|
||||
/* Trap the processor */
|
||||
" b .\n\t"
|
||||
: : [srcmd] "r" (srcmd), [sdram_reg] "r" (sdram_reg),
|
||||
[gpio_addr] "r" (gpio_addr), [gpio_data] "r" (gpio_data)
|
||||
: "x1");
|
||||
|
||||
panic();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A8K handlers to shutdown/reboot the system
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
/* Set a weak stub for platforms that don't configure system power off */
|
||||
#pragma weak system_power_off
|
||||
int system_power_off(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __dead2 a8k_system_off(void)
|
||||
{
|
||||
/* Call the platform specific system power off function */
|
||||
system_power_off();
|
||||
|
||||
/* board doesn't have a system off implementation */
|
||||
ERROR("%s: needs to be implemented\n", __func__);
|
||||
panic();
|
||||
}
|
||||
|
||||
void plat_marvell_system_reset(void)
|
||||
{
|
||||
mmio_write_32(MVEBU_RFU_BASE + MVEBU_RFU_GLOBL_SW_RST, 0x0);
|
||||
}
|
||||
|
||||
static void __dead2 a8k_system_reset(void)
|
||||
{
|
||||
plat_marvell_system_reset();
|
||||
|
||||
/* we shouldn't get to this point */
|
||||
panic();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
|
||||
* platform layer will take care of registering the handlers with PSCI.
|
||||
*****************************************************************************
|
||||
*/
|
||||
const plat_psci_ops_t plat_arm_psci_pm_ops = {
|
||||
.cpu_standby = a8k_cpu_standby,
|
||||
.pwr_domain_on = a8k_pwr_domain_on,
|
||||
.pwr_domain_off = a8k_pwr_domain_off,
|
||||
.pwr_domain_suspend = a8k_pwr_domain_suspend,
|
||||
.pwr_domain_on_finish = a8k_pwr_domain_on_finish,
|
||||
.get_sys_suspend_power_state = a8k_get_sys_suspend_power_state,
|
||||
.pwr_domain_suspend_finish = a8k_pwr_domain_suspend_finish,
|
||||
.pwr_domain_pwr_down_wfi = a8k_pwr_domain_pwr_down_wfi,
|
||||
.system_off = a8k_system_off,
|
||||
.system_reset = a8k_system_reset,
|
||||
.validate_power_state = a8k_validate_power_state,
|
||||
.validate_ns_entrypoint = a8k_validate_ns_entrypoint
|
||||
};
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#if MSS_SUPPORT
|
||||
#include <mss_mem.h>
|
||||
|
||||
#ifdef PM_TRACE_ENABLE
|
||||
#include <plat_pm_trace.h>
|
||||
|
||||
/* core trace APIs */
|
||||
core_trace_func funcTbl[PLATFORM_CORE_COUNT] = {
|
||||
pm_core_0_trace,
|
||||
pm_core_1_trace,
|
||||
pm_core_2_trace,
|
||||
pm_core_3_trace};
|
||||
|
||||
/*****************************************************************************
|
||||
* pm_core0_trace
|
||||
* pm_core1_trace
|
||||
* pm_core2_trace
|
||||
* pm_core_3trace
|
||||
*
|
||||
* This functions set trace info into core cyclic trace queue in MSS SRAM
|
||||
* memory space
|
||||
*****************************************************************************
|
||||
*/
|
||||
void pm_core_0_trace(unsigned int trace)
|
||||
{
|
||||
unsigned int current_position_core_0 =
|
||||
mmio_read_32(AP_MSS_ATF_CORE_0_CTRL_BASE);
|
||||
mmio_write_32((AP_MSS_ATF_CORE_0_INFO_BASE +
|
||||
(current_position_core_0 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
|
||||
mmio_read_32(AP_MSS_TIMER_BASE));
|
||||
mmio_write_32((AP_MSS_ATF_CORE_0_INFO_TRACE +
|
||||
(current_position_core_0 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
|
||||
trace);
|
||||
mmio_write_32(AP_MSS_ATF_CORE_0_CTRL_BASE,
|
||||
((current_position_core_0 + 1) &
|
||||
AP_MSS_ATF_TRACE_SIZE_MASK));
|
||||
}
|
||||
|
||||
void pm_core_1_trace(unsigned int trace)
|
||||
{
|
||||
unsigned int current_position_core_1 =
|
||||
mmio_read_32(AP_MSS_ATF_CORE_1_CTRL_BASE);
|
||||
mmio_write_32((AP_MSS_ATF_CORE_1_INFO_BASE +
|
||||
(current_position_core_1 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
|
||||
mmio_read_32(AP_MSS_TIMER_BASE));
|
||||
mmio_write_32((AP_MSS_ATF_CORE_1_INFO_TRACE +
|
||||
(current_position_core_1 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
|
||||
trace);
|
||||
mmio_write_32(AP_MSS_ATF_CORE_1_CTRL_BASE,
|
||||
((current_position_core_1 + 1) &
|
||||
AP_MSS_ATF_TRACE_SIZE_MASK));
|
||||
}
|
||||
|
||||
void pm_core_2_trace(unsigned int trace)
|
||||
{
|
||||
unsigned int current_position_core_2 =
|
||||
mmio_read_32(AP_MSS_ATF_CORE_2_CTRL_BASE);
|
||||
mmio_write_32((AP_MSS_ATF_CORE_2_INFO_BASE +
|
||||
(current_position_core_2 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
|
||||
mmio_read_32(AP_MSS_TIMER_BASE));
|
||||
mmio_write_32((AP_MSS_ATF_CORE_2_INFO_TRACE +
|
||||
(current_position_core_2 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
|
||||
trace);
|
||||
mmio_write_32(AP_MSS_ATF_CORE_2_CTRL_BASE,
|
||||
((current_position_core_2 + 1) &
|
||||
AP_MSS_ATF_TRACE_SIZE_MASK));
|
||||
}
|
||||
|
||||
void pm_core_3_trace(unsigned int trace)
|
||||
{
|
||||
unsigned int current_position_core_3 =
|
||||
mmio_read_32(AP_MSS_ATF_CORE_3_CTRL_BASE);
|
||||
mmio_write_32((AP_MSS_ATF_CORE_3_INFO_BASE +
|
||||
(current_position_core_3 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
|
||||
mmio_read_32(AP_MSS_TIMER_BASE));
|
||||
mmio_write_32((AP_MSS_ATF_CORE_3_INFO_TRACE +
|
||||
(current_position_core_3 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
|
||||
trace);
|
||||
mmio_write_32(AP_MSS_ATF_CORE_3_CTRL_BASE,
|
||||
((current_position_core_3 + 1) &
|
||||
AP_MSS_ATF_TRACE_SIZE_MASK));
|
||||
}
|
||||
#endif /* PM_TRACE_ENABLE */
|
||||
#endif /* MSS_SUPPORT */
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/marvell/thermal.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mvebu_def.h>
|
||||
|
||||
#define THERMAL_TIMEOUT 1200
|
||||
|
||||
#define THERMAL_SEN_CTRL_LSB_STRT_OFFSET 0
|
||||
#define THERMAL_SEN_CTRL_LSB_STRT_MASK \
|
||||
(0x1 << THERMAL_SEN_CTRL_LSB_STRT_OFFSET)
|
||||
#define THERMAL_SEN_CTRL_LSB_RST_OFFSET 1
|
||||
#define THERMAL_SEN_CTRL_LSB_RST_MASK \
|
||||
(0x1 << THERMAL_SEN_CTRL_LSB_RST_OFFSET)
|
||||
#define THERMAL_SEN_CTRL_LSB_EN_OFFSET 2
|
||||
#define THERMAL_SEN_CTRL_LSB_EN_MASK \
|
||||
(0x1 << THERMAL_SEN_CTRL_LSB_EN_OFFSET)
|
||||
|
||||
#define THERMAL_SEN_CTRL_STATS_VALID_OFFSET 16
|
||||
#define THERMAL_SEN_CTRL_STATS_VALID_MASK \
|
||||
(0x1 << THERMAL_SEN_CTRL_STATS_VALID_OFFSET)
|
||||
#define THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET 0
|
||||
#define THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK \
|
||||
(0x3FF << THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET)
|
||||
|
||||
#define THERMAL_SEN_OUTPUT_MSB 512
|
||||
#define THERMAL_SEN_OUTPUT_COMP 1024
|
||||
|
||||
struct tsen_regs {
|
||||
uint32_t ext_tsen_ctrl_lsb;
|
||||
uint32_t ext_tsen_ctrl_msb;
|
||||
uint32_t ext_tsen_status;
|
||||
};
|
||||
|
||||
static int ext_tsen_probe(struct tsen_config *tsen_cfg)
|
||||
{
|
||||
uint32_t reg, timeout = 0;
|
||||
struct tsen_regs *base;
|
||||
|
||||
if (tsen_cfg == NULL && tsen_cfg->regs_base == NULL) {
|
||||
ERROR("initial thermal sensor configuration is missing\n");
|
||||
return -1;
|
||||
}
|
||||
base = (struct tsen_regs *)tsen_cfg->regs_base;
|
||||
|
||||
INFO("initializing thermal sensor\n");
|
||||
|
||||
/* initialize thermal sensor hardware reset once */
|
||||
reg = mmio_read_32((uintptr_t)&base->ext_tsen_ctrl_lsb);
|
||||
reg &= ~THERMAL_SEN_CTRL_LSB_RST_OFFSET; /* de-assert TSEN_RESET */
|
||||
reg |= THERMAL_SEN_CTRL_LSB_EN_MASK; /* set TSEN_EN to 1 */
|
||||
reg |= THERMAL_SEN_CTRL_LSB_STRT_MASK; /* set TSEN_START to 1 */
|
||||
mmio_write_32((uintptr_t)&base->ext_tsen_ctrl_lsb, reg);
|
||||
|
||||
reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
|
||||
while ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0 &&
|
||||
timeout < THERMAL_TIMEOUT) {
|
||||
udelay(100);
|
||||
reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
if ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0) {
|
||||
ERROR("thermal sensor is not ready\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tsen_cfg->tsen_ready = 1;
|
||||
|
||||
VERBOSE("thermal sensor was initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ext_tsen_read(struct tsen_config *tsen_cfg, int *temp)
|
||||
{
|
||||
uint32_t reg;
|
||||
struct tsen_regs *base;
|
||||
|
||||
if (tsen_cfg == NULL && !tsen_cfg->tsen_ready) {
|
||||
ERROR("thermal sensor was not initialized\n");
|
||||
return -1;
|
||||
}
|
||||
base = (struct tsen_regs *)tsen_cfg->regs_base;
|
||||
|
||||
reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
|
||||
reg = ((reg & THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK) >>
|
||||
THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET);
|
||||
|
||||
/*
|
||||
* TSEN output format is signed as a 2s complement number
|
||||
* ranging from-512 to +511. when MSB is set, need to
|
||||
* calculate the complement number
|
||||
*/
|
||||
if (reg >= THERMAL_SEN_OUTPUT_MSB)
|
||||
reg -= THERMAL_SEN_OUTPUT_COMP;
|
||||
|
||||
if (tsen_cfg->tsen_divisor == 0) {
|
||||
ERROR("thermal sensor divisor cannot be zero\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*temp = ((tsen_cfg->tsen_gain * ((int)reg)) +
|
||||
tsen_cfg->tsen_offset) / tsen_cfg->tsen_divisor;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tsen_config tsen_cfg = {
|
||||
.tsen_offset = 153400,
|
||||
.tsen_gain = 425,
|
||||
.tsen_divisor = 1000,
|
||||
.tsen_ready = 0,
|
||||
.regs_base = (void *)MVEBU_AP_EXT_TSEN_BASE,
|
||||
.ptr_tsen_probe = ext_tsen_probe,
|
||||
.ptr_tsen_read = ext_tsen_read
|
||||
};
|
||||
|
||||
struct tsen_config *marvell_thermal_config_get(void)
|
||||
{
|
||||
return &tsen_cfg;
|
||||
}
|
||||
Reference in New Issue
Block a user