aboutsummaryrefslogtreecommitdiffstats
path: root/plat/xilinx/zynqmp
diff options
context:
space:
mode:
authorAlistair Delva <adelva@google.com>2021-02-16 21:01:22 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-02-16 21:01:22 +0000
commitefb2826bb8160e2d8e0fcec85133a7468484f9fd (patch)
tree37a21c69306801ee7cdda5167a30896c8740155b /plat/xilinx/zynqmp
parentb00a71fc312c9781fa6f404dccfb55b062b2ccac (diff)
parentfaa476c0caaa598afa5a6109d17102db5fe35ec6 (diff)
downloadplatform_external_arm-trusted-firmware-master.tar.gz
platform_external_arm-trusted-firmware-master.tar.bz2
platform_external_arm-trusted-firmware-master.zip
Original change: https://android-review.googlesource.com/c/platform/external/arm-trusted-firmware/+/1589611 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I3a25534ceed4f8e188510641080d8b8ed49b8f62
Diffstat (limited to 'plat/xilinx/zynqmp')
-rw-r--r--plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S6
-rw-r--r--plat/xilinx/zynqmp/bl31_zynqmp_setup.c33
-rw-r--r--plat/xilinx/zynqmp/include/zynqmp_def.h17
-rw-r--r--plat/xilinx/zynqmp/plat_zynqmp.c6
-rw-r--r--plat/xilinx/zynqmp/platform.mk9
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_clock.c45
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_clock.h4
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c46
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c367
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h15
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_sys.c232
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_sys.h22
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_defs.h50
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_svc_main.c121
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_svc_main.h5
-rw-r--r--plat/xilinx/zynqmp/sip_svc_setup.c15
-rw-r--r--plat/xilinx/zynqmp/tsp/tsp_plat_setup.c4
17 files changed, 448 insertions, 549 deletions
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
index beba66405..7eab337e9 100644
--- a/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -106,10 +106,10 @@ func plat_crash_console_putc
endfunc plat_crash_console_putc
/* ---------------------------------------------
- * int plat_crash_console_flush()
+ * void plat_crash_console_flush()
* Function to force a write of all buffered
* data that hasn't been output.
- * Out : return -1 on error else return 0.
+ * Out : void.
* Clobber list : r0
* ---------------------------------------------
*/
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index 6e0e811d4..d4cd7f65b 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -32,8 +32,9 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
{
assert(sec_state_is_valid(type));
- if (type == NON_SECURE)
+ if (type == NON_SECURE) {
return &bl33_image_ep_info;
+ }
return &bl32_image_ep_info;
}
@@ -62,12 +63,12 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
{
uint64_t atf_handoff_addr;
/* Register the console to provide early debug support */
- static console_cdns_t bl31_boot_console;
+ static console_t bl31_boot_console;
(void)console_cdns_register(ZYNQMP_UART_BASE,
zynqmp_get_uart_clk(),
ZYNQMP_UART_BAUDRATE,
&bl31_boot_console);
- console_set_scope(&bl31_boot_console.console,
+ console_set_scope(&bl31_boot_console,
CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT);
/* Initialize the platform config for future decision making */
@@ -99,14 +100,18 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info,
&bl33_image_ep_info,
atf_handoff_addr);
- if (ret == FSBL_HANDOFF_NO_STRUCT)
+ if (ret == FSBL_HANDOFF_NO_STRUCT) {
bl31_set_default_config();
- else if (ret != FSBL_HANDOFF_SUCCESS)
+ } else if (ret != FSBL_HANDOFF_SUCCESS) {
panic();
+ }
+ }
+ if (bl32_image_ep_info.pc) {
+ VERBOSE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
+ }
+ if (bl33_image_ep_info.pc) {
+ VERBOSE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
}
-
- NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
- NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
}
/* Enable the test setup */
@@ -134,12 +139,14 @@ 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)
+ if (!handler || id >= MAX_INTR_EL3) {
return -EINVAL;
+ }
/* Check if a handler has already been registered */
- if (type_el3_interrupt_table[id])
+ if (type_el3_interrupt_table[id]) {
return -EALREADY;
+ }
type_el3_interrupt_table[id] = handler;
@@ -154,8 +161,9 @@ static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
intr_id = plat_ic_get_pending_interrupt_id();
handler = type_el3_interrupt_table[intr_id];
- if (handler != NULL)
+ if (handler != NULL) {
handler(intr_id, flags, handle, cookie);
+ }
return 0;
}
@@ -178,8 +186,9 @@ void bl31_plat_runtime_setup(void)
set_interrupt_rm_flag(flags, NON_SECURE);
rc = register_interrupt_type_handler(INTR_TYPE_EL3,
rdo_el3_interrupt_handler, flags);
- if (rc)
+ if (rc) {
panic();
+ }
#endif
}
diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h
index 5d335d945..f47463000 100644
--- a/plat/xilinx/zynqmp/include/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/include/zynqmp_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,6 +7,7 @@
#ifndef ZYNQMP_DEF_H
#define ZYNQMP_DEF_H
+#include <plat/arm/common/smccc_def.h>
#include <plat/common/common_def.h>
#define ZYNQMP_CONSOLE_ID_cadence 1
@@ -340,12 +341,22 @@
#define PGGS_BASEADDR (0xFFD80050U)
#define PGGS_NUM_REGS U(4)
-/* Warm restart boot health status register and mask */
-#define PM_BOOT_HEALTH_STATUS_REG (GGS_BASEADDR + U(0x10))
+/* PMU GGS4 register 4 is used for warm restart boot health status */
+#define PMU_GLOBAL_GEN_STORAGE4 (GGS_BASEADDR + 0x10)
+/* Warm restart boot health status mask */
#define PM_BOOT_HEALTH_STATUS_MASK U(0x01)
+/* WDT restart scope shift and mask */
+#define RESTART_SCOPE_SHIFT (3)
+#define RESTART_SCOPE_MASK (0x3U << RESTART_SCOPE_SHIFT)
/*AFI registers */
#define AFIFM6_WRCTRL U(13)
#define FABRIC_WIDTH U(3)
+/* CSUDMA Module Base Address*/
+#define CSUDMA_BASE 0xFFC80000
+
+/* RSA-CORE Module Base Address*/
+#define RSA_CORE_BASE 0xFFCE0000
+
#endif /* ZYNQMP_DEF_H */
diff --git a/plat/xilinx/zynqmp/plat_zynqmp.c b/plat/xilinx/zynqmp/plat_zynqmp.c
index 906ce1b7f..58a52a3bf 100644
--- a/plat/xilinx/zynqmp/plat_zynqmp.c
+++ b/plat/xilinx/zynqmp/plat_zynqmp.c
@@ -9,11 +9,13 @@
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
- if (mpidr & MPIDR_CLUSTER_MASK)
+ if (mpidr & MPIDR_CLUSTER_MASK) {
return -1;
+ }
- if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT)
+ if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) {
return -1;
+ }
return zynqmp_calc_core_pos(mpidr);
}
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 44f20f69f..1cd168f7d 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -59,13 +59,14 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
-Iplat/xilinx/zynqmp/include/ \
-Iplat/xilinx/zynqmp/pm_service/ \
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.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/v2/gicv2_main.c \
- drivers/arm/gic/v2/gicv2_helpers.c \
+ ${GICV2_SOURCES} \
drivers/cadence/uart/aarch64/cdns_console.S \
plat/arm/common/arm_cci.c \
plat/arm/common/arm_common.c \
@@ -95,6 +96,8 @@ BL31_SOURCES += drivers/arm/cci/cci.c \
plat/xilinx/zynqmp/pm_service/pm_api_clock.c \
plat/xilinx/zynqmp/pm_service/pm_client.c
+BL31_CPPFLAGS += -fno-jump-tables
+
ifneq (${RESET_TO_BL31},1)
$(error "Using BL31 as the reset vector is only one option supported on ZynqMP. Please set RESET_TO_BL31 to 1.")
endif
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
index 852f92763..0cc517ec9 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -129,12 +129,26 @@
.div = NA_DIV, \
}
-#define GENERIC_DIV(id) \
+#define GENERIC_DIV1 \
{ \
- .type = TYPE_DIV##id, \
- .offset = PERIPH_DIV##id##_SHIFT, \
- .width = PERIPH_DIV##id##_WIDTH, \
+ .type = TYPE_DIV1, \
+ .offset = PERIPH_DIV1_SHIFT, \
+ .width = PERIPH_DIV1_WIDTH, \
+ .clkflags = CLK_SET_RATE_NO_REPARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = CLK_DIVIDER_ONE_BASED | \
+ CLK_DIVIDER_ALLOW_ZERO, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define GENERIC_DIV2 \
+ { \
+ .type = TYPE_DIV2, \
+ .offset = PERIPH_DIV2_SHIFT, \
+ .width = PERIPH_DIV2_WIDTH, \
.clkflags = CLK_SET_RATE_NO_REPARENT | \
+ CLK_SET_RATE_PARENT | \
CLK_IS_BASIC, \
.typeflags = CLK_DIVIDER_ONE_BASED | \
CLK_DIVIDER_ALLOW_ZERO, \
@@ -340,25 +354,25 @@ static struct pm_clock_node acpu_nodes[] = {
static struct pm_clock_node generic_mux_div_nodes[] = {
GENERIC_MUX,
- GENERIC_DIV(1),
+ GENERIC_DIV1,
};
static struct pm_clock_node generic_mux_div_gate_nodes[] = {
GENERIC_MUX,
- GENERIC_DIV(1),
+ GENERIC_DIV1,
GENERIC_GATE,
};
static struct pm_clock_node generic_mux_div_unused_gate_nodes[] = {
GENERIC_MUX,
- GENERIC_DIV(1),
+ GENERIC_DIV1,
IGNORE_UNUSED_GATE,
};
static struct pm_clock_node generic_mux_div_div_gate_nodes[] = {
GENERIC_MUX,
- GENERIC_DIV(1),
- GENERIC_DIV(2),
+ GENERIC_DIV1,
+ GENERIC_DIV2,
GENERIC_GATE,
};
@@ -410,8 +424,8 @@ static struct pm_clock_node dp_audio_video_ref_nodes[] = {
static struct pm_clock_node usb_nodes[] = {
GENERIC_MUX,
- GENERIC_DIV(1),
- GENERIC_DIV(2),
+ GENERIC_DIV1,
+ GENERIC_DIV2,
{
.type = TYPE_GATE,
.offset = USB_GATE_SHIFT,
@@ -2432,10 +2446,11 @@ enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks)
*
* @return Returns success. In case of error, name data is 0.
*/
-enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name)
+void pm_api_clock_get_name(unsigned int clock_id, char *name)
{
if (clock_id == CLK_MAX)
- memcpy(name, END_OF_CLK, CLK_NAME_LEN);
+ memcpy(name, END_OF_CLK, sizeof(END_OF_CLK) > CLK_NAME_LEN ?
+ CLK_NAME_LEN : sizeof(END_OF_CLK));
else if (!pm_clock_valid(clock_id))
memset(name, 0, CLK_NAME_LEN);
else if (clock_id < CLK_MAX_OUTPUT_CLK)
@@ -2443,8 +2458,6 @@ enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name)
else
memcpy(name, ext_clocks[clock_id - CLK_MAX_OUTPUT_CLK].name,
CLK_NAME_LEN);
-
- return PM_RET_SUCCESS;
}
/**
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
index 301ed24b6..5efd63ff5 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -294,7 +294,7 @@ struct pm_pll *pm_clock_get_pll(enum clock_id clock_id);
struct pm_pll *pm_clock_get_pll_by_related_clk(enum clock_id clock_id);
uint8_t pm_clock_has_div(unsigned int clock_id, enum pm_clock_div_id div_id);
-enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name);
+void pm_api_clock_get_name(unsigned int clock_id, char *name);
enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks);
enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id,
unsigned int index,
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
index 60e80d907..f165fb022 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -282,17 +282,29 @@ static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,
{
unsigned int shift;
enum pm_ret_status ret;
+ unsigned int val, mask;
- if (nid == NODE_SD_0)
+ if (nid == NODE_SD_0) {
shift = 0;
- else if (nid == NODE_SD_1)
+ mask = ZYNQMP_SD0_DLL_RST_MASK;
+ } else if (nid == NODE_SD_1) {
shift = ZYNQMP_SD_TAP_OFFSET;
- else
+ mask = ZYNQMP_SD1_DLL_RST_MASK;
+ } else {
return PM_RET_ERROR_ARGS;
+ }
- ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT);
- if (ret != PM_RET_SUCCESS)
+ ret = pm_mmio_read(ZYNQMP_SD_DLL_CTRL, &val);
+ if (ret != PM_RET_SUCCESS) {
return ret;
+ }
+
+ if ((val & mask) == 0) {
+ ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT);
+ if (ret != PM_RET_SUCCESS) {
+ return ret;
+ }
+ }
if (type == PM_TAPDELAY_INPUT) {
ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
@@ -300,9 +312,15 @@ static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,
(ZYNQMP_SD_ITAPCHGWIN << shift));
if (ret != PM_RET_SUCCESS)
goto reset_release;
- ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
- (ZYNQMP_SD_ITAPDLYENA_MASK << shift),
- (ZYNQMP_SD_ITAPDLYENA << shift));
+ if (value == 0)
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPDLYENA_MASK <<
+ shift), 0);
+ else
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPDLYENA_MASK <<
+ shift), (ZYNQMP_SD_ITAPDLYENA <<
+ shift));
if (ret != PM_RET_SUCCESS)
goto reset_release;
ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
@@ -314,8 +332,7 @@ static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,
(ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0);
} else if (type == PM_TAPDELAY_OUTPUT) {
ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
- (ZYNQMP_SD_OTAPDLYENA_MASK << shift),
- (ZYNQMP_SD_OTAPDLYENA << shift));
+ (ZYNQMP_SD_OTAPDLYENA_MASK << shift), 0);
if (ret != PM_RET_SUCCESS)
goto reset_release;
ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
@@ -326,7 +343,10 @@ static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,
}
reset_release:
- pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE);
+ if ((val & mask) == 0) {
+ (void)pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE);
+ }
+
return ret;
}
@@ -575,7 +595,7 @@ static enum pm_ret_status pm_ioctl_ulpi_reset(void)
*/
static enum pm_ret_status pm_ioctl_set_boot_health_status(unsigned int value)
{
- return pm_mmio_write(PM_BOOT_HEALTH_STATUS_REG,
+ return pm_mmio_write(PMU_GLOBAL_GEN_STORAGE4,
PM_BOOT_HEALTH_STATUS_MASK, value);
}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
index 4b8dfb614..9a6b497f3 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
@@ -19,39 +19,6 @@
#include "pm_common.h"
#include "pm_ipi.h"
-#define PINCTRL_FUNCTION_MASK U(0xFE)
-#define PINCTRL_VOLTAGE_STATUS_MASK U(0x01)
-#define NFUNCS_PER_PIN U(13)
-#define PINCTRL_NUM_MIOS U(78)
-#define MAX_PIN_PER_REG U(26)
-#define PINCTRL_BANK_ADDR_STEP U(28)
-
-#define PINCTRL_DRVSTRN0_REG_OFFSET U(0)
-#define PINCTRL_DRVSTRN1_REG_OFFSET U(4)
-#define PINCTRL_SCHCMOS_REG_OFFSET U(8)
-#define PINCTRL_PULLCTRL_REG_OFFSET U(12)
-#define PINCTRL_PULLSTAT_REG_OFFSET U(16)
-#define PINCTRL_SLEWCTRL_REG_OFFSET U(20)
-#define PINCTRL_VOLTAGE_STAT_REG_OFFSET U(24)
-
-#define IOU_SLCR_BANK1_CTRL5 U(0XFF180164)
-
-#define PINCTRL_CFG_ADDR_OFFSET(addr, reg, miopin) \
- ((addr) + 4 * PINCTRL_NUM_MIOS + PINCTRL_BANK_ADDR_STEP * \
- ((miopin) / MAX_PIN_PER_REG) + (reg))
-
-#define PINCTRL_PIN_OFFSET(_miopin) \
- ((_miopin) - (MAX_PIN_PER_REG * ((_miopin) / MAX_PIN_PER_REG)))
-
-#define PINCTRL_REGVAL_TO_PIN_CONFIG(_pin, _val) \
- (((_val) >> PINCTRL_PIN_OFFSET(_pin)) & 0x1)
-
-static uint8_t pm_pinctrl_mux[NFUNCS_PER_PIN] = {
- 0x02, 0x04, 0x08, 0x10, 0x18,
- 0x00, 0x20, 0x40, 0x60, 0x80,
- 0xA0, 0xC0, 0xE0
-};
-
struct pinctrl_function {
char name[FUNCTION_NAME_LEN];
uint16_t (*groups)[];
@@ -2604,18 +2571,13 @@ enum pm_ret_status pm_api_pinctrl_get_num_func_groups(unsigned int fid,
*
* This function is used by master to get name of function specified
* by given function ID.
- *
- * @return Returns success. In case of error, name data is 0.
*/
-enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid,
- char *name)
+void pm_api_pinctrl_get_function_name(unsigned int fid, char *name)
{
if (fid >= MAX_FUNCTION)
memcpy(name, END_OF_FUNCTION, FUNCTION_NAME_LEN);
else
memcpy(name, pinctrl_functions[fid].name, FUNCTION_NAME_LEN);
-
- return PM_RET_SUCCESS;
}
/**
@@ -2713,330 +2675,3 @@ enum pm_ret_status pm_api_pinctrl_get_pin_groups(unsigned int pin,
return PM_RET_SUCCESS;
}
-
-/**
- * pm_api_pinctrl_get_function() - Read function id set for the given pin
- * @pin Pin number
- * @nid Node ID of function currently set for given pin
- *
- * This function provides the function currently set for the given pin.
- *
- * @return Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin,
- unsigned int *id)
-{
- unsigned int i = 0, j = 0;
- enum pm_ret_status ret = PM_RET_SUCCESS;
- unsigned int ctrlreg, val, gid;
- uint16_t *grps;
-
- ctrlreg = IOU_SLCR_BASEADDR + 4U * pin;
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret != PM_RET_SUCCESS)
- return ret;
-
- val &= PINCTRL_FUNCTION_MASK;
-
- for (i = 0; i < NFUNCS_PER_PIN; i++)
- if (val == pm_pinctrl_mux[i])
- break;
-
- if (i == NFUNCS_PER_PIN)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- gid = *(*zynqmp_pin_groups[pin].groups + i);
-
- for (i = 0; i < MAX_FUNCTION; i++) {
- grps = *pinctrl_functions[i].groups;
- if (grps == NULL)
- continue;
- if (val != pinctrl_functions[i].regval)
- continue;
-
- for (j = 0; grps[j] != (uint16_t)END_OF_GROUPS; j++) {
- if (gid == grps[j]) {
- *id = i;
- goto done;
- }
- }
- }
- if (i == MAX_FUNCTION)
- ret = PM_RET_ERROR_ARGS;
-done:
- return ret;
-}
-
-/**
- * pm_api_pinctrl_set_function() - Set function id set for the given pin
- * @pin Pin number
- * @nid Node ID of function to set for given pin
- *
- * This function provides the function currently set for the given pin.
- *
- * @return Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin,
- unsigned int fid)
-{
- int i, j;
- unsigned int ctrlreg, val;
- uint16_t *pgrps, *fgrps;
-
- ctrlreg = IOU_SLCR_BASEADDR + 4U * pin;
- val = pinctrl_functions[fid].regval;
-
- for (i = 0; i < NFUNCS_PER_PIN; i++)
- if (val == pm_pinctrl_mux[i])
- break;
-
- if (i == NFUNCS_PER_PIN)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- pgrps = *zynqmp_pin_groups[pin].groups;
- if (!pgrps)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- fgrps = *pinctrl_functions[fid].groups;
- if (!fgrps)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- for (i = 0; fgrps[i] != (uint16_t)END_OF_GROUPS; i++)
- for (j = 0; pgrps[j] != (uint16_t)END_OF_GROUPS; j++)
- if (fgrps[i] == pgrps[j])
- goto match;
-
- return PM_RET_ERROR_NOTSUPPORTED;
-
-match:
- return pm_mmio_write(ctrlreg, PINCTRL_FUNCTION_MASK, val);
-}
-
-/**
- * pm_api_pinctrl_set_config() - Set configuration parameter for given pin
- * @pin: Pin for which configuration is to be set
- * @param: Configuration parameter to be set
- * @value: Value to be set for configuration parameter
- *
- * This function sets value of requested configuration parameter for given pin.
- *
- * @return Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin,
- unsigned int param,
- unsigned int value)
-{
- enum pm_ret_status ret;
- unsigned int ctrlreg, mask, val, offset;
-
- if (param >= PINCTRL_CONFIG_MAX)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- if (pin >= PINCTRL_NUM_MIOS)
- return PM_RET_ERROR_ARGS;
-
- mask = 1 << PINCTRL_PIN_OFFSET(pin);
-
- switch (param) {
- case PINCTRL_CONFIG_SLEW_RATE:
- if (value != PINCTRL_SLEW_RATE_FAST &&
- value != PINCTRL_SLEW_RATE_SLOW)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_SLEWCTRL_REG_OFFSET,
- pin);
- val = value << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- case PINCTRL_CONFIG_BIAS_STATUS:
- if (value != PINCTRL_BIAS_ENABLE &&
- value != PINCTRL_BIAS_DISABLE)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLSTAT_REG_OFFSET,
- pin);
-
- offset = PINCTRL_PIN_OFFSET(pin);
- if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
- offset = (offset < 12U) ?
- (offset + 14U) : (offset - 12U);
-
- val = value << offset;
- mask = 1 << offset;
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- case PINCTRL_CONFIG_PULL_CTRL:
-
- if (value != PINCTRL_BIAS_PULL_DOWN &&
- value != PINCTRL_BIAS_PULL_UP)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLSTAT_REG_OFFSET,
- pin);
-
- offset = PINCTRL_PIN_OFFSET(pin);
- if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
- offset = (offset < 12U) ?
- (offset + 14U) : (offset - 12U);
-
- val = PINCTRL_BIAS_ENABLE << offset;
- ret = pm_mmio_write(ctrlreg, 1 << offset, val);
- if (ret != PM_RET_SUCCESS)
- return ret;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLCTRL_REG_OFFSET,
- pin);
- val = value << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- case PINCTRL_CONFIG_SCHMITT_CMOS:
- if (value != PINCTRL_INPUT_TYPE_CMOS &&
- value != PINCTRL_INPUT_TYPE_SCHMITT)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_SCHCMOS_REG_OFFSET,
- pin);
-
- val = value << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- case PINCTRL_CONFIG_DRIVE_STRENGTH:
- if (value > PINCTRL_DRIVE_STRENGTH_12MA)
- return PM_RET_ERROR_ARGS;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_DRVSTRN0_REG_OFFSET,
- pin);
- val = (value >> 1) << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- if (ret)
- return ret;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_DRVSTRN1_REG_OFFSET,
- pin);
- val = (value & 0x01U) << PINCTRL_PIN_OFFSET(pin);
- ret = pm_mmio_write(ctrlreg, mask, val);
- break;
- default:
- ERROR("Invalid parameter %u\n", param);
- ret = PM_RET_ERROR_NOTSUPPORTED;
- break;
- }
-
- return ret;
-}
-
-/**
- * pm_api_pinctrl_get_config() - Get configuration parameter value for given pin
- * @pin: Pin for which configuration is to be read
- * @param: Configuration parameter to be read
- * @value: buffer to store value of configuration parameter
- *
- * This function reads value of requested configuration parameter for given pin.
- *
- * @return Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin,
- unsigned int param,
- unsigned int *value)
-{
- enum pm_ret_status ret;
- unsigned int ctrlreg, val;
-
- if (param >= PINCTRL_CONFIG_MAX)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- if (pin >= PINCTRL_NUM_MIOS)
- return PM_RET_ERROR_ARGS;
-
- switch (param) {
- case PINCTRL_CONFIG_SLEW_RATE:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_SLEWCTRL_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret != PM_RET_SUCCESS)
- return ret;
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_BIAS_STATUS:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLSTAT_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
- val = ((val & 0x3FFF) << 12) | ((val >> 14) & 0xFFF);
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_PULL_CTRL:
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_PULLCTRL_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_SCHMITT_CMOS:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_SCHCMOS_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_DRIVE_STRENGTH:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_DRVSTRN0_REG_OFFSET,
- pin);
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val) << 1;
-
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_DRVSTRN1_REG_OFFSET,
- pin);
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value |= PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
- break;
- case PINCTRL_CONFIG_VOLTAGE_STATUS:
- ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
- PINCTRL_VOLTAGE_STAT_REG_OFFSET,
- pin);
-
- ret = pm_mmio_read(ctrlreg, &val);
- if (ret)
- return ret;
-
- *value = val & PINCTRL_VOLTAGE_STATUS_MASK;
- break;
- default:
- return PM_RET_ERROR_NOTSUPPORTED;
- }
-
- return PM_RET_SUCCESS;
-}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
index 9923c00ba..2b8fca3cd 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -709,18 +709,7 @@ enum {
#define PINCTRL_DRIVE_STRENGTH_8MA 2U
#define PINCTRL_DRIVE_STRENGTH_12MA 3U
-enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin,
- unsigned int fid);
-enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin,
- unsigned int *id);
-enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin,
- unsigned int param,
- unsigned int value);
-enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin,
- unsigned int param,
- unsigned int *value);
-enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid,
- char *name);
+void pm_api_pinctrl_get_function_name(unsigned int fid, char *name);
enum pm_ret_status pm_api_pinctrl_get_function_groups(unsigned int fid,
unsigned int index,
uint16_t *groups);
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index b1720d9f6..9a53408fd 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -65,6 +65,10 @@ unsigned int pm_get_shutdown_scope(void)
PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4); \
}
+#define EM_PACK_PAYLOAD1(pl, arg0) { \
+ pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \
+}
+
/**
* pm_self_suspend() - PM call for processor to suspend itself
* @nid Node id of the processor or subsystem
@@ -655,7 +659,11 @@ void pm_get_callbackdata(uint32_t *data, size_t count)
*/
enum pm_ret_status pm_pinctrl_request(unsigned int pin)
{
- return PM_RET_SUCCESS;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, PM_PINCTRL_REQUEST, pin);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
}
/**
@@ -668,37 +676,44 @@ enum pm_ret_status pm_pinctrl_request(unsigned int pin)
*/
enum pm_ret_status pm_pinctrl_release(unsigned int pin)
{
- return PM_RET_SUCCESS;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, PM_PINCTRL_RELEASE, pin);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
}
/**
* pm_pinctrl_get_function() - Read function id set for the given pin
* @pin Pin number
- * @nid Node ID of function currently set for given pin
+ * @fid ID of function currently set for given pin
*
* This function provides the function currently set for the given pin.
*
* @return Returns status, either success or error+reason
*/
-enum pm_ret_status pm_pinctrl_get_function(unsigned int pin,
- enum pm_node_id *nid)
+enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, unsigned int *fid)
{
- return pm_api_pinctrl_get_function(pin, nid);
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD2(payload, PM_PINCTRL_GET_FUNCTION, pin);
+ return pm_ipi_send_sync(primary_proc, payload, fid, 1);
}
/**
* pm_pinctrl_set_function() - Set function id set for the given pin
* @pin Pin number
- * @nid Node ID of function to set for given pin
- *
- * This function provides the function currently set for the given pin.
+ * @fid ID of function to set for given pin
*
* @return Returns status, either success or error+reason
*/
-enum pm_ret_status pm_pinctrl_set_function(unsigned int pin,
- enum pm_node_id nid)
+enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, unsigned int fid)
{
- return pm_api_pinctrl_set_function(pin, (unsigned int)nid);
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_PINCTRL_SET_FUNCTION, pin, fid);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
}
/**
@@ -715,24 +730,30 @@ enum pm_ret_status pm_pinctrl_get_config(unsigned int pin,
unsigned int param,
unsigned int *value)
{
- return pm_api_pinctrl_get_config(pin, param, value);
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD3(payload, PM_PINCTRL_CONFIG_PARAM_GET, pin, param);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
}
/**
- * pm_pinctrl_set_config() - Read value of requested config param for given pin
+ * pm_pinctrl_set_config() - Set value of requested config param for given pin
* @pin Pin number
* @param Parameter to set
* @value Parameter value to set
*
- * This function provides the configuration parameter value for the given pin.
- *
* @return Returns status, either success or error+reason
*/
enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
unsigned int param,
unsigned int value)
{
- return pm_api_pinctrl_set_config(pin, param, value);
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD4(payload, PM_PINCTRL_CONFIG_PARAM_SET, pin, param,
+ value);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
}
/**
@@ -793,12 +814,10 @@ static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
*
* This function is used by master to get nmae of clock specified
* by given clock ID.
- *
- * @return Returns status, either success or error+reason
*/
-static enum pm_ret_status pm_clock_get_name(unsigned int clock_id, char *name)
+static void pm_clock_get_name(unsigned int clock_id, char *name)
{
- return pm_api_clock_get_name(clock_id, name);
+ pm_api_clock_get_name(clock_id, name);
}
/**
@@ -907,7 +926,13 @@ static enum pm_ret_status pm_clock_gate(unsigned int clock_id,
/* Send request to the PMU */
PM_PACK_PAYLOAD2(payload, api_id, clock_id);
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+
+ /* If action fails due to the lack of permissions filter the error */
+ if (status == PM_RET_ERROR_ACCESS)
+ status = PM_RET_SUCCESS;
+
+ return status;
}
/**
@@ -1229,13 +1254,10 @@ static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid,
*
* This function is used by master to get name of function specified
* by given function Id
- *
- * Return: Returns status, either success or error+reason.
*/
-static enum pm_ret_status pm_pinctrl_get_function_name(unsigned int fid,
- char *name)
+static void pm_pinctrl_get_function_name(unsigned int fid, char *name)
{
- return pm_api_pinctrl_get_function_name(fid, name);
+ pm_api_pinctrl_get_function_name(fid, name);
}
/**
@@ -1295,78 +1317,58 @@ static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id,
* @data Returned output data
*
* This function returns requested data.
- *
- * @return Returns status, either success or error+reason
*/
-enum pm_ret_status pm_query_data(enum pm_query_id qid,
- unsigned int arg1,
- unsigned int arg2,
- unsigned int arg3,
- unsigned int *data)
+void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
+ unsigned int arg3, unsigned int *data)
{
- enum pm_ret_status ret;
-
switch (qid) {
case PM_QID_CLOCK_GET_NAME:
- ret = pm_clock_get_name(arg1, (char *)data);
+ pm_clock_get_name(arg1, (char *)data);
break;
case PM_QID_CLOCK_GET_TOPOLOGY:
- ret = pm_clock_get_topology(arg1, arg2, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
break;
case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
- ret = pm_clock_get_fixedfactor_params(arg1, &data[1], &data[2]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
+ &data[2]);
break;
case PM_QID_CLOCK_GET_PARENTS:
- ret = pm_clock_get_parents(arg1, arg2, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
break;
case PM_QID_CLOCK_GET_ATTRIBUTES:
- ret = pm_clock_get_attributes(arg1, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_attributes(arg1, &data[1]);
break;
case PM_QID_PINCTRL_GET_NUM_PINS:
- ret = pm_pinctrl_get_num_pins(&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_num_pins(&data[1]);
break;
case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
- ret = pm_pinctrl_get_num_functions(&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_num_functions(&data[1]);
break;
case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
- ret = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
break;
case PM_QID_PINCTRL_GET_FUNCTION_NAME:
- ret = pm_pinctrl_get_function_name(arg1, (char *)data);
+ pm_pinctrl_get_function_name(arg1, (char *)data);
break;
case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
- ret = pm_pinctrl_get_function_groups(arg1, arg2,
- (uint16_t *)&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
+ (uint16_t *)&data[1]);
break;
case PM_QID_PINCTRL_GET_PIN_GROUPS:
- ret = pm_pinctrl_get_pin_groups(arg1, arg2,
- (uint16_t *)&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
+ (uint16_t *)&data[1]);
break;
case PM_QID_CLOCK_GET_NUM_CLOCKS:
- ret = pm_clock_get_num_clocks(&data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_num_clocks(&data[1]);
break;
case PM_QID_CLOCK_GET_MAX_DIVISOR:
- ret = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
- data[0] = (unsigned int)ret;
+ data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
break;
default:
- ret = PM_RET_ERROR_ARGS;
+ data[0] = PM_RET_ERROR_ARGS;
WARN("Unimplemented query service call: 0x%x\n", qid);
- break;
}
-
- return ret;
}
enum pm_ret_status pm_sha_hash(uint32_t address_high,
@@ -1548,3 +1550,101 @@ enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
return pm_ipi_send_sync(primary_proc, payload, mode, 1);
}
+
+/**
+ * pm_register_access() - PM API for register read/write access data
+ *
+ * @register_access_id Register_access_id which says register read/write
+ *
+ * @address Address of the register to be accessed
+ *
+ * @mask Mask value to be used while writing value
+ *
+ * @value Value to be written to register
+ *
+ * @out Returned output data
+ *
+ * This function returns requested data.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_access(unsigned int register_access_id,
+ unsigned int address,
+ unsigned int mask,
+ unsigned int value,
+ unsigned int *out)
+{
+ enum pm_ret_status ret;
+
+ if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
+ ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
+ ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
+ ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE))
+ return PM_RET_ERROR_ACCESS;
+
+ switch (register_access_id) {
+ case CONFIG_REG_WRITE:
+ ret = pm_mmio_write(address, mask, value);
+ break;
+ case CONFIG_REG_READ:
+ ret = pm_mmio_read(address, out);
+ break;
+ default:
+ ret = PM_RET_ERROR_ARGS;
+ WARN("Unimplemented register_access call\n\r");
+ }
+ return ret;
+}
+
+/**
+ * pm_efuse_access() - To program or read efuse bits.
+ *
+ * This function provides access to the xilskey library to program/read
+ * efuse bits.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * value: Returned output value
+ *
+ * @return Returns status, either success or error+reason
+ *
+ */
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
+
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_set_action(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_remove_action(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_send_errors(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index ff66d3f02..b0c26529d 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -28,6 +28,11 @@ enum pm_query_id {
PM_QID_CLOCK_GET_MAX_DIVISOR,
};
+enum pm_register_access_id {
+ CONFIG_REG_WRITE,
+ CONFIG_REG_READ,
+};
+
/**********************************************************
* System-level API function declarations
**********************************************************/
@@ -151,11 +156,8 @@ enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
unsigned int parent_id);
enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
unsigned int *parent_id);
-enum pm_ret_status pm_query_data(enum pm_query_id qid,
- unsigned int arg1,
- unsigned int arg2,
- unsigned int arg3,
- unsigned int *data);
+void pm_query_data(enum pm_query_id qid, unsigned int arg1, 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,
@@ -178,6 +180,11 @@ enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
enum pm_ret_status pm_aes_engine(uint32_t address_high,
uint32_t address_low,
uint32_t *value);
+enum pm_ret_status pm_register_access(unsigned int register_access_id,
+ unsigned int address,
+ unsigned int mask,
+ unsigned int value,
+ unsigned int *out);
enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
enum pm_pll_param param_id,
@@ -189,5 +196,10 @@ enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode);
enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode);
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+ uint32_t address_low, uint32_t *value);
+enum pm_ret_status em_set_action(unsigned int *value);
+enum pm_ret_status em_remove_action(unsigned int *value);
+enum pm_ret_status em_send_errors(unsigned int *value);
#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index cae36c9d8..3324431dd 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,7 +18,7 @@
* (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR
*/
#define PM_VERSION_MAJOR 1
-#define PM_VERSION_MINOR 0
+#define PM_VERSION_MINOR 1
#define PM_VERSION ((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
@@ -33,6 +33,7 @@
#define PM_STATE_CPU_IDLE 0x0U
#define PM_STATE_SUSPEND_TO_RAM 0xFU
+#define EM_FUNID_NUM_MASK 0xF0000U
/*********************************************************************
* Enum definitions
********************************************************************/
@@ -97,6 +98,9 @@ enum pm_api_id {
PM_PLL_GET_PARAMETER,
PM_PLL_SET_MODE,
PM_PLL_GET_MODE,
+ /* PM Register Access API */
+ PM_REGISTER_ACCESS,
+ PM_EFUSE_ACCESS,
PM_API_MAX
};
@@ -215,26 +219,29 @@ enum pm_opchar_type {
/**
* @PM_RET_SUCCESS: success
- * @PM_RET_ERROR_ARGS: illegal arguments provided
+ * @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated)
+ * @PM_RET_ERROR_NOTSUPPORTED: feature not supported (deprecated)
+ * @PM_RET_ERROR_INTERNAL: internal error
+ * @PM_RET_ERROR_CONFLICT: conflict
* @PM_RET_ERROR_ACCESS: access rights violation
+ * @PM_RET_ERROR_INVALID_NODE: invalid node
+ * @PM_RET_ERROR_DOUBLE_REQ: duplicate request for same node
+ * @PM_RET_ERROR_ABORT_SUSPEND: suspend procedure has been aborted
* @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU
- * @PM_RET_ERROR_NOTSUPPORTED: feature not supported
- * @PM_RET_ERROR_PROC: node is not a processor node
- * @PM_RET_ERROR_API_ID: illegal API ID
- * @PM_RET_ERROR_OTHER: other error
+ * @PM_RET_ERROR_NODE_USED: node is already in use
*/
enum pm_ret_status {
PM_RET_SUCCESS,
- PM_RET_ERROR_ARGS,
- PM_RET_ERROR_ACCESS,
- PM_RET_ERROR_TIMEOUT,
- PM_RET_ERROR_NOTSUPPORTED,
- PM_RET_ERROR_PROC,
- PM_RET_ERROR_API_ID,
- PM_RET_ERROR_FAILURE,
- PM_RET_ERROR_COMMUNIC,
- PM_RET_ERROR_DOUBLEREQ,
- PM_RET_ERROR_OTHER,
+ PM_RET_ERROR_ARGS = 1,
+ PM_RET_ERROR_NOTSUPPORTED = 4,
+ PM_RET_ERROR_INTERNAL = 2000,
+ PM_RET_ERROR_CONFLICT = 2001,
+ PM_RET_ERROR_ACCESS = 2002,
+ PM_RET_ERROR_INVALID_NODE = 2003,
+ PM_RET_ERROR_DOUBLE_REQ = 2004,
+ PM_RET_ERROR_ABORT_SUSPEND = 2005,
+ PM_RET_ERROR_TIMEOUT = 2006,
+ PM_RET_ERROR_NODE_USED = 2007
};
/**
@@ -317,4 +324,13 @@ enum pm_clock_div_id {
PM_CLOCK_DIV1_ID,
};
+/**
+ * EM API IDs
+ */
+enum em_api_id {
+ EM_SET_ACTION = 1,
+ EM_REMOVE_ACTION,
+ EM_SEND_ERRORS,
+};
+
#endif /* PM_DEFS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index 98dbe7d6e..a49bda8d2 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -29,8 +29,8 @@
#define PM_SET_SUSPEND_MODE 0xa02
#define PM_GET_TRUSTZONE_VERSION 0xa03
-/* !0 - UP, 0 - DOWN */
-static int32_t pm_up = 0;
+/* pm_up = !0 - UP, pm_up = 0 - DOWN */
+static int32_t pm_up, ipi_irq_flag;
#if ZYNQMP_WDT_RESTART
static spinlock_t inc_lock;
@@ -142,6 +142,8 @@ static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags,
void *handle, void *cookie)
{
int i;
+ uint32_t value;
+
/* enter wfi and stay there */
INFO("Entering wfi\n");
@@ -156,8 +158,9 @@ static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags,
spin_unlock(&inc_lock);
if (active_cores == 0) {
- pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET,
- PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM);
+ pm_mmio_read(PMU_GLOBAL_GEN_STORAGE4, &value);
+ value = (value & RESTART_SCOPE_MASK) >> RESTART_SCOPE_SHIFT;
+ pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET, value);
}
/* enter wfi and stay there */
@@ -210,6 +213,15 @@ int pm_setup(void)
status = pm_ipi_init(primary_proc);
+ ret = pm_get_api_version(&pm_ctx.api_version);
+ if (pm_ctx.api_version < PM_VERSION) {
+ ERROR("BL31: Platform Management API version error. Expected: "
+ "v%d.%d - Found: v%d.%d\n", PM_VERSION_MAJOR,
+ PM_VERSION_MINOR, pm_ctx.api_version >> 16,
+ pm_ctx.api_version & 0xFFFF);
+ return -EINVAL;
+ }
+
#if ZYNQMP_WDT_RESTART
status = pm_wdt_restart_setup();
if (status)
@@ -321,22 +333,21 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
case PM_GET_API_VERSION:
/* Check is PM API version already verified */
- if (pm_ctx.api_version == PM_VERSION) {
+ if (pm_ctx.api_version >= PM_VERSION) {
+ if (!ipi_irq_flag) {
+ /*
+ * Enable IPI IRQ
+ * assume the rich OS is OK to handle callback IRQs now.
+ * Even if we were wrong, it would not enable the IRQ in
+ * the GIC.
+ */
+ pm_ipi_irq_enable(primary_proc);
+ ipi_irq_flag = 1;
+ }
SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
- ((uint64_t)PM_VERSION << 32));
+ ((uint64_t)pm_ctx.api_version << 32));
}
- ret = pm_get_api_version(&pm_ctx.api_version);
- /*
- * Enable IPI IRQ
- * assume the rich OS is OK to handle callback IRQs now.
- * Even if we were wrong, it would not enable the IRQ in
- * the GIC.
- */
- pm_ipi_irq_enable(primary_proc);
- SMC_RET1(handle, (uint64_t)ret |
- ((uint64_t)pm_ctx.api_version << 32));
-
case PM_SET_CONFIGURATION:
ret = pm_set_configuration(pm_arg[0]);
SMC_RET1(handle, (uint64_t)ret);
@@ -423,7 +434,7 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
{
uint32_t result[4] = {0};
- pm_get_callbackdata(result, (sizeof(result)/sizeof(uint32_t)));
+ pm_get_callbackdata(result, ARRAY_SIZE(result));
SMC_RET2(handle,
(uint64_t)result[0] | ((uint64_t)result[1] << 32),
(uint64_t)result[2] | ((uint64_t)result[3] << 32));
@@ -474,8 +485,8 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
{
uint32_t data[4] = { 0 };
- ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
- pm_arg[3], data);
+ pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], data);
SMC_RET2(handle, (uint64_t)data[0] | ((uint64_t)data[1] << 32),
(uint64_t)data[2] | ((uint64_t)data[3] << 32));
}
@@ -606,8 +617,78 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32));
}
+ case PM_REGISTER_ACCESS:
+ {
+ uint32_t value;
+
+ ret = pm_register_access(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_EFUSE_ACCESS:
+ {
+ uint32_t value;
+
+ ret = pm_efuse_access(pm_arg[0], pm_arg[1], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
default:
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
}
}
+
+/**
+ * em_smc_handler() - SMC handler for EM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - Arguments
+ * @cookie - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return - Unused
+ *
+ * Determines that smc_fid is valid and supported EM SMC Function ID from the
+ * list of em_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for EM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie, void *handle, uint64_t flags)
+{
+ enum pm_ret_status ret;
+
+ switch (smc_fid & FUNCID_NUM_MASK) {
+ /* EM API Functions */
+ case EM_SET_ACTION:
+ {
+ uint32_t value;
+
+ ret = em_set_action(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case EM_REMOVE_ACTION:
+ {
+ uint32_t value;
+
+ ret = em_remove_action(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case EM_SEND_ERRORS:
+ {
+ uint32_t value;
+
+ ret = em_send_errors(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ default:
+ WARN("Unimplemented EM Service Call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
index 0968f64cb..abadd4065 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,4 +14,7 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
uint64_t x4, void *cookie, void *handle,
uint64_t flags);
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie, void *handle,
+ uint64_t flags);
#endif /* PM_SVC_MAIN_H */
diff --git a/plat/xilinx/zynqmp/sip_svc_setup.c b/plat/xilinx/zynqmp/sip_svc_setup.c
index 9b182749c..114da33d6 100644
--- a/plat/xilinx/zynqmp/sip_svc_setup.c
+++ b/plat/xilinx/zynqmp/sip_svc_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,6 +25,9 @@
#define PM_FID_MASK 0xf000u
#define PM_FID_VALUE 0u
#define IPI_FID_VALUE 0x1000u
+#define EM_FID_MASK 0xf0000u
+#define EM_FID_VALUE 0xE0000u
+#define is_em_fid(_fid) (((_fid) & EM_FID_MASK) == EM_FID_VALUE)
#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE)
#define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE)
@@ -41,9 +44,7 @@ DEFINE_SVC_UUID2(zynqmp_sip_uuid,
static int32_t sip_svc_setup(void)
{
/* PM implementation as SiP Service */
- pm_setup();
-
- return 0;
+ return pm_setup();
}
/**
@@ -61,8 +62,12 @@ uintptr_t sip_svc_smc_handler(uint32_t smc_fid,
void *handle,
u_register_t flags)
{
+ /* Let EM SMC handler deal with EM-related requests */
+ if (is_em_fid(smc_fid)) {
+ return em_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ } else if (is_pm_fid(smc_fid)) {
/* Let PM SMC handler deal with PM-related requests */
- if (is_pm_fid(smc_fid)) {
return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
flags);
}
diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
index 7f0ac74cf..5e770f75c 100644
--- a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
+++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
@@ -21,12 +21,12 @@ void tsp_early_platform_setup(void)
* Register a different console than already in use to display
* messages from TSP
*/
- static console_cdns_t tsp_boot_console;
+ static console_t tsp_boot_console;
(void)console_cdns_register(ZYNQMP_UART_BASE,
zynqmp_get_uart_clk(),
ZYNQMP_UART_BAUDRATE,
&tsp_boot_console);
- console_set_scope(&tsp_boot_console.console,
+ console_set_scope(&tsp_boot_console,
CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT);
/* Initialize the platform config for future decision making */