diff options
author | Alistair Delva <adelva@google.com> | 2021-02-16 21:01:22 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-02-16 21:01:22 +0000 |
commit | efb2826bb8160e2d8e0fcec85133a7468484f9fd (patch) | |
tree | 37a21c69306801ee7cdda5167a30896c8740155b /plat/xilinx/zynqmp | |
parent | b00a71fc312c9781fa6f404dccfb55b062b2ccac (diff) | |
parent | faa476c0caaa598afa5a6109d17102db5fe35ec6 (diff) | |
download | platform_external_arm-trusted-firmware-master.tar.gz platform_external_arm-trusted-firmware-master.tar.bz2 platform_external_arm-trusted-firmware-master.zip |
Merge branch 'aosp/upstream-master' into HEAD am: faa476c0caHEADandroid-s-beta-5android-s-beta-4android-s-beta-3android-s-beta-2android-s-beta-1mastermain-cg-testing-releaseandroid-s-beta-5android-s-beta-4
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.S | 6 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/bl31_zynqmp_setup.c | 33 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/include/zynqmp_def.h | 17 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/plat_zynqmp.c | 6 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/platform.mk | 9 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_api_clock.c | 45 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_api_clock.h | 4 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c | 46 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c | 367 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h | 15 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 232 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 22 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_defs.h | 50 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 121 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_svc_main.h | 5 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/sip_svc_setup.c | 15 | ||||
-rw-r--r-- | plat/xilinx/zynqmp/tsp/tsp_plat_setup.c | 4 |
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 */ |