#include "pmoc_comm.h" #include "drv_pmc.h" #include #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); }