248 lines
6.0 KiB
C
248 lines
6.0 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/module.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/debugfs.h>
|
|
#include "inc/mt6370_pmu.h"
|
|
#include "inc/mt6370_pmu_dsv_debugfs.h"
|
|
#include <mt-plat/aee.h>
|
|
|
|
|
|
int irq_count[DSV_MODE_MAX];
|
|
|
|
#define IRQ_COUNT_MAX 20
|
|
#define MT6370_DB_VBST_MAX_V 0x2C /*6.2v*/
|
|
#define MT6370_PMU_REG_DB_VBST_MASK 0x3F
|
|
#define DB_MASK_DEFAULT_SHIFT 0x3
|
|
|
|
int g_db_vbst;
|
|
int g_vbst_adjustment;
|
|
int g_irq_count_max;
|
|
int g_irq_mask;
|
|
int g_irq_mask_warning;
|
|
int g_irq_disable;
|
|
|
|
int mt6370_pmu_dsv_scp_ocp_irq_debug(struct mt6370_pmu_chip *chip,
|
|
enum dsv_dbg_mode_t mode)
|
|
{
|
|
int ret = 0, err = 0;
|
|
int dbvbst, dbvpos, dbvneg, dbmask;
|
|
char s[50] = "";
|
|
|
|
if (!g_irq_mask)
|
|
return ret;
|
|
|
|
if (!(g_irq_disable & (1 << mode)))
|
|
return ret;
|
|
|
|
irq_count[mode] = irq_count[mode] + 1;
|
|
|
|
if (irq_count[mode] > g_irq_count_max) {
|
|
irq_count[mode] = 0;
|
|
|
|
mt6370_pmu_reg_update_bits(chip, MT6370_PMU_DBMASK,
|
|
1 << (DB_MASK_DEFAULT_SHIFT + mode),
|
|
1 << (DB_MASK_DEFAULT_SHIFT + mode));
|
|
|
|
dbvbst = mt6370_pmu_reg_read(chip, MT6370_PMU_REG_DBVBST);
|
|
dbvpos = mt6370_pmu_reg_read(chip, MT6370_PMU_REG_DBVPOS);
|
|
dbvneg = mt6370_pmu_reg_read(chip, MT6370_PMU_REG_DBVNEG);
|
|
dbmask = mt6370_pmu_reg_read(chip, MT6370_PMU_DBMASK);
|
|
pr_info("%s: DB_VBST = 0x%x, DB_VPOS = 0x%x, DB_VNEG = 0x%x, DBMASK = 0x%x\n",
|
|
__func__, dbvbst, dbvpos, dbvneg, dbmask);
|
|
|
|
err = snprintf(s, 50, "Vbst=0x%x,Vpos=0x%x,Vneg=0x%x,mask=0x%x",
|
|
dbvbst, dbvpos, dbvneg, dbmask);
|
|
if (err >= 0 && g_irq_mask_warning)
|
|
aee_kernel_warning("mt6370 dsv irq",
|
|
"db irq type = %x %s\n", mode, s);
|
|
ret = 1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
void mt6370_pmu_dsv_auto_vbst_adjustment(struct mt6370_pmu_chip *chip,
|
|
enum dsv_dbg_mode_t mode)
|
|
{
|
|
int db_vbst;
|
|
|
|
if (!g_vbst_adjustment)
|
|
return;
|
|
|
|
irq_count[mode] = irq_count[mode] + 1;
|
|
|
|
if (irq_count[mode] > g_irq_count_max) {
|
|
irq_count[mode] = 0;
|
|
|
|
g_db_vbst = mt6370_pmu_reg_read(chip, MT6370_PMU_REG_DBVBST);
|
|
db_vbst = MT6370_PMU_REG_DB_VBST_MASK & g_db_vbst;
|
|
|
|
if (db_vbst < MT6370_DB_VBST_MAX_V) {
|
|
/*0.05V per step*/
|
|
mt6370_pmu_reg_update_bits(chip, MT6370_PMU_REG_DBVBST,
|
|
MT6370_PMU_REG_DB_VBST_MASK, db_vbst + 1);
|
|
|
|
db_vbst = mt6370_pmu_reg_read(chip,
|
|
MT6370_PMU_REG_DBVBST);
|
|
|
|
pr_info("%s: set DB_VBST from 0x%x to 0x%x\n",
|
|
__func__, g_db_vbst, db_vbst);
|
|
|
|
aee_kernel_warning("mt6370 dsv auto vbst ",
|
|
"set DB_VBST= 0x%x\n", db_vbst);
|
|
|
|
} else
|
|
pr_info_ratelimited("%s: fixed DB_VBST = 0x%x\n",
|
|
__func__, g_db_vbst);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
static ssize_t mt6370_pmu_dsv_debug_write(struct file *file,
|
|
const char __user *buf, size_t size, loff_t *ppos)
|
|
{
|
|
char lbuf[128];
|
|
char *b = &lbuf[0];
|
|
int flag = 0;
|
|
ssize_t res;
|
|
char *token;
|
|
unsigned int val = 0;
|
|
|
|
if (*ppos != 0 || size >= sizeof(lbuf) || size == 0)
|
|
return -EINVAL;
|
|
|
|
res = simple_write_to_buffer(lbuf, sizeof(lbuf) - 1, ppos, buf, size);
|
|
if (res <= 0)
|
|
return -EFAULT;
|
|
|
|
lbuf[size] = '\0';
|
|
|
|
if (!strncmp(b, "vbst_adjustment ", strlen("vbst_adjustment "))) {
|
|
b += strlen("vbst_adjustment ");
|
|
flag = DSV_VAR_VBST_ADJUSTMENT;
|
|
} else if (!strncmp(b, "irq_count_max ", strlen("irq_count_max "))) {
|
|
b += strlen("irq_count_max ");
|
|
flag = DSV_VAR_IRQ_COUNT;
|
|
} else if (!strncmp(b, "irq_mask ", strlen("irq_mask "))) {
|
|
b += strlen("irq_mask ");
|
|
flag = DSV_VAR_IRQ_MASK;
|
|
} else if (!strncmp(b, "irq_mask_warning ",
|
|
strlen("irq_mask_warning "))) {
|
|
b += strlen("irq_mask_warning ");
|
|
flag = DSV_VAR_IRQ_MASK_WARNING;
|
|
} else if (!strncmp(b, "irq_disable ",
|
|
strlen("irq_disable "))) {
|
|
b += strlen("irq_disable ");
|
|
flag = DSV_VAR_IRQ_DISABLE;
|
|
} else
|
|
return -EINVAL;
|
|
|
|
token = strsep(&b, " ");
|
|
if (token == NULL)
|
|
return -EINVAL;
|
|
|
|
if (kstrtouint(token, 0, &val))
|
|
return -EINVAL;
|
|
|
|
switch (flag) {
|
|
case DSV_VAR_VBST_ADJUSTMENT:
|
|
g_vbst_adjustment = val;
|
|
pr_info("[%s] set vbst_adjustment = 0x%x\n",
|
|
__func__, g_vbst_adjustment);
|
|
break;
|
|
case DSV_VAR_IRQ_COUNT:
|
|
g_irq_count_max = val;
|
|
pr_info("[%s] set irq_count_max = 0x%x\n",
|
|
__func__, g_irq_count_max);
|
|
break;
|
|
case DSV_VAR_IRQ_MASK:
|
|
g_irq_mask = val;
|
|
pr_info("[%s] set irq_mask = 0x%x\n",
|
|
__func__, g_irq_mask);
|
|
break;
|
|
case DSV_VAR_IRQ_MASK_WARNING:
|
|
g_irq_mask_warning = val;
|
|
pr_info("[%s] set irq_mask_warning = 0x%x\n",
|
|
__func__, g_irq_mask_warning);
|
|
break;
|
|
case DSV_VAR_IRQ_DISABLE:
|
|
g_irq_disable = val;
|
|
pr_info("[%s] set irq_disable = 0x%x\n",
|
|
__func__, g_irq_disable);
|
|
break;
|
|
default:
|
|
pr_info("[%s] do nothing\n", __func__);
|
|
break;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static int mt6370_pmu_dsv_debug_show(struct seq_file *s, void *unused)
|
|
{
|
|
seq_printf(s, "vbst_adjustment = %d\n", g_vbst_adjustment);
|
|
seq_printf(s, "irq_count_max = %d\n", g_irq_count_max);
|
|
seq_printf(s, "irq_mask = 0x%x\n", g_irq_mask);
|
|
seq_printf(s, "irq_mask_warning = 0x%x\n", g_irq_mask_warning);
|
|
seq_printf(s, "irq_disable = 0x%x\n", g_irq_disable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mt6370_pmu_dsv_debug_open(struct inode *inode,
|
|
struct file *file)
|
|
{
|
|
return single_open(file, mt6370_pmu_dsv_debug_show, NULL);
|
|
}
|
|
|
|
static const struct file_operations mt6370_pmu_dsv_debug_ops = {
|
|
.open = mt6370_pmu_dsv_debug_open,
|
|
.read = seq_read,
|
|
.write = mt6370_pmu_dsv_debug_write,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
#endif
|
|
|
|
int mt6370_pmu_dsv_debug_init(struct mt6370_pmu_chip *chip)
|
|
{
|
|
#ifdef CONFIG_DEBUG_FS
|
|
struct dentry *mt6370_pmu_dir;
|
|
#endif
|
|
g_db_vbst = mt6370_pmu_reg_read(chip, MT6370_PMU_REG_DBVBST);
|
|
g_vbst_adjustment = 0;
|
|
g_irq_count_max = IRQ_COUNT_MAX;
|
|
g_irq_mask = 1;
|
|
g_irq_mask_warning = 0;
|
|
g_irq_disable |= (1 << DSV_VPOS_OCP);
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
mt6370_pmu_dir = debugfs_create_dir("mt6370_pmu", NULL);
|
|
if (!mt6370_pmu_dir) {
|
|
pr_info("create /sys/kernel/debug/mt6370_pmu failed\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
debugfs_create_file("mt6370_pmu_dsv", 0644,
|
|
mt6370_pmu_dir, NULL,
|
|
&mt6370_pmu_dsv_debug_ops);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
MODULE_AUTHOR("Wilma Wu");
|
|
MODULE_DESCRIPTION("MT6370 Display Bias Debugfs Driver");
|
|
MODULE_LICENSE("GPL");
|
|
|