You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2132 lines
61 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2020. All rights reserved.
* Description: ioctl functions
*/
#define LOG_MODULE_ID SOC_ID_PM
#define LOG_FUNC_TRACE 1
#include "drv_pmoc.h"
#include "drv_pmoc_debug.h"
#include <linux/huanglong/securec.h>
#include <asm/io.h>
#include "soc_log.h"
#include "drv_sys_ext.h"
#include "td_type.h"
#include "osal_ext.h"
#include "drv_ioctl_pmoc.h"
#include "drv_pmoc_adapt.h"
#include "drv_pmoc_lpmcu_config.h"
#define INVALID_VALUE 0xffffffff
#define GPIO_BITS_PER_GROUP 8
#define PMOC_LOG_PRINT_LEN 65
#define MCU_NODE "huanglong-mcu-custom0"
typedef struct {
td_u32 cmd;
td_s32(*f_driver_cmd_process)(td_void *arg);
} pmoc_ioctl_map;
typedef struct {
ext_pmoc_wakeup_src source;
td_s32(*f_driver_suspend_param_process)(td_bool set, pmoc_cmd_suspend_attr *attr);
} pmoc_suspend_param_process_map;
#ifndef CONFIG_SOCT_COMMON_KERNEL
#ifndef CONFIG_SOCT_OH_KERNEL
static td_u32 g_s3_s4_gpio_num;
static td_u32 g_s3_s4_gpio_group[S3_S4_OPERATION_NUM];
static td_u32 g_s3_s4_gpio_bit[S3_S4_OPERATION_NUM];
static td_u32 g_s3_gpio_level[S3_S4_OPERATION_NUM];
static td_u32 g_s4_gpio_level[S3_S4_OPERATION_NUM];
#endif
#endif
static pmoc_wakeup_message g_wakeup_message;
static td_u32 *g_lpmcu_base = TD_NULL;
static osal_semaphore g_pmoc_sem;
static ext_pmoc_wakeup_type g_wakeup_type = EXT_PMOC_WAKEUP_TO_DDR;
static pmoc_dts_info g_dts_info;
static osal_task *g_pmoc_thread = TD_NULL;
td_void pmoc_set_shutdown_type(ext_pmoc_wakeup_type type)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_RESUME_RESET_ADDR / sizeof(td_u32);
tmp.val32 = readl(lpmcu_vir_addr);
tmp.val8[2] = type; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr);
soc_dbg_func_exit();
return;
}
static td_s32 pmoc_ir_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
td_u32 i;
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_IR_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
if (attr->param.ir_param.ir_num >= EXT_PMOC_WAKEUP_IRKEY_MAXNUM) {
attr->param.ir_param.ir_num = EXT_PMOC_WAKEUP_IRKEY_MAXNUM;
}
tmp.val32 = 0;
tmp.val8[0] = attr->enable;
tmp.val8[1] = attr->param.ir_param.ir_type;
tmp.val8[2] = attr->param.ir_param.ir_num; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr++);
for (i = 0; i < attr->param.ir_param.ir_num; i++) {
writel(attr->param.ir_param.ir_low_val[i], lpmcu_vir_addr++);
writel(attr->param.ir_param.ir_high_val[i], lpmcu_vir_addr++);
}
} else {
tmp.val32 = readl(lpmcu_vir_addr++);
attr->enable = tmp.val8[0];
attr->param.ir_param.ir_type = tmp.val8[1];
attr->param.ir_param.ir_num = tmp.val8[2]; /* 2: array offset value */
if (attr->param.ir_param.ir_num >= EXT_PMOC_WAKEUP_IRKEY_MAXNUM) {
attr->param.ir_param.ir_num = EXT_PMOC_WAKEUP_IRKEY_MAXNUM;
}
for (i = 0; i < attr->param.ir_param.ir_num; i++) {
attr->param.ir_param.ir_low_val[i] = readl(lpmcu_vir_addr++);
attr->param.ir_param.ir_high_val[i] = readl(lpmcu_vir_addr++);
}
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_keyled_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_KEYLED_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
writel(attr->enable, lpmcu_vir_addr++);
writel(attr->param.keyled_param.keyled_type, lpmcu_vir_addr++);
writel(attr->param.keyled_param.wakeup_key, lpmcu_vir_addr++);
} else {
attr->enable = readl(lpmcu_vir_addr++);
attr->param.keyled_param.keyled_type = readl(lpmcu_vir_addr++);
attr->param.keyled_param.wakeup_key = readl(lpmcu_vir_addr++);
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_gpio_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
td_u32 i;
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_GPIO_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
if (attr->param.gpio_param.num >= EXT_PMOC_WAKEUP_GPIO_MAXNUM) {
attr->param.gpio_param.num = EXT_PMOC_WAKEUP_GPIO_MAXNUM;
}
tmp.val32 = 0;
tmp.val8[0] = attr->enable;
tmp.val8[1] = attr->param.gpio_param.num;
writel(tmp.val32, lpmcu_vir_addr++);
for (i = 0; i < attr->param.gpio_param.num; i++) {
if (attr->param.gpio_param.group[i] > g_dts_info.gpio_aon_group_max ||
attr->param.gpio_param.group[i] < g_dts_info.gpio_aon_group_min) {
soc_err_print_info("gpio aon group is illegal\n");
soc_err_print_u32(i);
soc_err_print_u32(attr->param.gpio_param.group[i]);
return TD_FAILURE;
}
tmp.val32 = 0;
tmp.val8[0] = attr->param.gpio_param.group[i];
tmp.val8[1] = attr->param.gpio_param.bit[i];
tmp.val8[2] = attr->param.gpio_param.interrupt_type[i]; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr++);
}
} else {
tmp.val32 = readl(lpmcu_vir_addr++);
attr->enable = tmp.val8[0];
attr->param.gpio_param.num = tmp.val8[1];
if (attr->param.gpio_param.num >= EXT_PMOC_WAKEUP_GPIO_MAXNUM) {
attr->param.gpio_param.num = EXT_PMOC_WAKEUP_GPIO_MAXNUM;
}
for (i = 0; i < attr->param.gpio_param.num; i++) {
tmp.val32 = readl(lpmcu_vir_addr++);
attr->param.gpio_param.group[i] = tmp.val8[0];
attr->param.gpio_param.bit[i] = tmp.val8[1];
attr->param.gpio_param.interrupt_type[i] = tmp.val8[2]; /* 2: array offset value */
}
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_lsadc_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
td_u32 i;
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_LSADC_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
tmp.val32 = 0;
tmp.val8[0] = attr->enable;
tmp.val8[1] = attr->param.lsadc_param.channel_mask;
writel(tmp.val32, lpmcu_vir_addr++);
for (i = 0; i < EXT_PMOC_LSADC_CHANNEL_MAXNUM; i++) {
tmp.val32 = 0;
tmp.val16[0] = attr->param.lsadc_param.key_value_range[i].low;
tmp.val16[1] = attr->param.lsadc_param.key_value_range[i].high;
writel(tmp.val32, lpmcu_vir_addr++);
}
} else {
tmp.val32 = readl(lpmcu_vir_addr++);
attr->enable = tmp.val8[0];
attr->param.lsadc_param.channel_mask = tmp.val8[1];
for (i = 0; i < EXT_PMOC_LSADC_CHANNEL_MAXNUM; i++) {
tmp.val32 = readl(lpmcu_vir_addr++);
attr->param.lsadc_param.key_value_range[i].low = tmp.val16[0];
attr->param.lsadc_param.key_value_range[i].high = tmp.val16[1];
}
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_uart_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_UART_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
tmp.val32 = 0;
tmp.val8[0] = attr->enable;
tmp.val8[1] = attr->param.uart_param.wakeup_key;
writel(tmp.val32, lpmcu_vir_addr);
} else {
tmp.val32 = readl(lpmcu_vir_addr);
attr->enable = tmp.val8[0];
attr->param.uart_param.wakeup_key = tmp.val8[1];
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_eth_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_ETH_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
tmp.val32 = 0;
tmp.val8[0] = attr->enable;
tmp.val8[1] = attr->param.eth_param.mute_wakeup_enable;
writel(tmp.val32, lpmcu_vir_addr++);
writel(attr->param.eth_param.time_to_passive_standby, lpmcu_vir_addr);
} else {
tmp.val32 = readl(lpmcu_vir_addr++);
attr->enable = tmp.val8[0];
attr->param.eth_param.mute_wakeup_enable = tmp.val8[1];
attr->param.eth_param.time_to_passive_standby = readl(lpmcu_vir_addr);
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_usb_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
td_s32 ret;
td_u32 usb_mask;
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_USB_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
tmp.val32 = 0;
tmp.val8[0] = attr->enable;
writel(tmp.val32, lpmcu_vir_addr);
soc_info_print_h32(attr->param.usb_param.usb_wakeup_mask);
ret = pmoc_set_usb_wakeup_mask(attr->param.usb_param.usb_wakeup_mask);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_usb_wakeup_mask, ret);
return ret;
}
} else {
ret = pmoc_get_usb_wakeup_mask(&usb_mask);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_get_usb_wakeup_mask, ret);
return ret;
}
tmp.val32 = readl(lpmcu_vir_addr);
attr->enable = tmp.val8[0];
attr->param.usb_param.usb_wakeup_mask = usb_mask;
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_voice_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_VOICE_WAKEUP_ENABLE_VALUE / sizeof(td_u32);
if (set) {
tmp.val32 = 0;
tmp.val8[0] = attr->enable;
writel(tmp.val32, lpmcu_vir_addr);
} else {
tmp.val32 = readl(lpmcu_vir_addr);
attr->enable = tmp.val8[0];
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_vga_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_VGA_WAKEUP_ENABLE_VALUE / sizeof(td_u32);
if (set) {
tmp.val32 = 0;
tmp.val8[0] = attr->enable;
writel(tmp.val32, lpmcu_vir_addr);
} else {
tmp.val32 = readl(lpmcu_vir_addr);
attr->enable = tmp.val8[0];
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_scart_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
soc_dbg_func_enter();
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_hdmirx_plugin_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_HDMI_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
tmp.val32 = readl(lpmcu_vir_addr);
tmp.val8[2] = attr->enable; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr);
lpmcu_vir_addr = g_lpmcu_base + LPMCU_HDMIRX_PLUGIN_PORT_ADDR / sizeof(td_u32);
writel(attr->param.hdmirx_plugin_param.port, lpmcu_vir_addr);
} else {
tmp.val32 = readl(lpmcu_vir_addr);
attr->enable = tmp.val8[2]; /* 2: array offset value */
lpmcu_vir_addr = g_lpmcu_base + LPMCU_HDMIRX_PLUGIN_PORT_ADDR / sizeof(td_u32);
attr->param.hdmirx_plugin_param.port = readl(lpmcu_vir_addr);
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_hdmirx_cec_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_HDMI_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
tmp.val32 = readl(lpmcu_vir_addr);
tmp.val8[1] = attr->enable;
writel(tmp.val32, lpmcu_vir_addr);
} else {
tmp.val32 = readl(lpmcu_vir_addr);
attr->enable = tmp.val8[1];
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_hdmitx_cec_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
u32_data tmp;
td_u8 i;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_HDMI_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
tmp.val32 = readl(lpmcu_vir_addr);
tmp.val8[0] = attr->enable;
writel(tmp.val32, lpmcu_vir_addr);
lpmcu_vir_addr = g_lpmcu_base + LPMCU_HDMITX_CEC_PARAM_ADDR / sizeof(td_u32);
for (i = 0; i < LPMCU_WAKEUP_HDMITX_ID_MAXNUM; i++) {
tmp.val32 = 0;
tmp.val8[0] = attr->param.hdmitx_cec_param.id[i];
tmp.val8[1] = attr->param.hdmitx_cec_param.cec_control[i];
writel(tmp.val32, lpmcu_vir_addr++);
}
} else {
tmp.val32 = readl(lpmcu_vir_addr);
attr->enable = tmp.val8[0];
lpmcu_vir_addr = g_lpmcu_base + LPMCU_HDMITX_CEC_PARAM_ADDR / sizeof(td_u32);
for (i = 0; i < LPMCU_WAKEUP_HDMITX_ID_MAXNUM; i++) {
tmp.val32 = readl(lpmcu_vir_addr++);
attr->param.hdmitx_cec_param.id[i] = tmp.val8[0];
attr->param.hdmitx_cec_param.cec_control[i] = tmp.val8[1];
}
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_timeout_suspend_param(td_bool set, pmoc_cmd_suspend_attr *attr)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_TIMEOUT_SUSPEND_PARAM_ADDR / sizeof(td_u32);
if (set) {
tmp.val32 = 0;
tmp.val8[0] = attr->enable;
tmp.val8[1] = attr->param.timeout_param.pvr_enable;
tmp.val8[2] = attr->param.timeout_param.mute_wakeup_enable; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr++);
writel(attr->param.timeout_param.suspend_period, lpmcu_vir_addr);
} else {
tmp.val32 = readl(lpmcu_vir_addr++);
attr->enable = tmp.val8[0];
attr->param.timeout_param.pvr_enable = tmp.val8[1];
attr->param.timeout_param.mute_wakeup_enable = tmp.val8[2]; /* 2: array offset value */
attr->param.timeout_param.suspend_period = readl(lpmcu_vir_addr);
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static pmoc_suspend_param_process_map g_suspend_param_process_func[] = {
{ EXT_PMOC_WAKEUP_TYPE_IR, pmoc_ir_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_KEYLED, pmoc_keyled_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_GPIO, pmoc_gpio_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_LSADC, pmoc_lsadc_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_UART, pmoc_uart_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_ETH, pmoc_eth_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_USB, pmoc_usb_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_VOICE, pmoc_voice_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_VGA, pmoc_vga_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_SCART, pmoc_scart_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_HDMIRX_PLUGIN, pmoc_hdmirx_plugin_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_HDMIRX_CEC, pmoc_hdmirx_cec_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_HDMITX_CEC, pmoc_hdmitx_cec_suspend_param },
{ EXT_PMOC_WAKEUP_TYPE_TIMEOUT, pmoc_timeout_suspend_param },
};
static td_s32 pmoc_set_suspend_param(td_void *arg)
{
td_s32 ret;
td_u8 i;
td_u8 source_num;
pmoc_cmd_suspend_attr attr = {0};
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = memcpy_s(&attr, sizeof(pmoc_cmd_suspend_attr), arg, sizeof(pmoc_cmd_suspend_attr));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
source_num = sizeof(g_suspend_param_process_func) / sizeof(g_suspend_param_process_func[0]);
for (i = 0; i < source_num; i++) {
if (attr.source == g_suspend_param_process_func[i].source) {
ret = g_suspend_param_process_func[i].f_driver_suspend_param_process(TD_TRUE, &attr);
if (ret != TD_SUCCESS) {
soc_err_print_h32(attr.source);
soc_err_print_s32(ret);
return ret;
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
}
return TD_FAILURE;
}
td_s32 pmoc_get_suspend_param(td_void *arg)
{
td_s32 ret;
td_u8 i;
td_u8 source_num;
pmoc_cmd_suspend_attr attr = {0};
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = memcpy_s(&attr, sizeof(pmoc_cmd_suspend_attr), arg, sizeof(pmoc_cmd_suspend_attr));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
source_num = sizeof(g_suspend_param_process_func) / sizeof(g_suspend_param_process_func[0]);
for (i = 0; i < source_num; i++) {
if (attr.source == g_suspend_param_process_func[i].source) {
ret = g_suspend_param_process_func[i].f_driver_suspend_param_process(TD_FALSE, &attr);
if (ret != TD_SUCCESS) {
soc_err_print_h32(attr.source);
soc_err_print_s32(ret);
return ret;
}
ret = memcpy_s(arg, sizeof(pmoc_cmd_suspend_attr), &attr, sizeof(pmoc_cmd_suspend_attr));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
}
return TD_FAILURE;
}
static td_s32 pmoc_set_wakeup_type(td_void *arg)
{
td_s32 ret;
u32_data tmp;
ext_pmoc_wakeup_type type;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = memcpy_s(&type, sizeof(ext_pmoc_wakeup_type), arg, sizeof(ext_pmoc_wakeup_type));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
g_wakeup_type = type;
lpmcu_vir_addr = g_lpmcu_base + LPMCU_RESUME_RESET_ADDR / sizeof(td_u32);
tmp.val32 = readl(lpmcu_vir_addr);
tmp.val8[0] = type;
writel(tmp.val32, lpmcu_vir_addr);
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_standby_ready(td_void *arg)
{
soc_dbg_func_enter();
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_set_gpio_power_off(td_void *arg)
{
td_s32 ret;
td_u32 i;
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
ext_pmoc_poweroff_gpio_param param = {0};
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = memcpy_s(&param, sizeof(ext_pmoc_poweroff_gpio_param), arg, sizeof(ext_pmoc_poweroff_gpio_param));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
if (param.num >= EXT_PMOC_POWEROFF_GPIO_MAXNUM) {
param.num = EXT_PMOC_POWEROFF_GPIO_MAXNUM;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_GPIO_POWEROFF_PARAM_ADDR / sizeof(td_u32);
writel(param.num, lpmcu_vir_addr++);
for (i = 0; i < param.num; i++) {
if (param.group[i] > g_dts_info.gpio_aon_group_max || param.group[i] < g_dts_info.gpio_aon_group_min) {
soc_err_print_info("gpio aon group is illegal\n");
soc_err_print_u32(i);
soc_err_print_u32(param.group[i]);
return TD_FAILURE;
}
tmp.val32 = 0;
tmp.val8[0] = param.group[i];
tmp.val8[1] = param.bit[i];
tmp.val8[2] = param.level[i]; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr++);
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_set_display_param(td_void *arg)
{
td_s32 ret;
td_u32 *lpmcu_vir_addr = TD_NULL;
ext_pmoc_display_param display_param = {0};
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = memcpy_s(&display_param, sizeof(ext_pmoc_display_param), arg, sizeof(ext_pmoc_display_param));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_KEYLED_TYPE_ADDR / sizeof(td_u32);
writel(display_param.keyled_type, lpmcu_vir_addr);
lpmcu_vir_addr = g_lpmcu_base + LPMCU_KEYLED_DISPLAY_ADDR / sizeof(td_u32);
writel(display_param.display_type, lpmcu_vir_addr++);
writel(display_param.display_value, lpmcu_vir_addr++);
soc_dbg_func_exit();
return TD_SUCCESS;
}
td_s32 pmoc_get_standby_period(td_void *arg)
{
td_s32 ret;
td_u32 period;
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
if (g_wakeup_message.wakeup_type >= EXT_PMOC_WAKEUP_TYPE_MAX) {
soc_err_print_info("wakeup type is illegal");
return TD_FAILURE;
}
period = g_wakeup_message.standby_period;
ret = memcpy_s(arg, sizeof(td_u32), &period, sizeof(td_u32));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
td_s32 pmoc_get_wakeup_attr(td_void *arg)
{
td_s32 ret;
ext_pmoc_wakeup_attr attr = {0};
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
if (g_wakeup_message.wakeup_type >= EXT_PMOC_WAKEUP_TYPE_MAX) {
return TD_FAILURE;
}
attr.source = g_wakeup_message.wakeup_type;
if (attr.source == EXT_PMOC_WAKEUP_TYPE_IR) {
attr.wakeup_param.ir_param.ir_low_val = g_wakeup_message.ir_low_val;
attr.wakeup_param.ir_param.ir_high_val = g_wakeup_message.ir_high_val;
} else if (attr.source == EXT_PMOC_WAKEUP_TYPE_GPIO) {
attr.wakeup_param.gpio_param.group = g_wakeup_message.gpio_wakeup_port / GPIO_BITS_PER_GROUP;
attr.wakeup_param.gpio_param.bit = g_wakeup_message.gpio_wakeup_port % GPIO_BITS_PER_GROUP;
} else if (attr.source == EXT_PMOC_WAKEUP_TYPE_LSADC) {
attr.wakeup_param.lsadc_param.channel = g_wakeup_message.lsadc_channel;
attr.wakeup_param.lsadc_param.key_value = g_wakeup_message.lsadc_wakeup_key;
}
ret = memcpy_s(arg, sizeof(ext_pmoc_wakeup_attr), &attr, sizeof(ext_pmoc_wakeup_attr));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_clean_wakeup_param(td_void *arg)
{
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_WAKEUP_DATA_ADDR / sizeof(td_u32);
writel(INVALID_VALUE, lpmcu_vir_addr++);
writel(INVALID_VALUE, lpmcu_vir_addr++);
writel(INVALID_VALUE, lpmcu_vir_addr++);
writel(INVALID_VALUE, lpmcu_vir_addr++);
writel(INVALID_VALUE, lpmcu_vir_addr);
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_enter_active_standby(td_void *arg)
{
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_quit_active_standby(td_void *arg)
{
soc_dbg_func_enter();
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_get_chip_temprature(td_void *arg)
{
td_s32 ret;
td_s16 real_temp;
td_s32 temperature;
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = pmoc_tsensor_read(&real_temp);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_tsensor_read, ret);
return TD_FAILURE;
}
temperature = real_temp;
ret = memcpy_s(arg, sizeof(td_u32), &temperature, sizeof(td_u32));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_set_standby_led(td_void *arg)
{
td_s32 ret;
u32_data param;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = memcpy_s(&param.val32, sizeof(td_u32), arg, sizeof(td_u32));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_STANDBY_LED_PARAM_ADDR / sizeof(td_u32);
if (param.val8[0] > g_dts_info.gpio_aon_group_max || param.val8[0] < g_dts_info.gpio_aon_group_min) {
soc_err_print_info("gpio aon group is illegal\n");
soc_err_print_u32(param.val8[0]);
return TD_FAILURE;
}
writel(param.val32, lpmcu_vir_addr);
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_set_breath_led(td_void *arg)
{
td_s32 ret;
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
ext_pmoc_breath_led_param param = {0};
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = memcpy_s(&param, sizeof(ext_pmoc_breath_led_param), arg, sizeof(ext_pmoc_breath_led_param));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
if (param.group > g_dts_info.gpio_aon_group_max || param.group < g_dts_info.gpio_aon_group_min) {
soc_err_print_info("gpio aon group is illegal\n");
soc_err_print_u32(param.group);
return TD_FAILURE;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_BREATH_LED_PARAM_ADDR / sizeof(td_u32);
tmp.val32 = 0;
tmp.val8[0] = param.group;
tmp.val8[1] = param.bit;
writel(tmp.val32, lpmcu_vir_addr++);
writel(param.led_breath_cycle, lpmcu_vir_addr);
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_set_mcu_msg(td_void *arg)
{
td_s32 ret;
td_u32 *lpmcu_vir_addr = TD_NULL;
ext_pmoc_mcu_message msg = {0};
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = memcpy_s(&msg, sizeof(ext_pmoc_mcu_message), arg, sizeof(ext_pmoc_mcu_message));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
if (msg.index >= EXT_PMOC_CUSTOM_REG_MAX) {
soc_err_print_info("custom reg index is illegal\n");
soc_err_print_u32(msg.index);
return TD_FAILURE;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_CUSTOM_MSG_ADDR / sizeof(td_u32) + msg.index;
writel(msg.value, lpmcu_vir_addr);
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_get_mcu_msg(td_void *arg)
{
td_s32 ret;
td_u32 *lpmcu_vir_addr = TD_NULL;
ext_pmoc_mcu_message msg = {0};
soc_dbg_func_enter();
pmoc_check_param_return_if(arg == TD_NULL, TD_FAILURE);
ret = memcpy_s(&msg, sizeof(ext_pmoc_mcu_message), arg, sizeof(ext_pmoc_mcu_message));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
if (msg.index >= EXT_PMOC_CUSTOM_REG_MAX) {
soc_err_print_info("custom reg index is illegal\n");
soc_err_print_u32(msg.index);
return TD_FAILURE;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_CUSTOM_MSG_ADDR / sizeof(td_u32) + msg.index;
msg.value = readl(lpmcu_vir_addr);
ret = memcpy_s(arg, sizeof(ext_pmoc_mcu_message), &msg, sizeof(ext_pmoc_mcu_message));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return TD_FAILURE;
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static pmoc_ioctl_map g_pmoc_func[] = {
{ CMD_PMOC_SET_SUSPEND_ATTR, pmoc_set_suspend_param },
{ CMD_PMOC_GET_SUSPEND_ATTR, pmoc_get_suspend_param },
{ CMD_PMOC_SET_WAKEUP_TYPE, pmoc_set_wakeup_type },
{ CMD_PMOC_STANDBY_READY, pmoc_standby_ready },
{ CMD_PMOC_GET_WAKEUP_ATTR, pmoc_get_wakeup_attr },
{ CMD_PMOC_GET_STANDBY_PERIOD, pmoc_get_standby_period },
{ CMD_PMOC_CLEAN_WAKEUP_PARAM, pmoc_clean_wakeup_param },
{ CMD_PMOC_ENTER_ACTIVE_STANDBY, pmoc_enter_active_standby },
{ CMD_PMOC_QUIT_ACTIVE_STANDBY, pmoc_quit_active_standby },
{ CMD_PMOC_SET_DISPLAY_PARAM, pmoc_set_display_param },
{ CMD_PMOC_SET_GPIO_POWEROFF, pmoc_set_gpio_power_off },
{ CMD_PMOC_GET_CHIP_TEMPERATURE, pmoc_get_chip_temprature },
{ CMD_PMOC_SET_STANDBY_LED, pmoc_set_standby_led },
{ CMD_PMOC_SET_BREATH_LED, pmoc_set_breath_led },
{ CMD_PMOC_SET_MCU_MSG, pmoc_set_mcu_msg },
{ CMD_PMOC_GET_MCU_MSG, pmoc_get_mcu_msg },
};
td_s32 pmoc_ioctl(td_u32 cmd, td_void *arg, td_void *private_data)
{
td_u8 cmd_num;
td_u8 i;
td_s32 ret;
soc_dbg_func_enter();
cmd_num = sizeof(g_pmoc_func) / sizeof(g_pmoc_func[0]);
for (i = 0; i < cmd_num; i++) {
if (cmd == g_pmoc_func[i].cmd) {
ret = osal_sem_down_interruptible(&g_pmoc_sem);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_sem_down_interruptible, ret);
return ret;
}
ret = g_pmoc_func[i].f_driver_cmd_process(arg);
if (ret != TD_SUCCESS) {
soc_err_print_h32(cmd);
soc_err_print_s32(ret);
osal_sem_up(&g_pmoc_sem);
return ret;
}
osal_sem_up(&g_pmoc_sem);
return TD_SUCCESS;
}
}
soc_err_print_info("ioctl cmd is not support\n");
return TD_FAILURE;
}
#ifndef MODULE
td_void pmoc_inject_timesleep_to_timekeeping(td_void)
{
td_u32 *lpmcu_vir_addr = TD_NULL;
struct timespec64 sleep_time = {0};
td_u32 delta;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_STANDBY_PERIOD / sizeof(td_u32);
delta = readl(lpmcu_vir_addr);
sleep_time.tv_sec += delta;
timekeeping_inject_sleeptime64(&sleep_time);
soc_dbg_func_exit();
return;
}
#endif
static td_void lpmcu_log_to_bbox(td_void)
{
td_u32 i, log_len;
td_u8 log_print[PMOC_LOG_PRINT_LEN + 1] = {0};
td_u32 log_data[LPMCU_LOG_DATA_SIZE / sizeof(td_u32) + 1] = {0};
td_char *log_msg = TD_NULL;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_LOG_FLAG_ADDR / sizeof(td_u32);
if (readl(lpmcu_vir_addr) == LPMCU_LOG_WRITE_FLAG) {
writel(0, lpmcu_vir_addr++);
log_len = readl(lpmcu_vir_addr);
log_len = (log_len > LPMCU_LOG_DATA_SIZE) ? LPMCU_LOG_DATA_SIZE : log_len;
soc_dbg_print_u32(log_len);
writel(0, lpmcu_vir_addr++);
for (i = 0; i < log_len / sizeof(td_u32); i++) {
log_data[i] = readl(lpmcu_vir_addr + i);
writel(0, lpmcu_vir_addr + i);
}
log_msg = (td_u8 *)log_data;
for (i = 0; *log_msg != '\0'; log_msg++) {
if (i == PMOC_LOG_PRINT_LEN) {
log_print[i] = '\0';
soc_log_alert("%s\n", log_print);
i = 0;
log_print[i++] = *log_msg;
continue;
}
if (*log_msg == '\n') {
log_print[i] = '\0';
soc_log_alert("%s\n", log_print);
i = 0;
continue;
}
log_print[i++] = *log_msg;
}
}
soc_dbg_func_exit();
return;
}
td_void pmoc_get_wakeup_message(td_void)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
lpmcu_vir_addr = g_lpmcu_base + LPMCU_WAKEUP_DATA_ADDR / sizeof(td_u32);
g_wakeup_message.wakeup_type = readl(lpmcu_vir_addr++);
g_wakeup_message.gpio_wakeup_port = readl(lpmcu_vir_addr++);
g_wakeup_message.ir_low_val = readl(lpmcu_vir_addr++);
g_wakeup_message.ir_high_val = readl(lpmcu_vir_addr++);
g_wakeup_message.standby_period = readl(lpmcu_vir_addr++);
tmp.val32 = readl(lpmcu_vir_addr);
g_wakeup_message.lsadc_channel = tmp.val16[0];
g_wakeup_message.lsadc_wakeup_key = tmp.val16[1];
lpmcu_log_to_bbox();
/* clear reg mute flag */
lpmcu_vir_addr = g_lpmcu_base + LPMCU_REG_MUTE / sizeof(td_u32);
writel(0, lpmcu_vir_addr);
soc_dbg_func_exit();
return;
}
td_void pmoc_set_lpmcu_dbg_level(td_u32 value)
{
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
soc_info_print_u32(value);
if ((value != 0) && (value != 1)) {
soc_err_print_info("plese set dbg level: 0(lpmcu without log), 1(lpmcu with log)\n");
return;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_DBG_MASK_ADDR / sizeof(td_u32);
tmp.val32 = readl(lpmcu_vir_addr);
tmp.val8[1] = value;
writel(tmp.val32, lpmcu_vir_addr);
soc_dbg_func_exit();
return;
}
td_s32 pmoc_load_wakeup_param(td_void)
{
td_s32 ret;
soc_dbg_func_enter();
ret = pmoc_set_wakeup_type_to_hrf(g_wakeup_type);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_wakeup_type_to_hrf, ret);
return TD_FAILURE;
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_check_firmware_file(td_void)
{
td_s32 ret;
td_u32 i;
td_u32 path_num;
td_void *fp = TD_NULL;
td_u8 fw_name[128]; /* 128: len */
td_u8 *path[] = {
"/lib/firmware/",
"/vendor/firmware/"
};
path_num = sizeof(path) / sizeof(path[0]);
for (i = 0; i < path_num; i++) {
ret = snprintf_s(fw_name, sizeof(fw_name), sizeof(fw_name) - 1, "%s%s", path[i], LPMCU_BIN_PATH);
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return ret;
}
fp = osal_klib_fopen(fw_name, OSAL_O_RDONLY, 0);
if (fp == TD_NULL) {
continue;
}
osal_klib_fclose(fp);
return TD_SUCCESS;
}
return TD_FAILURE;
}
static td_s32 pmoc_load_lpmcu_code(td_void)
{
td_s32 ret;
osal_firmware *fw = TD_NULL;
ret = pmoc_check_firmware_file();
if (ret != TD_SUCCESS) {
return ret;
}
ret = osal_request_firmware_into_buf(&fw, LPMCU_BIN_PATH, g_lpmcu_base, LPMCU_CODE_MAXSIZE);
if (ret != 0) {
soc_err_print_call_fun_err(osal_request_firmware_into_buf, ret);
return ret;
}
osal_release_firmware(fw);
return TD_SUCCESS;
}
static td_s32 pmoc_load_firmware_thread(td_void *data)
{
td_s32 ret;
while (!osal_kthread_should_stop()) {
osal_msleep(500); /* 500 ms */
ret = pmoc_load_lpmcu_code();
if (ret != TD_SUCCESS) {
continue;
}
break;
}
return TD_SUCCESS;
}
static td_s32 pmoc_try_loading_firmware(td_void)
{
td_s32 ret;
ret = pmoc_load_lpmcu_code();
if (ret == TD_SUCCESS) {
return TD_SUCCESS;
}
g_pmoc_thread = osal_kthread_create(pmoc_load_firmware_thread, TD_NULL, "lpmcu_loading_thread", 0);
if (g_pmoc_thread == TD_NULL) {
soc_err_print_call_fun_err(osal_kthread_create, TD_FAILURE);
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_s32 set_ddr_gpio_custom_param(td_void)
{
td_s32 ret;
td_u32 ddr_gpio_group, ddr_gpio_bit, ddr_gpio_level;
td_u32 *lpmcu_vir_addr = NULL;
u32_data tmp;
ret = osal_dts_get_u32_byname(MCU_NODE, "ddr_gpio_group", &ddr_gpio_group);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
ret = osal_dts_get_u32_byname(MCU_NODE, "ddr_gpio_bit", &ddr_gpio_bit);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
ret = osal_dts_get_u32_byname(MCU_NODE, "ddr_gpio_level", &ddr_gpio_level);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
lpmcu_vir_addr = (td_u32 *)(g_lpmcu_base + LPMCU_GPIO_POWERCTRL_DDR_PARAM_ADDR / sizeof(td_u32));
tmp.val32 = 0;
tmp.val8[0] = ddr_gpio_group;
tmp.val8[1] = ddr_gpio_bit;
tmp.val8[2] = ddr_gpio_level; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr);
return TD_SUCCESS;
}
static td_s32 pmoc_set_gpio_poweroff_custom_param(td_void)
{
td_s32 ret;
u32_data tmp;
td_u32 poweroff_num, i;
td_u32 poweroff_group[EXT_PMOC_POWEROFF_GPIO_MAXNUM] = {0};
td_u32 poweroff_bit[EXT_PMOC_POWEROFF_GPIO_MAXNUM] = {0};
td_u32 poweroff_level[EXT_PMOC_POWEROFF_GPIO_MAXNUM] = {0};
td_u32 *lpmcu_vir_addr = NULL;
ret = osal_dts_get_u32_byname(MCU_NODE, "gpio_poweroff_num", &poweroff_num);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
if (poweroff_num == 0) {
return TD_SUCCESS;
}
poweroff_num = (poweroff_num > EXT_PMOC_POWEROFF_GPIO_MAXNUM) ? EXT_PMOC_POWEROFF_GPIO_MAXNUM : poweroff_num;
lpmcu_vir_addr = (td_u32 *)(g_lpmcu_base + LPMCU_GPIO_POWEROFF_PARAM_ADDR / sizeof(td_u32));
writel(poweroff_num, lpmcu_vir_addr++);
ret = osal_dts_get_array_byname(MCU_NODE, "gpio_poweroff_group", poweroff_group, poweroff_num);
if (ret < 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return ret;
}
ret = osal_dts_get_array_byname(MCU_NODE, "gpio_poweroff_bit", poweroff_bit, poweroff_num);
if (ret < 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return ret;
}
ret = osal_dts_get_array_byname(MCU_NODE, "gpio_poweroff_level", poweroff_level, poweroff_num);
if (ret < 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return ret;
}
for (i = 0; i < poweroff_num; i++) {
if (poweroff_group[i] > g_dts_info.gpio_aon_group_max || poweroff_group[i] < g_dts_info.gpio_aon_group_min) {
soc_err_print_info("gpio aon group is illegal\n");
soc_err_print_u32(poweroff_group[i]);
return TD_FAILURE;
}
tmp.val32 = 0;
tmp.val8[0] = poweroff_group[i];
tmp.val8[1] = poweroff_bit[i];
tmp.val8[2] = poweroff_level[i]; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr++);
}
return TD_SUCCESS;
}
static td_s32 pmoc_set_keyled_custom_param(td_void)
{
td_s32 ret;
td_u32 keyled_wakeup_enable;
td_u32 keyled_type;
td_u32 keyled_wakeup_key;
td_u32 keyled_display_mode;
td_u32 display_value;
td_u32 *lpmcu_vir_addr = NULL;
ret = osal_dts_get_u32_byname(MCU_NODE, "keyled_wakeup_enable", &keyled_wakeup_enable);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
if (keyled_wakeup_enable == 0)
return TD_SUCCESS;
lpmcu_vir_addr = (td_u32 *)(g_lpmcu_base + LPMCU_KEYLED_SUSPEND_PARAM_ADDR / sizeof(td_u32));
writel(keyled_wakeup_enable, lpmcu_vir_addr++);
ret = osal_dts_get_u32_byname(MCU_NODE, "keyled_type", &keyled_type);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
writel(keyled_type, lpmcu_vir_addr++);
ret = osal_dts_get_u32_byname(MCU_NODE, "keyled_wakeup_key", &keyled_wakeup_key);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
writel(keyled_wakeup_key, lpmcu_vir_addr++);
ret = osal_dts_get_u32_byname(MCU_NODE, "keyled_display_mode", &keyled_display_mode);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
writel(keyled_display_mode, lpmcu_vir_addr++);
ret = osal_dts_get_u32_byname(MCU_NODE, "display_value", &display_value);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
writel(display_value, lpmcu_vir_addr);
return TD_SUCCESS;
}
#ifndef CONFIG_SOCT_COMMON_KERNEL
#ifndef CONFIG_SOCT_OH_KERNEL
static td_s32 pmoc_get_s3_s4_param(td_void)
{
td_s32 ret;
ret = osal_dts_get_u32_byname(MCU_NODE, "s3_s4_gpio_num", &g_s3_s4_gpio_num);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
g_s3_s4_gpio_num = (g_s3_s4_gpio_num > S3_S4_OPERATION_NUM) ? S3_S4_OPERATION_NUM : g_s3_s4_gpio_num;
ret = osal_dts_get_array_byname(MCU_NODE, "s3_s4_gpio_group",
g_s3_s4_gpio_group, S3_S4_OPERATION_NUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_array_byname(MCU_NODE, "s3_s4_gpio_bit", g_s3_s4_gpio_bit, S3_S4_OPERATION_NUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_array_byname(MCU_NODE, "s3_gpio_level", g_s3_gpio_level, S3_S4_OPERATION_NUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_array_byname(MCU_NODE, "s4_gpio_level", g_s4_gpio_level, S3_S4_OPERATION_NUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_void pmoc_set_s3_s4_param(td_bool is_s3)
{
td_u32 i;
u32_data tmp;
td_u32 *lpmcu_vir_addr = NULL;
soc_dbg_func_enter();
if (g_dts_info.product_flag != 0x2) { /* 0x2: bit1 is pc product flag */
return;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_S3_S4_GPIO_NUM_ADDR / sizeof(td_u32);
tmp.val32 = 0;
tmp.val8[0] = g_s3_s4_gpio_num;
writel(tmp.val32, lpmcu_vir_addr);
lpmcu_vir_addr = g_lpmcu_base + LPMCU_S3_S4_GPIO_PARAM_ADDR / sizeof(td_u32);
for (i = 0; i < g_s3_s4_gpio_num; i++) {
tmp.val32 = 0;
tmp.val8[0] = g_s3_s4_gpio_group[i];
tmp.val8[1] = g_s3_s4_gpio_bit[i];
tmp.val8[2] = is_s3 ? g_s3_gpio_level[i] : g_s4_gpio_level[i]; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr++);
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_S3_S4_FLAG_ADDR / sizeof(td_u32);
writel(0, lpmcu_vir_addr);
soc_dbg_func_exit();
return;
}
#endif
#endif
static td_s32 pmoc_get_gpio_message(td_u32 *lpmcu_vir_addr, td_u32 gpio_wakeup_num)
{
td_u32 i;
td_s32 ret;
u32_data tmp;
td_u32 gpio_wakeup_group[LPMCU_WAKEUP_GPIO_MAXNUM] = {0};
td_u32 gpio_wakeup_bit[LPMCU_WAKEUP_GPIO_MAXNUM] = {0};
td_u32 gpio_interrupt_type[LPMCU_WAKEUP_GPIO_MAXNUM] = {0};
pmoc_check_param_return_if(lpmcu_vir_addr == TD_NULL, TD_FAILURE);
pmoc_check_param_return_if(gpio_wakeup_num > LPMCU_WAKEUP_GPIO_MAXNUM, TD_FAILURE);
ret = osal_dts_get_array_byname(MCU_NODE, "gpio_wakeup_group",
gpio_wakeup_group, LPMCU_WAKEUP_GPIO_MAXNUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_array_byname(MCU_NODE, "gpio_wakeup_bit",
gpio_wakeup_bit, LPMCU_WAKEUP_GPIO_MAXNUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_array_byname(MCU_NODE, "gpio_interrupt_type",
gpio_interrupt_type, LPMCU_WAKEUP_GPIO_MAXNUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
for (i = 0; i < gpio_wakeup_num; i++) {
tmp.val32 = 0;
tmp.val8[0] = gpio_wakeup_group[i];
tmp.val8[1] = gpio_wakeup_bit[i];
tmp.val8[2] = gpio_interrupt_type[i]; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr++);
}
return TD_SUCCESS;
}
static td_s32 pmoc_set_gpio_custom_param(td_void)
{
td_s32 ret;
u32_data tmp;
td_u32 gpio_wakeup_enable = 0;
td_u32 gpio_wakeup_num = 0;
td_u32 *lpmcu_vir_addr = NULL;
ret = osal_dts_get_u32_byname(MCU_NODE, "gpio_wakeup_enable", &gpio_wakeup_enable);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
if (gpio_wakeup_enable == 0)
return TD_SUCCESS;
ret = osal_dts_get_u32_byname(MCU_NODE, "gpio_wakeup_num", &gpio_wakeup_num);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
gpio_wakeup_num = (gpio_wakeup_num > LPMCU_WAKEUP_GPIO_MAXNUM) ? LPMCU_WAKEUP_GPIO_MAXNUM : gpio_wakeup_num;
lpmcu_vir_addr = (td_u32 *)(g_lpmcu_base + LPMCU_GPIO_SUSPEND_PARAM_ADDR / sizeof(td_u32));
tmp.val32 = 0;
tmp.val8[0] = gpio_wakeup_enable;
tmp.val8[1] = gpio_wakeup_num;
writel(tmp.val32, lpmcu_vir_addr++);
ret = pmoc_get_gpio_message(lpmcu_vir_addr, gpio_wakeup_num);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_get_gpio_message, ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_s32 pmoc_get_ir_message(td_u32 *lpmcu_vir_addr, td_u32 ir_wakeup_num)
{
td_s32 ret;
td_u32 i;
td_u32 ir_high_value[LPMCU_WAKEUP_IRKEY_MAXNUM] = {0};
td_u32 ir_low_value[LPMCU_WAKEUP_IRKEY_MAXNUM] = {0};
pmoc_check_param_return_if(lpmcu_vir_addr == TD_NULL, TD_FAILURE);
pmoc_check_param_return_if(ir_wakeup_num > LPMCU_WAKEUP_IRKEY_MAXNUM, TD_FAILURE);
ret = osal_dts_get_array_byname(MCU_NODE, "ir_low_value", ir_low_value, LPMCU_WAKEUP_IRKEY_MAXNUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_array_byname(MCU_NODE, "ir_high_value", ir_high_value, LPMCU_WAKEUP_IRKEY_MAXNUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
for (i = 0; i < ir_wakeup_num; i++) {
writel(ir_low_value[i], lpmcu_vir_addr++);
writel(ir_high_value[i], lpmcu_vir_addr++);
}
return TD_SUCCESS;
}
static td_s32 pmoc_set_ir_custom_param(td_void)
{
td_s32 ret;
td_u32 ir_wakeup_enable;
td_u32 ir_type;
td_u32 ir_wakeup_num;
td_u32 *lpmcu_vir_addr = NULL;
u32_data tmp;
ret = osal_dts_get_u32_byname(MCU_NODE, "ir_wakeup_enable", &ir_wakeup_enable);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
if (ir_wakeup_enable == 0)
return TD_SUCCESS;
ret = osal_dts_get_u32_byname(MCU_NODE, "ir_type", &ir_type);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
ret = osal_dts_get_u32_byname(MCU_NODE, "ir_wakeup_num", &ir_wakeup_num);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
ir_wakeup_num = (ir_wakeup_num > LPMCU_WAKEUP_IRKEY_MAXNUM) ? LPMCU_WAKEUP_IRKEY_MAXNUM : ir_wakeup_num;
lpmcu_vir_addr = (td_u32 *)(g_lpmcu_base + LPMCU_IR_SUSPEND_PARAM_ADDR / sizeof(td_u32));
tmp.val32 = 0;
tmp.val8[0] = ir_wakeup_enable;
tmp.val8[1] = ir_type;
tmp.val8[2] = ir_wakeup_num; /* 2: array offset value */
writel(tmp.val32, lpmcu_vir_addr++);
ret = pmoc_get_ir_message(lpmcu_vir_addr, ir_wakeup_num);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_get_ir_message, ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
#ifndef CONFIG_SOCT_COMMON_KERNEL
#ifndef CONFIG_SOCT_OH_KERNEL
static td_s32 pmoc_set_usb_custom_param(td_void)
{
td_s32 ret;
td_u32 usb_wakeup_enable = 0;
td_u32 *lpmcu_vir_addr = NULL;
u32_data tmp;
ret = osal_dts_get_u32_byname(MCU_NODE, "usb_wakeup_enable", &usb_wakeup_enable);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_USB_SUSPEND_PARAM_ADDR / sizeof(td_u32);
tmp.val32 = 0;
tmp.val8[0] = usb_wakeup_enable;
writel(tmp.val32, lpmcu_vir_addr);
return TD_SUCCESS;
}
#endif
#endif
static td_s32 pmoc_set_timeout_custom_param(td_void)
{
td_s32 ret;
td_u32 timeout_wakeup_enable = 0;
td_u32 timeout_wakeup_period = 0;
td_u32 *lpmcu_vir_addr = NULL;
u32_data tmp;
ret = osal_dts_get_u32_byname(MCU_NODE, "timeout_wakeup_enable", &timeout_wakeup_enable);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
if (timeout_wakeup_enable == 0)
return TD_SUCCESS;
lpmcu_vir_addr = g_lpmcu_base + LPMCU_TIMEOUT_SUSPEND_PARAM_ADDR / sizeof(td_u32);
tmp.val32 = 0;
tmp.val8[0] = timeout_wakeup_enable;
writel(tmp.val32, lpmcu_vir_addr);
ret = osal_dts_get_u32_byname(MCU_NODE, "timeout_wakeup_period", &timeout_wakeup_period);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_TIMEOUT_SUSPEND_TIME_ADDR / sizeof(td_u32);
writel(timeout_wakeup_period, lpmcu_vir_addr);
return TD_SUCCESS;
}
static td_s32 pmoc_set_lsadc_custom_param(td_void)
{
td_s32 ret;
td_s32 i;
td_u32 lsadc_wakeup_enable;
td_u32 lsadc_channel_mask;
td_u32 *lpmcu_vir_addr = NULL;
u32_data tmp;
td_u32 lsadc_high_value[LPMCU_LSADC_CHANNEL_NUM] = {0};
td_u32 lsadc_low_value[LPMCU_LSADC_CHANNEL_NUM] = {0};
ret = osal_dts_get_u32_byname(MCU_NODE, "lsadc_wakeup_enable", &lsadc_wakeup_enable);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
if (lsadc_wakeup_enable == 0)
return TD_SUCCESS;
ret = osal_dts_get_u32_byname(MCU_NODE, "lsadc_channel_mask", &lsadc_channel_mask);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
lpmcu_vir_addr = (td_u32 *)(g_lpmcu_base + LPMCU_LSADC_SUSPEND_PARAM_ADDR / sizeof(td_u32));
tmp.val32 = 0;
tmp.val8[0] = lsadc_wakeup_enable;
tmp.val8[1] = lsadc_channel_mask;
writel(tmp.val32, lpmcu_vir_addr++);
ret = osal_dts_get_array_byname(MCU_NODE, "lsadc_low_value", lsadc_low_value, LPMCU_LSADC_CHANNEL_NUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_array_byname(MCU_NODE, "lsadc_high_value", lsadc_high_value, LPMCU_LSADC_CHANNEL_NUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
for (i = 0; i < LPMCU_LSADC_CHANNEL_NUM; i++) {
tmp.val32 = 0;
tmp.val16[0] = lsadc_low_value[i];
tmp.val16[1] = lsadc_high_value[i];
writel(tmp.val32, lpmcu_vir_addr++);
}
return TD_SUCCESS;
}
static td_s32 pmoc_set_dbg_custom_param(td_void)
{
td_s32 ret;
td_u32 dbg_mask = 0;
td_u32 *lpmcu_vir_addr = NULL;
u32_data tmp;
ret = osal_dts_get_u32_byname(MCU_NODE, "dbg_mask", &dbg_mask);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_DBG_MASK_ADDR / sizeof(td_u32);
tmp.val32 = 0;
tmp.val8[1] = dbg_mask;
writel(tmp.val32, lpmcu_vir_addr);
return TD_SUCCESS;
}
#ifndef CONFIG_SOCT_COMMON_KERNEL
#ifndef CONFIG_SOCT_OH_KERNEL
static td_s32 pmoc_get_state_gpio_message(td_u32 *lpmcu_vir_addr, td_u32 gpio_state_num)
{
td_u32 i;
td_s32 ret;
u32_data tmp;
td_u32 gpio_state_group[LPMCU_STATE_GPIO_MAXNUM] = {0};
td_u32 gpio_state_bit[LPMCU_STATE_GPIO_MAXNUM] = {0};
pmoc_check_param_return_if(lpmcu_vir_addr == TD_NULL, TD_FAILURE);
pmoc_check_param_return_if(gpio_state_num > LPMCU_STATE_GPIO_MAXNUM, TD_FAILURE);
ret = osal_dts_get_array_byname(MCU_NODE, "gpio_state_group",
gpio_state_group, LPMCU_STATE_GPIO_MAXNUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_array_byname(MCU_NODE, "gpio_state_bit",
gpio_state_bit, LPMCU_STATE_GPIO_MAXNUM);
if (ret <= 0) {
soc_err_print_call_fun_err(osal_dts_get_array_byname, ret);
return TD_FAILURE;
}
for (i = 0; i < gpio_state_num; i++) {
tmp.val32 = 0;
tmp.val8[0] = gpio_state_group[i];
tmp.val8[1] = gpio_state_bit[i];
writel(tmp.val32, lpmcu_vir_addr++);
}
return TD_SUCCESS;
}
static td_s32 pmoc_set_suspend_state_param(td_void)
{
td_s32 ret;
u32_data tmp;
td_u32 gpio_state_enable = 0;
td_u32 gpio_state_num = 0;
td_u32 *lpmcu_vir_addr = NULL;
ret = osal_dts_get_u32_byname(MCU_NODE, "gpio_state_enable", &gpio_state_enable);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
ret = osal_dts_get_u32_byname(MCU_NODE, "gpio_state_num", &gpio_state_num);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return ret;
}
gpio_state_num = (gpio_state_num > LPMCU_STATE_GPIO_MAXNUM) ? LPMCU_STATE_GPIO_MAXNUM : gpio_state_num;
lpmcu_vir_addr = (td_u32 *)(g_lpmcu_base + LPMCU_MCU_SUSPEND_STATE_ADDR / sizeof(td_u32));
tmp.val32 = 0;
tmp.val8[0] = gpio_state_enable;
tmp.val8[1] = gpio_state_num;
writel(tmp.val32, lpmcu_vir_addr++);
ret = pmoc_get_state_gpio_message(lpmcu_vir_addr, gpio_state_num);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_get_state_gpio_message, ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
#endif
#endif
td_s32 pmoc_set_default_custom_param(td_void)
{
td_s32 ret;
soc_dbg_func_enter();
#ifdef CONFIG_SOCT_COMMON_KERNEL
ret = set_ddr_gpio_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(set_ddr_gpio_custom_param, ret);
return TD_FAILURE;
}
ret = pmoc_set_gpio_poweroff_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_gpio_poweroff_custom_param, ret);
return TD_FAILURE;
}
ret = pmoc_set_keyled_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_keyled_custom_param, ret);
return TD_FAILURE;
}
ret = pmoc_set_ir_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_ir_custom_param, ret);
return TD_FAILURE;
}
ret = pmoc_set_lsadc_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_lsadc_custom_param, ret);
return TD_FAILURE;
}
#endif
ret = pmoc_set_gpio_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_gpio_custom_param, ret);
return TD_FAILURE;
}
ret = pmoc_set_timeout_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_timeout_custom_param, ret);
return TD_FAILURE;
}
ret = pmoc_set_dbg_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_dbg_custom_param, ret);
return TD_FAILURE;
}
#ifndef CONFIG_SOCT_COMMON_KERNEL
#ifndef CONFIG_SOCT_OH_KERNEL
ret = pmoc_set_usb_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_usb_custom_param, ret);
return TD_FAILURE;
}
ret = pmoc_get_s3_s4_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_get_s3_s4_param, ret);
return TD_FAILURE;
}
ret = pmoc_set_suspend_state_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_suspend_state_param, ret);
return TD_FAILURE;
}
#endif
#endif
soc_dbg_func_exit();
return TD_SUCCESS;
}
static td_s32 pmoc_load_standby_param(td_void)
{
td_s32 ret;
u32_data tmp;
td_u32 *lpmcu_vir_addr = TD_NULL;
ext_chip_name_id chip_name_id;
ext_chip_revision chip_revision;
td_u32 board_id = 0;
soc_dbg_func_enter();
ret = ext_drv_sys_get_chip_name_id(&chip_name_id);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_drv_sys_get_chip_name_id, ret);
return TD_FAILURE;
}
ret = ext_drv_sys_get_chip_revision(&chip_revision);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_drv_sys_get_chip_revision, ret);
return TD_FAILURE;
}
ret = ext_drv_sys_get_board_id(&board_id);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_drv_sys_get_board_id, ret);
return TD_FAILURE;
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_CHIP_NAME_ID_ADDR / sizeof(td_u32);
writel(chip_name_id, lpmcu_vir_addr);
lpmcu_vir_addr = g_lpmcu_base + LPMCU_CHIP_REVERSION_ADDR / sizeof(td_u32);
tmp.val32 = 0;
tmp.val16[0] = chip_revision;
tmp.val16[1] = (td_u16)board_id;
writel(tmp.val32, lpmcu_vir_addr);
lpmcu_vir_addr = g_lpmcu_base + LPMCU_GPIO_AON_GROUP_ADDR / sizeof(td_u32);
tmp.val32 = 0;
tmp.val8[0] = (td_u8)g_dts_info.gpio_aon_group_max;
tmp.val8[1] = (td_u8)g_dts_info.gpio_aon_group_min;
writel(tmp.val32, lpmcu_vir_addr);
lpmcu_vir_addr = g_lpmcu_base + LPMCU_REG_MUTE_ADDR / sizeof(td_u32);
writel(g_dts_info.reg_mute_addr, lpmcu_vir_addr);
lpmcu_vir_addr = g_lpmcu_base + LPMCU_MUTE_WAKEUP_ENABLE_VALUE / sizeof(td_u32);
writel(g_dts_info.mute_wakeup_enable, lpmcu_vir_addr);
lpmcu_vir_addr = g_lpmcu_base + LPMCU_MUTE_WAKEUP_DISABLE_VALUE / sizeof(td_u32);
writel(g_dts_info.mute_wakeup_disable, lpmcu_vir_addr);
#if defined(CONFIG_RESERVED13) || defined(CONFIG_RESERVED9)
lpmcu_vir_addr = g_lpmcu_base + LPMCU_PRODUCT_FLAG_ADDR / sizeof(td_u32);
writel(g_dts_info.product_flag, lpmcu_vir_addr);
#endif
ret = pmoc_set_default_custom_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_set_default_custom_param, ret);
return TD_FAILURE;
}
soc_dbg_func_exit();
return TD_SUCCESS;
}
td_s32 pmoc_load_lpmcu(td_void)
{
td_u32 i;
td_s32 ret;
td_u32 *lpmcu_vir_addr = TD_NULL;
soc_dbg_func_enter();
ret = pmoc_try_loading_firmware();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_try_loading_firmware, ret);
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_STANDBY_DATA_ADDR / sizeof(td_u32);
for (i = 0; i < LPMCU_STANDBY_DATA_SIZE / sizeof(td_u32); i++) {
writel(0, lpmcu_vir_addr++);
}
lpmcu_vir_addr = g_lpmcu_base + LPMCU_LOG_FLAG_ADDR / sizeof(td_u32);
if (readl(lpmcu_vir_addr) != LPMCU_LOG_WRITE_FLAG) {
for (i = 0; i < (LPMCU_LOG_TOTLE_SIZE >> 2); i++) { /* right shift 2 means from byte to word */
writel(0, lpmcu_vir_addr++);
}
}
ret = pmoc_load_standby_param();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pmoc_load_standby_param, ret);
goto exit;
}
soc_dbg_func_exit();
return TD_SUCCESS;
exit:
if (g_pmoc_thread != TD_NULL) {
osal_kthread_destroy(g_pmoc_thread, 1);
g_pmoc_thread = TD_NULL;
}
return TD_FAILURE;
}
td_void pmoc_unload_lpmcu(td_void)
{
if (g_pmoc_thread != TD_NULL) {
osal_kthread_destroy(g_pmoc_thread, 1);
g_pmoc_thread = TD_NULL;
}
return;
}
td_s32 pmoc_sem_init(td_void)
{
td_s32 ret;
ret = osal_sem_init(&g_pmoc_sem, 1);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_sem_init, ret);
return ret;
}
return TD_SUCCESS;
}
td_void pmoc_sem_deinit(td_void)
{
osal_sem_destroy(&g_pmoc_sem);
return;
}
td_s32 pmoc_register_remap(td_void)
{
g_lpmcu_base = osal_ioremap_nocache(LPMCU_RAM_BASE, LPMCU_SIZE);
if (g_lpmcu_base == TD_NULL) {
soc_err_print_call_fun_err(osal_ioremap_nocache, TD_FAILURE);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_void pmoc_register_unmap(td_void)
{
osal_iounmap(g_lpmcu_base, LPMCU_SIZE);
return;
}
td_s32 pmoc_dts_read(td_void)
{
td_s32 ret;
ret = osal_dts_get_u32_byname("huanglong,pmoc", "pmoc_gpio_aon_group_min", &g_dts_info.gpio_aon_group_min);
if (ret < 0) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_u32_byname("huanglong,pmoc", "pmoc_gpio_aon_group_max", &g_dts_info.gpio_aon_group_max);
if (ret < 0) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_u32_byname("huanglong,pmoc", "reg_mute", &g_dts_info.reg_mute_addr);
if (ret < 0) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_u32_byname("huanglong,pmoc", "mute_wakeup_enable", &g_dts_info.mute_wakeup_enable);
if (ret < 0) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return TD_FAILURE;
}
ret = osal_dts_get_u32_byname("huanglong,pmoc", "mute_wakeup_disable", &g_dts_info.mute_wakeup_disable);
if (ret < 0) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return TD_FAILURE;
}
#if defined(CONFIG_RESERVED13) || defined(CONFIG_RESERVED9)
ret = osal_dts_get_u32_byname("huanglong,pmoc", "product_flag", &g_dts_info.product_flag);
if (ret < 0) {
soc_err_print_call_fun_err(osal_dts_get_u32_byname, ret);
return TD_FAILURE;
}
#endif
return TD_SUCCESS;
}
td_s32 pmoc_get_dts_data(pmoc_dts_info *info)
{
pmoc_check_param_return_if(info == TD_NULL, TD_FAILURE);
*info = g_dts_info;
return TD_SUCCESS;
}