#include #include #include #include #include "drv_dev_defines.h" #include "version.h" #include "pmoc_comm.h" #include "temperature.h" #include "drv_svb.h" #include "drv_pmc.h" #include "drv_pm_ddr.h" #include "xmedia_errcode.h" #define DEFAULT_THREAD_TIME 100 #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, lotus_pmc_wakeup_type) #define XMEDIA_PM_GET_ATTR _IOWR('n', CMD_PM_GET_ALL_ATTR, lotus_pmc_all_attr) #define XMEDIA_PM_SET_ATTR _IOWR('n', CMD_PM_SET_ALL_ATTR, lotus_pmc_all_attr) #define XMEDIA_PM_GET_RTC_ATTR _IOWR('n', CMD_PM_GET_RTC_ATTR, lotus_pmc_rtc_attr) #define XMEDIA_PM_SET_RTC_ATTR _IOWR('n', CMD_PM_SET_RTC_ATTR, lotus_pmc_rtc_attr) #define XMEDIA_PM_GET_WK_ATTR _IOWR('n', CMD_PM_GET_WK_ATTR, lotus_pmc_wakeup_attr) #define XMEDIA_PM_SET_WK_ATTR _IOWR('n', CMD_PM_SET_WK_ATTR, lotus_pmc_wakeup_attr) #define XMEDIA_PM_GET_RTC_TIMER _IO('n', CMD_PM_GET_RTC_TIMER) #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) #ifdef PM_WAKEUP1_SUPPORT #define XMEDIA_PM_GET_WK_INFO _IOWR('n', CMD_PM_GET_WK_INFO, lotus_pm_wakeup_info) #endif #define XMEDIA_PM_GET_RTC_INFO _IOR('n', CMD_PM_GET_RTC_INFO, lotus_pm_rtc_info) static osal_dev_t *g_pm_dev = XMEDIA_NULL; static osal_task_t *g_ctrl_thread = XMEDIA_NULL; xmedia_bool g_pm_resume = false; xmedia_s32 pm_ctrl_thread(xmedia_void *data) { xmedia_s32 ret; bool was_frozen; set_freezable(); ret = drv_svb_init(); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "svb init fail\n"); return XMEDIA_FAILURE; } if (!is_svb_enabled()) return XMEDIA_SUCCESS; temp_init(); while (!kthread_freezable_should_stop(&was_frozen)) { if (was_frozen || g_pm_resume) { pr_info("T Ctrl Thread resumed after freeze\n"); temp_init(); g_pm_resume = false; } freezable_schedule_timeout_interruptible(msecs_to_jiffies(DEFAULT_THREAD_TIME)); temp_control_thread(); } return XMEDIA_SUCCESS; } static int drv_pm_proc_show(struct osal_proc_dir_entry *s) { xmedia_char version_info[128] = {0}; VERSION_FORMAT(version_info, "Pm", "V1.0", ""); osal_seq_printf(s, "\n%s\n", version_info); osal_seq_printf(s, "Temperature : %d\n", get_chip_temperature()); osal_seq_printf(s, "CpuFreq(khz) : %d\n", get_cpu_freq() / 1000); osal_seq_printf(s, "HPM : %u\n", get_chip_hpm()); osal_seq_printf(s, "CoreVolt(mv) : %u\n", get_core_volt()); return 0; } xmedia_s32 drv_pm_open(xmedia_void *private_data) { return XMEDIA_SUCCESS; } xmedia_s32 drv_pm_close(xmedia_void *private_data) { return XMEDIA_SUCCESS; } static long drv_pm_ioctl(unsigned int cmd, unsigned long arg, xmedia_void *private_data) { xmedia_s32 ret = XMEDIA_SUCCESS; lotus_pmc_wakeup_type *type; lotus_pmc_all_attr *param; lotus_pmc_rtc_attr *rtc_attr; lotus_pmc_wakeup_attr *wk_attr; struct aux_mem *aux; #ifdef PM_WAKEUP1_SUPPORT lotus_pm_wakeup_info *wakeup_info; #endif lotus_pm_rtc_info *rtc_info; switch (cmd) { case XMEDIA_PM_INIT: ret = lotus_pmc_init(); break; case XMEDIA_PM_DEINIT: lotus_pmc_deinit(); break; case XMEDIA_PM_SET_ATTR: param = (lotus_pmc_all_attr *)arg; ret = lotus_set_all_attr(param); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "lotus_set_wakeup_source failed: %d\n", ret); return ret; } break; case XMEDIA_PM_GET_ATTR: param = (lotus_pmc_all_attr *)arg; ret = lotus_get_all_attr(param); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "lotus_get_wakeup_source failed: %d\n", ret); return ret; } break; case XMEDIA_PM_GET_RTC_ATTR: rtc_attr = (lotus_pmc_rtc_attr *)arg; ret = lotus_get_rtc_attr(rtc_attr); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "lotus_get_rtc_attr failed: %d\n", ret); return ret; } break; case XMEDIA_PM_SET_RTC_ATTR: rtc_attr = (lotus_pmc_rtc_attr *)arg; ret = lotus_set_rtc_attr(rtc_attr); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "lotus_set_rtc_attr failed: %d\n", ret); return ret; } break; case XMEDIA_PM_GET_WK_ATTR: wk_attr = (lotus_pmc_wakeup_attr *)arg; ret = lotus_get_wakeup_attr(wk_attr); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "lotus_set_wakeup_attr failed: %d\n", ret); return ret; } break; case XMEDIA_PM_SET_WK_ATTR: wk_attr = (lotus_pmc_wakeup_attr *)arg; ret = lotus_set_wakeup_attr(wk_attr); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "lotus_set_wakeup_attr failed: %d\n", ret); return ret; } break; case XMEDIA_PM_GET_WAKEUP_SOURCE: type = (lotus_pmc_wakeup_type *)arg; ret = lotus_get_wakeup_type(type); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "lotus_get_wakeup_type failed:%d\n", ret); return ret; } break; case XMEDIA_PM_GET_RTC_TIMER: lotus_get_rtc_timer(); return XMEDIA_SUCCESS; case XMEDIA_PM_SET_AUX: aux = (struct aux_mem *)arg; ret = lotus_pmc_set_aux(aux); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "lotus_set_aux failed:%d\n", ret); return ret; } break; case XMEDIA_PM_GET_DDR_PARAM: #ifdef CONFIG_PM struct lpds_param *plpds_param; plpds_param = (struct lpds_param *)arg; ret = pm_ddr_param_get(plpds_param); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "get ddr param failed:%d\n", ret); return ret; } break; #else return XMEDIA_ERRCODE_NOT_SUPPORT; #endif #ifdef PM_WAKEUP1_SUPPORT case XMEDIA_PM_GET_WK_INFO: wakeup_info = (lotus_pm_wakeup_info *)arg; ret = lotus_pm_get_wakeup_info(wakeup_info); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "get wakeup info failed:%d\n", ret); return ret; } break; #endif case XMEDIA_PM_GET_RTC_INFO: rtc_info = (lotus_pm_rtc_info *)arg; ret = lotus_pm_get_rtc_info(rtc_info); if (ret != XMEDIA_SUCCESS) { PM_TRACE(MODULE_DBG_ERR, "get rtc info failed:%d\n", ret); return ret; } break; default: break; } return ret; } xmedia_s32 drv_pm_suspend(osal_dev_t *pdev) { osal_printk("pm suspend OK!\n"); return XMEDIA_SUCCESS; } xmedia_s32 drv_pm_resume(osal_dev_t *pdev) { g_pm_resume = true; osal_printk("pm resume OK!\n"); return XMEDIA_SUCCESS; } static struct osal_fileops g_pm_fops = { .open = drv_pm_open, .unlocked_ioctl = drv_pm_ioctl, .release = drv_pm_close, }; struct osal_pmops g_pm_drv_ops = { .pm_suspend = drv_pm_suspend, .pm_resume = drv_pm_resume, }; xmedia_s32 pmoc_drv_modinit(xmedia_void) { osal_proc_entry_t *proc = XMEDIA_NULL; g_pm_dev = osal_createdev(UMAP_DEVNAME_PM_BASE); if (g_pm_dev == XMEDIA_NULL) { PM_TRACE(MODULE_DBG_ERR, "pm create dev err!\n"); goto out0; } g_pm_dev->fops = &g_pm_fops; g_pm_dev->minor = UMAP_PM_MINOR_BASE; g_pm_dev->osal_pmops = &g_pm_drv_ops; if (osal_registerdevice(g_pm_dev) < 0) { PM_TRACE(MODULE_DBG_ERR, "regist pm device err!\n"); goto out1; } g_ctrl_thread = osal_kthread_create(pm_ctrl_thread, XMEDIA_NULL, "lotus_pm_control"); if (g_ctrl_thread == XMEDIA_NULL) { PM_TRACE(MODULE_DBG_ERR, "create pm control failed.\n"); goto out2; } /* create proc */ proc = osal_create_proc_entry(MPP_MOD_PM, XMEDIA_NULL); if (proc == XMEDIA_NULL) { PM_TRACE(MODULE_DBG_ERR, "MODULE_DBG_ERR, Create pm proc err!\n"); goto out3; } proc->read = drv_pm_proc_show; proc->write = XMEDIA_NULL; osal_printk("load xm_pm.ko OK!\n"); return XMEDIA_SUCCESS; out3: osal_kthread_destroy(g_ctrl_thread, 1); g_ctrl_thread = XMEDIA_NULL; out2: osal_deregisterdevice(g_pm_dev); out1: osal_destroydev(g_pm_dev); g_pm_dev = XMEDIA_NULL; out0: osal_printk("load xm_pm.ko err!\n"); return XMEDIA_FAILURE; } xmedia_void pmoc_drv_modexit(xmedia_void) { osal_remove_proc_entry(MPP_MOD_PM, XMEDIA_NULL); if (g_ctrl_thread && is_svb_enabled()) { osal_kthread_destroy(g_ctrl_thread, 1); g_ctrl_thread = XMEDIA_NULL; } drv_svb_deinit(); osal_deregisterdevice(g_pm_dev); osal_destroydev(g_pm_dev); g_pm_dev = XMEDIA_NULL; osal_printk("unload xm_pm.ko OK!\n"); return; } #ifdef MODULE module_init(pmoc_drv_modinit); module_exit(pmoc_drv_modexit); MODULE_LICENSE("GPL"); #else int __init pmoc_driver_init(void) { return pmoc_drv_modinit(); } #endif