cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mtk-dvfsrc-regulator.c (5159B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Copyright (c) 2020 MediaTek Inc.
      4
      5#include <linux/err.h>
      6#include <linux/init.h>
      7#include <linux/module.h>
      8#include <linux/platform_device.h>
      9#include <linux/of_device.h>
     10#include <linux/of_platform.h>
     11#include <linux/regulator/driver.h>
     12#include <linux/regulator/of_regulator.h>
     13#include <linux/soc/mediatek/mtk_dvfsrc.h>
     14
     15#define DVFSRC_ID_VCORE		0
     16#define DVFSRC_ID_VSCP		1
     17
     18#define MT_DVFSRC_REGULAR(match, _name,	_volt_table)	\
     19[DVFSRC_ID_##_name] = {					\
     20	.desc = {					\
     21		.name = match,				\
     22		.of_match = of_match_ptr(match),	\
     23		.ops = &dvfsrc_vcore_ops,		\
     24		.type = REGULATOR_VOLTAGE,		\
     25		.id = DVFSRC_ID_##_name,		\
     26		.owner = THIS_MODULE,			\
     27		.n_voltages = ARRAY_SIZE(_volt_table),	\
     28		.volt_table = _volt_table,		\
     29	},	\
     30}
     31
     32/*
     33 * DVFSRC regulators' information
     34 *
     35 * @desc: standard fields of regulator description.
     36 * @voltage_selector:  Selector used for get_voltage_sel() and
     37 *			   set_voltage_sel() callbacks
     38 */
     39
     40struct dvfsrc_regulator {
     41	struct regulator_desc	desc;
     42};
     43
     44/*
     45 * MTK DVFSRC regulators' init data
     46 *
     47 * @size: num of regulators
     48 * @regulator_info: regulator info.
     49 */
     50struct dvfsrc_regulator_init_data {
     51	u32 size;
     52	struct dvfsrc_regulator *regulator_info;
     53};
     54
     55static inline struct device *to_dvfsrc_dev(struct regulator_dev *rdev)
     56{
     57	return rdev_get_dev(rdev)->parent;
     58}
     59
     60static int dvfsrc_set_voltage_sel(struct regulator_dev *rdev,
     61				  unsigned int selector)
     62{
     63	struct device *dvfsrc_dev = to_dvfsrc_dev(rdev);
     64	int id = rdev_get_id(rdev);
     65
     66	if (id == DVFSRC_ID_VCORE)
     67		mtk_dvfsrc_send_request(dvfsrc_dev,
     68					MTK_DVFSRC_CMD_VCORE_REQUEST,
     69					selector);
     70	else if (id == DVFSRC_ID_VSCP)
     71		mtk_dvfsrc_send_request(dvfsrc_dev,
     72					MTK_DVFSRC_CMD_VSCP_REQUEST,
     73					selector);
     74	else
     75		return -EINVAL;
     76
     77	return 0;
     78}
     79
     80static int dvfsrc_get_voltage_sel(struct regulator_dev *rdev)
     81{
     82	struct device *dvfsrc_dev = to_dvfsrc_dev(rdev);
     83	int id = rdev_get_id(rdev);
     84	int val, ret;
     85
     86	if (id == DVFSRC_ID_VCORE)
     87		ret = mtk_dvfsrc_query_info(dvfsrc_dev,
     88					    MTK_DVFSRC_CMD_VCORE_LEVEL_QUERY,
     89					    &val);
     90	else if (id == DVFSRC_ID_VSCP)
     91		ret = mtk_dvfsrc_query_info(dvfsrc_dev,
     92					    MTK_DVFSRC_CMD_VSCP_LEVEL_QUERY,
     93					    &val);
     94	else
     95		return -EINVAL;
     96
     97	if (ret != 0)
     98		return ret;
     99
    100	return val;
    101}
    102
    103static const struct regulator_ops dvfsrc_vcore_ops = {
    104	.list_voltage = regulator_list_voltage_table,
    105	.get_voltage_sel = dvfsrc_get_voltage_sel,
    106	.set_voltage_sel = dvfsrc_set_voltage_sel,
    107};
    108
    109static const unsigned int mt8183_voltages[] = {
    110	725000,
    111	800000,
    112};
    113
    114static struct dvfsrc_regulator mt8183_regulators[] = {
    115	MT_DVFSRC_REGULAR("dvfsrc-vcore", VCORE,
    116			  mt8183_voltages),
    117};
    118
    119static const struct dvfsrc_regulator_init_data regulator_mt8183_data = {
    120	.size = ARRAY_SIZE(mt8183_regulators),
    121	.regulator_info = &mt8183_regulators[0],
    122};
    123
    124static const unsigned int mt6873_voltages[] = {
    125	575000,
    126	600000,
    127	650000,
    128	725000,
    129};
    130
    131static struct dvfsrc_regulator mt6873_regulators[] = {
    132	MT_DVFSRC_REGULAR("dvfsrc-vcore", VCORE,
    133			  mt6873_voltages),
    134	MT_DVFSRC_REGULAR("dvfsrc-vscp", VSCP,
    135			  mt6873_voltages),
    136};
    137
    138static const struct dvfsrc_regulator_init_data regulator_mt6873_data = {
    139	.size = ARRAY_SIZE(mt6873_regulators),
    140	.regulator_info = &mt6873_regulators[0],
    141};
    142
    143static const struct of_device_id mtk_dvfsrc_regulator_match[] = {
    144	{
    145		.compatible = "mediatek,mt8183-dvfsrc",
    146		.data = &regulator_mt8183_data,
    147	}, {
    148		.compatible = "mediatek,mt8192-dvfsrc",
    149		.data = &regulator_mt6873_data,
    150	}, {
    151		.compatible = "mediatek,mt6873-dvfsrc",
    152		.data = &regulator_mt6873_data,
    153	}, {
    154		/* sentinel */
    155	},
    156};
    157MODULE_DEVICE_TABLE(of, mtk_dvfsrc_regulator_match);
    158
    159static int dvfsrc_vcore_regulator_probe(struct platform_device *pdev)
    160{
    161	const struct of_device_id *match;
    162	struct device *dev = &pdev->dev;
    163	struct regulator_config config = { };
    164	struct regulator_dev *rdev;
    165	const struct dvfsrc_regulator_init_data *regulator_init_data;
    166	struct dvfsrc_regulator *mt_regulators;
    167	int i;
    168
    169	match = of_match_node(mtk_dvfsrc_regulator_match, dev->parent->of_node);
    170
    171	if (!match) {
    172		dev_err(dev, "invalid compatible string\n");
    173		return -ENODEV;
    174	}
    175
    176	regulator_init_data = match->data;
    177
    178	mt_regulators = regulator_init_data->regulator_info;
    179	for (i = 0; i < regulator_init_data->size; i++) {
    180		config.dev = dev->parent;
    181		config.driver_data = (mt_regulators + i);
    182		rdev = devm_regulator_register(dev, &(mt_regulators + i)->desc,
    183					       &config);
    184		if (IS_ERR(rdev)) {
    185			dev_err(dev, "failed to register %s\n",
    186				(mt_regulators + i)->desc.name);
    187			return PTR_ERR(rdev);
    188		}
    189	}
    190
    191	return 0;
    192}
    193
    194static struct platform_driver mtk_dvfsrc_regulator_driver = {
    195	.driver = {
    196		.name  = "mtk-dvfsrc-regulator",
    197	},
    198	.probe = dvfsrc_vcore_regulator_probe,
    199};
    200
    201static int __init mtk_dvfsrc_regulator_init(void)
    202{
    203	return platform_driver_register(&mtk_dvfsrc_regulator_driver);
    204}
    205subsys_initcall(mtk_dvfsrc_regulator_init);
    206
    207static void __exit mtk_dvfsrc_regulator_exit(void)
    208{
    209	platform_driver_unregister(&mtk_dvfsrc_regulator_driver);
    210}
    211module_exit(mtk_dvfsrc_regulator_exit);
    212
    213MODULE_AUTHOR("Arvin wang <arvin.wang@mediatek.com>");
    214MODULE_LICENSE("GPL v2");