Initial commit: Linux kernel 4.19 for Unplugged OS

This commit is contained in:
ziv committed 2025-10-06 13:52:42 +00:00
commit d30235b04c
80519 files changed
+35800681

No files matched your search

@@ -0,0 +1,12 @@
MTK_LPM_GS_DUMP_VERSION = $(strip $(subst ",, $(CONFIG_MTK_LPM_GS_DUMP_VERSION)))
ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/power_gs_v1
ccflags-y += -I$(srctree)/drivers/misc/mediatek/lpm/inc/
ccflags-y += -I$(srctree)/drivers/misc/mediatek/lpm/mtk_lpm_fs/
ccflags-y += -I$(srctree)/drivers/misc/mediatek/lpm/modules/include/
obj-$(CONFIG_MTK_LPM_DBG_COMMON) += mtk_dbg_fs_common.o
obj-$(CONFIG_MTK_LPM_DBG_COMMON) += mtk_lpm_timer.o
obj-$(CONFIG_MTK_LPM_GS_DUMP_SUPPORT) += mtk_lpm_pwr_gs.o
obj-$(CONFIG_MTK_LPM_GS_DUMP_SUPPORT) += gs/${MTK_LPM_GS_DUMP_VERSION}/mtk_lpm_pwr_gs_common.o
obj-$(CONFIG_MTK_LPM_GS_DUMP_SUPPORT) += gs/${MTK_LPM_GS_DUMP_VERSION}/mtk_lpm_pwr_gs_dump_clk.o
obj-$(CONFIG_MTK_LPM_GS_DUMP_SUPPORT) += gs/${MTK_LPM_GS_DUMP_VERSION}/mtk_lpm_pwr_gs_dump_pmic.o
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <gs/mtk_lpm_pwr_gs.h>
#include <gs/v1/mtk_lpm_pwr_gs_internal.h>
int mtk_lpm_pwr_gs_common_init(void)
{
mtk_lpm_gs_dump_pmic_init();
mtk_lpm_gs_dump_dcm_init();
return 0;
}
void mtk_lpm_pwr_gs_common_deinit(void)
{
mtk_lpm_gs_dump_pmic_deinit();
mtk_lpm_gs_dump_dcm_deinit();
}
@@ -0,0 +1,254 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <gs/mtk_lpm_pwr_gs.h>
#include <gs/v1/mtk_power_gs.h>
#include <mt-plat/upmu_common.h>
#define MTK_LPM_GS_CMP_SEARCH (1u << 0)
struct mtk_lpm_gs_dcm_info_inst {
struct mtk_lpm_gs_clk_info *info;
};
static struct base_remap br;
#define DEBUG_BUF_SIZE 2048
static char buf[DEBUG_BUF_SIZE] = { 0 };
static struct mtk_lpm_gs_dcm_info_inst mtk_lpm_gs_clks;
void __iomem *_get_virt_base_from_table(unsigned int pa)
{
unsigned int k;
void __iomem *io_base = 0;
if (br.table) {
for (k = 0; k < br.table_pos; k++)
if (br.table[k].pa == pa)
return (io_base = br.table[k].va);
} else
pr_info("Power_gs: cannot find virtual address\n");
return io_base;
}
/* Check phys addr is existed in table or not */
bool _is_exist_in_phys_to_virt_table(unsigned int pa)
{
unsigned int k;
if (br.table)
for (k = 0; k < br.table_pos; k++)
if (br.table[k].pa == pa)
return true;
return false;
}
unsigned int mt_power_gs_base_remap_init(char *scenario, char *pmic_name,
const unsigned int *pmic_gs, unsigned int pmic_gs_len)
{
unsigned int i, base;
struct phys_to_virt_table *table;
if (!br.table)
br.table = kmalloc(sizeof(struct phys_to_virt_table) *
REMAP_SIZE_MASK + 1, GFP_KERNEL);
if (br.table) {
table = br.table;
for (i = 0; i < pmic_gs_len; i += 3) {
base = (pmic_gs[i] & (~(unsigned long)REMAP_SIZE_MASK));
if (!_is_exist_in_phys_to_virt_table(base)) {
table[br.table_pos].pa = base;
table[br.table_pos].va =
ioremap_nocache(base,
REMAP_SIZE_MASK + 1);
if (!table[br.table_pos].va)
pr_info("ioremap_nocache(0x%x, 0x%x)\n",
base, REMAP_SIZE_MASK + 1);
if (br.table_pos < br.table_size)
br.table_pos++;
else {
pr_info("base_remap in maximum size\n");
return 0;
}
}
}
}
return 0;
}
static u16 gs_pmic_read(u16 reg)
{
u32 reg_val = 0;
#if defined(CONFIG_MTK_PMIC_NEW_ARCH)
u32 ret = 0;
ret = pmic_read_interface_nolock(reg, &reg_val, 0xFFFF, 0x0);
#endif
return (u16)reg_val;
}
static bool _is_pmic_addr(unsigned int addr)
{
return (addr >> 16) ? 0 : 1;
}
unsigned int _golden_read_reg(unsigned int addr)
{
unsigned int reg_val;
unsigned int base = addr & (~(unsigned long)REMAP_SIZE_MASK);
unsigned int offset = addr & (unsigned long)REMAP_SIZE_MASK;
void __iomem *io_base;
if (_is_pmic_addr(addr))
reg_val = gs_pmic_read(addr);
else {
#if 0
io_base = ioremap_nocache(base, REMAP_SIZE_MASK+1);
reg_val = ioread32(io_base + offset);
iounmap(io_base);
#else
io_base = _get_virt_base_from_table(base);
if (io_base)
reg_val = ioread32(io_base + offset);
else
reg_val = 0;
#endif
}
return reg_val;
}
#define PER_LINE_TO_PRINT 8
static void mt_power_gs_clk_compare(char *pmic_name,
struct mtk_lpm_gs_clk_user *user)
{
unsigned int i, k, val0, val1, val2, diff, dump_cnt = 0;
char *p;
/* dump diff mode */
p = buf;
p += snprintf(p, sizeof(buf), "\n");
p += snprintf(p, sizeof(buf) - (p - buf),
"Scenario - %s - Addr - Value - Mask - Golden - Wrong Bit\n",
pmic_name);
for (i = 0; i < user->array_sz; i += 3) {
val0 = _golden_read_reg(user->array[i]);
val1 = val0 & user->array[i + 1];
val2 = user->array[i + 2] & user->array[i + 1];
if (val1 != val2) {
dump_cnt++;
p += snprintf(p, sizeof(buf) - (p - buf),
"%s - %s - 0x%08x - 0x%08x - 0x%08x - 0x%08x -",
user->name, pmic_name, user->array[i], val0,
user->array[i + 1], user->array[i + 2]);
for (k = 0, diff = val1 ^ val2; diff != 0; k++,
diff >>= 1) {
if ((diff % 2) != 0)
p += snprintf(p,
sizeof(buf) - (p - buf),
" %d", k);
}
p += snprintf(p, sizeof(buf) - (p - buf), "\n");
if (dump_cnt &&
((dump_cnt % PER_LINE_TO_PRINT) == 0)) {
pr_notice("%s", buf);
p = buf;
p += snprintf(p, sizeof(buf), "\n");
}
}
}
if (dump_cnt % PER_LINE_TO_PRINT)
pr_notice("%s", buf);
}
int mtk_lpm_gs_clk_cmp_init(void *data)
{
int i = 0;
struct mtk_lpm_gs_clk_info *_info;
struct mtk_lpm_gs_clk *const *_dcm;
if (!data)
return -EINVAL;
_info = (struct mtk_lpm_gs_clk_info *)data;
for (i = 0, _dcm = _info->dcm; *_dcm ; i++, _dcm++) {
if (_info->attach) {
int ret = 0;
ret = _info->attach((*_dcm));
if (!ret) {
int idx = 0;
for (idx = 0; idx < MTK_LPM_PWR_GS_TYPE_MAX;
++idx) {
mt_power_gs_base_remap_init(
(*_dcm)->user[idx].name,
(*_dcm)->name,
(*_dcm)->user[idx].array,
(*_dcm)->user[idx].array_sz);
}
}
}
}
mtk_lpm_gs_clks.info = _info;
return 0;
}
int __mtk_lpm_gs_clk_cmp(unsigned int flag, unsigned int type, int user)
{
int i = 0, is_found;
struct mtk_lpm_gs_clk_info *_info = mtk_lpm_gs_clks.info;
struct mtk_lpm_gs_clk *const *_dcm;
for (i = 0, _dcm = _info->dcm; *_dcm ; i++, _dcm++) {
is_found = (flag & MTK_LPM_GS_CMP_SEARCH) ? 0 : 1;
if (!is_found && ((*_dcm)->type == type))
is_found = 1;
if (is_found)
mt_power_gs_clk_compare((*_dcm)->name,
&((*_dcm)->user[user]));
}
return 0;
}
int mtk_lpm_gs_clk_cmp(int user)
{
return __mtk_lpm_gs_clk_cmp(0, 0, user);
}
int mtk_lpm_gs_clk_cmp_by_type(int user, unsigned int type)
{
return __mtk_lpm_gs_clk_cmp(MTK_LPM_GS_CMP_SEARCH, type, user);
}
struct mtk_lpm_gs_cmp mtk_lpm_gs_cmp_clk = {
.cmp_init = mtk_lpm_gs_clk_cmp_init,
.cmp = mtk_lpm_gs_clk_cmp,
.cmp_by_type = mtk_lpm_gs_clk_cmp_by_type,
};
int mtk_lpm_gs_dump_dcm_init(void)
{
mtk_lpm_pwr_gs_compare_register(MTK_LPM_GS_CMP_CLK, &mtk_lpm_gs_cmp_clk);
return 0;
}
void mtk_lpm_gs_dump_dcm_deinit(void)
{
mtk_lpm_pwr_gs_compare_unregister(MTK_LPM_GS_CMP_CLK);
}
@@ -0,0 +1,189 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <gs/mtk_lpm_pwr_gs.h>
#include <gs/v1/mtk_power_gs.h>
#define PER_LINE_TO_PRINT 8
#define DEBUG_BUF_SIZE 2048
static char buf[DEBUG_BUF_SIZE] = { 0 };
static int slp_chk_golden_diff_mode = 1;
struct mtk_lpm_gs_pmic_info_inst {
unsigned int count_pmic;
struct mtk_lpm_gs_pmic_info *info;
};
static struct mtk_lpm_gs_pmic_info_inst mtk_lpm_pmics;
void generic_dump_pmic(const char *pmic_name, int pmic_num,
struct mtk_lpm_gs_pmic_user *user,
struct regmap *regmap)
{
unsigned int i, k, val0 = 0, val1, val2, diff, dump_cnt = 0, ret;
char *p;
if (!pmic_name || !user)
goto ERROR;
if (IS_ERR(regmap)) {
pr_info("%s regmap get failed\n", __func__);
goto ERROR;
}
/* dump diff mode */
if (slp_chk_golden_diff_mode) {
p = buf;
p += snprintf(p, sizeof(buf), "\n");
p += snprintf(p, sizeof(buf) - (p - buf),
"Scenario - %s - Addr - Value - Mask - Golden - Wrong Bit\n",
pmic_name);
for (i = 0; i < user->array_sz; i += 3) {
ret = regmap_read(regmap, user->array[i], &val0);
if (ret) {
pr_info("read pmic-%d 0x%x error\n",
pmic_num, user->array[i]);
goto ERROR;
}
val1 = val0 & user->array[i + 1];
val2 = user->array[i + 2] & user->array[i + 1];
if (val1 != val2) {
dump_cnt++;
p += snprintf(p, sizeof(buf) - (p - buf),
"%s - %s - 0x%08x - 0x%08x- 0x%08x - 0x%08x -",
user->name, pmic_name, user->array[i], val0,
user->array[i + 1], user->array[i + 2]);
for (k = 0, diff = val1 ^ val2; diff != 0; k++,
diff >>= 1) {
if ((diff % 2) != 0)
p += snprintf(p,
sizeof(buf) - (p - buf),
" %d", k);
}
p += snprintf(p, sizeof(buf) - (p - buf), "\n");
if (dump_cnt &&
((dump_cnt % PER_LINE_TO_PRINT) == 0)) {
pr_info("%s", buf);
p = buf;
p += snprintf(p, sizeof(buf), "\n");
}
}
}
if (dump_cnt % PER_LINE_TO_PRINT)
pr_info("%s", buf);
/* dump raw data mode */
} else {
p = buf;
p += snprintf(p, sizeof(buf), "\n");
p += snprintf(p, sizeof(buf) - (p - buf),
"Scenario - PMIC - Addr - Value\n");
for (i = 0; i < user->array_sz; i += 3) {
ret = regmap_read(regmap, user->array[i], &val0);
if (ret) {
pr_info("read pmic-%d 0x%x error\n",
pmic_num, user->array[i]);
goto ERROR;
}
dump_cnt++;
p += snprintf(p, sizeof(buf) - (p - buf),
"%s - %s-%d - 0x%08x - 0x%08x\n",
user->name, pmic_name, pmic_num,
user->array[i], val0);
if (dump_cnt && ((dump_cnt % PER_LINE_TO_PRINT) == 0)) {
pr_info("%s", buf);
p = buf;
p += snprintf(p, sizeof(buf), "\n");
}
}
if (dump_cnt % PER_LINE_TO_PRINT)
pr_info("%s", buf);
}
ERROR:
return;
}
int mtk_lpm_gs_pmic_cmp_init(void *data)
{
int i = 0;
struct mtk_lpm_gs_pmic_info *_info;
struct mtk_lpm_gs_pmic *const *_pmic;
if (!data)
return -EINVAL;
_info = (struct mtk_lpm_gs_pmic_info *)data;
for (i = 0, _pmic = _info->pmic; *_pmic ; i++, _pmic++) {
if (_info->attach)
_info->attach((*_pmic));
}
mtk_lpm_pmics.count_pmic = i;
mtk_lpm_pmics.info = _info;
return 0;
}
int mtk_lpm_gs_pmic_cmp(int user)
{
int i = 0;
struct mtk_lpm_gs_pmic_info *_info = mtk_lpm_pmics.info;
struct mtk_lpm_gs_pmic *const *_pmic;
struct regulator *regulator;
struct regmap *regmap;
for (i = 0, _pmic = _info->pmic; *_pmic ; i++, _pmic++) {
regulator = regulator_get_optional(NULL, (*_pmic)->regulator);
if (IS_ERR(regulator)) {
pr_info("%s regulator get failed\n", __func__);
continue;
}
regmap = regulator_get_regmap(regulator);
if ((regmap == NULL) || IS_ERR(regmap)) {
pr_info("%s regmap get failed\n", __func__);
continue;
}
generic_dump_pmic((*_pmic)->pwr_domain, i,
&((*_pmic)->user[user]), regmap);
}
return 0;
}
struct mtk_lpm_gs_cmp mtk_lpm_gs_cmp_pmic = {
.cmp_init = mtk_lpm_gs_pmic_cmp_init,
.cmp = mtk_lpm_gs_pmic_cmp,
};
int mtk_lpm_gs_dump_pmic_init(void)
{
mtk_lpm_pwr_gs_compare_register(MTK_LPM_GS_CMP_PMIC,
&mtk_lpm_gs_cmp_pmic);
return 0;
}
void mtk_lpm_gs_dump_pmic_deinit(void)
{
mtk_lpm_pwr_gs_compare_unregister(MTK_LPM_GS_CMP_PMIC);
}
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#ifndef _MTK_LPM_PWR_GS_INITERNAL_H__
#define _MTK_LPM_PWR_GS_INITERNAL_H__
int mtk_lpm_gs_dump_pmic_init(void);
void mtk_lpm_gs_dump_pmic_deinit(void);
int mtk_lpm_gs_dump_dcm_init(void);
void mtk_lpm_gs_dump_dcm_deinit(void);
#endif
@@ -0,0 +1,245 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/console.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/syscore_ops.h>
#include <mtk_dbg_common_v1.h>
#include <mtk_lpm_module.h>
#include <mtk_resource_constraint_v1.h>
#include <mtk_suspend_sysfs.h>
#include <mtk_spm_sysfs.h>
#define MTK_DGB_SUSP_NODE "/sys/kernel/debug/suspend/suspend_state"
#undef mtk_dbg_log
#define mtk_dbg_log(fmt, args...) \
do { \
int l = scnprintf(p, sz, fmt, ##args); \
p += l; \
sz -= l; \
} while (0)
static struct wakeup_source *mtk_suspend_lock;
/* debugfs for blocking syscore callback */
static int spm_syscore_block_suspend(void) { return -EINVAL; }
static void spm_syscore_block_resume(void) {}
static struct syscore_ops spm_block_syscore_ops = {
.suspend = spm_syscore_block_suspend,
.resume = spm_syscore_block_resume,
};
/* debugfs for debug in syscore callback */
static int spm_syscore_dbg_suspend(void)
{
return 0;
}
static void spm_syscore_dbg_resume(void) {}
static struct syscore_ops spm_dbg_syscore_ops = {
.suspend = spm_syscore_dbg_suspend,
.resume = spm_syscore_dbg_resume,
};
static ssize_t mtk_dbg_suspend_state_read(char *ToUser, size_t sz, void *priv)
{
char *p = ToUser;
if (!ToUser)
return -EINVAL;
mtk_dbg_log("mtk_suspend command help\n");
mtk_dbg_log("kernel suspend disable/enable:\n");
mtk_dbg_log("echo kernel_suspend 0/1 > %s\n", MTK_DGB_SUSP_NODE);
mtk_dbg_log("mtk_suspend disable/enable:\n");
mtk_dbg_log("echo mtk_suspend 0/1 > %s\n", MTK_DGB_SUSP_NODE);
return p - ToUser;
}
static ssize_t mtk_dbg_suspend_state_write(char *FromUser,
size_t sz, void *priv)
{
char cmd[128];
int param;
if (!FromUser)
return -EINVAL;
if (sscanf(FromUser, "%127s %d", cmd, &param) == 2) {
if (!strcmp(cmd, "kernel_suspend")) {
/* 0:require wakelock */
if (!param)
__pm_stay_awake(mtk_suspend_lock);
/* 1:release wakelock */
else
__pm_relax(mtk_suspend_lock);
} else if (!strcmp(cmd, "mtk_suspend")) {
/* 0:block in syscore */
if (!param)
register_syscore_ops(&spm_block_syscore_ops);
/* 1:unblock in syscore */
else
unregister_syscore_ops(&spm_block_syscore_ops);
}
return sz;
}
return -EINVAL;
}
static const struct mtk_lp_sysfs_op mtk_dbg_suspend_state_fops = {
.fs_read = mtk_dbg_suspend_state_read,
.fs_write = mtk_dbg_suspend_state_write,
};
static ssize_t mtk_dbg_get_spm_sleep_count(char *ToUserBuf,
size_t sz, void *priv)
{
int bLen;
bLen = snprintf(ToUserBuf, sz, "%lu\n",
mtk_lpm_smc_spm_dbg(MT_SPM_DBG_SMC_UID_SUSPEND_DBG_CTRL,
MT_LPM_SMC_ACT_GET,
DBG_CTRL_COUNT, 0));
return (bLen > sz) ? sz : bLen;
}
static const struct mtk_lp_sysfs_op mtk_dbg_spm_sleep_count_fops = {
.fs_read = mtk_dbg_get_spm_sleep_count,
};
static void mtk_dbg_suspend_fs_init(void)
{
mtk_suspend_sysfs_root_entry_create();
mtk_suspend_sysfs_entry_node_add("suspend_state"
, 0444, &mtk_dbg_suspend_state_fops, NULL);
mtk_suspend_sysfs_entry_node_add("spm_sleep_count"
, 0444, &mtk_dbg_spm_sleep_count_fops, NULL);
}
static ssize_t mtk_dbg_get_spm_last_wakeup_src(char *ToUserBuf,
size_t sz, void *priv)
{
int bLen = snprintf(ToUserBuf, sz, "0x%lx\n",
mtk_lpm_smc_spm_dbg(MT_SPM_DBG_SMC_UID_FS,
MT_LPM_SMC_ACT_GET,
WAKE_STA_R12, 0));
return (bLen > sz) ? sz : bLen;
}
static const struct mtk_lp_sysfs_op mtk_dbg_spm_last_wakesrc_fops = {
.fs_read = mtk_dbg_get_spm_last_wakeup_src,
};
static ssize_t mtk_dbg_get_spm_last_debug_flag(char *ToUserBuf,
size_t sz, void *priv)
{
int bLen = snprintf(ToUserBuf, sz, "0x%lx\n",
mtk_lpm_smc_spm_dbg(MT_SPM_DBG_SMC_UID_FS,
MT_LPM_SMC_ACT_GET,
WAKE_STA_DEBUG_FLAG, 0));
return (bLen > sz) ? sz : bLen;
}
static const struct mtk_lp_sysfs_op mtk_dbg_spm_last_debugflag_fops = {
.fs_read = mtk_dbg_get_spm_last_debug_flag,
};
static ssize_t mtk_dbg_get_spmfw_version(char *ToUserBuf,
size_t sz, void *priv)
{
int index = 0;
const char *version;
char *p = ToUserBuf;
struct device_node *node =
of_find_compatible_node(NULL, NULL, "mediatek,sleep");
if (node == NULL) {
mtk_dbg_log("No Found mediatek,mediatek,sleep\n");
goto return_size;
}
while (!of_property_read_string_index(node,
"spmfw_version", index, &version)) {
mtk_dbg_log("%d: %s\n", index, version);
index++;
}
mtk_dbg_log("spmfw index: %lu\n",
mtk_lpm_smc_spm(MT_SPM_SMC_UID_FW_TYPE,
MT_LPM_SMC_ACT_GET, 0, 0));
mtk_dbg_log("spmfw ready: %d\n",
(mtk_lpm_smc_spm_dbg(MT_SPM_DBG_SMC_UID_RC_SWITCH,
MT_LPM_SMC_ACT_GET,
MT_RM_CONSTRAINT_ID_DRAM, -1)
& MT_SPM_RC_VALID_FW) ? 1 : 0);
if (node)
of_node_put(node);
return_size:
return p - ToUserBuf;
}
static const struct mtk_lp_sysfs_op mtk_dbg_spm_spmfw_ver_fops = {
.fs_read = mtk_dbg_get_spmfw_version,
};
static void mtk_dbg_spm_fs_init(void)
{
mtk_spm_sysfs_root_entry_create();
mtk_spm_sysfs_entry_node_add("spm_last_wakeup_src", 0444
, &mtk_dbg_spm_last_wakesrc_fops, NULL);
mtk_spm_sysfs_entry_node_add("spm_last_debug_flag", 0444
, &mtk_dbg_spm_last_debugflag_fops, NULL);
mtk_spm_sysfs_entry_node_add("spmfw_version", 0444
, &mtk_dbg_spm_spmfw_ver_fops, NULL);
}
static bool mtk_system_console_suspend;
void mtk_dbg_common_fs_exit(void)
{
/* restore suspend console */
console_suspend_enabled = mtk_system_console_suspend;
/* wakeup source deinit */
wakeup_source_unregister(mtk_suspend_lock);
/* remove syscore callback */
unregister_syscore_ops(&spm_block_syscore_ops);
unregister_syscore_ops(&spm_dbg_syscore_ops);
}
int mtk_dbg_common_fs_init(void)
{
/* wakeup source init for suspend enable and disable */
mtk_suspend_lock = wakeup_source_register(NULL, "mtk_suspend_wakelock");
if (!mtk_suspend_lock) {
pr_info("%s %d: init wakeup source fail!", __func__, __LINE__);
return -1;
}
/* backup and disable suspend console (enable log print) */
mtk_system_console_suspend = console_suspend_enabled;
console_suspend_enabled = false;
mtk_dbg_suspend_fs_init();
mtk_dbg_spm_fs_init();
register_syscore_ops(&spm_dbg_syscore_ops);
pr_info("%s %d: finish", __func__, __LINE__);
return 0;
}
@@ -0,0 +1,100 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <gs/mtk_lpm_pwr_gs.h>
static DEFINE_SPINLOCK(mtk_lpm_gs_locker);
static struct mtk_lpm_gs_cmp *mtk_lpm_gs_cmps[MTK_LPM_GS_CMP_MAX];
int mtk_lpm_pwr_gs_compare_register(int comparer, struct mtk_lpm_gs_cmp *cmp)
{
if ((comparer < 0) || (comparer >= MTK_LPM_GS_CMP_MAX)
|| !cmp || mtk_lpm_gs_cmps[comparer])
return -EINVAL;
spin_lock(&mtk_lpm_gs_locker);
mtk_lpm_gs_cmps[comparer] = cmp;
if (mtk_lpm_gs_cmps[comparer]->init)
mtk_lpm_gs_cmps[comparer]->init();
spin_unlock(&mtk_lpm_gs_locker);
return 0;
}
void mtk_lpm_pwr_gs_compare_unregister(int comparer)
{
if ((comparer < 0) || (comparer >= MTK_LPM_GS_CMP_MAX))
return;
spin_lock(&mtk_lpm_gs_locker);
if (mtk_lpm_gs_cmps[comparer] && mtk_lpm_gs_cmps[comparer]->deinit)
mtk_lpm_gs_cmps[comparer]->deinit();
mtk_lpm_gs_cmps[comparer] = NULL;
spin_unlock(&mtk_lpm_gs_locker);
}
int mtk_lpm_pwr_gs_compare(int comparer, int user)
{
int ret = 0;
if ((comparer < 0) || (comparer >= MTK_LPM_GS_CMP_MAX)
|| !mtk_lpm_gs_cmps[comparer])
return -EINVAL;
if (mtk_lpm_gs_cmps[comparer]->cmp) {
spin_lock(&mtk_lpm_gs_locker);
mtk_lpm_gs_cmps[comparer]->cmp(user);
spin_unlock(&mtk_lpm_gs_locker);
} else
ret = -EACCES;
return ret;
}
int mtk_lpm_pwr_gs_compare_by_type(int comparer, int user,
unsigned int type)
{
int ret = 0;
if ((comparer < 0) || (comparer >= MTK_LPM_GS_CMP_MAX)
|| !mtk_lpm_gs_cmps[comparer])
return -EINVAL;
if ((user < 0) || (user >= MTK_LPM_GS_CMP_MAX))
return -EINVAL;
spin_lock(&mtk_lpm_gs_locker);
if (mtk_lpm_gs_cmps[comparer]->cmp_by_type)
mtk_lpm_gs_cmps[comparer]->cmp_by_type(user, type);
else if (mtk_lpm_gs_cmps[comparer]->cmp)
mtk_lpm_gs_cmps[comparer]->cmp(user);
else
ret = -EACCES;
spin_unlock(&mtk_lpm_gs_locker);
return ret;
}
int mtk_lpm_pwr_gs_compare_init(int comparer, void *info)
{
int ret = 0;
if ((comparer < 0) || (comparer >= MTK_LPM_GS_CMP_MAX)
|| !mtk_lpm_gs_cmps[comparer])
return -EINVAL;
if (mtk_lpm_gs_cmps[comparer]->cmp_init) {
spin_lock(&mtk_lpm_gs_locker);
mtk_lpm_gs_cmps[comparer]->cmp_init(info);
spin_unlock(&mtk_lpm_gs_locker);
} else
ret = -EACCES;
return ret;
}
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <mtk_lpm_timer.h>
#define MTK_LPM_TIMER_GET_INTERVAL(ms) msecs_to_jiffies(ms)
#define MTK_LPM_TIMER_GET_TIME(jif) jiffies_to_msecs(jif)
#define MTK_LPM_TIMER_NEXT_INTERVAL(interval) (jiffies + interval)
static void mtk_lpm_timer_tm_func(struct timer_list *t)
{
int ret = -EINVAL;
struct mt_lpm_timer *timer = from_timer(timer, t, tm);
if (timer && timer->timeout) {
unsigned long dur = jiffies - timer->cur;
ret = timer->timeout(MTK_LPM_TIMER_GET_TIME(dur),
timer->priv);
}
if (ret)
return;
if (timer->type == MTK_LPM_TIMER_REPEAT) {
mod_timer(&timer->tm,
MTK_LPM_TIMER_NEXT_INTERVAL(timer->interval));
timer->cur = jiffies;
}
}
static int __is_mtk_lpm_timer_running(struct mt_lpm_timer *timer)
{
if (!timer)
return -EINVAL;
return timer_pending(&timer->tm);
}
int mtk_lpm_timer_init(struct mt_lpm_timer *timer, int type)
{
if (!timer)
return -EINVAL;
timer_setup(&timer->tm, mtk_lpm_timer_tm_func,
TIMER_DEFERRABLE);
timer->interval = 0;
timer->type = type;
return 0;
}
void mtk_lpm_timer_stop(struct mt_lpm_timer *timer)
{
if (!timer)
return;
del_timer_sync(&timer->tm);
}
int mtk_lpm_timer_start(struct mt_lpm_timer *timer)
{
if (!timer || (timer->interval == 0))
return -EINVAL;
if (!__is_mtk_lpm_timer_running(timer)) {
mod_timer(&timer->tm,
MTK_LPM_TIMER_NEXT_INTERVAL(timer->interval));
timer->cur = jiffies;
}
return 0;
}
int mtk_lpm_timer_interval_update(struct mt_lpm_timer *timer,
unsigned long long ms)
{
if (!timer)
return -EINVAL;
timer->interval = MTK_LPM_TIMER_GET_INTERVAL(ms);
mod_timer_pending(&timer->tm,
MTK_LPM_TIMER_NEXT_INTERVAL(timer->interval));
return 0;
}
int mtk_lpm_timer_is_running(struct mt_lpm_timer *timer)
{
return __is_mtk_lpm_timer_running(timer);
}
unsigned long mtk_lpm_timer_interval(struct mt_lpm_timer *timer)
{
if (!timer)
return 0;
return MTK_LPM_TIMER_GET_TIME(timer->interval);
}