1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2024-11-19 13:27:49 +00:00
a155-U-u1/kernel-5.10/drivers/misc/mediatek/dvfsrc/dvfsrc-met.c
2024-03-11 06:53:12 +11:00

387 lines
8.2 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/arm-smccc.h>
#include <linux/clk.h>
#include <linux/interconnect.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/interconnect.h>
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/soc/mediatek/mtk_sip_svc.h>
#include <linux/soc/mediatek/mtk_dvfsrc.h>
#include "dvfsrc-met.h"
static struct mtk_dvfsrc_met *dvfsrc_drv;
enum met_info_index {
INFO_OPP_IDX = 0,
INFO_FREQ_IDX,
INFO_VCORE_IDX,
INFO_SPM_LEVEL_IDX,
INFO_MAX,
};
static unsigned int met_vcorefs_info[INFO_MAX];
static char *met_info_name[INFO_MAX] = {
"OPP",
"FREQ",
"VCORE",
"x__SPM_LEVEL",
};
int vcorefs_get_num_opp(void)
{
return mtk_dvfsrc_query_opp_info(MTK_DVFSRC_NUM_DVFS_OPP);
}
EXPORT_SYMBOL(vcorefs_get_num_opp);
int vcorefs_get_opp_info_num(void)
{
return INFO_MAX;
}
EXPORT_SYMBOL(vcorefs_get_opp_info_num);
char **vcorefs_get_opp_info_name(void)
{
return met_info_name;
}
EXPORT_SYMBOL(vcorefs_get_opp_info_name);
unsigned int *vcorefs_get_opp_info(void)
{
struct mtk_dvfsrc_met *dvfsrc = dvfsrc_drv;
if (dvfsrc) {
met_vcorefs_info[INFO_OPP_IDX] =
mtk_dvfsrc_query_opp_info(MTK_DVFSRC_CURR_DVFS_OPP);
met_vcorefs_info[INFO_FREQ_IDX] =
mtk_dvfsrc_query_opp_info(MTK_DVFSRC_CURR_DRAM_KHZ);
met_vcorefs_info[INFO_VCORE_IDX] =
mtk_dvfsrc_query_opp_info(MTK_DVFSRC_CURR_VCORE_UV);
met_vcorefs_info[INFO_SPM_LEVEL_IDX] =
dvfsrc->dvd->met->get_current_level(dvfsrc);
}
return met_vcorefs_info;
}
EXPORT_SYMBOL(vcorefs_get_opp_info);
int vcorefs_get_src_req_num(void)
{
struct mtk_dvfsrc_met *dvfsrc = dvfsrc_drv;
if (dvfsrc)
return dvfsrc->dvd->met->dvfsrc_get_src_req_num();
return 0;
}
EXPORT_SYMBOL(vcorefs_get_src_req_num);
char **vcorefs_get_src_req_name(void)
{
struct mtk_dvfsrc_met *dvfsrc = dvfsrc_drv;
if (dvfsrc)
return dvfsrc->dvd->met->dvfsrc_get_src_req_name();
return NULL;
}
EXPORT_SYMBOL(vcorefs_get_src_req_name);
unsigned int *vcorefs_get_src_req(void)
{
struct mtk_dvfsrc_met *dvfsrc = dvfsrc_drv;
if (dvfsrc)
return dvfsrc->dvd->met->dvfsrc_get_src_req(dvfsrc);
return NULL;
}
EXPORT_SYMBOL(vcorefs_get_src_req);
int get_cur_ddr_ratio(void)
{
struct mtk_dvfsrc_met *dvfsrc = dvfsrc_drv;
if (dvfsrc)
return dvfsrc->dvd->met->dvfsrc_get_ddr_ratio(dvfsrc);
return 0;
}
EXPORT_SYMBOL(get_cur_ddr_ratio);
static ssize_t dvfsrc_met_dump_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
char *p = buf;
char *buff_end = p + PAGE_SIZE;
char **name;
unsigned int *value;
int i, res_num;
p += snprintf(p, buff_end - p,
"NUM_VCORE_OPP : %d\n",
vcorefs_get_num_opp());
res_num = vcorefs_get_opp_info_num();
name = vcorefs_get_opp_info_name();
value = vcorefs_get_opp_info();
p += snprintf(p, buff_end - p,
"NUM_OPP_INFO : %d\n", res_num);
for (i = 0; i < res_num; i++) {
p += snprintf(p, buff_end - p,
"%s : %d\n",
name[i], value[i]);
}
res_num = vcorefs_get_src_req_num();
name = vcorefs_get_src_req_name();
value = vcorefs_get_src_req();
p += snprintf(p, buff_end - p,
"NUM SRC_REQ: %d\n", res_num);
if (name && value) {
for (i = 0; i < res_num; i++) {
p += snprintf(p, buff_end - p,
"%s : %d\n",
name[i], value[i]);
}
}
return p - buf;
}
static DEVICE_ATTR_RO(dvfsrc_met_dump);
static struct attribute *dvfsrc_attrs[] = {
&dev_attr_dvfsrc_met_dump.attr,
NULL,
};
static struct attribute_group dvfsrc_met_attr_group = {
.attrs = dvfsrc_attrs,
};
static int dvfsrc_met_register_sysfs(struct device *dev)
{
int ret;
ret = sysfs_create_group(&dev->kobj, &dvfsrc_met_attr_group);
if (ret)
return ret;
ret = sysfs_create_link(&dev->parent->kobj, &dev->kobj,
"met");
return ret;
}
static void dvfsrc_met_unregister_sysfs(struct device *dev)
{
sysfs_remove_link(&dev->parent->kobj, "met");
sysfs_remove_group(&dev->kobj, &dvfsrc_met_attr_group);
}
static const struct dvfsrc_met_data mt6873_data = {
.met = &mt6873_met_config,
.version = 0x6873,
};
static const struct dvfsrc_met_data mt6853_data = {
.met = &mt6873_met_config,
.version = 0x6853,
};
static const struct dvfsrc_met_data mt6789_data = {
.met = &mt6873_met_config,
.version = 0x6789,
};
static const struct dvfsrc_met_data mt6885_data = {
.met = &mt6873_met_config,
.version = 0x6885,
};
static const struct dvfsrc_met_data mt6893_data = {
.met = &mt6873_met_config,
.version = 0x6893,
};
static const struct dvfsrc_met_data mt6833_data = {
.met = &mt6873_met_config,
.version = 0x6833,
};
static const struct dvfsrc_met_data mt6877_data = {
.met = &mt6873_met_config,
.version = 0x6877,
};
static const struct dvfsrc_met_data mt6983_data = {
.met = &mt6983_met_config,
.version = 0x6983,
};
static const struct dvfsrc_met_data mt6895_data = {
.met = &mt6983_met_config,
.version = 0x6895,
};
static const struct dvfsrc_met_data mt6879_data = {
.met = &mt6983_met_config,
.version = 0x6879,
};
static const struct dvfsrc_met_data mt6855_data = {
.met = &mt6983_met_config,
.version = 0x6855,
};
static const struct of_device_id dvfsrc_met_of_match[] = {
#if IS_ENABLED(CONFIG_MTK_DVFSRC_MET_MT6873)
{
.compatible = "mediatek,mt6873-dvfsrc",
.data = &mt6873_data,
}, {
.compatible = "mediatek,mt6853-dvfsrc",
.data = &mt6853_data,
}, {
.compatible = "mediatek,mt6789-dvfsrc",
.data = &mt6789_data,
}, {
.compatible = "mediatek,mt6885-dvfsrc",
.data = &mt6885_data,
}, {
.compatible = "mediatek,mt6893-dvfsrc",
.data = &mt6893_data,
}, {
.compatible = "mediatek,mt6833-dvfsrc",
.data = &mt6833_data,
}, {
.compatible = "mediatek,mt6877-dvfsrc",
.data = &mt6877_data,
}, {
.compatible = "mediatek,mt6983-dvfsrc",
.data = &mt6983_data,
}, {
.compatible = "mediatek,mt6895-dvfsrc",
.data = &mt6895_data,
}, {
.compatible = "mediatek,mt6879-dvfsrc",
.data = &mt6879_data,
}, {
.compatible = "mediatek,mt6855-dvfsrc",
.data = &mt6855_data,
},
#endif
{
/* sentinel */
},
};
static int mtk_dvfsrc_met_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct device *dev = &pdev->dev;
struct platform_device *parent_dev;
struct resource *res;
struct mtk_dvfsrc_met *dvfsrc;
match = of_match_node(dvfsrc_met_of_match, dev->parent->of_node);
if (!match) {
dev_info(dev, "invalid compatible string\n");
return -ENODEV;
}
dvfsrc = devm_kzalloc(&pdev->dev, sizeof(*dvfsrc), GFP_KERNEL);
if (!dvfsrc)
return -ENOMEM;
parent_dev = to_platform_device(dev->parent);
dvfsrc->dvd = match->data;
dvfsrc->dev = &pdev->dev;
res = platform_get_resource_byname(parent_dev,
IORESOURCE_MEM, "dvfsrc");
if (!res) {
dev_info(dev, "dvfsrc debug resource not found\n");
return -ENODEV;
}
dvfsrc->regs = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (IS_ERR(dvfsrc->regs))
return PTR_ERR(dvfsrc->regs);
dvfsrc->dvfsrc_vcore_power =
regulator_get_optional(dvfsrc->dev, "rc-vcore");
if (IS_ERR(dvfsrc->dvfsrc_vcore_power)) {
dev_info(dvfsrc->dev, "get dvfsrc_vcore failed = %ld\n",
PTR_ERR(dvfsrc->dvfsrc_vcore_power));
dvfsrc->dvfsrc_vcore_power = NULL;
}
dvfsrc->bw_path = of_icc_get(dvfsrc->dev, "icc-bw");
if (IS_ERR(dvfsrc->bw_path)) {
dev_info(dvfsrc->dev, "get icc-bw fail\n");
dvfsrc->bw_path = NULL;
}
dvfsrc->hrt_path = of_icc_get(dvfsrc->dev, "icc-hrt-bw");
if (IS_ERR(dvfsrc->hrt_path)) {
dev_info(dvfsrc->dev, "get icc-hrt_bw fail\n");
dvfsrc->hrt_path = NULL;
}
dvfsrc_drv = dvfsrc;
platform_set_drvdata(pdev, dvfsrc);
dvfsrc_met_register_sysfs(dev);
return 0;
}
static int mtk_dvfsrc_met_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
dvfsrc_met_unregister_sysfs(dev);
dvfsrc_drv = NULL;
return 0;
}
static const struct of_device_id mtk_dvfsrc_met_of_match[] = {
{
.compatible = "mediatek,dvfsrc-met",
}, {
/* sentinel */
},
};
static struct platform_driver mtk_dvfsrc_met_driver = {
.probe = mtk_dvfsrc_met_probe,
.remove = mtk_dvfsrc_met_remove,
.driver = {
.name = "mtk-dvfsrc-met",
.of_match_table = of_match_ptr(mtk_dvfsrc_met_of_match),
},
};
int __init mtk_dvfsrc_met_init(void)
{
return platform_driver_register(&mtk_dvfsrc_met_driver);
}
void __exit mtk_dvfsrc_met_exit(void)
{
platform_driver_unregister(&mtk_dvfsrc_met_driver);
}