633 lines
18 KiB
C
633 lines
18 KiB
C
#include "pmoc_comm.h"
|
|
#include "drv_pmc.h"
|
|
#include <linux/rtc.h>
|
|
#include "xmedia_errcode.h"
|
|
#include "mmz.h"
|
|
|
|
extern int lotus_rtc_aov_read_time(struct device *dev, struct rtc_time *time, unsigned char *ms_count);
|
|
extern int lotus_rtc_aov_set_alarm_time(struct device *dev, unsigned int alarm_time, unsigned char alarm_enable);
|
|
extern int pm_set_aux_src(void __iomem *aux_src, unsigned long size);
|
|
extern int lotus_rtc_aov_get_resume_time(struct device *dev, struct rtc_time *time, unsigned char *ms_count);
|
|
extern int lotus_rtc_aov_get_suspend_time(struct device *dev, struct rtc_time *time, unsigned char *ms);
|
|
extern int lotus_rtc_aov_get_current_time(struct device *dev, struct rtc_time *time, unsigned char *ms);
|
|
|
|
static xmedia_void *virt_pwr_base_addr = XMEDIA_NULL;
|
|
#ifdef CONFIG_PM
|
|
static xmedia_void *virt_aux_store_addr = XMEDIA_NULL;
|
|
#endif
|
|
struct mutex pmc_mutex;
|
|
|
|
xmedia_s32 lotus_pmc_init(xmedia_void)
|
|
{
|
|
virt_pwr_base_addr = osal_ioremap(PWR_BASE_ADDR, 0x40);
|
|
if (virt_pwr_base_addr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "lotus_pmc_init ioremap err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
mutex_init(&pmc_mutex);
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 lotus_pmc_set_aux(struct aux_mem *aux)
|
|
{
|
|
#ifdef CONFIG_PM
|
|
if (virt_aux_store_addr != XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "%s aux is exist!\n", __func__);
|
|
return XMEDIA_ERRCODE_EXIST;
|
|
}
|
|
|
|
virt_aux_store_addr = mmz_map(aux->phy_addr, aux->size, 0);
|
|
if (virt_aux_store_addr == NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "%s addr 0x%llx mmap error!\n", __func__, aux->phy_addr);
|
|
return XMEDIA_ERRCODE_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
pm_set_aux_src(virt_aux_store_addr, aux->size);
|
|
|
|
return XMEDIA_SUCCESS;
|
|
#else
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
#endif
|
|
}
|
|
|
|
xmedia_void lotus_pmc_deinit(xmedia_void)
|
|
{
|
|
if (virt_pwr_base_addr != XMEDIA_NULL) {
|
|
osal_iounmap(virt_pwr_base_addr);
|
|
virt_pwr_base_addr = XMEDIA_NULL;
|
|
}
|
|
|
|
#ifdef CONFIG_PM
|
|
if (virt_aux_store_addr != XMEDIA_NULL) {
|
|
mmz_unmap(virt_aux_store_addr);
|
|
pm_set_aux_src(0, 0);
|
|
virt_aux_store_addr = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
xmedia_s32 lotus_get_wakeup_type(lotus_pmc_wakeup_type *type)
|
|
{
|
|
xmedia_u32 status;
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
|
|
if (virt_pwr_base_addr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "pmc not init err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
|
|
if (type == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "set_wakeup_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
|
|
status = osal_readl(virt_pwr_base_addr + PMR_STATUS_OFFSET);
|
|
status &= PWR_STATUS_WAKEUP_SOURCE;
|
|
status >>= 2;
|
|
switch (status) {
|
|
case 1:
|
|
*type = PMC_SRC_WAKEUP;
|
|
break;
|
|
case 4:
|
|
*type = PMC_SRC_STARTUP;
|
|
break;
|
|
case 8:
|
|
*type = PMC_SRC_BUTTON;
|
|
break;
|
|
case 16:
|
|
*type = PMC_SRC_RTC;
|
|
break;
|
|
default:
|
|
*type = PMC_SRC_MAX;
|
|
ret = XMEDIA_FAILURE;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifdef PM_WAKEUP1_SUPPORT
|
|
xmedia_s32 lotus_pm_get_wakeup_info(lotus_pm_wakeup_info *info)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
xmedia_u32 status;
|
|
xmedia_u32 wakeup0_crtl, wakeup1_crtl;
|
|
|
|
ret = lotus_get_wakeup_type(&info->type);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (info->type == PMC_SRC_WAKEUP) {
|
|
|
|
wakeup0_crtl = osal_readl(virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
wakeup1_crtl = osal_readl(virt_pwr_base_addr + PWR_WAKEUP1_CRTL_OFFSET);
|
|
|
|
/* wakeup0 and wakeup1 is both enable */
|
|
if (((wakeup0_crtl & PWR_WAKEUPN_IOSHARE) == 0) && ((wakeup1_crtl & PWR_WAKEUPN_IOSHARE) == 0)) {
|
|
status = osal_readl(virt_pwr_base_addr + PWR_STATUS_BACKUP_OFFSET);
|
|
|
|
if (status & WAKEUP_STATUS_GPIO0_MASK)
|
|
info->detail = 0;
|
|
else if (status & WAKEUP_STATUS_GPIO1_MASK)
|
|
info->detail = 1;
|
|
else {
|
|
info->detail = 0;
|
|
PM_TRACE(MODULE_DBG_ERR, "wakeup int happened, but do not find gpio wakeup status!\n");
|
|
ret = XMEDIA_FAILURE;
|
|
}
|
|
|
|
/* wakeup1 is only enabled */
|
|
} else if ((wakeup1_crtl & PWR_WAKEUPN_IOSHARE) == 0) {
|
|
info->detail = 1;
|
|
} else if ((wakeup0_crtl & PWR_WAKEUPN_IOSHARE) == 0) {
|
|
info->detail = 0;
|
|
} else {
|
|
info->detail = 0;
|
|
PM_TRACE(MODULE_DBG_ERR, "wakeup int happened, but do not find gpio wakeup config!\n");
|
|
ret = XMEDIA_ERRCODE_NOT_CONFIG;
|
|
}
|
|
} else {
|
|
info->detail = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static xmedia_s32 lotus_config_wakeup_gpio(lotus_pmc_all_attr *attr)
|
|
{
|
|
xmedia_u32 value;
|
|
|
|
if (attr->wakeup_attr.wakeup_enable && attr->wakeup_ext_attr_arry[0].wakeup_enable) {
|
|
if (attr->wakeup_attr.wakeup_polarity != PMC_PWR_HIGH_LEVEL || attr->wakeup_ext_attr_arry[0].wakeup_polarity != PMC_PWR_HIGH_LEVEL)
|
|
return XMEDIA_ERRCODE_NOT_SUPPORT;
|
|
}
|
|
|
|
if (!attr->wakeup_attr.wakeup_enable) {
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
value |= PWR_WAKEUPN_IOSHARE;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
|
|
} else if (attr->wakeup_attr.wakeup_polarity == PMC_PWR_HIGH_LEVEL ||
|
|
attr->wakeup_attr.wakeup_polarity == PMC_PWR_RISING_EDGE) {
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
|
|
value &= ~PWR_WAKEUPN_IOSHARE;
|
|
/* pull down */
|
|
value |= PWR_WAKEUP_PD;
|
|
/* do not pull up */
|
|
value &= ~PWR_WAKEUP_PU;
|
|
|
|
/* driver strength level2 */
|
|
value &= ~PWR_WAKEUP_DS_MASK;
|
|
value |= PWR_WAKEUP_DS_2;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
} else {
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
|
|
value &= ~PWR_WAKEUPN_IOSHARE;
|
|
/* do not pull down */
|
|
value &= ~PWR_WAKEUP_PD;
|
|
/* pull up */
|
|
value |= PWR_WAKEUP_PU;
|
|
|
|
/* driver strength level2 */
|
|
value &= ~PWR_WAKEUP_DS_MASK;
|
|
value |= PWR_WAKEUP_DS_2;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
}
|
|
|
|
if (!attr->wakeup_ext_attr_arry[0].wakeup_enable) {
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP1_CRTL_OFFSET);
|
|
value |= PWR_WAKEUPN_IOSHARE;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP1_CRTL_OFFSET);
|
|
|
|
} else if (attr->wakeup_ext_attr_arry[0].wakeup_polarity == PMC_PWR_HIGH_LEVEL ||
|
|
attr->wakeup_ext_attr_arry[0].wakeup_polarity == PMC_PWR_RISING_EDGE) {
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP1_CRTL_OFFSET);
|
|
|
|
value &= ~PWR_WAKEUPN_IOSHARE;
|
|
/* pull down */
|
|
value |= PWR_WAKEUP_PD;
|
|
/* do not pull up */
|
|
value &= ~PWR_WAKEUP_PU;
|
|
|
|
/* driver strength level2 */
|
|
value &= ~PWR_WAKEUP_DS_MASK;
|
|
value |= PWR_WAKEUP_DS_2;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP1_CRTL_OFFSET);
|
|
} else {
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP1_CRTL_OFFSET);
|
|
|
|
value &= ~PWR_WAKEUPN_IOSHARE;
|
|
/* do not pull down */
|
|
value &= ~PWR_WAKEUP_PD;
|
|
/* pull up */
|
|
value |= PWR_WAKEUP_PU;
|
|
|
|
/* driver strength level2 */
|
|
value &= ~PWR_WAKEUP_DS_MASK;
|
|
value |= PWR_WAKEUP_DS_2;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP1_CRTL_OFFSET);
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
#else
|
|
static xmedia_s32 lotus_config_wakeup_gpio(lotus_pmc_all_attr *attr)
|
|
{
|
|
xmedia_u32 value;
|
|
|
|
if (!attr->wakeup_attr.wakeup_enable) {
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
value |= PWR_WAKEUPN_IOSHARE;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
|
|
} else if (attr->wakeup_attr.wakeup_polarity == PMC_PWR_HIGH_LEVEL ||
|
|
attr->wakeup_attr.wakeup_polarity == PMC_PWR_RISING_EDGE) {
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
|
|
value &= ~PWR_WAKEUPN_IOSHARE;
|
|
/* pull down */
|
|
value |= PWR_WAKEUP_PD;
|
|
/* do not pull up */
|
|
value &= ~PWR_WAKEUP_PU;
|
|
|
|
/* driver strength level2 */
|
|
value &= ~PWR_WAKEUP_DS_MASK;
|
|
value |= PWR_WAKEUP_DS_2;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
} else {
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
|
|
value &= ~PWR_WAKEUPN_IOSHARE;
|
|
/* do not pull down */
|
|
value &= ~PWR_WAKEUP_PD;
|
|
/* pull up */
|
|
value |= PWR_WAKEUP_PU;
|
|
|
|
/* driver strength level2 */
|
|
value &= ~PWR_WAKEUP_DS_MASK;
|
|
value |= PWR_WAKEUP_DS_2;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP_CRTL_OFFSET);
|
|
}
|
|
|
|
value = osal_readl(virt_pwr_base_addr + PWR_WAKEUP1_CRTL_OFFSET);
|
|
value |= PWR_WAKEUPN_IOSHARE;
|
|
osal_writel(value, virt_pwr_base_addr + PWR_WAKEUP1_CRTL_OFFSET);
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
#endif
|
|
xmedia_s32 lotus_set_all_attr(lotus_pmc_all_attr *attr)
|
|
{
|
|
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
|
|
if (virt_pwr_base_addr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "pmc not init err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "set_wakeup_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
|
|
ret = lotus_config_wakeup_gpio(attr);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
#ifdef PM_WAKEUP1_SUPPORT
|
|
if ((!attr->wakeup_attr.wakeup_enable) && attr->wakeup_ext_attr_arry[0].wakeup_enable)
|
|
ret = lotus_set_wakeup_attr(&(attr->wakeup_ext_attr_arry[0]));
|
|
else
|
|
ret = lotus_set_wakeup_attr(&(attr->wakeup_attr));
|
|
#else
|
|
ret = lotus_set_wakeup_attr(&(attr->wakeup_attr));
|
|
#endif
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
ret = lotus_set_button_attr(&(attr->button_attr));
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
ret = lotus_set_rtc_attr(&(attr->rtc_attr));
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
|
|
}
|
|
|
|
xmedia_s32 lotus_get_all_attr(lotus_pmc_all_attr *attr)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
|
|
if (virt_pwr_base_addr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "pmc not init err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "set_wakeup_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
|
|
attr->startup_enable = 1;
|
|
attr->button_enable = 1;
|
|
|
|
ret = lotus_get_wakeup_attr(&(attr->wakeup_attr));
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
ret = lotus_get_button_attr(&(attr->button_attr));
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
ret = lotus_get_rtc_attr(&(attr->rtc_attr));
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
|
|
}
|
|
|
|
xmedia_s32 lotus_set_wakeup_attr(lotus_pmc_wakeup_attr *attr)
|
|
{
|
|
xmedia_u32 status;
|
|
|
|
if (virt_pwr_base_addr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "set_Wakeup_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "set_Wakeup_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
|
|
mutex_lock(&pmc_mutex);
|
|
status = osal_readl(virt_pwr_base_addr + PWR_CTRL0_OFFSET);
|
|
status &= ~PWR_POWER_UNMASK;
|
|
if (attr->wakeup_enable == 1) {
|
|
osal_writel(status & ~PWR_WAKEUP_MASK, (virt_pwr_base_addr + PWR_CTRL0_OFFSET));
|
|
} else {
|
|
osal_writel(status | PWR_WAKEUP_MASK, (virt_pwr_base_addr + PWR_CTRL0_OFFSET));
|
|
}
|
|
|
|
if (attr->wakeup_polarity < PMC_PWR_MAX) {
|
|
status = osal_readl(virt_pwr_base_addr + PWR_CTRL0_OFFSET);
|
|
status &= ~PWR_WAKEUP_POLARITY;
|
|
status |= (attr->wakeup_polarity << 3);
|
|
osal_writel(status, (virt_pwr_base_addr + PWR_CTRL0_OFFSET));
|
|
} else {
|
|
mutex_unlock(&pmc_mutex);
|
|
PM_TRACE(MODULE_DBG_ERR, "set_Wakeup_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
|
|
mutex_unlock(&pmc_mutex);
|
|
PM_TRACE(MODULE_DBG_INFO, "set_wakeup_attr success!\n");
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 lotus_get_wakeup_attr(lotus_pmc_wakeup_attr *attr)
|
|
{
|
|
xmedia_u32 status;
|
|
|
|
if (virt_pwr_base_addr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "pmc not init err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "get_wakeup_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
|
|
status = osal_readl(virt_pwr_base_addr + PWR_CTRL0_OFFSET);
|
|
status &=~ PWR_POWER_UNMASK;
|
|
|
|
attr->wakeup_enable = !((status & PWR_WAKEUP_MASK) >> 6);
|
|
attr->wakeup_polarity = (status & PWR_WAKEUP_POLARITY) >> 3;
|
|
|
|
PM_TRACE(MODULE_DBG_INFO, "get_wakeup_attr success!\n");
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 lotus_set_button_attr(lotus_pmc_button_attr *attr)
|
|
{
|
|
xmedia_u32 status;
|
|
|
|
if (virt_pwr_base_addr ==XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "set_button_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "set_button_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
|
|
mutex_lock(&pmc_mutex);
|
|
status = osal_readl(virt_pwr_base_addr + PWR_CTRL0_OFFSET);
|
|
status &=~ PWR_POWER_UNMASK;
|
|
if (attr->button_adj_enable == 1) {
|
|
osal_writel(status &~ PWR_BUTTON_ADJ_MASK, (virt_pwr_base_addr + PWR_CTRL0_OFFSET));
|
|
if (attr->button_adj_time <= PWR_BUTTON_ADJ_TIME_MAX) {
|
|
status = osal_readl(virt_pwr_base_addr + PWR_CTRL0_OFFSET);
|
|
status &=~ PWR_POWER_UNMASK;
|
|
status &=~ PWR_BUTTON_ADJ_TIME_MASK;
|
|
status |= (attr->button_adj_time << PWR_BUTTON_ADJ_TIME_SHIFT);
|
|
osal_writel(status, (virt_pwr_base_addr + PWR_CTRL0_OFFSET));
|
|
} else {
|
|
mutex_unlock(&pmc_mutex);
|
|
PM_TRACE(MODULE_DBG_ERR, "set_button_adjust_time parameter err!\n");
|
|
return XMEDIA_ERRCODE_INVALID_PARAM;
|
|
}
|
|
} else {
|
|
osal_writel(status | PWR_BUTTON_ADJ_MASK, (virt_pwr_base_addr + PWR_CTRL0_OFFSET));
|
|
}
|
|
|
|
mutex_unlock(&pmc_mutex);
|
|
PM_TRACE(MODULE_DBG_INFO, "set_button_adjust_time success!\n");
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 lotus_get_button_attr(lotus_pmc_button_attr *attr)
|
|
{
|
|
xmedia_u32 status;
|
|
|
|
if (virt_pwr_base_addr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "pmc not init err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "get_button_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
|
|
status = osal_readl(virt_pwr_base_addr + PWR_CTRL0_OFFSET);
|
|
status &=~ PWR_POWER_UNMASK;
|
|
|
|
attr->button_adj_enable = !((status & PWR_BUTTON_ADJ_MASK) >> PWR_BUTTON_ADJ_MASK_SHIFT);
|
|
attr->button_adj_time = (status & PWR_BUTTON_ADJ_TIME_MASK) >> PWR_BUTTON_ADJ_TIME_SHIFT;
|
|
|
|
PM_TRACE(MODULE_DBG_INFO, "get_button_adjust_time success!\n");
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 lotus_set_rtc_attr(lotus_pmc_rtc_attr *attr)
|
|
{
|
|
xmedia_u32 status;
|
|
struct rtc_device *dev;
|
|
struct rtc_wkalrm alarm = {0};
|
|
xmedia_u32 ret;
|
|
|
|
if (virt_pwr_base_addr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "pmc not init err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "set_wakeup_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
|
|
status = osal_readl(virt_pwr_base_addr + PWR_CTRL0_OFFSET);
|
|
status &=~ PWR_POWER_UNMASK;
|
|
|
|
if (attr->rtc_enable == 1) {
|
|
osal_writel(status & ~PWR_RTC_MASK, (virt_pwr_base_addr + PWR_CTRL0_OFFSET));
|
|
|
|
dev = rtc_class_open("rtc0");
|
|
if (dev == XMEDIA_NULL) {
|
|
goto rtc_failure;
|
|
}
|
|
ret = rtc_read_alarm(dev, &alarm);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
goto rtc_failure;
|
|
}
|
|
PM_TRACE(MODULE_DBG_DEBUG, "rtc_read_alarm start: %d-%d-%d-%d-%d-%d, %d-%d-%d\n", alarm.time.tm_year, \
|
|
alarm.time.tm_mon, alarm.time.tm_mday, alarm.time.tm_hour, alarm.time.tm_min, alarm.time.tm_sec, alarm.time.tm_year, alarm.time.tm_yday, alarm.time.tm_isdst);
|
|
|
|
lotus_rtc_aov_set_alarm_time(dev->dev.parent, attr->rtc_timeout, 1);
|
|
rtc_class_close(dev);
|
|
} else {
|
|
osal_writel(status | PWR_RTC_MASK, (virt_pwr_base_addr + PWR_CTRL0_OFFSET));
|
|
}
|
|
PM_TRACE(MODULE_DBG_INFO, "set_rtc_attr success!\n");
|
|
return XMEDIA_SUCCESS;
|
|
|
|
rtc_failure:
|
|
PM_TRACE(MODULE_DBG_ERR, "set rtc timeout failure!\n");
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
xmedia_s32 lotus_get_rtc_attr(lotus_pmc_rtc_attr *attr)
|
|
{
|
|
xmedia_u32 status;
|
|
|
|
if (virt_pwr_base_addr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "pmc not init err!\n");
|
|
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
|
}
|
|
|
|
if (attr == XMEDIA_NULL) {
|
|
PM_TRACE(MODULE_DBG_ERR, "set_wakeup_attr parameter err!\n");
|
|
return XMEDIA_ERRCODE_NULL_PTR;
|
|
}
|
|
|
|
status = osal_readl(virt_pwr_base_addr + PWR_CTRL0_OFFSET);
|
|
status &=~ PWR_POWER_UNMASK;
|
|
|
|
attr->rtc_enable = !((status & PWR_RTC_MASK) >> 5);;
|
|
|
|
attr->rtc_timeout = 0;
|
|
|
|
PM_TRACE(MODULE_DBG_INFO, "get_rtc_attr success!\n");
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 lotus_pm_get_rtc_info(lotus_pm_rtc_info *info)
|
|
{
|
|
struct rtc_device *dev;
|
|
struct rtc_time linuxTime = {0};
|
|
unsigned char ms_count;
|
|
int ret = XMEDIA_SUCCESS;
|
|
time64_t seconds = 0;
|
|
|
|
dev = rtc_class_open("rtc0");
|
|
if (dev == XMEDIA_NULL) {
|
|
return XMEDIA_ERRCODE_OPEN_FAILED;
|
|
}
|
|
|
|
ret = lotus_rtc_aov_get_resume_time(dev->dev.parent, &linuxTime, &ms_count);
|
|
if (ret != 0) {
|
|
PM_TRACE(MODULE_DBG_INFO, "rtc get resume time fail: 0x%X\n", ret);
|
|
goto out;
|
|
}
|
|
|
|
seconds = rtc_tm_to_time64(&linuxTime);
|
|
|
|
info->rtc_delta_time = seconds * 1000 + ms_count * 10;
|
|
|
|
PM_TRACE(MODULE_DBG_INFO, "get rtc resume time: %d-%d-%d %d:%d:%d.%d \n", linuxTime.tm_year, linuxTime.tm_mon, linuxTime.tm_mday, linuxTime.tm_hour, linuxTime.tm_min, linuxTime.tm_sec, ms_count * 10);
|
|
|
|
ret = lotus_rtc_aov_get_suspend_time(dev->dev.parent, &linuxTime, &ms_count);
|
|
if (ret != 0) {
|
|
PM_TRACE(MODULE_DBG_INFO, "rtc get resume time fail: 0x%X\n", ret);
|
|
goto out;
|
|
}
|
|
|
|
seconds = rtc_tm_to_time64(&linuxTime);
|
|
|
|
info->rtc_last_suspend_time = seconds * 1000 + ms_count * 10;
|
|
|
|
PM_TRACE(MODULE_DBG_INFO, "get rtc suspend time: %d-%d-%d %d:%d:%d.%d \n", linuxTime.tm_year, linuxTime.tm_mon, linuxTime.tm_mday, linuxTime.tm_hour, linuxTime.tm_min, linuxTime.tm_sec, ms_count * 10);
|
|
|
|
ret = lotus_rtc_aov_get_current_time(dev->dev.parent, &linuxTime, &ms_count);
|
|
|
|
if (ret != 0) {
|
|
PM_TRACE(MODULE_DBG_INFO, "rtc get resume time fail: 0x%X\n", ret);
|
|
goto out;
|
|
}
|
|
|
|
seconds = rtc_tm_to_time64(&linuxTime);
|
|
|
|
info->rtc_current_time = seconds * 1000 + ms_count * 10;
|
|
|
|
PM_TRACE(MODULE_DBG_INFO, "get rtc current time: %d-%d-%d %d:%d:%d.%d \n", linuxTime.tm_year, linuxTime.tm_mon, linuxTime.tm_mday, linuxTime.tm_hour, linuxTime.tm_min, linuxTime.tm_sec, ms_count * 10);
|
|
out:
|
|
if (dev)
|
|
rtc_class_close(dev);
|
|
|
|
return ret;
|
|
}
|
|
|
|
xmedia_void lotus_get_rtc_timer(xmedia_void)
|
|
{
|
|
struct rtc_device *dev;
|
|
struct rtc_time linuxTime = {0};
|
|
unsigned char ms_count;
|
|
|
|
dev = rtc_class_open("rtc0");
|
|
if (dev == XMEDIA_NULL) {
|
|
return;
|
|
}
|
|
lotus_rtc_aov_read_time(dev->dev.parent, &linuxTime, &ms_count);
|
|
rtc_class_close(dev);
|
|
osal_printk("get rtc timer:%d:%d:%d \n", linuxTime.tm_min, linuxTime.tm_sec, ms_count);
|
|
}
|
|
|