341 lines
7.3 KiB
C
341 lines
7.3 KiB
C
/*
|
|
* Copyright (c) XMEDIA. All rights reserved.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
|
|
#include "common.h"
|
|
#include "xmedia_debug.h"
|
|
#include "xmedia_errcode.h"
|
|
#include "xmedia_pm.h"
|
|
|
|
#include "pm_aux.h"
|
|
#include "pm_ddr.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
#define PM_USR_TRACE(level, fmt, ...) \
|
|
do { \
|
|
MODULE_TRACE(level, MOD_ID_PM, "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
|
} while (0)
|
|
|
|
#define XMEDIA_PM_INIT _IO('n', CMD_PM_INIT)
|
|
#define XMEDIA_PM_DEINIT _IO('n', CMD_PM_DEINIT)
|
|
#define XMEDIA_PM_GET_WAKEUP_SOURCE _IOWR('n', CMD_PM_GET_WK_SOURCE, xmedia_pm_wakeup_source)
|
|
#define XMEDIA_PM_GET_ATTR _IOWR('n', CMD_PM_GET_ALL_ATTR, xmedia_pm_attr)
|
|
#define XMEDIA_PM_SET_ATTR _IOWR('n', CMD_PM_SET_ALL_ATTR, xmedia_pm_attr)
|
|
#define XMEDIA_PM_SET_AUX _IOWR('n', CMD_PM_SET_AUX, struct aux_mem)
|
|
#define XMEDIA_PM_GET_DDR_PARAM _IOR('n', CMD_PM_GET_DDR_PARAM, struct lpds_param)
|
|
#define XMEDIA_PM_GET_WAKEUP_INFO _IOWR('n', CMD_PM_GET_WK_INFO, xmedia_pm_wakeup_info)
|
|
#define XMEDIA_PM_GET_RTC_INFO _IOR('n', CMD_PM_GET_RTC_INFO, xmedia_pm_rtc_info)
|
|
|
|
typedef enum {
|
|
CMD_PM_INIT = 0,
|
|
CMD_PM_DEINIT,
|
|
CMD_PM_SET_ALL_ATTR,
|
|
CMD_PM_GET_ALL_ATTR,
|
|
CMD_PM_GET_RTC_ATTR,
|
|
CMD_PM_SET_RTC_ATTR,
|
|
CMD_PM_GET_WK_ATTR,
|
|
CMD_PM_SET_WK_ATTR,
|
|
CMD_PM_GET_WK_SOURCE,
|
|
CMD_PM_SET_AUX,
|
|
CMD_PM_GET_DDR_PARAM,
|
|
CMD_PM_GET_RTC_INFO,
|
|
CMD_PM_GET_WK_INFO,
|
|
CMD_PM_END = 0xFFFF,
|
|
} xmedia_pm_ioctl_cmd;
|
|
|
|
static xmedia_s32 g_pm_mod_fd = -1;
|
|
static xmedia_s32 g_suspend_fd = -1;
|
|
|
|
static pthread_mutex_t g_pm_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
static bool g_pm_init = XMEDIA_FALSE;
|
|
|
|
#define PM_MUTEX_LOCK() \
|
|
do { \
|
|
(void)pthread_mutex_lock(&g_pm_mutex); \
|
|
} while (0)
|
|
|
|
#define PM_MUTEX_UNLOCK() \
|
|
do { \
|
|
(void)pthread_mutex_unlock(&g_pm_mutex); \
|
|
} while (0)
|
|
|
|
#define PM_CHECK_INIT_RETURN() \
|
|
do { \
|
|
PM_MUTEX_LOCK(); \
|
|
if (g_pm_init != XMEDIA_TRUE) { \
|
|
PM_USR_TRACE(MODULE_DBG_ERR, "pm not init!\n"); \
|
|
PM_MUTEX_UNLOCK(); \
|
|
return XMEDIA_ERRCODE_NOT_INIT; \
|
|
} \
|
|
PM_MUTEX_UNLOCK(); \
|
|
} while (0)
|
|
|
|
xmedia_s32 xmedia_pm_init(xmedia_void)
|
|
{
|
|
xmedia_pm_init_param param;
|
|
|
|
param.type = PM_INIT_TYPE_NORMAL;
|
|
return xmedia_pm_init_ext(¶m);
|
|
}
|
|
|
|
xmedia_s32 xmedia_pm_init_ext(xmedia_pm_init_param *param)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
struct aux_mem aux;
|
|
|
|
if (param == NULL)
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
|
|
if (param->type >= PM_INIT_TYPE_MAX)
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
|
|
if (g_pm_init == XMEDIA_TRUE)
|
|
return XMEDIA_ERRCODE_BUSY;
|
|
|
|
if ((!is_ram_off_str()) && (param->type == PM_INIT_TYPE_STR)) {
|
|
if (read_aux_to_ddr(&aux) != XMEDIA_SUCCESS)
|
|
return XMEDIA_ERRCODE_NOT_READY;
|
|
}
|
|
|
|
PM_MUTEX_LOCK();
|
|
|
|
if (param->type == PM_INIT_TYPE_STR) {
|
|
if (g_suspend_fd < 0) {
|
|
g_suspend_fd = open("/sys/power/state", O_RDWR | O_SYNC);
|
|
if (g_suspend_fd < 0) {
|
|
PM_USR_TRACE(MODULE_DBG_ERR, "open /dev/power/state err, ret:%d \n", g_suspend_fd);
|
|
ret = XMEDIA_ERRCODE_OPEN_FAILED;
|
|
goto UNLOCK;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (g_pm_mod_fd < 0) {
|
|
g_pm_mod_fd = open("/dev/pm", O_RDONLY);
|
|
if (g_pm_mod_fd < 0) {
|
|
PM_USR_TRACE(MODULE_DBG_ERR, "open /dev/pm err, ret:%d \n", g_pm_mod_fd);
|
|
ret = XMEDIA_ERRCODE_OPEN_FAILED;
|
|
goto UNLOCK;
|
|
}
|
|
|
|
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_INIT, NULL, NULL);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
PM_USR_TRACE(MODULE_DBG_ERR, "drv pm init err\n");
|
|
goto UNLOCK;
|
|
}
|
|
|
|
if ((!is_ram_off_str()) && (param->type == PM_INIT_TYPE_STR)) {
|
|
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_SET_AUX, &aux, NULL);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
ioctl(g_pm_mod_fd, XMEDIA_PM_DEINIT, NULL, NULL);
|
|
PM_USR_TRACE(MODULE_DBG_ERR, "drv set aux err\n");
|
|
goto UNLOCK;
|
|
}
|
|
}
|
|
}
|
|
|
|
g_pm_init = XMEDIA_TRUE;
|
|
|
|
UNLOCK:
|
|
PM_MUTEX_UNLOCK();
|
|
|
|
if (is_ram_off_str() && (param->type == PM_INIT_TYPE_STR)) {
|
|
|
|
if (ret == XMEDIA_SUCCESS) {
|
|
|
|
ret = ddr_param_check_and_save();
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
PM_USR_TRACE(MODULE_DBG_ERR, "ddr param check/save err ret=%d\n", ret);
|
|
PM_MUTEX_LOCK();
|
|
g_pm_init = XMEDIA_FALSE;
|
|
PM_MUTEX_UNLOCK();
|
|
}
|
|
}
|
|
} else {
|
|
if (ret != XMEDIA_SUCCESS)
|
|
aux_free_mem();
|
|
}
|
|
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
|
|
PM_MUTEX_LOCK();
|
|
if (g_suspend_fd >= 0) {
|
|
close(g_suspend_fd);
|
|
g_suspend_fd = -1;
|
|
}
|
|
|
|
if (g_pm_mod_fd >= 0) {
|
|
close(g_pm_mod_fd);
|
|
g_pm_mod_fd = -1;
|
|
}
|
|
PM_MUTEX_UNLOCK();
|
|
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
xmedia_s32 xmedia_pm_deinit(xmedia_void)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
|
|
PM_CHECK_INIT_RETURN();
|
|
|
|
PM_MUTEX_LOCK();
|
|
|
|
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_DEINIT, NULL, NULL);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
goto UNLOCK;
|
|
}
|
|
|
|
close(g_pm_mod_fd);
|
|
g_pm_mod_fd = -1;
|
|
|
|
close(g_suspend_fd);
|
|
g_suspend_fd = -1;
|
|
|
|
g_pm_init = XMEDIA_FALSE;
|
|
|
|
UNLOCK:
|
|
PM_MUTEX_UNLOCK();
|
|
|
|
if (!is_ram_off_str()) {
|
|
aux_free_mem();
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
xmedia_s32 xmedia_pm_get_wakeup_source(xmedia_pm_wakeup_source *source)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
|
|
PM_CHECK_INIT_RETURN();
|
|
PM_MUTEX_LOCK();
|
|
|
|
if (source == XMEDIA_NULL) {
|
|
PM_MUTEX_UNLOCK();
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_WAKEUP_SOURCE, (unsigned int)source, NULL);
|
|
|
|
PM_MUTEX_UNLOCK();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
xmedia_s32 xmedia_pm_get_attr(xmedia_pm_attr *attr)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
|
|
PM_CHECK_INIT_RETURN();
|
|
PM_MUTEX_LOCK();
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_MUTEX_UNLOCK();
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_ATTR, (unsigned int)attr, NULL);
|
|
|
|
PM_MUTEX_UNLOCK();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
xmedia_s32 xmedia_pm_set_attr(xmedia_pm_attr *attr)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_FAILURE;
|
|
|
|
PM_CHECK_INIT_RETURN();
|
|
PM_MUTEX_LOCK();
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_MUTEX_UNLOCK();
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_SET_ATTR, (unsigned int)attr, NULL);
|
|
|
|
PM_MUTEX_UNLOCK();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
xmedia_s32 xmedia_pm_get_ddr_param(struct lpds_param *p_lpds_param)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_FAILURE;
|
|
|
|
PM_CHECK_INIT_RETURN();
|
|
PM_MUTEX_LOCK();
|
|
|
|
if (p_lpds_param == XMEDIA_NULL) {
|
|
PM_MUTEX_UNLOCK();
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_DDR_PARAM, (unsigned int)p_lpds_param, NULL);
|
|
|
|
PM_MUTEX_UNLOCK();
|
|
|
|
return ret;
|
|
}
|
|
|
|
xmedia_s32 xmedia_pm_suspend(xmedia_void)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_FAILURE;
|
|
xmedia_char suspend_str[] = "mem";
|
|
|
|
PM_CHECK_INIT_RETURN();
|
|
PM_MUTEX_LOCK();
|
|
|
|
if (g_suspend_fd >= 0) {
|
|
if (write(g_suspend_fd, suspend_str, strlen(suspend_str)) == strlen(suspend_str)) {
|
|
ret = XMEDIA_SUCCESS;
|
|
} else {
|
|
ret = XMEDIA_ERRCODE_COPY_DATA_ERROR;
|
|
}
|
|
}
|
|
|
|
PM_MUTEX_UNLOCK();
|
|
return ret;
|
|
}
|
|
|
|
xmedia_s32 xmedia_pm_get_rtc_info(xmedia_pm_rtc_info *rtc_info)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
|
|
PM_CHECK_INIT_RETURN();
|
|
PM_MUTEX_LOCK();
|
|
|
|
if (rtc_info == XMEDIA_NULL) {
|
|
PM_MUTEX_UNLOCK();
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_RTC_INFO, (unsigned int)rtc_info, NULL);
|
|
|
|
PM_MUTEX_UNLOCK();
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|