blob: 6f94f420f86c7d8f77377998b5126784518623b8 [file] [log] [blame]
/*
* 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;
}