mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 01:24:27 +00:00

When system level DVFS is enabled, voltage can be changed to optimize the power consumption. Signed-off-by: Jacky Bai <ping.bai@nxp.com> Reviewed-by: Ye Li <ye.li@nxp.com> Change-Id: Idfa0e637402078f3daf6e7c4ea1abb9af7675494
201 lines
3.9 KiB
C
201 lines
3.9 KiB
C
/*
|
|
* Copyright 2020-2024 NXP
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <errno.h>
|
|
|
|
#include <common/debug.h>
|
|
#include <drivers/delay_timer.h>
|
|
#include <lib/mmio.h>
|
|
|
|
#include "upower_api.h"
|
|
#include "upower_defs.h"
|
|
|
|
#define UPOWER_AP_MU1_ADDR U(0x29280000)
|
|
|
|
struct MU_t *muptr = (struct MU_t *)UPOWER_AP_MU1_ADDR;
|
|
|
|
void upower_apd_inst_isr(upwr_isr_callb txrx_isr,
|
|
upwr_isr_callb excp_isr)
|
|
{
|
|
/* Do nothing */
|
|
}
|
|
|
|
int upower_status(int status)
|
|
{
|
|
int ret = -1;
|
|
|
|
switch (status) {
|
|
case 0:
|
|
VERBOSE("finished successfully!\n");
|
|
ret = 0;
|
|
break;
|
|
case -1:
|
|
VERBOSE("memory allocation or resource failed!\n");
|
|
break;
|
|
case -2:
|
|
VERBOSE("invalid argument!\n");
|
|
break;
|
|
case -3:
|
|
VERBOSE("called in an invalid API state!\n");
|
|
break;
|
|
default:
|
|
VERBOSE("invalid return status\n");
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
void upower_wait_resp(void)
|
|
{
|
|
while (muptr->RSR.B.RF0 == 0) {
|
|
udelay(100);
|
|
}
|
|
upwr_txrx_isr();
|
|
}
|
|
|
|
static void user_upwr_rdy_callb(uint32_t soc, uint32_t vmajor, uint32_t vminor)
|
|
{
|
|
NOTICE("%s: soc=%x\n", __func__, soc);
|
|
NOTICE("%s: RAM version:%d.%d\n", __func__, vmajor, vminor);
|
|
}
|
|
|
|
int upower_init(void)
|
|
{
|
|
int status;
|
|
|
|
status = upwr_init(APD_DOMAIN, muptr, NULL, NULL, upower_apd_inst_isr, NULL);
|
|
if (upower_status(status)) {
|
|
ERROR("%s: upower init failure\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
NOTICE("%s: start uPower RAM service\n", __func__);
|
|
status = upwr_start(1, user_upwr_rdy_callb);
|
|
upower_wait_resp();
|
|
/* poll status */
|
|
if (upower_status(status)) {
|
|
NOTICE("%s: upower init failure\n", __func__);
|
|
return status;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int upower_pwm(int domain_id, bool pwr_on)
|
|
{
|
|
int ret, ret_val;
|
|
uint32_t swt;
|
|
|
|
if (domain_id == 9U || domain_id == 11U || domain_id == 12U) {
|
|
swt = BIT_32(12) | BIT_32(11) | BIT_32(10) | BIT_32(9);
|
|
} else {
|
|
swt = BIT_32(domain_id);
|
|
}
|
|
|
|
if (pwr_on) {
|
|
ret = upwr_pwm_power_on(&swt, NULL, NULL);
|
|
} else {
|
|
ret = upwr_pwm_power_off(&swt, NULL, NULL);
|
|
}
|
|
|
|
if (ret) {
|
|
NOTICE("%s failed: ret: %d, pwr_on: %d\n", __func__, ret, pwr_on);
|
|
return ret;
|
|
}
|
|
upower_wait_resp();
|
|
|
|
ret = upwr_poll_req_status(UPWR_SG_PWRMGMT, NULL, NULL, &ret_val, 1000);
|
|
if (ret != UPWR_REQ_OK) {
|
|
NOTICE("Failure %d, %s\n", ret, __func__);
|
|
if (ret == UPWR_REQ_BUSY) {
|
|
return -EBUSY;
|
|
} else {
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int upower_read_temperature(uint32_t sensor_id, int32_t *temperature)
|
|
{
|
|
int ret, ret_val;
|
|
upwr_resp_t err_code;
|
|
int64_t t;
|
|
|
|
ret = upwr_tpm_get_temperature(sensor_id, NULL);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
|
|
upower_wait_resp();
|
|
ret = upwr_poll_req_status(UPWR_SG_TEMPM, NULL, &err_code, &ret_val, 1000);
|
|
if (ret > UPWR_REQ_OK) {
|
|
return ret;
|
|
}
|
|
|
|
t = ret_val & 0xff;
|
|
*temperature = (2673049 * t * t * t / 10000000 + 3734262 * t * t / 100000 +
|
|
4487042 * t / 100 - 4698694) / 100000;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int upower_pmic_i2c_write(uint32_t reg_addr, uint32_t reg_val)
|
|
{
|
|
int ret, ret_val;
|
|
upwr_resp_t err_code;
|
|
|
|
ret = upwr_xcp_i2c_access(0x32, 1, 1, reg_addr, reg_val, NULL);
|
|
if (ret) {
|
|
WARN("pmic i2c read failed ret %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
upower_wait_resp();
|
|
ret = upwr_poll_req_status(UPWR_SG_EXCEPT, NULL, &err_code, &ret_val, 1000);
|
|
if (ret != UPWR_REQ_OK) {
|
|
WARN("i2c poll Failure %d, err_code %d, ret_val 0x%x\n",
|
|
ret, err_code, ret_val);
|
|
return ret;
|
|
}
|
|
|
|
VERBOSE("PMIC write reg[0x%x], val[0x%x]\n", reg_addr, reg_val);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int upower_pmic_i2c_read(uint32_t reg_addr, uint32_t *reg_val)
|
|
{
|
|
int ret, ret_val;
|
|
upwr_resp_t err_code;
|
|
|
|
if (reg_val == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
ret = upwr_xcp_i2c_access(0x32, -1, 1, reg_addr, 0, NULL);
|
|
if (ret) {
|
|
WARN("pmic i2c read failed ret %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
upower_wait_resp();
|
|
ret = upwr_poll_req_status(UPWR_SG_EXCEPT, NULL, &err_code, &ret_val, 1000);
|
|
if (ret != UPWR_REQ_OK) {
|
|
WARN("i2c poll Failure %d, err_code %d, ret_val 0x%x\n",
|
|
ret, err_code, ret_val);
|
|
return ret;
|
|
}
|
|
|
|
*reg_val = ret_val;
|
|
|
|
VERBOSE("PMIC read reg[0x%x], val[0x%x]\n", reg_addr, *reg_val);
|
|
|
|
return 0;
|
|
}
|