Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright (c) 2020 MediaTek Inc.
0004 
0005 #include <linux/err.h>
0006 #include <linux/init.h>
0007 #include <linux/module.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/of_device.h>
0010 #include <linux/of_platform.h>
0011 #include <linux/regulator/driver.h>
0012 #include <linux/regulator/of_regulator.h>
0013 #include <linux/soc/mediatek/mtk_dvfsrc.h>
0014 
0015 #define DVFSRC_ID_VCORE     0
0016 #define DVFSRC_ID_VSCP      1
0017 
0018 #define MT_DVFSRC_REGULAR(match, _name, _volt_table)    \
0019 [DVFSRC_ID_##_name] = {                 \
0020     .desc = {                   \
0021         .name = match,              \
0022         .of_match = of_match_ptr(match),    \
0023         .ops = &dvfsrc_vcore_ops,       \
0024         .type = REGULATOR_VOLTAGE,      \
0025         .id = DVFSRC_ID_##_name,        \
0026         .owner = THIS_MODULE,           \
0027         .n_voltages = ARRAY_SIZE(_volt_table),  \
0028         .volt_table = _volt_table,      \
0029     },  \
0030 }
0031 
0032 /*
0033  * DVFSRC regulators' information
0034  *
0035  * @desc: standard fields of regulator description.
0036  * @voltage_selector:  Selector used for get_voltage_sel() and
0037  *             set_voltage_sel() callbacks
0038  */
0039 
0040 struct dvfsrc_regulator {
0041     struct regulator_desc   desc;
0042 };
0043 
0044 /*
0045  * MTK DVFSRC regulators' init data
0046  *
0047  * @size: num of regulators
0048  * @regulator_info: regulator info.
0049  */
0050 struct dvfsrc_regulator_init_data {
0051     u32 size;
0052     struct dvfsrc_regulator *regulator_info;
0053 };
0054 
0055 static inline struct device *to_dvfsrc_dev(struct regulator_dev *rdev)
0056 {
0057     return rdev_get_dev(rdev)->parent;
0058 }
0059 
0060 static int dvfsrc_set_voltage_sel(struct regulator_dev *rdev,
0061                   unsigned int selector)
0062 {
0063     struct device *dvfsrc_dev = to_dvfsrc_dev(rdev);
0064     int id = rdev_get_id(rdev);
0065 
0066     if (id == DVFSRC_ID_VCORE)
0067         mtk_dvfsrc_send_request(dvfsrc_dev,
0068                     MTK_DVFSRC_CMD_VCORE_REQUEST,
0069                     selector);
0070     else if (id == DVFSRC_ID_VSCP)
0071         mtk_dvfsrc_send_request(dvfsrc_dev,
0072                     MTK_DVFSRC_CMD_VSCP_REQUEST,
0073                     selector);
0074     else
0075         return -EINVAL;
0076 
0077     return 0;
0078 }
0079 
0080 static int dvfsrc_get_voltage_sel(struct regulator_dev *rdev)
0081 {
0082     struct device *dvfsrc_dev = to_dvfsrc_dev(rdev);
0083     int id = rdev_get_id(rdev);
0084     int val, ret;
0085 
0086     if (id == DVFSRC_ID_VCORE)
0087         ret = mtk_dvfsrc_query_info(dvfsrc_dev,
0088                         MTK_DVFSRC_CMD_VCORE_LEVEL_QUERY,
0089                         &val);
0090     else if (id == DVFSRC_ID_VSCP)
0091         ret = mtk_dvfsrc_query_info(dvfsrc_dev,
0092                         MTK_DVFSRC_CMD_VSCP_LEVEL_QUERY,
0093                         &val);
0094     else
0095         return -EINVAL;
0096 
0097     if (ret != 0)
0098         return ret;
0099 
0100     return val;
0101 }
0102 
0103 static const struct regulator_ops dvfsrc_vcore_ops = {
0104     .list_voltage = regulator_list_voltage_table,
0105     .get_voltage_sel = dvfsrc_get_voltage_sel,
0106     .set_voltage_sel = dvfsrc_set_voltage_sel,
0107 };
0108 
0109 static const unsigned int mt8183_voltages[] = {
0110     725000,
0111     800000,
0112 };
0113 
0114 static struct dvfsrc_regulator mt8183_regulators[] = {
0115     MT_DVFSRC_REGULAR("dvfsrc-vcore", VCORE,
0116               mt8183_voltages),
0117 };
0118 
0119 static const struct dvfsrc_regulator_init_data regulator_mt8183_data = {
0120     .size = ARRAY_SIZE(mt8183_regulators),
0121     .regulator_info = &mt8183_regulators[0],
0122 };
0123 
0124 static const unsigned int mt6873_voltages[] = {
0125     575000,
0126     600000,
0127     650000,
0128     725000,
0129 };
0130 
0131 static struct dvfsrc_regulator mt6873_regulators[] = {
0132     MT_DVFSRC_REGULAR("dvfsrc-vcore", VCORE,
0133               mt6873_voltages),
0134     MT_DVFSRC_REGULAR("dvfsrc-vscp", VSCP,
0135               mt6873_voltages),
0136 };
0137 
0138 static const struct dvfsrc_regulator_init_data regulator_mt6873_data = {
0139     .size = ARRAY_SIZE(mt6873_regulators),
0140     .regulator_info = &mt6873_regulators[0],
0141 };
0142 
0143 static const struct of_device_id mtk_dvfsrc_regulator_match[] = {
0144     {
0145         .compatible = "mediatek,mt8183-dvfsrc",
0146         .data = &regulator_mt8183_data,
0147     }, {
0148         .compatible = "mediatek,mt8192-dvfsrc",
0149         .data = &regulator_mt6873_data,
0150     }, {
0151         .compatible = "mediatek,mt6873-dvfsrc",
0152         .data = &regulator_mt6873_data,
0153     }, {
0154         /* sentinel */
0155     },
0156 };
0157 MODULE_DEVICE_TABLE(of, mtk_dvfsrc_regulator_match);
0158 
0159 static int dvfsrc_vcore_regulator_probe(struct platform_device *pdev)
0160 {
0161     const struct of_device_id *match;
0162     struct device *dev = &pdev->dev;
0163     struct regulator_config config = { };
0164     struct regulator_dev *rdev;
0165     const struct dvfsrc_regulator_init_data *regulator_init_data;
0166     struct dvfsrc_regulator *mt_regulators;
0167     int i;
0168 
0169     match = of_match_node(mtk_dvfsrc_regulator_match, dev->parent->of_node);
0170 
0171     if (!match) {
0172         dev_err(dev, "invalid compatible string\n");
0173         return -ENODEV;
0174     }
0175 
0176     regulator_init_data = match->data;
0177 
0178     mt_regulators = regulator_init_data->regulator_info;
0179     for (i = 0; i < regulator_init_data->size; i++) {
0180         config.dev = dev->parent;
0181         config.driver_data = (mt_regulators + i);
0182         rdev = devm_regulator_register(dev, &(mt_regulators + i)->desc,
0183                            &config);
0184         if (IS_ERR(rdev)) {
0185             dev_err(dev, "failed to register %s\n",
0186                 (mt_regulators + i)->desc.name);
0187             return PTR_ERR(rdev);
0188         }
0189     }
0190 
0191     return 0;
0192 }
0193 
0194 static struct platform_driver mtk_dvfsrc_regulator_driver = {
0195     .driver = {
0196         .name  = "mtk-dvfsrc-regulator",
0197     },
0198     .probe = dvfsrc_vcore_regulator_probe,
0199 };
0200 
0201 static int __init mtk_dvfsrc_regulator_init(void)
0202 {
0203     return platform_driver_register(&mtk_dvfsrc_regulator_driver);
0204 }
0205 subsys_initcall(mtk_dvfsrc_regulator_init);
0206 
0207 static void __exit mtk_dvfsrc_regulator_exit(void)
0208 {
0209     platform_driver_unregister(&mtk_dvfsrc_regulator_driver);
0210 }
0211 module_exit(mtk_dvfsrc_regulator_exit);
0212 
0213 MODULE_AUTHOR("Arvin wang <arvin.wang@mediatek.com>");
0214 MODULE_LICENSE("GPL v2");