PMU Global/Local 部分寄存器只能通过处于EL3的Secure Master 访问。
在R5中访问PMU的寄存器,需要通过MMIO 服务来实现(其实就是通过核间IPI来实现)
#include "xipipsu.h"
#include "pm_api_sys.h"
#define IPI_DEVICE_ID XPAR_XIPIPSU_0_DEVICE_ID
#define IPI_PMU_PM_INT_MASK XPAR_XIPIPS_TARGET_PSU_PMU_0_CH0_MASK
#define MMIO_READ_API_ID 20U
#define PMU_PWR_STATUS_REG 0xFFD600CC
#define PMU_PB_ERR 0xFFD60338
int main(void)
{
XIpiPsu IpiInstance;
XIpiPsu_Config *Config;
s32 Status;
u32 Value;
/* Initialize IPI peripheral */
xil_printf("Enter from main\r\n");
Config = XIpiPsu_LookupConfig(IPI_DEVICE_ID);
if (Config == NULL)
{
xil_printf("Config Null\r\n");
goto END;
}
Status = XIpiPsu_CfgInitialize(&IpiInstance, Config, Config->BaseAddress);
if (0x0U != Status)
{
xil_printf("Config init failed\r\n");
goto END;
}
/* Initialize the XilPM library */
Status = XPm_InitXilpm(&IpiInstance);
if (0x0U != Status) {
xil_printf("XilPM init failed\r\n"); goto END;
}
/* Read using XPm_MmioRead() */
Status = XPm_MmioRead(PMU_PWR_STATUS_REG, &Value);
if (0x0U != Status)
{
xil_printf("XilPM MMIO Read failed\r\n"); goto END;
}
xil_printf("Value read from 0x%x: 0x%x\r\n",PMU_PWR_STATUS_REG, Value);
/* Read using XPm_MmioRead() */
Status = XPm_MmioRead(PMU_PB_ERR, &Value);
if (0x0U != Status)
{
xil_printf("XilPM MMIO Read failed\r\n"); goto END;
}
xil_printf("Value read from 0x%x: 0x%x\r\n",PMU_PB_ERR, Value);
END:
xil_printf("Exit from main\r\n");
return 0;
}入代码块语言
PMU使用IPI来接收和响应外部的调用,在读取寄存器时,也会对寄存器进行check,如果寄存器不在默认允许的寄存器列表中,外部master是无法读取到寄存器值的。
我们要根据自己需要读取的寄存器去检查该寄存器是否存在于PMU中的pmAccessTable中,如果不存在,则需要手动添加。 比如我们要读取PMU_PB_ERR,默认在pmAccessTable中是不存在的,需要手动添加。
PMU在收到外部ipi中断后,会回调XPfw_PmIpiHandler这个回调函数。
XPfw_PmIpiHandler--->PmProcessRequest
在PmProcessRequest会根据收到的payload type进入不同的任务分支。
我们读取寄存器,需要借助PM_MMIO_READ来实现:
在PmMmioRead中,会有对读取的寄存器进行检查:mGetMmioAccessRead
在pmAccessTable表中,将我们需要访问的寄存器添加进去,ex:
在 pmu_local.h中增加定义:
#define PMU_LOCAL_PMU_PB_ERR ( ( PMU_LOCAL_BASEADDR ) + ((u32)0X00000338U) )
#define PMU_LOCAL_PMU_PWR_STATUS ( ( PMU_LOCAL_BASEADDR ) + ((u32)0X000000CCU) )
在pm_mmio_access.c中的pmAccessTable表中增加:
/* PMU Local FW error register */
{
.startAddr = PMU_LOCAL_PMU_PB_ERR,
.endAddr = PMU_LOCAL_PMU_PB_ERR,
.access = MMIO_ACCESS_RW(IPI_PMU_0_IER_RPU_0_MASK |
IPI_PMU_0_IER_RPU_1_MASK),
},
{
.startAddr = PMU_LOCAL_PMU_PWR_STATUS,
.endAddr = PMU_LOCAL_PMU_PWR_STATUS,
.access = MMIO_ACCESS_RW(IPI_PMU_0_IER_RPU_0_MASK |
IPI_PMU_0_IER_RPU_1_MASK),
},
#ifdef ENABLE_EM
/* PMU Local FW error register */
{
.startAddr = PMU_LOCAL_PMU_SERV_ERR,
.endAddr = PMU_LOCAL_PMU_SERV_ERR,
.access = MMIO_ACCESS_RW(IPI_PMU_0_IER_RPU_0_MASK |
IPI_PMU_0_IER_RPU_1_MASK),
},
#endif块语言
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。