Commit f76918a8 authored by Rajan Vaja's avatar Rajan Vaja Committed by Jolly Shah
Browse files

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: default avatarRajan Vaja <rajanv@xilinx.com>
Signed-off-by: default avatarJolly Shah <jollys@xilinx.com>
parent d0e2c51a
......@@ -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
/*
* 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 <arch_helpers.h>
#include <delay_timer.h>
#include <mmio.h>
#include <platform.h>
#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;
}
/*
* 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_ */
......@@ -11,6 +11,7 @@
#include <arch_helpers.h>
#include <platform.h>
#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);
}
......@@ -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_ */
......@@ -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
};
......
......@@ -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);
......
......@@ -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__ */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment