Merge pull request #1369 from sivadur/xilinxdiff
Xilinx platform mangement related changes
This commit is contained in:
commit
1f4d62df6c
|
@ -8,8 +8,11 @@
|
|||
#include <generic_delay_timer.h>
|
||||
#include <mmio.h>
|
||||
#include <platform.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <xlat_tables.h>
|
||||
#include "../zynqmp_private.h"
|
||||
#include "pm_api_sys.h"
|
||||
|
||||
/*
|
||||
* Table of regions to map using the MMU.
|
||||
|
@ -59,40 +62,103 @@ unsigned int zynqmp_get_uart_clk(void)
|
|||
#if LOG_LEVEL >= LOG_LEVEL_NOTICE
|
||||
static const struct {
|
||||
unsigned int id;
|
||||
unsigned int ver;
|
||||
char *name;
|
||||
bool evexists;
|
||||
} zynqmp_devices[] = {
|
||||
{
|
||||
.id = 0x10,
|
||||
.name = "3EG",
|
||||
},
|
||||
{
|
||||
.id = 0x10,
|
||||
.ver = 0x2c,
|
||||
.name = "3CG",
|
||||
},
|
||||
{
|
||||
.id = 0x11,
|
||||
.name = "2EG",
|
||||
},
|
||||
{
|
||||
.id = 0x11,
|
||||
.ver = 0x2c,
|
||||
.name = "2CG",
|
||||
},
|
||||
{
|
||||
.id = 0x20,
|
||||
.name = "5EV",
|
||||
.evexists = true,
|
||||
},
|
||||
{
|
||||
.id = 0x20,
|
||||
.ver = 0x100,
|
||||
.name = "5EG",
|
||||
.evexists = true,
|
||||
},
|
||||
{
|
||||
.id = 0x20,
|
||||
.ver = 0x12c,
|
||||
.name = "5CG",
|
||||
},
|
||||
{
|
||||
.id = 0x21,
|
||||
.name = "4EV",
|
||||
.evexists = true,
|
||||
},
|
||||
{
|
||||
.id = 0x21,
|
||||
.ver = 0x100,
|
||||
.name = "4EG",
|
||||
.evexists = true,
|
||||
},
|
||||
{
|
||||
.id = 0x21,
|
||||
.ver = 0x12c,
|
||||
.name = "4CG",
|
||||
},
|
||||
{
|
||||
.id = 0x30,
|
||||
.name = "7EV",
|
||||
.evexists = true,
|
||||
},
|
||||
{
|
||||
.id = 0x30,
|
||||
.ver = 0x100,
|
||||
.name = "7EG",
|
||||
.evexists = true,
|
||||
},
|
||||
{
|
||||
.id = 0x30,
|
||||
.ver = 0x12c,
|
||||
.name = "7CG",
|
||||
},
|
||||
{
|
||||
.id = 0x38,
|
||||
.name = "9EG",
|
||||
},
|
||||
{
|
||||
.id = 0x38,
|
||||
.ver = 0x2c,
|
||||
.name = "9CG",
|
||||
},
|
||||
{
|
||||
.id = 0x39,
|
||||
.name = "6EG",
|
||||
},
|
||||
{
|
||||
.id = 0x39,
|
||||
.ver = 0x2c,
|
||||
.name = "6CG",
|
||||
},
|
||||
{
|
||||
.id = 0x40,
|
||||
.name = "11EG",
|
||||
},
|
||||
{ /* For testing purpose only */
|
||||
.id = 0x50,
|
||||
.ver = 0x2c,
|
||||
.name = "15CG",
|
||||
},
|
||||
{
|
||||
.id = 0x50,
|
||||
.name = "15EG",
|
||||
|
@ -105,30 +171,75 @@ static const struct {
|
|||
.id = 0x59,
|
||||
.name = "17EG",
|
||||
},
|
||||
{
|
||||
.id = 0x60,
|
||||
.name = "28DR",
|
||||
},
|
||||
{
|
||||
.id = 0x61,
|
||||
.name = "21DR",
|
||||
},
|
||||
{
|
||||
.id = 0x62,
|
||||
.name = "29DR",
|
||||
},
|
||||
{
|
||||
.id = 0x63,
|
||||
.name = "23DR",
|
||||
},
|
||||
{
|
||||
.id = 0x64,
|
||||
.name = "27DR",
|
||||
},
|
||||
{
|
||||
.id = 0x65,
|
||||
.name = "25DR",
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned int zynqmp_get_silicon_id(void)
|
||||
{
|
||||
uint32_t id;
|
||||
|
||||
id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
|
||||
|
||||
id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
|
||||
id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
|
||||
|
||||
return id;
|
||||
}
|
||||
#define ZYNQMP_PL_STATUS_BIT 9
|
||||
#define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT)
|
||||
#define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK)
|
||||
|
||||
static char *zynqmp_get_silicon_idcode_name(void)
|
||||
{
|
||||
unsigned int id;
|
||||
uint32_t id, ver, chipid[2];
|
||||
size_t i, j, len;
|
||||
enum pm_ret_status ret;
|
||||
const char *name = "EG/EV";
|
||||
|
||||
id = zynqmp_get_silicon_id();
|
||||
for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
|
||||
if (zynqmp_devices[i].id == id)
|
||||
return zynqmp_devices[i].name;
|
||||
ret = pm_get_chipid(chipid);
|
||||
if (ret)
|
||||
return "UNKN";
|
||||
|
||||
id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
|
||||
ZYNQMP_CSU_IDCODE_SVD_MASK);
|
||||
id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
|
||||
ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
|
||||
if (zynqmp_devices[i].id == id &&
|
||||
zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK))
|
||||
break;
|
||||
}
|
||||
return "UNKN";
|
||||
|
||||
if (i >= ARRAY_SIZE(zynqmp_devices))
|
||||
return "UNKN";
|
||||
|
||||
if (!zynqmp_devices[i].evexists)
|
||||
return zynqmp_devices[i].name;
|
||||
|
||||
if (ver & ZYNQMP_PL_STATUS_MASK)
|
||||
return zynqmp_devices[i].name;
|
||||
|
||||
len = strlen(zynqmp_devices[i].name) - 2;
|
||||
for (j = 0; j < strlen(name); j++) {
|
||||
zynqmp_devices[i].name[len] = name[j];
|
||||
len++;
|
||||
}
|
||||
zynqmp_devices[i].name[len] = '\0';
|
||||
|
||||
return zynqmp_devices[i].name;
|
||||
}
|
||||
|
||||
static unsigned int zynqmp_get_rtl_ver(void)
|
||||
|
@ -195,60 +306,29 @@ static void zynqmp_print_platform_name(void)
|
|||
break;
|
||||
}
|
||||
|
||||
NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n",
|
||||
NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x\n",
|
||||
zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
|
||||
(rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE,
|
||||
zynqmp_is_pmu_up() ? ", with PMU firmware" : "");
|
||||
(rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE);
|
||||
}
|
||||
#else
|
||||
static inline void zynqmp_print_platform_name(void) { }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Indicator for PMUFW discovery:
|
||||
* 0 = No FW found
|
||||
* non-zero = FW is present
|
||||
*/
|
||||
static int zynqmp_pmufw_present;
|
||||
|
||||
/*
|
||||
* zynqmp_discover_pmufw - Discover presence of PMUFW
|
||||
*
|
||||
* Discover the presence of PMUFW and store it for later run-time queries
|
||||
* through zynqmp_is_pmu_up.
|
||||
* NOTE: This discovery method is fragile and will break if:
|
||||
* - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW
|
||||
* (be it by error or intentionally)
|
||||
* - XPPU/XMPU may restrict ATF's access to the PMU address space
|
||||
*/
|
||||
static int zynqmp_discover_pmufw(void)
|
||||
{
|
||||
zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL);
|
||||
zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT;
|
||||
|
||||
return !!zynqmp_pmufw_present;
|
||||
}
|
||||
|
||||
/*
|
||||
* zynqmp_is_pmu_up - Find if PMU firmware is up and running
|
||||
*
|
||||
* Return 0 if firmware is not available, non 0 otherwise
|
||||
*/
|
||||
int zynqmp_is_pmu_up(void)
|
||||
{
|
||||
return zynqmp_pmufw_present;
|
||||
}
|
||||
|
||||
unsigned int zynqmp_get_bootmode(void)
|
||||
{
|
||||
uint32_t r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
|
||||
uint32_t r;
|
||||
unsigned int ret;
|
||||
|
||||
ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
|
||||
|
||||
if (ret != PM_RET_SUCCESS)
|
||||
r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
|
||||
|
||||
return r & CRL_APB_BOOT_MODE_MASK;
|
||||
}
|
||||
|
||||
void zynqmp_config_setup(void)
|
||||
{
|
||||
zynqmp_discover_pmufw();
|
||||
zynqmp_print_platform_name();
|
||||
generic_delay_timer_init();
|
||||
}
|
||||
|
|
|
@ -35,6 +35,19 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
|||
return &bl32_image_ep_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the build time defaults. We want to do this when doing a JTAG boot
|
||||
* or if we can't find any other config data.
|
||||
*/
|
||||
static inline void bl31_set_default_config(void)
|
||||
{
|
||||
bl32_image_ep_info.pc = BL32_BASE;
|
||||
bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
|
||||
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
|
||||
bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform any BL31 specific platform actions. Here is an opportunity to copy
|
||||
* parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
|
||||
|
@ -69,15 +82,15 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2,
|
|||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
|
||||
|
||||
if (zynqmp_get_bootmode() == ZYNQMP_BOOTMODE_JTAG) {
|
||||
/* use build time defaults in JTAG boot mode */
|
||||
bl32_image_ep_info.pc = BL32_BASE;
|
||||
bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
|
||||
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
|
||||
bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS);
|
||||
bl31_set_default_config();
|
||||
} else {
|
||||
/* use parameters from FSBL */
|
||||
fsbl_atf_handover(&bl32_image_ep_info, &bl33_image_ep_info);
|
||||
enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info,
|
||||
&bl33_image_ep_info);
|
||||
if (ret == FSBL_HANDOFF_NO_STRUCT)
|
||||
bl31_set_default_config();
|
||||
else if (ret != FSBL_HANDOFF_SUCCESS)
|
||||
panic();
|
||||
}
|
||||
|
||||
NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
|
||||
|
@ -103,6 +116,39 @@ static void zynqmp_testing_setup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if ZYNQMP_WDT_RESTART
|
||||
static interrupt_type_handler_t type_el3_interrupt_table[MAX_INTR_EL3];
|
||||
|
||||
int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
|
||||
{
|
||||
/* Validate 'handler' and 'id' parameters */
|
||||
if (!handler || id >= MAX_INTR_EL3)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if a handler has already been registered */
|
||||
if (type_el3_interrupt_table[id])
|
||||
return -EALREADY;
|
||||
|
||||
type_el3_interrupt_table[id] = handler;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
|
||||
void *handle, void *cookie)
|
||||
{
|
||||
uint32_t intr_id;
|
||||
interrupt_type_handler_t handler;
|
||||
|
||||
intr_id = plat_ic_get_pending_interrupt_id();
|
||||
handler = type_el3_interrupt_table[intr_id];
|
||||
if (handler != NULL)
|
||||
handler(intr_id, flags, handle, cookie);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
/* Initialize the gic cpu and distributor interfaces */
|
||||
|
@ -113,6 +159,16 @@ void bl31_platform_setup(void)
|
|||
|
||||
void bl31_plat_runtime_setup(void)
|
||||
{
|
||||
#if ZYNQMP_WDT_RESTART
|
||||
uint64_t flags = 0;
|
||||
uint64_t rc;
|
||||
|
||||
set_interrupt_rm_flag(flags, NON_SECURE);
|
||||
rc = register_interrupt_type_handler(INTR_TYPE_EL3,
|
||||
rdo_el3_interrupt_handler, flags);
|
||||
if (rc)
|
||||
panic();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#if !ZYNQMP_WDT_RESTART
|
||||
#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
|
@ -115,6 +116,29 @@
|
|||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
#else
|
||||
#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(IRQ_TTC3_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
#endif
|
||||
|
||||
#define PLAT_ARM_G0_IRQ_PROPS(grp)
|
||||
|
||||
|
|
|
@ -27,46 +27,6 @@ void zynqmp_cpu_standby(plat_local_state_t cpu_state)
|
|||
wfi();
|
||||
}
|
||||
|
||||
static int zynqmp_nopmu_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
uint32_t r;
|
||||
unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
|
||||
|
||||
VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
|
||||
|
||||
if (cpu_id == -1)
|
||||
return PSCI_E_INTERN_FAIL;
|
||||
|
||||
/* program RVBAR */
|
||||
mmio_write_32(APU_RVBAR_L_0 + (cpu_id << 3), zynqmp_sec_entry);
|
||||
mmio_write_32(APU_RVBAR_H_0 + (cpu_id << 3), zynqmp_sec_entry >> 32);
|
||||
|
||||
/* clear VINITHI */
|
||||
r = mmio_read_32(APU_CONFIG_0);
|
||||
r &= ~(1 << APU_CONFIG_0_VINITHI_SHIFT << cpu_id);
|
||||
mmio_write_32(APU_CONFIG_0, r);
|
||||
|
||||
/* clear power down request */
|
||||
r = mmio_read_32(APU_PWRCTL);
|
||||
r &= ~(1 << cpu_id);
|
||||
mmio_write_32(APU_PWRCTL, r);
|
||||
|
||||
/* power up island */
|
||||
mmio_write_32(PMU_GLOBAL_REQ_PWRUP_EN, 1 << cpu_id);
|
||||
mmio_write_32(PMU_GLOBAL_REQ_PWRUP_TRIG, 1 << cpu_id);
|
||||
/* FIXME: we should have a way to break out */
|
||||
while (mmio_read_32(PMU_GLOBAL_REQ_PWRUP_STATUS) & (1 << cpu_id))
|
||||
;
|
||||
|
||||
/* release core reset */
|
||||
r = mmio_read_32(CRF_APB_RST_FPD_APU);
|
||||
r &= ~((CRF_APB_RST_FPD_APU_ACPU_PWRON_RESET |
|
||||
CRF_APB_RST_FPD_APU_ACPU_RESET) << cpu_id);
|
||||
mmio_write_32(CRF_APB_RST_FPD_APU, r);
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static int zynqmp_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
|
||||
|
@ -78,6 +38,8 @@ static int zynqmp_pwr_domain_on(u_register_t mpidr)
|
|||
return PSCI_E_INTERN_FAIL;
|
||||
|
||||
proc = pm_get_proc(cpu_id);
|
||||
/* Clear power down request */
|
||||
pm_client_wakeup(proc);
|
||||
|
||||
/* Send request to PMU to wake up selected APU CPU core */
|
||||
pm_req_wakeup(proc->node_id, 1, zynqmp_sec_entry, REQ_ACK_BLOCKING);
|
||||
|
@ -85,24 +47,6 @@ static int zynqmp_pwr_domain_on(u_register_t mpidr)
|
|||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void zynqmp_nopmu_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
uint32_t r;
|
||||
unsigned int cpu_id = plat_my_core_pos();
|
||||
|
||||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
|
||||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
|
||||
__func__, i, target_state->pwr_domain_state[i]);
|
||||
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
/* set power down request */
|
||||
r = mmio_read_32(APU_PWRCTL);
|
||||
r |= (1 << cpu_id);
|
||||
mmio_write_32(APU_PWRCTL, r);
|
||||
}
|
||||
|
||||
static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
unsigned int cpu_id = plat_my_core_pos();
|
||||
|
@ -126,33 +70,6 @@ static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state)
|
|||
pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0);
|
||||
}
|
||||
|
||||
static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_state)
|
||||
{
|
||||
uint32_t r;
|
||||
unsigned int cpu_id = plat_my_core_pos();
|
||||
|
||||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
|
||||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
|
||||
__func__, i, target_state->pwr_domain_state[i]);
|
||||
|
||||
/* set power down request */
|
||||
r = mmio_read_32(APU_PWRCTL);
|
||||
r |= (1 << cpu_id);
|
||||
mmio_write_32(APU_PWRCTL, r);
|
||||
|
||||
/* program RVBAR */
|
||||
mmio_write_32(APU_RVBAR_L_0 + (cpu_id << 3), zynqmp_sec_entry);
|
||||
mmio_write_32(APU_RVBAR_H_0 + (cpu_id << 3), zynqmp_sec_entry >> 32);
|
||||
|
||||
/* clear VINITHI */
|
||||
r = mmio_read_32(APU_CONFIG_0);
|
||||
r &= ~(1 << APU_CONFIG_0_VINITHI_SHIFT << cpu_id);
|
||||
mmio_write_32(APU_CONFIG_0, r);
|
||||
|
||||
/* enable power up on IRQ */
|
||||
mmio_write_32(PMU_GLOBAL_REQ_PWRUP_EN, 1 << cpu_id);
|
||||
}
|
||||
|
||||
static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
|
||||
{
|
||||
unsigned int state;
|
||||
|
@ -186,24 +103,6 @@ static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
|||
gicv2_pcpu_distif_init();
|
||||
}
|
||||
|
||||
static void zynqmp_nopmu_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
uint32_t r;
|
||||
unsigned int cpu_id = plat_my_core_pos();
|
||||
|
||||
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
|
||||
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
|
||||
__func__, i, target_state->pwr_domain_state[i]);
|
||||
|
||||
/* disable power up on IRQ */
|
||||
mmio_write_32(PMU_GLOBAL_REQ_PWRUP_DIS, 1 << cpu_id);
|
||||
|
||||
/* clear powerdown bit */
|
||||
r = mmio_read_32(APU_PWRCTL);
|
||||
r &= ~(1 << cpu_id);
|
||||
mmio_write_32(APU_PWRCTL, r);
|
||||
}
|
||||
|
||||
static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
unsigned int cpu_id = plat_my_core_pos();
|
||||
|
@ -230,15 +129,6 @@ static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_st
|
|||
/*******************************************************************************
|
||||
* ZynqMP handlers to shutdown/reboot the system
|
||||
******************************************************************************/
|
||||
static void __dead2 zynqmp_nopmu_system_off(void)
|
||||
{
|
||||
ERROR("ZynqMP System Off: operation not handled.\n");
|
||||
|
||||
/* disable coherency */
|
||||
plat_arm_interconnect_exit_coherency();
|
||||
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 zynqmp_system_off(void)
|
||||
{
|
||||
|
@ -247,29 +137,7 @@ static void __dead2 zynqmp_system_off(void)
|
|||
|
||||
/* Send the power down request to the PMU */
|
||||
pm_system_shutdown(PMF_SHUTDOWN_TYPE_SHUTDOWN,
|
||||
PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM);
|
||||
|
||||
while (1)
|
||||
wfi();
|
||||
}
|
||||
|
||||
static void __dead2 zynqmp_nopmu_system_reset(void)
|
||||
{
|
||||
/*
|
||||
* This currently triggers a system reset. I.e. the whole
|
||||
* system will be reset! Including RPUs, PMU, PL, etc.
|
||||
*/
|
||||
|
||||
/* disable coherency */
|
||||
plat_arm_interconnect_exit_coherency();
|
||||
|
||||
/* bypass RPLL (needed on 1.0 silicon) */
|
||||
uint32_t reg = mmio_read_32(CRL_APB_RPLL_CTRL);
|
||||
reg |= CRL_APB_RPLL_CTRL_BYPASS;
|
||||
mmio_write_32(CRL_APB_RPLL_CTRL, reg);
|
||||
|
||||
/* trigger system reset */
|
||||
mmio_write_32(CRL_APB_RESET_CTRL, CRL_APB_RESET_CTRL_SOFT_RESET);
|
||||
pm_get_shutdown_scope());
|
||||
|
||||
while (1)
|
||||
wfi();
|
||||
|
@ -282,7 +150,7 @@ static void __dead2 zynqmp_system_reset(void)
|
|||
|
||||
/* Send the system reset request to the PMU */
|
||||
pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET,
|
||||
PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM);
|
||||
pm_get_shutdown_scope());
|
||||
|
||||
while (1)
|
||||
wfi();
|
||||
|
@ -341,20 +209,6 @@ static const struct plat_psci_ops zynqmp_psci_ops = {
|
|||
.get_sys_suspend_power_state = zynqmp_get_sys_suspend_power_state,
|
||||
};
|
||||
|
||||
static const struct plat_psci_ops zynqmp_nopmu_psci_ops = {
|
||||
.cpu_standby = zynqmp_cpu_standby,
|
||||
.pwr_domain_on = zynqmp_nopmu_pwr_domain_on,
|
||||
.pwr_domain_off = zynqmp_nopmu_pwr_domain_off,
|
||||
.pwr_domain_suspend = zynqmp_nopmu_pwr_domain_suspend,
|
||||
.pwr_domain_on_finish = zynqmp_pwr_domain_on_finish,
|
||||
.pwr_domain_suspend_finish = zynqmp_nopmu_pwr_domain_suspend_finish,
|
||||
.system_off = zynqmp_nopmu_system_off,
|
||||
.system_reset = zynqmp_nopmu_system_reset,
|
||||
.validate_power_state = zynqmp_validate_power_state,
|
||||
.validate_ns_entrypoint = zynqmp_validate_ns_entrypoint,
|
||||
.get_sys_suspend_power_state = zynqmp_get_sys_suspend_power_state,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Export the platform specific power ops.
|
||||
******************************************************************************/
|
||||
|
@ -363,10 +217,7 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
|||
{
|
||||
zynqmp_sec_entry = sec_entrypoint;
|
||||
|
||||
if (zynqmp_is_pmu_up())
|
||||
*psci_ops = &zynqmp_psci_ops;
|
||||
else
|
||||
*psci_ops = &zynqmp_nopmu_psci_ops;
|
||||
*psci_ops = &zynqmp_psci_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <debug.h>
|
||||
#include <mmio.h>
|
||||
#include "zynqmp_def.h"
|
||||
#include "zynqmp_private.h"
|
||||
|
||||
/*
|
||||
* ATFHandoffParams
|
||||
|
@ -147,8 +148,11 @@ static int get_fsbl_estate(const struct xfsbl_partition *partition)
|
|||
*
|
||||
* Process the handoff paramters from the FSBL and populate the BL32 and BL33
|
||||
* image info structures accordingly.
|
||||
*
|
||||
* Return: Return the status of the handoff. The value will be from the
|
||||
* fsbl_handoff enum.
|
||||
*/
|
||||
void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33)
|
||||
enum fsbl_handoff fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33)
|
||||
{
|
||||
uint64_t atf_handoff_addr;
|
||||
const struct xfsbl_atf_handoff_params *ATFHandoffParams;
|
||||
|
@ -157,8 +161,8 @@ void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33)
|
|||
assert((atf_handoff_addr < BL31_BASE) ||
|
||||
(atf_handoff_addr > (uint64_t)&__BL31_END__));
|
||||
if (!atf_handoff_addr) {
|
||||
ERROR("BL31: No ATF handoff structure passed\n");
|
||||
panic();
|
||||
WARN("BL31: No ATF handoff structure passed\n");
|
||||
return FSBL_HANDOFF_NO_STRUCT;
|
||||
}
|
||||
|
||||
ATFHandoffParams = (struct xfsbl_atf_handoff_params *)atf_handoff_addr;
|
||||
|
@ -168,7 +172,7 @@ void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33)
|
|||
(ATFHandoffParams->magic[3] != 'X')) {
|
||||
ERROR("BL31: invalid ATF handoff structure at %llx\n",
|
||||
atf_handoff_addr);
|
||||
panic();
|
||||
return FSBL_HANDOFF_INVAL_STRUCT;
|
||||
}
|
||||
|
||||
VERBOSE("BL31: ATF handoff params at:0x%llx, entries:%u\n",
|
||||
|
@ -176,7 +180,7 @@ void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33)
|
|||
if (ATFHandoffParams->num_entries > FSBL_MAX_PARTITIONS) {
|
||||
ERROR("BL31: ATF handoff params: too many partitions (%u/%u)\n",
|
||||
ATFHandoffParams->num_entries, FSBL_MAX_PARTITIONS);
|
||||
panic();
|
||||
return FSBL_HANDOFF_TOO_MANY_PARTS;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -261,4 +265,6 @@ void fsbl_atf_handover(entry_point_info_t *bl32, entry_point_info_t *bl33)
|
|||
else
|
||||
EP_SET_EE(image->h.attr, EP_EE_LITTLE);
|
||||
}
|
||||
|
||||
return FSBL_HANDOFF_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ override PROGRAMMABLE_RESET_ADDRESS := 1
|
|||
PSCI_EXTENDED_STATE_ID := 1
|
||||
A53_DISABLE_NON_TEMPORAL_HINT := 0
|
||||
SEPARATE_CODE_AND_RODATA := 1
|
||||
ZYNQMP_WDT_RESTART := 0
|
||||
override RESET_TO_BL31 := 1
|
||||
|
||||
# Do not enable SVE
|
||||
|
@ -41,6 +42,10 @@ endif
|
|||
ZYNQMP_CONSOLE ?= cadence
|
||||
$(eval $(call add_define_val,ZYNQMP_CONSOLE,ZYNQMP_CONSOLE_ID_${ZYNQMP_CONSOLE}))
|
||||
|
||||
ifdef ZYNQMP_WDT_RESTART
|
||||
$(eval $(call add_define,ZYNQMP_WDT_RESTART))
|
||||
endif
|
||||
|
||||
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
|
||||
-Iinclude/plat/arm/common/aarch64/ \
|
||||
-Iplat/xilinx/zynqmp/include/ \
|
||||
|
|
|
@ -19,6 +19,19 @@
|
|||
#include "pm_common.h"
|
||||
#include "pm_ipi.h"
|
||||
|
||||
/* default shutdown/reboot scope is system(2) */
|
||||
static unsigned int pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
|
||||
|
||||
/**
|
||||
* pm_get_shutdown_scope() - Get the currently set shutdown scope
|
||||
*
|
||||
* @return Shutdown scope value
|
||||
*/
|
||||
unsigned int pm_get_shutdown_scope(void)
|
||||
{
|
||||
return pm_shutdown_scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigning of argument values into array elements.
|
||||
*/
|
||||
|
@ -130,10 +143,7 @@ enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
|
|||
{
|
||||
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||
uint64_t encoded_address;
|
||||
const struct pm_proc *proc = pm_get_proc_by_node(target);
|
||||
|
||||
/* invoke APU-specific code for waking up another APU core */
|
||||
pm_client_wakeup(proc);
|
||||
|
||||
/* encode set Address into 1st bit of address */
|
||||
encoded_address = address;
|
||||
|
@ -218,7 +228,8 @@ enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
|
|||
|
||||
/**
|
||||
* pm_system_shutdown() - PM call to request a system shutdown or restart
|
||||
* @restart Shutdown or restart? 0 for shutdown, 1 for restart
|
||||
* @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
|
||||
* @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
|
@ -226,8 +237,14 @@ enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype)
|
|||
{
|
||||
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||
|
||||
if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
|
||||
/* Setting scope for subsequent PSCI reboot or shutdown */
|
||||
pm_shutdown_scope = subtype;
|
||||
return PM_RET_SUCCESS;
|
||||
}
|
||||
|
||||
PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
|
||||
return pm_ipi_send(primary_proc, payload);
|
||||
return pm_ipi_send_non_blocking(primary_proc, payload);
|
||||
}
|
||||
|
||||
/* APIs for managing PM slaves: */
|
||||
|
@ -342,18 +359,38 @@ enum pm_ret_status pm_set_configuration(unsigned int phys_addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* pm_get_node_status() - PM call to request a node's current power state
|
||||
* @nid Node id of the slave
|
||||
* pm_init_finalize() - Call to notify PMU firmware that master has power
|
||||
* management enabled and that it has finished its
|
||||
* initialization
|
||||
*
|
||||
* @return Status returned by the PMU firmware
|
||||
*/
|
||||
enum pm_ret_status pm_init_finalize(void)
|
||||
{
|
||||
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||
|
||||
/* Send request to the PMU */
|
||||
PM_PACK_PAYLOAD1(payload, PM_INIT_FINALIZE);
|
||||
return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_get_node_status() - PM call to request a node's current status
|
||||
* @nid Node id
|
||||
* @ret_buff Buffer for the return values:
|
||||
* [0] - Current power state of the node
|
||||
* [1] - Current requirements for the node (slave nodes only)
|
||||
* [2] - Current usage status for the node (slave nodes only)
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
enum pm_ret_status pm_get_node_status(enum pm_node_id nid)
|
||||
enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
|
||||
uint32_t *ret_buff)
|
||||
{
|
||||
/* TODO: Add power state argument!! */
|
||||
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||
|
||||
PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
|
||||
return pm_ipi_send(primary_proc, payload);
|
||||
return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -501,7 +538,7 @@ enum pm_ret_status pm_fpga_load(uint32_t address_low,
|
|||
/* Send request to the PMU */
|
||||
PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
|
||||
size, flags);
|
||||
return pm_ipi_send(primary_proc, payload);
|
||||
return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -538,15 +575,30 @@ enum pm_ret_status pm_get_chipid(uint32_t *value)
|
|||
}
|
||||
|
||||
/**
|
||||
* pm_get_callbackdata() - Read from IPI response buffer
|
||||
* @data - array of PAYLOAD_ARG_CNT elements
|
||||
* pm_secure_rsaaes() - Load the secure images.
|
||||
*
|
||||
* Read value from ipi buffer response buffer.
|
||||
* This function provides access to the xilsecure library to load
|
||||
* the authenticated, encrypted, and authenicated/encrypted images.
|
||||
*
|
||||
* address_low: lower 32-bit Linear memory space address
|
||||
*
|
||||
* address_high: higher 32-bit Linear memory space address
|
||||
*
|
||||
* size: Number of 32bit words
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
void pm_get_callbackdata(uint32_t *data, size_t count)
|
||||
enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
|
||||
uint32_t address_high,
|
||||
uint32_t size,
|
||||
uint32_t flags)
|
||||
{
|
||||
pm_ipi_buff_read_callb(data, count);
|
||||
pm_ipi_irq_clear(primary_proc);
|
||||
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||
|
||||
/* Send request to the PMU */
|
||||
PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
|
||||
size, flags);
|
||||
return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1074,3 +1126,43 @@ enum pm_ret_status pm_query_data(enum pm_query_id qid,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum pm_ret_status pm_sha_hash(uint32_t address_high,
|
||||
uint32_t address_low,
|
||||
uint32_t size,
|
||||
uint32_t flags)
|
||||
{
|
||||
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||
|
||||
/* Send request to the PMU */
|
||||
PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
|
||||
size, flags);
|
||||
return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
|
||||
}
|
||||
|
||||
enum pm_ret_status pm_rsa_core(uint32_t address_high,
|
||||
uint32_t address_low,
|
||||
uint32_t size,
|
||||
uint32_t flags)
|
||||
{
|
||||
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||
|
||||
/* Send request to the PMU */
|
||||
PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
|
||||
size, flags);
|
||||
return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
|
||||
}
|
||||
|
||||
enum pm_ret_status pm_secure_image(uint32_t address_low,
|
||||
uint32_t address_high,
|
||||
uint32_t key_lo,
|
||||
uint32_t key_hi,
|
||||
uint32_t *value)
|
||||
{
|
||||
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||
|
||||
/* Send request to the PMU */
|
||||
PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
|
||||
key_hi, key_lo);
|
||||
return pm_ipi_send_sync(primary_proc, payload, value, 2);
|
||||
}
|
||||
|
|
|
@ -76,7 +76,9 @@ enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
|
|||
/* Miscellaneous API functions */
|
||||
enum pm_ret_status pm_get_api_version(unsigned int *version);
|
||||
enum pm_ret_status pm_set_configuration(unsigned int phys_addr);
|
||||
enum pm_ret_status pm_get_node_status(enum pm_node_id node);
|
||||
enum pm_ret_status pm_init_finalize(void);
|
||||
enum pm_ret_status pm_get_node_status(enum pm_node_id node,
|
||||
uint32_t *ret_buff);
|
||||
enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
|
||||
unsigned int event,
|
||||
unsigned int wake,
|
||||
|
@ -107,7 +109,11 @@ enum pm_ret_status pm_fpga_load(uint32_t address_low,
|
|||
enum pm_ret_status pm_fpga_get_status(unsigned int *value);
|
||||
|
||||
enum pm_ret_status pm_get_chipid(uint32_t *value);
|
||||
void pm_get_callbackdata(uint32_t *data, size_t count);
|
||||
enum pm_ret_status pm_secure_rsaaes(uint32_t address_high,
|
||||
uint32_t address_low,
|
||||
uint32_t size,
|
||||
uint32_t flags);
|
||||
unsigned int pm_get_shutdown_scope(void);
|
||||
enum pm_ret_status pm_pinctrl_request(unsigned int pin);
|
||||
enum pm_ret_status pm_pinctrl_release(unsigned int pin);
|
||||
enum pm_ret_status pm_pinctrl_get_function(unsigned int pin,
|
||||
|
@ -146,4 +152,17 @@ enum pm_ret_status pm_query_data(enum pm_query_id qid,
|
|||
unsigned int arg2,
|
||||
unsigned int arg3,
|
||||
unsigned int *data);
|
||||
enum pm_ret_status pm_sha_hash(uint32_t address_high,
|
||||
uint32_t address_low,
|
||||
uint32_t size,
|
||||
uint32_t flags);
|
||||
enum pm_ret_status pm_rsa_core(uint32_t address_high,
|
||||
uint32_t address_low,
|
||||
uint32_t size,
|
||||
uint32_t flags);
|
||||
enum pm_ret_status pm_secure_image(uint32_t address_low,
|
||||
uint32_t address_high,
|
||||
uint32_t key_lo,
|
||||
uint32_t key_hi,
|
||||
uint32_t *value);
|
||||
#endif /* _PM_API_SYS_H_ */
|
||||
|
|
|
@ -26,10 +26,15 @@
|
|||
#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5) + 1)
|
||||
#define UNDEFINED_CPUID (~0)
|
||||
|
||||
#define PM_SUSPEND_MODE_STD 0
|
||||
#define PM_SUSPEND_MODE_POWER_OFF 1
|
||||
|
||||
DEFINE_BAKERY_LOCK(pm_client_secure_lock);
|
||||
|
||||
extern const struct pm_ipi apu_ipi;
|
||||
|
||||
static uint32_t suspend_mode = PM_SUSPEND_MODE_STD;
|
||||
|
||||
/* Order in pm_procs_all array must match cpu ids */
|
||||
static const struct pm_proc pm_procs_all[] = {
|
||||
{
|
||||
|
@ -165,6 +170,19 @@ static void pm_client_set_wakeup_sources(void)
|
|||
uint8_t pm_wakeup_nodes_set[NODE_MAX];
|
||||
uintptr_t isenabler1 = BASE_GICD_BASE + GICD_ISENABLER + 4;
|
||||
|
||||
/* In case of power-off suspend, only NODE_EXTERN must be set */
|
||||
if (suspend_mode == PM_SUSPEND_MODE_POWER_OFF) {
|
||||
enum pm_ret_status ret;
|
||||
|
||||
ret = pm_set_wakeup_source(NODE_APU, NODE_EXTERN, 1);
|
||||
/**
|
||||
* If NODE_EXTERN could not be set as wake source, proceed with
|
||||
* standard suspend (no one will wake the system otherwise)
|
||||
*/
|
||||
if (ret == PM_RET_SUCCESS)
|
||||
return;
|
||||
}
|
||||
|
||||
zeromem(&pm_wakeup_nodes_set, sizeof(pm_wakeup_nodes_set));
|
||||
|
||||
for (reg_num = 0; reg_num < NUM_GICD_ISENABLER; reg_num++) {
|
||||
|
@ -305,3 +323,13 @@ void pm_client_wakeup(const struct pm_proc *proc)
|
|||
|
||||
bakery_lock_release(&pm_client_secure_lock);
|
||||
}
|
||||
|
||||
enum pm_ret_status pm_set_suspend_mode(uint32_t mode)
|
||||
{
|
||||
if ((mode != PM_SUSPEND_MODE_STD) &&
|
||||
(mode != PM_SUSPEND_MODE_POWER_OFF))
|
||||
return PM_RET_ERROR_ARGS;
|
||||
|
||||
suspend_mode = mode;
|
||||
return PM_RET_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ void pm_client_suspend(const struct pm_proc *proc, unsigned int state);
|
|||
void pm_client_abort_suspend(void);
|
||||
void pm_client_wakeup(const struct pm_proc *proc);
|
||||
enum pm_ret_status set_ocm_retention(void);
|
||||
enum pm_ret_status pm_set_suspend_mode(uint32_t mode);
|
||||
|
||||
/* Global variables to be set in pm_client.c */
|
||||
extern const struct pm_proc *primary_proc;
|
||||
|
|
|
@ -62,7 +62,7 @@ enum pm_api_id {
|
|||
PM_RESET_GET_STATUS,
|
||||
PM_MMIO_WRITE,
|
||||
PM_MMIO_READ,
|
||||
PM_INIT,
|
||||
PM_INIT_FINALIZE,
|
||||
PM_FPGA_LOAD,
|
||||
PM_FPGA_GET_STATUS,
|
||||
PM_GET_CHIPID,
|
||||
|
@ -88,6 +88,7 @@ enum pm_api_id {
|
|||
PM_CLOCK_GETRATE,
|
||||
PM_CLOCK_SETPARENT,
|
||||
PM_CLOCK_GETPARENT,
|
||||
PM_SECURE_IMAGE,
|
||||
PM_API_MAX
|
||||
};
|
||||
|
||||
|
@ -141,7 +142,7 @@ enum pm_node_id {
|
|||
NODE_GPIO,
|
||||
NODE_CAN_0,
|
||||
NODE_CAN_1,
|
||||
NODE_AFI,
|
||||
NODE_EXTERN,
|
||||
NODE_APLL,
|
||||
NODE_VPLL,
|
||||
NODE_DPLL,
|
||||
|
@ -239,11 +240,22 @@ enum pm_boot_status {
|
|||
PM_BOOT_ERROR,
|
||||
};
|
||||
|
||||
/**
|
||||
* @PMF_SHUTDOWN_TYPE_SHUTDOWN: shutdown
|
||||
* @PMF_SHUTDOWN_TYPE_RESET: reset/reboot
|
||||
* @PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY: set the shutdown/reboot scope
|
||||
*/
|
||||
enum pm_shutdown_type {
|
||||
PMF_SHUTDOWN_TYPE_SHUTDOWN,
|
||||
PMF_SHUTDOWN_TYPE_RESET,
|
||||
PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY,
|
||||
};
|
||||
|
||||
/**
|
||||
* @PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM: shutdown/reboot APU subsystem only
|
||||
* @PMF_SHUTDOWN_SUBTYPE_PS_ONLY: shutdown/reboot entire PS (but not PL)
|
||||
* @PMF_SHUTDOWN_SUBTYPE_SYSTEM: shutdown/reboot entire system
|
||||
*/
|
||||
enum pm_shutdown_subtype {
|
||||
PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM,
|
||||
PMF_SHUTDOWN_SUBTYPE_PS_ONLY,
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define IPI_BUFFER_REQ_OFFSET 0x0U
|
||||
#define IPI_BUFFER_RESP_OFFSET 0x20U
|
||||
|
||||
#define IPI_BLOCKING 1
|
||||
#define IPI_NON_BLOCKING 0
|
||||
|
||||
DEFINE_BAKERY_LOCK(pm_secure_lock);
|
||||
|
||||
const struct pm_ipi apu_ipi = {
|
||||
|
@ -63,7 +66,8 @@ int pm_ipi_init(const struct pm_proc *proc)
|
|||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc,
|
||||
uint32_t payload[PAYLOAD_ARG_CNT])
|
||||
uint32_t payload[PAYLOAD_ARG_CNT],
|
||||
uint32_t is_blocking)
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
uintptr_t buffer_base = proc->ipi->buffer_base +
|
||||
|
@ -75,12 +79,38 @@ static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc,
|
|||
mmio_write_32(buffer_base + offset, payload[i]);
|
||||
offset += PAYLOAD_ARG_SIZE;
|
||||
}
|
||||
|
||||
/* Generate IPI to PMU */
|
||||
ipi_mb_notify(proc->ipi->apu_ipi_id, proc->ipi->pmu_ipi_id, 1);
|
||||
ipi_mb_notify(proc->ipi->apu_ipi_id, proc->ipi->pmu_ipi_id,
|
||||
is_blocking);
|
||||
|
||||
return PM_RET_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_ipi_send_non_blocking() - Sends IPI request to the PMU without blocking
|
||||
* notification
|
||||
* @proc Pointer to the processor who is initiating request
|
||||
* @payload API id and call arguments to be written in IPI buffer
|
||||
*
|
||||
* Send an IPI request to the power controller.
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
enum pm_ret_status pm_ipi_send_non_blocking(const struct pm_proc *proc,
|
||||
uint32_t payload[PAYLOAD_ARG_CNT])
|
||||
{
|
||||
enum pm_ret_status ret;
|
||||
|
||||
bakery_lock_get(&pm_secure_lock);
|
||||
|
||||
ret = pm_ipi_send_common(proc, payload, IPI_NON_BLOCKING);
|
||||
|
||||
bakery_lock_release(&pm_secure_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_ipi_send() - Sends IPI request to the PMU
|
||||
* @proc Pointer to the processor who is initiating request
|
||||
|
@ -97,7 +127,7 @@ enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
|
|||
|
||||
bakery_lock_get(&pm_secure_lock);
|
||||
|
||||
ret = pm_ipi_send_common(proc, payload);
|
||||
ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING);
|
||||
|
||||
bakery_lock_release(&pm_secure_lock);
|
||||
|
||||
|
@ -179,7 +209,7 @@ enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
|
|||
|
||||
bakery_lock_get(&pm_secure_lock);
|
||||
|
||||
ret = pm_ipi_send_common(proc, payload);
|
||||
ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING);
|
||||
if (ret != PM_RET_SUCCESS)
|
||||
goto unlock;
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ int pm_ipi_init(const struct pm_proc *proc);
|
|||
|
||||
enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
|
||||
uint32_t payload[PAYLOAD_ARG_CNT]);
|
||||
enum pm_ret_status pm_ipi_send_non_blocking(const struct pm_proc *proc,
|
||||
uint32_t payload[PAYLOAD_ARG_CNT]);
|
||||
enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
|
||||
uint32_t payload[PAYLOAD_ARG_CNT],
|
||||
unsigned int *value, size_t count);
|
||||
|
|
|
@ -10,19 +10,30 @@
|
|||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <gic_common.h>
|
||||
#include <runtime_svc.h>
|
||||
#include <string.h>
|
||||
#include "../zynqmp_private.h"
|
||||
#include "pm_api_sys.h"
|
||||
#include "pm_client.h"
|
||||
#include "pm_ipi.h"
|
||||
#if ZYNQMP_WDT_RESTART
|
||||
#include <arch_helpers.h>
|
||||
#include <gicv2.h>
|
||||
#include <mmio.h>
|
||||
#include <platform.h>
|
||||
#include <spinlock.h>
|
||||
#endif
|
||||
|
||||
#define PM_GET_CALLBACK_DATA 0xa01
|
||||
#define PM_SET_SUSPEND_MODE 0xa02
|
||||
#define PM_GET_TRUSTZONE_VERSION 0xa03
|
||||
|
||||
/* 0 - UP, !0 - DOWN */
|
||||
static int32_t pm_down = !0;
|
||||
/* !0 - UP, 0 - DOWN */
|
||||
static int32_t pm_up = 0;
|
||||
|
||||
#if ZYNQMP_WDT_RESTART
|
||||
static spinlock_t inc_lock;
|
||||
static int active_cores = 0;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* pm_context - Structure which contains data for power management
|
||||
|
@ -35,6 +46,142 @@ static struct {
|
|||
uint32_t payload[PAYLOAD_ARG_CNT];
|
||||
} pm_ctx;
|
||||
|
||||
#if ZYNQMP_WDT_RESTART
|
||||
/**
|
||||
* trigger_wdt_restart() - Trigger warm restart event to APU cores
|
||||
*
|
||||
* This function triggers SGI for all active APU CPUs. SGI handler then
|
||||
* power down CPU and call system reset.
|
||||
*/
|
||||
static void trigger_wdt_restart(void)
|
||||
{
|
||||
uint32_t core_count = 0;
|
||||
uint32_t core_status[3];
|
||||
uint32_t target_cpu_list = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
pm_get_node_status(NODE_APU_0 + i, core_status);
|
||||
if (core_status[0] == 1) {
|
||||
core_count++;
|
||||
target_cpu_list |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&inc_lock);
|
||||
active_cores = core_count;
|
||||
spin_unlock(&inc_lock);
|
||||
|
||||
INFO("Active Cores: %d\n", active_cores);
|
||||
|
||||
/* trigger SGI to active cores */
|
||||
gicv2_raise_sgi(ARM_IRQ_SEC_SGI_7, target_cpu_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* ttc_fiq_handler() - TTC Handler for timer event
|
||||
* @id number of the highest priority pending interrupt of the type
|
||||
* that this handler was registered for
|
||||
* @flags security state, bit[0]
|
||||
* @handler pointer to 'cpu_context' structure of the current CPU for the
|
||||
* security state specified in the 'flags' parameter
|
||||
* @cookie unused
|
||||
*
|
||||
* Function registered as INTR_TYPE_EL3 interrupt handler
|
||||
*
|
||||
* When WDT event is received in PMU, PMU needs to notify master to do cleanup
|
||||
* if required. PMU sets up timer and starts timer to overflow in zero time upon
|
||||
* WDT event. ATF handles this timer event and takes necessary action required
|
||||
* for warm restart.
|
||||
*
|
||||
* In presence of non-secure software layers (EL1/2) sets the interrupt
|
||||
* at registered entrance in GIC and informs that PMU responsed or demands
|
||||
* action.
|
||||
*/
|
||||
static uint64_t ttc_fiq_handler(uint32_t id, uint32_t flags, void *handle,
|
||||
void *cookie)
|
||||
{
|
||||
INFO("BL31: Got TTC FIQ\n");
|
||||
|
||||
/* Clear TTC interrupt by reading interrupt register */
|
||||
mmio_read_32(TTC3_INTR_REGISTER_1);
|
||||
|
||||
/* Disable the timer interrupts */
|
||||
mmio_write_32(TTC3_INTR_ENABLE_1, 0);
|
||||
|
||||
trigger_wdt_restart();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* zynqmp_sgi7_irq() - Handler for SGI7 IRQ
|
||||
* @id number of the highest priority pending interrupt of the type
|
||||
* that this handler was registered for
|
||||
* @flags security state, bit[0]
|
||||
* @handler pointer to 'cpu_context' structure of the current CPU for the
|
||||
* security state specified in the 'flags' parameter
|
||||
* @cookie unused
|
||||
*
|
||||
* Function registered as INTR_TYPE_EL3 interrupt handler
|
||||
*
|
||||
* On receiving WDT event from PMU, ATF generates SGI7 to all running CPUs.
|
||||
* In response to SGI7 interrupt, each CPUs do clean up if required and last
|
||||
* running CPU calls system restart.
|
||||
*/
|
||||
static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags,
|
||||
void *handle, void *cookie)
|
||||
{
|
||||
int i;
|
||||
/* enter wfi and stay there */
|
||||
INFO("Entering wfi\n");
|
||||
|
||||
spin_lock(&inc_lock);
|
||||
active_cores--;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
mmio_write_32(BASE_GICD_BASE + GICD_CPENDSGIR + 4 * i,
|
||||
0xffffffff);
|
||||
}
|
||||
|
||||
spin_unlock(&inc_lock);
|
||||
|
||||
if (active_cores == 0) {
|
||||
pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET,
|
||||
PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM);
|
||||
}
|
||||
|
||||
/* enter wfi and stay there */
|
||||
while (1)
|
||||
wfi();
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_wdt_restart_setup() - Setup warm restart interrupts
|
||||
*
|
||||
* This function sets up handler for SGI7 and TTC interrupts
|
||||
* used for warm restart.
|
||||
*/
|
||||
static int pm_wdt_restart_setup(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* register IRQ handler for SGI7 */
|
||||
ret = request_intr_type_el3(ARM_IRQ_SEC_SGI_7, zynqmp_sgi7_irq);
|
||||
if (ret) {
|
||||
WARN("BL31: registering SGI7 interrupt failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = request_intr_type_el3(IRQ_TTC3_1, ttc_fiq_handler);
|
||||
if (ret)
|
||||
WARN("BL31: registering TTC3 interrupt failed\n");
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* pm_setup() - PM service setup
|
||||
*
|
||||
|
@ -52,11 +199,14 @@ int pm_setup(void)
|
|||
{
|
||||
int status, ret;
|
||||
|
||||
if (!zynqmp_is_pmu_up())
|
||||
return -ENODEV;
|
||||
|
||||
status = pm_ipi_init(primary_proc);
|
||||
|
||||
#if ZYNQMP_WDT_RESTART
|
||||
status = pm_wdt_restart_setup();
|
||||
if (status)
|
||||
WARN("BL31: warm-restart setup failed\n");
|
||||
#endif
|
||||
|
||||
if (status >= 0) {
|
||||
INFO("BL31: PM Service Init Complete: API v%d.%d\n",
|
||||
PM_VERSION_MAJOR, PM_VERSION_MINOR);
|
||||
|
@ -66,7 +216,7 @@ int pm_setup(void)
|
|||
ret = status;
|
||||
}
|
||||
|
||||
pm_down = status;
|
||||
pm_up = !status;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -95,7 +245,7 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
|
|||
uint32_t pm_arg[4];
|
||||
|
||||
/* Handle case where PM wasn't initialized properly */
|
||||
if (pm_down)
|
||||
if (!pm_up)
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
|
||||
pm_arg[0] = (uint32_t)x1;
|
||||
|
@ -116,9 +266,16 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
|
|||
SMC_RET1(handle, (uint64_t)ret);
|
||||
|
||||
case PM_REQ_WAKEUP:
|
||||
ret = pm_req_wakeup(pm_arg[0], pm_arg[1], pm_arg[2],
|
||||
{
|
||||
/* Use address flag is encoded in the 1st bit of the low-word */
|
||||
unsigned int set_addr = pm_arg[1] & 0x1;
|
||||
uint64_t address = (uint64_t)pm_arg[2] << 32;
|
||||
|
||||
address |= pm_arg[1] & (~0x1);
|
||||
ret = pm_req_wakeup(pm_arg[0], set_addr, address,
|
||||
pm_arg[3]);
|
||||
SMC_RET1(handle, (uint64_t)ret);
|
||||
}
|
||||
|
||||
case PM_FORCE_POWERDOWN:
|
||||
ret = pm_force_powerdown(pm_arg[0], pm_arg[1]);
|
||||
|
@ -175,10 +332,19 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
|
|||
ret = pm_set_configuration(pm_arg[0]);
|
||||
SMC_RET1(handle, (uint64_t)ret);
|
||||
|
||||
case PM_GET_NODE_STATUS:
|
||||
ret = pm_get_node_status(pm_arg[0]);
|
||||
case PM_INIT_FINALIZE:
|
||||
ret = pm_init_finalize();
|
||||
SMC_RET1(handle, (uint64_t)ret);
|
||||
|
||||
case PM_GET_NODE_STATUS:
|
||||
{
|
||||
uint32_t buff[3];
|
||||
|
||||
ret = pm_get_node_status(pm_arg[0], buff);
|
||||
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buff[0] << 32),
|
||||
(uint64_t)buff[1] | ((uint64_t)buff[2] << 32));
|
||||
}
|
||||
|
||||
case PM_GET_OP_CHARACTERISTIC:
|
||||
{
|
||||
uint32_t result;
|
||||
|
@ -239,15 +405,10 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
|
|||
result[1]);
|
||||
}
|
||||
|
||||
case PM_GET_CALLBACK_DATA:
|
||||
{
|
||||
uint32_t result[4];
|
||||
|
||||
pm_get_callbackdata(result, sizeof(result));
|
||||
SMC_RET2(handle,
|
||||
(uint64_t)result[0] | ((uint64_t)result[1] << 32),
|
||||
(uint64_t)result[2] | ((uint64_t)result[3] << 32));
|
||||
}
|
||||
case PM_SECURE_RSA_AES:
|
||||
ret = pm_secure_rsaaes(pm_arg[0], pm_arg[1], pm_arg[2],
|
||||
pm_arg[3]);
|
||||
SMC_RET1(handle, (uint64_t)ret);
|
||||
|
||||
case PM_PINCTRL_REQUEST:
|
||||
ret = pm_pinctrl_request(pm_arg[0]);
|
||||
|
@ -361,6 +522,30 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
|
|||
SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
|
||||
((uint64_t)ZYNQMP_TZ_VERSION << 32));
|
||||
|
||||
case PM_SET_SUSPEND_MODE:
|
||||
ret = pm_set_suspend_mode(pm_arg[0]);
|
||||
SMC_RET1(handle, (uint64_t)ret);
|
||||
|
||||
case PM_SECURE_SHA:
|
||||
ret = pm_sha_hash(pm_arg[0], pm_arg[1], pm_arg[2],
|
||||
pm_arg[3]);
|
||||
SMC_RET1(handle, (uint64_t)ret);
|
||||
|
||||
case PM_SECURE_RSA:
|
||||
ret = pm_rsa_core(pm_arg[0], pm_arg[1], pm_arg[2],
|
||||
pm_arg[3]);
|
||||
SMC_RET1(handle, (uint64_t)ret);
|
||||
|
||||
case PM_SECURE_IMAGE:
|
||||
{
|
||||
uint32_t result[2];
|
||||
|
||||
ret = pm_secure_image(pm_arg[0], pm_arg[1], pm_arg[2],
|
||||
pm_arg[3], &result[0]);
|
||||
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32),
|
||||
result[1]);
|
||||
}
|
||||
|
||||
default:
|
||||
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
|
|
|
@ -101,6 +101,14 @@
|
|||
#define BASE_GICH_BASE 0xF9040000
|
||||
#define BASE_GICV_BASE 0xF9060000
|
||||
|
||||
#if ZYNQMP_WDT_RESTART
|
||||
#define IRQ_SEC_IPI_APU 67
|
||||
#define IRQ_TTC3_1 77
|
||||
#define TTC3_BASE_ADDR 0xFF140000
|
||||
#define TTC3_INTR_REGISTER_1 (TTC3_BASE_ADDR + 0x54)
|
||||
#define TTC3_INTR_ENABLE_1 (TTC3_BASE_ADDR + 0x60)
|
||||
#endif
|
||||
|
||||
#define ARM_IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define ARM_IRQ_SEC_SGI_0 8
|
||||
|
@ -158,7 +166,8 @@
|
|||
#define ZYNQMP_CSU_IDCODE_XILINX_ID 0x093
|
||||
|
||||
#define ZYNQMP_CSU_IDCODE_SVD_SHIFT 12
|
||||
#define ZYNQMP_CSU_IDCODE_SVD_MASK (0xE << ZYNQMP_CSU_IDCODE_SVD_SHIFT)
|
||||
#define ZYNQMP_CSU_IDCODE_SVD_MASK (0x7 << \
|
||||
ZYNQMP_CSU_IDCODE_SVD_SHIFT)
|
||||
#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT 15
|
||||
#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK (0xF << ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT)
|
||||
#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT 19
|
||||
|
@ -173,6 +182,12 @@
|
|||
|
||||
#define ZYNQMP_CSU_VERSION_OFFSET 0x44
|
||||
|
||||
/* Efuse */
|
||||
#define EFUSE_BASEADDR 0xFFCC0000
|
||||
#define EFUSE_IPDISABLE_OFFSET 0x1018
|
||||
#define EFUSE_IPDISABLE_VERSION 0x1FFU
|
||||
#define ZYNQMP_EFUSE_IPDISABLE_SHIFT 20
|
||||
|
||||
/* Access control register defines */
|
||||
#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
|
||||
#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
|
||||
|
|
|
@ -84,7 +84,7 @@ const static struct zynqmp_ipi_config zynqmp_ipi_table[] = {
|
|||
{
|
||||
.ipi_bit_mask = 0x20000,
|
||||
.ipi_reg_base = 0xFF331000,
|
||||
.secure_only = IPI_SECURE_MASK,
|
||||
.secure_only = 0,
|
||||
},
|
||||
/* PMU2 IPI */
|
||||
{
|
||||
|
|
|
@ -7,17 +7,32 @@
|
|||
#ifndef __ZYNQMP_PRIVATE_H__
|
||||
#define __ZYNQMP_PRIVATE_H__
|
||||
|
||||
#include <bl_common.h>
|
||||
#include <interrupt_mgmt.h>
|
||||
|
||||
void zynqmp_config_setup(void);
|
||||
|
||||
/* ZynqMP specific functions */
|
||||
unsigned int zynqmp_get_uart_clk(void);
|
||||
int zynqmp_is_pmu_up(void);
|
||||
unsigned int zynqmp_get_bootmode(void);
|
||||
|
||||
/* For FSBL handover */
|
||||
void fsbl_atf_handover(entry_point_info_t *bl32_image_ep_info,
|
||||
enum fsbl_handoff {
|
||||
FSBL_HANDOFF_SUCCESS = 0,
|
||||
FSBL_HANDOFF_NO_STRUCT,
|
||||
FSBL_HANDOFF_INVAL_STRUCT,
|
||||
FSBL_HANDOFF_TOO_MANY_PARTS,
|
||||
};
|
||||
|
||||
#if ZYNQMP_WDT_RESTART
|
||||
/*
|
||||
* Register handler to specific GIC entrance
|
||||
* for INTR_TYPE_EL3 type of interrupt
|
||||
*/
|
||||
int request_intr_type_el3(uint32_t, interrupt_type_handler_t);
|
||||
#endif
|
||||
|
||||
enum fsbl_handoff fsbl_atf_handover(entry_point_info_t *bl32_image_ep_info,
|
||||
entry_point_info_t *bl33_image_ep_info);
|
||||
|
||||
#endif /* __ZYNQMP_PRIVATE_H__ */
|
||||
|
|
Loading…
Reference in New Issue