From f76918a80602588408d6d7b6ba374df9c95d7261 Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Wed, 17 Jan 2018 02:39:23 -0800 Subject: [PATCH] zynqmp: pm: Implement IOCTL APIs for remoteproc Implement ioctl APIs which uses MMIO operations to control RPU operations. Below IOCTLs are supported in this patch: * Get RPU operation mode * Set RPU operation mode * Configure RPU boot address (OCM/TCM) * Configure TCM combined mode Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah --- plat/xilinx/zynqmp/platform.mk | 1 + plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c | 181 +++++++++++++++++++ plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h | 43 +++++ plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 22 +++ plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 5 + plat/xilinx/zynqmp/pm_service/pm_defs.h | 1 + plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 9 + plat/xilinx/zynqmp/zynqmp_def.h | 10 + 8 files changed, 272 insertions(+) create mode 100644 plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c create mode 100644 plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index cefb73a65..2abcd288c 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -78,6 +78,7 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ plat/xilinx/zynqmp/pm_service/pm_svc_main.c \ plat/xilinx/zynqmp/pm_service/pm_api_sys.c \ plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c \ + plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c \ plat/xilinx/zynqmp/pm_service/pm_ipi.c \ plat/xilinx/zynqmp/pm_service/pm_client.c \ plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c new file mode 100644 index 000000000..6f94f420f --- /dev/null +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for ioctl. + */ + +#include +#include +#include +#include +#include "pm_api_ioctl.h" +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_common.h" +#include "pm_ipi.h" +#include "../zynqmp_def.h" + +/** + * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode + * @mode Buffer to store value of oper mode(Split/Lock-step) + * + * This function provides current configured RPU operational mode. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(unsigned int *mode) +{ + unsigned int val; + + val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); + val &= ZYNQMP_SLSPLIT_MASK; + if (val) + *mode = PM_RPU_MODE_SPLIT; + else + *mode = PM_RPU_MODE_LOCKSTEP; + + return PM_RET_SUCCESS; +} + +/** + * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode + * @mode Value to set for oper mode(Split/Lock-step) + * + * This function configures RPU operational mode(Split/Lock-step). + * It also sets TCM combined mode in RPU lock-step and TCM non-combined + * mode for RPU split mode. In case of Lock step mode, RPU1's output is + * clamped. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(unsigned int mode) +{ + unsigned int val; + + if (mmio_read_32(CRL_APB_RST_LPD_TOP) && CRL_APB_RPU_AMBA_RESET) + return PM_RET_ERROR_ACCESS; + + val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); + + if (mode == PM_RPU_MODE_SPLIT) { + val |= ZYNQMP_SLSPLIT_MASK; + val &= ~ZYNQMP_TCM_COMB_MASK; + val &= ~ZYNQMP_SLCLAMP_MASK; + } else if (mode == PM_RPU_MODE_LOCKSTEP) { + val &= ~ZYNQMP_SLSPLIT_MASK; + val |= ZYNQMP_TCM_COMB_MASK; + val |= ZYNQMP_SLCLAMP_MASK; + } else { + return PM_RET_ERROR_ARGS; + } + + mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val); + + return PM_RET_SUCCESS; +} + +/** + * pm_ioctl_config_boot_addr() - Configure RPU boot address + * @nid Node ID of RPU + * @value Value to set for boot address (TCM/OCM) + * + * This function configures RPU boot address(memory). + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid, + unsigned int value) +{ + unsigned int rpu_cfg_addr, val; + + if (nid == NODE_RPU_0) + rpu_cfg_addr = ZYNQMP_RPU0_CFG; + else if (nid == NODE_RPU_1) + rpu_cfg_addr = ZYNQMP_RPU1_CFG; + else + return PM_RET_ERROR_ARGS; + + val = mmio_read_32(rpu_cfg_addr); + + if (value == PM_RPU_BOOTMEM_LOVEC) + val &= ~ZYNQMP_VINITHI_MASK; + else if (value == PM_RPU_BOOTMEM_HIVEC) + val |= ZYNQMP_VINITHI_MASK; + else + return PM_RET_ERROR_ARGS; + + mmio_write_32(rpu_cfg_addr, val); + + return PM_RET_SUCCESS; +} + +/** + * pm_ioctl_config_tcm_comb() - Configure TCM combined mode + * @value Value to set (Split/Combined) + * + * This function configures TCM to be in split mode or combined + * mode. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_config_tcm_comb(unsigned int value) +{ + unsigned int val; + + val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); + + if (value == PM_RPU_TCM_SPLIT) + val &= ~ZYNQMP_TCM_COMB_MASK; + else if (value == PM_RPU_TCM_COMB) + val |= ZYNQMP_TCM_COMB_MASK; + else + return PM_RET_ERROR_ARGS; + + mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val); + + return PM_RET_SUCCESS; +} + +/** + * pm_api_ioctl() - PM IOCTL API for device control and configs + * @node_id Node ID of the device + * @ioctl_id ID of the requested IOCTL + * @arg1 Argument 1 to requested IOCTL call + * @arg2 Argument 2 to requested IOCTL call + * @value Returned output value + * + * This function calls IOCTL to firmware for device control and configuration. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *value) +{ + int ret; + + switch (ioctl_id) { + case IOCTL_GET_RPU_OPER_MODE: + ret = pm_ioctl_get_rpu_oper_mode(value); + break; + case IOCTL_SET_RPU_OPER_MODE: + ret = pm_ioctl_set_rpu_oper_mode(arg1); + break; + case IOCTL_RPU_BOOT_ADDR_CONFIG: + ret = pm_ioctl_config_boot_addr(nid, arg1); + break; + case IOCTL_TCM_COMB_CONFIG: + ret = pm_ioctl_config_tcm_comb(arg1); + break; + default: + ret = PM_RET_ERROR_NOTSUPPORTED; + } + + return ret; +} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h new file mode 100644 index 000000000..9dae69fed --- /dev/null +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for pin control. + */ + +#ifndef _PM_API_IOCTL_H_ +#define _PM_API_IOCTL_H_ + +#include "pm_common.h" + +enum pm_ioctl_id { + IOCTL_GET_RPU_OPER_MODE, + IOCTL_SET_RPU_OPER_MODE, + IOCTL_RPU_BOOT_ADDR_CONFIG, + IOCTL_TCM_COMB_CONFIG, +}; + +enum rpu_oper_mode { + PM_RPU_MODE_LOCKSTEP, + PM_RPU_MODE_SPLIT, +}; + +enum rpu_boot_mem { + PM_RPU_BOOTMEM_LOVEC, + PM_RPU_BOOTMEM_HIVEC, +}; + +enum rpu_tcm_comb { + PM_RPU_TCM_SPLIT, + PM_RPU_TCM_COMB, +}; + +enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *value); +#endif /* _PM_API_IOCTL_H_ */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index 14c78fd45..be243717e 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -11,6 +11,7 @@ #include #include +#include "pm_api_ioctl.h" #include "pm_api_pinctrl.h" #include "pm_api_sys.h" #include "pm_client.h" @@ -636,3 +637,24 @@ enum pm_ret_status pm_pinctrl_set_config(unsigned int pin, { return pm_api_pinctrl_set_config(pin, param, value); } + +/** + * pm_ioctl() - PM IOCTL API for device control and configs + * @node_id Node ID of the device + * @ioctl_id ID of the requested IOCTL + * @arg1 Argument 1 to requested IOCTL call + * @arg2 Argument 2 to requested IOCTL call + * @out Returned output value + * + * This function calls IOCTL to firmware for device control and configuration. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_ioctl(enum pm_node_id nid, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *value) +{ + return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value); +} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index f240d4915..1c91e8f49 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -105,5 +105,10 @@ enum pm_ret_status pm_pinctrl_get_config(unsigned int pin, enum pm_ret_status pm_pinctrl_set_config(unsigned int pin, unsigned int param, unsigned int value); +enum pm_ret_status pm_ioctl(enum pm_node_id nid, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + 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 c9656e31f..afd92f649 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -75,6 +75,7 @@ enum pm_api_id { PM_PINCTRL_SET_FUNCTION, PM_PINCTRL_CONFIG_PARAM_GET, PM_PINCTRL_CONFIG_PARAM_SET, + PM_IOCTL, PM_API_MAX }; diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index 22b6bc39f..648de24ba 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -280,6 +280,15 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ret = pm_pinctrl_set_config(pm_arg[0], pm_arg[1], pm_arg[2]); SMC_RET1(handle, (uint64_t)ret); + case PM_IOCTL: + { + uint32_t value; + + ret = pm_ioctl(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], &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); diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 45fa387d6..54036f99b 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -47,7 +47,9 @@ #define CRL_APB_RPLL_CTRL (CRL_APB_BASE + 0x30) #define CRL_APB_BOOT_MODE_USER (CRL_APB_BASE + 0x200) #define CRL_APB_RESET_CTRL (CRL_APB_BASE + 0x218) +#define CRL_APB_RST_LPD_TOP (CRL_APB_BASE + 0x23C) +#define CRL_APB_RPU_AMBA_RESET (1 << 2) #define CRL_APB_RPLL_CTRL_BYPASS (1 << 3) #define CRL_APB_RESET_CTRL_SOFT_RESET (1 << 4) @@ -176,4 +178,12 @@ #define IOU_SLCR_BASEADDR 0xFF180000 +#define ZYNQMP_RPU_GLBL_CNTL 0xFF9A0000 +#define ZYNQMP_RPU0_CFG 0xFF9A0100 +#define ZYNQMP_RPU1_CFG 0xFF9A0200 +#define ZYNQMP_SLSPLIT_MASK 0x08 +#define ZYNQMP_TCM_COMB_MASK 0x40 +#define ZYNQMP_SLCLAMP_MASK 0x10 +#define ZYNQMP_VINITHI_MASK 0x04 + #endif /* __ZYNQMP_DEF_H__ */