Commit a8de89c9 authored by davidcunado-arm's avatar davidcunado-arm Committed by GitHub
Browse files

Merge pull request #709 from Xilinx/zynqmp-2016-09

xilinx: ZynqMP updates
- new SIP calls for bitstream programming
- new SIP call to discover the SOC silicon version
- support the delay timer
parents e69c1956 8787c0e0
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
*/ */
#include <debug.h> #include <debug.h>
#include <generic_delay_timer.h>
#include <mmio.h> #include <mmio.h>
#include <platform.h> #include <platform.h>
#include <xlat_tables.h> #include <xlat_tables.h>
...@@ -89,6 +90,18 @@ static unsigned int zynqmp_get_system_timer_freq(void) ...@@ -89,6 +90,18 @@ static unsigned int zynqmp_get_system_timer_freq(void)
return 100000000; return 100000000;
} }
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;
}
#if LOG_LEVEL >= LOG_LEVEL_NOTICE #if LOG_LEVEL >= LOG_LEVEL_NOTICE
static const struct { static const struct {
unsigned int id; unsigned int id;
...@@ -140,18 +153,6 @@ static const struct { ...@@ -140,18 +153,6 @@ static const struct {
}, },
}; };
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;
}
static char *zynqmp_get_silicon_idcode_name(void) static char *zynqmp_get_silicon_idcode_name(void)
{ {
unsigned int id; unsigned int id;
...@@ -289,6 +290,8 @@ void zynqmp_config_setup(void) ...@@ -289,6 +290,8 @@ void zynqmp_config_setup(void)
/* Program freq register in System counter and enable system counter. */ /* Program freq register in System counter and enable system counter. */
mmio_write_32(IOU_SCNTRS_BASEFREQ, zynqmp_get_system_timer_freq()); mmio_write_32(IOU_SCNTRS_BASEFREQ, zynqmp_get_system_timer_freq());
mmio_write_32(IOU_SCNTRS_CONTROL, IOU_SCNTRS_CONTROL_EN); mmio_write_32(IOU_SCNTRS_CONTROL, IOU_SCNTRS_CONTROL_EN);
generic_delay_timer_init();
} }
unsigned int plat_get_syscnt_freq2(void) unsigned int plat_get_syscnt_freq2(void)
......
...@@ -118,11 +118,31 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2, ...@@ -118,11 +118,31 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2,
NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
} }
/* Enable the test setup */
#ifndef ZYNQMP_TESTING
static void zynqmp_testing_setup(void) { }
#else
static void zynqmp_testing_setup(void)
{
uint32_t actlr_el3, actlr_el2;
/* Enable CPU ACTLR AND L2ACTLR RW access from non-secure world */
actlr_el3 = read_actlr_el3();
actlr_el2 = read_actlr_el2();
actlr_el3 |= ACTLR_EL3_L2ACTLR_BIT | ACTLR_EL3_CPUACTLR_BIT;
actlr_el2 |= ACTLR_EL3_L2ACTLR_BIT | ACTLR_EL3_CPUACTLR_BIT;
write_actlr_el3(actlr_el3);
write_actlr_el2(actlr_el2);
}
#endif
void bl31_platform_setup(void) void bl31_platform_setup(void)
{ {
/* Initialize the gic cpu and distributor interfaces */ /* Initialize the gic cpu and distributor interfaces */
plat_arm_gic_driver_init(); plat_arm_gic_driver_init();
plat_arm_gic_init(); plat_arm_gic_init();
zynqmp_testing_setup();
} }
void bl31_plat_runtime_setup(void) void bl31_plat_runtime_setup(void)
......
...@@ -56,8 +56,7 @@ ...@@ -56,8 +56,7 @@
* little space for growth. * little space for growth.
*/ */
#ifndef ZYNQMP_ATF_MEM_BASE #ifndef ZYNQMP_ATF_MEM_BASE
# define BL31_BASE 0xfffe5000 # define BL31_BASE 0xfffea000
# define BL31_PROGBITS_LIMIT 0xffffa000
# define BL31_LIMIT 0xffffffff # define BL31_LIMIT 0xffffffff
#else #else
# define BL31_BASE (ZYNQMP_ATF_MEM_BASE) # define BL31_BASE (ZYNQMP_ATF_MEM_BASE)
...@@ -101,11 +100,7 @@ ...@@ -101,11 +100,7 @@
******************************************************************************/ ******************************************************************************/
#define ADDR_SPACE_SIZE (1ull << 32) #define ADDR_SPACE_SIZE (1ull << 32)
#define MAX_MMAP_REGIONS 7 #define MAX_MMAP_REGIONS 7
#if IMAGE_BL32 #define MAX_XLAT_TABLES 5
# define MAX_XLAT_TABLES 5
#else
# define MAX_XLAT_TABLES 4
#endif
#define CACHE_WRITEBACK_SHIFT 6 #define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) #define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
......
...@@ -147,7 +147,7 @@ static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state) ...@@ -147,7 +147,7 @@ static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state)
* invoking CPU_on function, during which resume address will * invoking CPU_on function, during which resume address will
* be set. * be set.
*/ */
pm_self_suspend(proc->node_id, MAX_LATENCY, 0, 0); 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) static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_state)
...@@ -179,6 +179,7 @@ static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_sta ...@@ -179,6 +179,7 @@ static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_sta
static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state) static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
{ {
unsigned int state;
unsigned int cpu_id = plat_my_core_pos(); unsigned int cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id); const struct pm_proc *proc = pm_get_proc(cpu_id);
...@@ -186,15 +187,14 @@ static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state) ...@@ -186,15 +187,14 @@ static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
__func__, i, target_state->pwr_domain_state[i]); __func__, i, target_state->pwr_domain_state[i]);
state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
/* Send request to PMU to suspend this core */ /* Send request to PMU to suspend this core */
pm_self_suspend(proc->node_id, MAX_LATENCY, 0, zynqmp_sec_entry); pm_self_suspend(proc->node_id, MAX_LATENCY, state, zynqmp_sec_entry);
/* APU is to be turned off */ /* APU is to be turned off */
if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
/* Power down L2 cache */
pm_set_requirement(NODE_L2, 0, 0, REQ_ACK_NO);
/* Send request for OCM retention state */
set_ocm_retention();
/* disable coherency */ /* disable coherency */
plat_arm_interconnect_exit_coherency(); plat_arm_interconnect_exit_coherency();
} }
...@@ -242,6 +242,13 @@ static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_st ...@@ -242,6 +242,13 @@ static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_st
/* enable coherency */ /* enable coherency */
plat_arm_interconnect_enter_coherency(); plat_arm_interconnect_enter_coherency();
/* APU was turned off */
if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
plat_arm_gic_init();
} else {
gicv2_cpuif_enable();
gicv2_pcpu_distif_init();
}
} }
/******************************************************************************* /*******************************************************************************
...@@ -308,7 +315,20 @@ int zynqmp_validate_power_state(unsigned int power_state, ...@@ -308,7 +315,20 @@ int zynqmp_validate_power_state(unsigned int power_state,
{ {
VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
/* FIXME: populate req_state */ int pstate = psci_get_pstate_type(power_state);
assert(req_state);
/* Sanity check the requested state */
if (pstate == PSTATE_TYPE_STANDBY)
req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
else
req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
/* We expect the 'state id' to be zero */
if (psci_get_pstate_id(power_state))
return PSCI_E_INVALID_PARAMS;
return PSCI_E_SUCCESS; return PSCI_E_SUCCESS;
} }
......
...@@ -31,6 +31,7 @@ PROGRAMMABLE_RESET_ADDRESS := 1 ...@@ -31,6 +31,7 @@ PROGRAMMABLE_RESET_ADDRESS := 1
PSCI_EXTENDED_STATE_ID := 1 PSCI_EXTENDED_STATE_ID := 1
A53_DISABLE_NON_TEMPORAL_HINT := 0 A53_DISABLE_NON_TEMPORAL_HINT := 0
SEPARATE_CODE_AND_RODATA := 1 SEPARATE_CODE_AND_RODATA := 1
RESET_TO_BL31 := 1
ifdef ZYNQMP_ATF_MEM_BASE ifdef ZYNQMP_ATF_MEM_BASE
$(eval $(call add_define,ZYNQMP_ATF_MEM_BASE)) $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE))
...@@ -64,6 +65,8 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ ...@@ -64,6 +65,8 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
lib/xlat_tables/aarch64/xlat_tables.c \ lib/xlat_tables/aarch64/xlat_tables.c \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
drivers/arm/gic/common/gic_common.c \ drivers/arm/gic/common/gic_common.c \
drivers/arm/gic/v2/gicv2_main.c \ drivers/arm/gic/v2/gicv2_main.c \
drivers/arm/gic/v2/gicv2_helpers.c \ drivers/arm/gic/v2/gicv2_helpers.c \
......
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
* pm_self_suspend() - PM call for processor to suspend itself * pm_self_suspend() - PM call for processor to suspend itself
* @nid Node id of the processor or subsystem * @nid Node id of the processor or subsystem
* @latency Requested maximum wakeup latency (not supported) * @latency Requested maximum wakeup latency (not supported)
* @state Requested state (not supported) * @state Requested state
* @address Resume address * @address Resume address
* *
* This is a blocking call, it will return only once PMU has responded. * This is a blocking call, it will return only once PMU has responded.
...@@ -97,7 +97,7 @@ enum pm_ret_status pm_self_suspend(enum pm_node_id nid, ...@@ -97,7 +97,7 @@ enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
* Do client specific suspend operations * Do client specific suspend operations
* (e.g. set powerdown request bit) * (e.g. set powerdown request bit)
*/ */
pm_client_suspend(proc); pm_client_suspend(proc, state);
/* Send request to the PMU */ /* Send request to the PMU */
PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency, PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
state, address, (address >> 32)); state, address, (address >> 32));
...@@ -476,7 +476,7 @@ enum pm_ret_status pm_mmio_write(uintptr_t address, ...@@ -476,7 +476,7 @@ enum pm_ret_status pm_mmio_write(uintptr_t address,
/* Send request to the PMU */ /* Send request to the PMU */
PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value); PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
return pm_ipi_send(primary_proc, payload); return pm_ipi_send_sync(primary_proc, payload, NULL);
} }
/** /**
...@@ -497,3 +497,47 @@ enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value) ...@@ -497,3 +497,47 @@ enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address); PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
return pm_ipi_send_sync(primary_proc, payload, value); return pm_ipi_send_sync(primary_proc, payload, value);
} }
/**
* pm_fpga_load() - Load the bitstream into the PL.
*
* This function provides access to the xilfpga library to load
* the Bit-stream into PL.
*
* 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
*/
enum pm_ret_status pm_fpga_load(uint32_t address_low,
uint32_t address_high,
uint32_t size,
uint32_t flags)
{
uint32_t payload[PAYLOAD_ARG_CNT];
/* 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);
}
/**
* pm_fpga_get_status() - Read value from fpga status register
* @value Value to read
*
* This function provides access to the xilfpga library to get
* the fpga status
* @return Returns status, either success or error+reason
*/
enum pm_ret_status pm_fpga_get_status(unsigned int *value)
{
uint32_t payload[PAYLOAD_ARG_CNT];
/* Send request to the PMU */
PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
return pm_ipi_send_sync(primary_proc, payload, value);
}
...@@ -109,4 +109,10 @@ enum pm_ret_status pm_mmio_write(uintptr_t address, ...@@ -109,4 +109,10 @@ enum pm_ret_status pm_mmio_write(uintptr_t address,
unsigned int mask, unsigned int mask,
unsigned int value); unsigned int value);
enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value); enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value);
enum pm_ret_status pm_fpga_load(uint32_t address_high,
uint32_t address_low,
uint32_t size,
uint32_t flags);
enum pm_ret_status pm_fpga_get_status(unsigned int *value);
#endif /* _PM_API_SYS_H_ */ #endif /* _PM_API_SYS_H_ */
...@@ -33,26 +33,25 @@ ...@@ -33,26 +33,25 @@
* for getting information about and changing state of the APU. * for getting information about and changing state of the APU.
*/ */
#include <assert.h>
#include <bakery_lock.h> #include <bakery_lock.h>
#include <gicv2.h> #include <gicv2.h>
#include <gic_common.h>
#include <bl_common.h> #include <bl_common.h>
#include <mmio.h> #include <mmio.h>
#include <string.h>
#include <utils.h> #include <utils.h>
#include "pm_api_sys.h" #include "pm_api_sys.h"
#include "pm_client.h" #include "pm_client.h"
#include "pm_ipi.h" #include "pm_ipi.h"
#include "../zynqmp_def.h" #include "../zynqmp_def.h"
#define OCM_BANK_0 0xFFFC0000 #define IRQ_MAX 84
#define OCM_BANK_1 (OCM_BANK_0 + 0x10000) #define NUM_GICD_ISENABLER ((IRQ_MAX >> 5) + 1)
#define OCM_BANK_2 (OCM_BANK_1 + 0x10000)
#define OCM_BANK_3 (OCM_BANK_2 + 0x10000)
#define UNDEFINED_CPUID (~0) #define UNDEFINED_CPUID (~0)
DEFINE_BAKERY_LOCK(pm_client_secure_lock); DEFINE_BAKERY_LOCK(pm_client_secure_lock);
/* Declaration of linker defined symbol */
extern unsigned long __BL31_END__;
extern const struct pm_ipi apu_ipi; extern const struct pm_ipi apu_ipi;
/* Order in pm_procs_all array must match cpu ids */ /* Order in pm_procs_all array must match cpu ids */
...@@ -79,36 +78,146 @@ static const struct pm_proc const pm_procs_all[] = { ...@@ -79,36 +78,146 @@ static const struct pm_proc const pm_procs_all[] = {
}, },
}; };
/* Interrupt to PM node ID map */
static enum pm_node_id irq_node_map[IRQ_MAX + 1] = {
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN, /* 3 */
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN, /* 7 */
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN, /* 11 */
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_NAND,
NODE_QSPI, /* 15 */
NODE_GPIO,
NODE_I2C_0,
NODE_I2C_1,
NODE_SPI_0, /* 19 */
NODE_SPI_1,
NODE_UART_0,
NODE_UART_1,
NODE_CAN_0, /* 23 */
NODE_CAN_1,
NODE_UNKNOWN,
NODE_RTC,
NODE_RTC, /* 27 */
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN, /* 31 */
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN, /* 35, NODE_IPI_APU */
NODE_TTC_0,
NODE_TTC_0,
NODE_TTC_0,
NODE_TTC_1, /* 39 */
NODE_TTC_1,
NODE_TTC_1,
NODE_TTC_2,
NODE_TTC_2, /* 43 */
NODE_TTC_2,
NODE_TTC_3,
NODE_TTC_3,
NODE_TTC_3, /* 47 */
NODE_SD_0,
NODE_SD_1,
NODE_SD_0,
NODE_SD_1, /* 51 */
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN,
NODE_UNKNOWN, /* 55 */
NODE_UNKNOWN,
NODE_ETH_0,
NODE_ETH_0,
NODE_ETH_1, /* 59 */
NODE_ETH_1,
NODE_ETH_2,
NODE_ETH_2,
NODE_ETH_3, /* 63 */
NODE_ETH_3,
NODE_USB_0,
NODE_USB_0,
NODE_USB_0, /* 67 */
NODE_USB_0,
NODE_USB_0,
NODE_USB_1,
NODE_USB_1, /* 71 */
NODE_USB_1,
NODE_USB_1,
NODE_USB_1,
NODE_USB_0, /* 75 */
NODE_USB_0,
NODE_ADMA,
NODE_ADMA,
NODE_ADMA, /* 79 */
NODE_ADMA,
NODE_ADMA,
NODE_ADMA,
NODE_ADMA, /* 83 */
NODE_ADMA,
};
/** /**
* set_ocm_retention() - Configure OCM memory banks for retention * irq_to_pm_node - Get PM node ID corresponding to the interrupt number
* * @irq: Interrupt number
* APU specific requirements for suspend action:
* OCM has to enter retention state in order to preserve saved
* context after suspend request. OCM banks are determined by
* __BL31_END__ linker symbol.
* *
* Return: Returns status, either success or error+reason * Return: PM node ID corresponding to the specified interrupt
*/ */
enum pm_ret_status set_ocm_retention(void) static enum pm_node_id irq_to_pm_node(unsigned int irq)
{ {
enum pm_ret_status ret; assert(irq <= IRQ_MAX);
return irq_node_map[irq];
/* OCM_BANK_0 will always be occupied */ }
ret = pm_set_requirement(NODE_OCM_BANK_0, PM_CAP_CONTEXT, 0,
REQ_ACK_NO); /**
* pm_client_set_wakeup_sources - Set all slaves with enabled interrupts as wake
/* Check for other OCM banks */ * sources in the PMU firmware
if ((unsigned long)&__BL31_END__ >= OCM_BANK_1) */
ret = pm_set_requirement(NODE_OCM_BANK_1, PM_CAP_CONTEXT, 0, static void pm_client_set_wakeup_sources(void)
REQ_ACK_NO); {
if ((unsigned long)&__BL31_END__ >= OCM_BANK_2) uint32_t reg_num;
ret = pm_set_requirement(NODE_OCM_BANK_2, PM_CAP_CONTEXT, 0, uint8_t pm_wakeup_nodes_set[NODE_MAX];
REQ_ACK_NO); uintptr_t isenabler1 = BASE_GICD_BASE + GICD_ISENABLER + 4;
if ((unsigned long)&__BL31_END__ >= OCM_BANK_3)
ret = pm_set_requirement(NODE_OCM_BANK_3, PM_CAP_CONTEXT, 0, memset(&pm_wakeup_nodes_set, 0, sizeof(pm_wakeup_nodes_set));
REQ_ACK_NO);
for (reg_num = 0; reg_num < NUM_GICD_ISENABLER; reg_num++) {
return ret; uint32_t base_irq = reg_num << ISENABLER_SHIFT;
uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2));
if (!reg)
continue;
while (reg) {
enum pm_node_id node;
uint32_t idx, ret, irq, lowest_set = reg & (-reg);
idx = __builtin_ctz(lowest_set);
irq = base_irq + idx;
if (irq > IRQ_MAX)
break;
node = irq_to_pm_node(irq);
reg &= ~lowest_set;
if ((node != NODE_UNKNOWN) &&
(!pm_wakeup_nodes_set[node])) {
ret = pm_set_wakeup_source(NODE_APU, node, 1);
pm_wakeup_nodes_set[node] = !ret;
}
}
}
} }
/** /**
...@@ -162,11 +271,15 @@ const struct pm_proc *primary_proc = &pm_procs_all[0]; ...@@ -162,11 +271,15 @@ const struct pm_proc *primary_proc = &pm_procs_all[0];
* *
* This function should contain any PU-specific actions * This function should contain any PU-specific actions
* required prior to sending suspend request to PMU * required prior to sending suspend request to PMU
* Actions taken depend on the state system is suspending to.
*/ */
void pm_client_suspend(const struct pm_proc *proc) void pm_client_suspend(const struct pm_proc *proc, unsigned int state)
{ {
bakery_lock_get(&pm_client_secure_lock); bakery_lock_get(&pm_client_secure_lock);
if (state == PM_STATE_SUSPEND_TO_RAM)
pm_client_set_wakeup_sources();
/* Set powerdown request */ /* Set powerdown request */
mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask); mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask);
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include "pm_common.h" #include "pm_common.h"
/* Functions to be implemented by each PU */ /* Functions to be implemented by each PU */
void pm_client_suspend(const struct pm_proc *proc); void pm_client_suspend(const struct pm_proc *proc, unsigned int state);
void pm_client_abort_suspend(void); void pm_client_abort_suspend(void);
void pm_client_wakeup(const struct pm_proc *proc); void pm_client_wakeup(const struct pm_proc *proc);
enum pm_ret_status set_ocm_retention(void); enum pm_ret_status set_ocm_retention(void);
......
...@@ -53,6 +53,10 @@ ...@@ -53,6 +53,10 @@
#define MAX_LATENCY (~0U) #define MAX_LATENCY (~0U)
#define MAX_QOS 100U #define MAX_QOS 100U
/* State arguments of the self suspend */
#define PM_STATE_CPU_IDLE 0x0U
#define PM_STATE_SUSPEND_TO_RAM 0xFU
/********************************************************************* /*********************************************************************
* Enum definitions * Enum definitions
********************************************************************/ ********************************************************************/
...@@ -82,6 +86,10 @@ enum pm_api_id { ...@@ -82,6 +86,10 @@ enum pm_api_id {
PM_RESET_GET_STATUS, PM_RESET_GET_STATUS,
PM_MMIO_WRITE, PM_MMIO_WRITE,
PM_MMIO_READ, PM_MMIO_READ,
PM_INIT,
PM_FPGA_LOAD,
PM_FPGA_GET_STATUS,
PM_GET_CHIPID,
PM_API_MAX PM_API_MAX
}; };
...@@ -143,6 +151,12 @@ enum pm_node_id { ...@@ -143,6 +151,12 @@ enum pm_node_id {
NODE_IOPLL, NODE_IOPLL,
NODE_DDR, NODE_DDR,
NODE_IPI_APU, NODE_IPI_APU,
NODE_IPI_RPU_0,
NODE_GPU,
NODE_PCIE,
NODE_PCAP,
NODE_RTC,
NODE_MAX
}; };
enum pm_request_ack { enum pm_request_ack {
......
...@@ -228,6 +228,22 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ...@@ -228,6 +228,22 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
ret = pm_mmio_read(pm_arg[0], &value); ret = pm_mmio_read(pm_arg[0], &value);
SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
} }
case PM_FPGA_LOAD:
ret = pm_fpga_load(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
SMC_RET1(handle, (uint64_t)ret);
case PM_FPGA_GET_STATUS:
{
uint32_t value;
ret = pm_fpga_get_status(&value);
SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
}
case PM_GET_CHIPID:
SMC_RET1(handle, zynqmp_get_silicon_id());
default: default:
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK); SMC_RET1(handle, SMC_UNK);
......
...@@ -201,4 +201,8 @@ ...@@ -201,4 +201,8 @@
#define ZYNQMP_CSU_VERSION_OFFSET 0x44 #define ZYNQMP_CSU_VERSION_OFFSET 0x44
/* Access control register defines */
#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
#endif /* __ZYNQMP_DEF_H__ */ #endif /* __ZYNQMP_DEF_H__ */
...@@ -39,6 +39,7 @@ void zynqmp_config_setup(void); ...@@ -39,6 +39,7 @@ void zynqmp_config_setup(void);
unsigned int zynqmp_get_uart_clk(void); unsigned int zynqmp_get_uart_clk(void);
int zynqmp_is_pmu_up(void); int zynqmp_is_pmu_up(void);
unsigned int zynqmp_get_bootmode(void); unsigned int zynqmp_get_bootmode(void);
unsigned int zynqmp_get_silicon_id(void);
/* For FSBL handover */ /* For FSBL handover */
void fsbl_atf_handover(entry_point_info_t *bl32_image_ep_info, void fsbl_atf_handover(entry_point_info_t *bl32_image_ep_info,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment