/* * 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 #include #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(¶m, 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(¶m.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(¶m, 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; }