plat: send an sgi to communicate to linux

Upon recieving the interrupt send an SGI.
The sgi number is communicated by linux.

Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
Change-Id: Ib8f07ff7132ba5ac202b546914efb16d04820ed3
Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@xilinx.com>
This commit is contained in:
Venkatesh Yadav Abbarapu 2021-03-31 03:07:40 -06:00 committed by Manish Pandey
parent 8b48bfb897
commit 78c7beb49c
4 changed files with 54 additions and 0 deletions

View File

@ -16,6 +16,7 @@
#include "pm_client.h"
#include "pm_defs.h"
#include "pm_svc_main.h"
#include "../drivers/arm/gic/v3/gicv3_private.h"
/*********************************************************************
* Target module IDs macros
@ -23,6 +24,7 @@
#define LIBPM_MODULE_ID 0x2
#define LOADER_MODULE_ID 0x7
#define MODE 0x80000000
/* default shutdown/reboot scope is system(2) */
static unsigned int pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
@ -862,6 +864,7 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
uint32_t flag)
{
uint32_t payload[PAYLOAD_ARG_CNT];
int ret;
switch (ioctl_id) {
case IOCTL_SET_PLL_FRAC_MODE:
@ -872,6 +875,15 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
return pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2, flag);
case IOCTL_GET_PLL_FRAC_DATA:
return pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value, flag);
case IOCTL_SET_SGI:
/* Get the sgi number */
ret = pm_register_sgi(arg1);
if (ret) {
return PM_RET_ERROR_ARGS;
}
gicd_write_irouter(gicv3_driver_data->gicd_base,
PLAT_VERSAL_IPI_IRQ, MODE);
return PM_RET_SUCCESS;
default:
/* Send request to the PMC */
PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_IOCTL,

View File

@ -92,6 +92,7 @@
#define IOCTL_GET_PLL_FRAC_MODE 9
#define IOCTL_SET_PLL_FRAC_DATA 10
#define IOCTL_GET_PLL_FRAC_DATA 11
#define IOCTL_SET_SGI 25
/* Parameter ID for PLL IOCTLs */
/* Fractional data portion for PLL */

View File

@ -17,14 +17,29 @@
#include "pm_api_sys.h"
#include "pm_client.h"
#include "pm_ipi.h"
#include <drivers/arm/gicv3.h>
#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U
#define INVALID_SGI 0xFF
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
/* pm_up = true - UP, pm_up = false - DOWN */
static bool pm_up;
static unsigned int sgi = INVALID_SGI;
static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
void *cookie)
{
int cpu;
unsigned int reg;
(void)plat_ic_acknowledge_interrupt();
cpu = plat_my_core_pos() + 1;
if (sgi != INVALID_SGI) {
reg = (cpu | (sgi << XSCUGIC_SGIR_EL1_INITID_SHIFT));
write_icc_asgi1r_el1(reg);
}
/* Clear FIQ */
plat_ic_end_of_interrupt(id);
@ -32,6 +47,31 @@ static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
return 0;
}
/**
* pm_register_sgi() - PM register the IPI interrupt
*
* @sgi - SGI number to be used for communication.
* @return On success, the initialization function must return 0.
* Any other return value will cause the framework to ignore
* the service
*
* Update the SGI number to be used.
*
*/
int pm_register_sgi(unsigned int sgi_num)
{
if (sgi != INVALID_SGI) {
return -EBUSY;
}
if (sgi_num >= GICV3_MAX_SGI_TARGETS) {
return -EINVAL;
}
sgi = sgi_num;
return 0;
}
/**
* pm_setup() - PM service setup
*

View File

@ -14,4 +14,5 @@ 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);
int pm_register_sgi(unsigned int sgi_num);
#endif /* PM_SVC_MAIN_H */