1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020 MediaTek Inc.
4 * Copyright (c) 2024 Collabora Ltd.
5 * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
11 #include <linux/regulator/driver.h>
12 #include <linux/regulator/of_regulator.h>
13 #include <linux/soc/mediatek/dvfsrc.h>
15 enum dvfsrc_regulator_id
{
21 struct dvfsrc_regulator_pdata
{
22 const struct regulator_desc
*descs
;
26 #define MTK_DVFSRC_VREG(match, _name, _volt_table) \
30 .ops = &dvfsrc_vcore_ops, \
31 .type = REGULATOR_VOLTAGE, \
32 .id = DVFSRC_ID_##_name, \
33 .owner = THIS_MODULE, \
34 .n_voltages = ARRAY_SIZE(_volt_table), \
35 .volt_table = _volt_table, \
38 static inline struct device
*to_dvfs_regulator_dev(struct regulator_dev
*rdev
)
40 return rdev_get_dev(rdev
)->parent
;
43 static inline struct device
*to_dvfsrc_dev(struct regulator_dev
*rdev
)
45 return to_dvfs_regulator_dev(rdev
)->parent
;
48 static int dvfsrc_get_cmd(int rdev_id
, enum mtk_dvfsrc_cmd
*cmd
)
52 *cmd
= MTK_DVFSRC_CMD_VCORE_LEVEL
;
55 *cmd
= MTK_DVFSRC_CMD_VSCP_LEVEL
;
64 static int dvfsrc_set_voltage_sel(struct regulator_dev
*rdev
,
65 unsigned int selector
)
67 struct device
*dvfsrc_dev
= to_dvfsrc_dev(rdev
);
68 enum mtk_dvfsrc_cmd req_cmd
;
69 int id
= rdev_get_id(rdev
);
72 ret
= dvfsrc_get_cmd(id
, &req_cmd
);
76 return mtk_dvfsrc_send_request(dvfsrc_dev
, req_cmd
, selector
);
79 static int dvfsrc_get_voltage_sel(struct regulator_dev
*rdev
)
81 struct device
*dvfsrc_dev
= to_dvfsrc_dev(rdev
);
82 enum mtk_dvfsrc_cmd query_cmd
;
83 int id
= rdev_get_id(rdev
);
86 ret
= dvfsrc_get_cmd(id
, &query_cmd
);
90 ret
= mtk_dvfsrc_query_info(dvfsrc_dev
, query_cmd
, &val
);
97 static const struct regulator_ops dvfsrc_vcore_ops
= {
98 .list_voltage
= regulator_list_voltage_table
,
99 .get_voltage_sel
= dvfsrc_get_voltage_sel
,
100 .set_voltage_sel
= dvfsrc_set_voltage_sel
,
103 static const unsigned int mt6873_voltages
[] = {
110 static const struct regulator_desc mt6873_regulators
[] = {
111 MTK_DVFSRC_VREG("dvfsrc-vcore", VCORE
, mt6873_voltages
),
112 MTK_DVFSRC_VREG("dvfsrc-vscp", VSCP
, mt6873_voltages
),
115 static const struct dvfsrc_regulator_pdata mt6873_data
= {
116 .descs
= mt6873_regulators
,
117 .size
= ARRAY_SIZE(mt6873_regulators
),
120 static const unsigned int mt8183_voltages
[] = {
125 static const struct regulator_desc mt8183_regulators
[] = {
126 MTK_DVFSRC_VREG("dvfsrc-vcore", VCORE
, mt8183_voltages
),
129 static const struct dvfsrc_regulator_pdata mt8183_data
= {
130 .descs
= mt8183_regulators
,
131 .size
= ARRAY_SIZE(mt8183_regulators
),
134 static const unsigned int mt8195_voltages
[] = {
141 static const struct regulator_desc mt8195_regulators
[] = {
142 MTK_DVFSRC_VREG("dvfsrc-vcore", VCORE
, mt8195_voltages
),
143 MTK_DVFSRC_VREG("dvfsrc-vscp", VSCP
, mt8195_voltages
),
146 static const struct dvfsrc_regulator_pdata mt8195_data
= {
147 .descs
= mt8195_regulators
,
148 .size
= ARRAY_SIZE(mt8195_regulators
),
151 static int dvfsrc_vcore_regulator_probe(struct platform_device
*pdev
)
153 struct regulator_config config
= { .dev
= &pdev
->dev
};
154 const struct dvfsrc_regulator_pdata
*pdata
;
157 pdata
= device_get_match_data(&pdev
->dev
);
161 for (i
= 0; i
< pdata
->size
; i
++) {
162 const struct regulator_desc
*vrdesc
= &pdata
->descs
[i
];
163 struct regulator_dev
*rdev
;
165 rdev
= devm_regulator_register(&pdev
->dev
, vrdesc
, &config
);
167 return dev_err_probe(&pdev
->dev
, PTR_ERR(rdev
),
168 "failed to register %s\n", vrdesc
->name
);
174 static const struct of_device_id mtk_dvfsrc_regulator_match
[] = {
175 { .compatible
= "mediatek,mt6873-dvfsrc-regulator", .data
= &mt6873_data
},
176 { .compatible
= "mediatek,mt8183-dvfsrc-regulator", .data
= &mt8183_data
},
177 { .compatible
= "mediatek,mt8192-dvfsrc-regulator", .data
= &mt6873_data
},
178 { .compatible
= "mediatek,mt8195-dvfsrc-regulator", .data
= &mt8195_data
},
181 MODULE_DEVICE_TABLE(of
, mtk_dvfsrc_regulator_match
);
183 static struct platform_driver mtk_dvfsrc_regulator_driver
= {
185 .name
= "mtk-dvfsrc-regulator",
186 .of_match_table
= mtk_dvfsrc_regulator_match
,
187 .probe_type
= PROBE_PREFER_ASYNCHRONOUS
,
189 .probe
= dvfsrc_vcore_regulator_probe
,
191 module_platform_driver(mtk_dvfsrc_regulator_driver
);
193 MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
194 MODULE_AUTHOR("Arvin wang <arvin.wang@mediatek.com>");
195 MODULE_DESCRIPTION("MediaTek DVFS Resource Collector Regulator driver");
196 MODULE_LICENSE("GPL");