Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Device driver for regulators in Hi6421V530 IC
0004 //
0005 // Copyright (c) <2017> HiSilicon Technologies Co., Ltd.
0006 //              http://www.hisilicon.com
0007 // Copyright (c) <2017> Linaro Ltd.
0008 //              https://www.linaro.org
0009 //
0010 // Author: Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>
0011 //         Guodong Xu <guodong.xu@linaro.org>
0012 
0013 #include <linux/mfd/hi6421-pmic.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/regmap.h>
0018 #include <linux/regulator/driver.h>
0019 
0020 /*
0021  * struct hi6421v530_regulator_info - hi6421v530 regulator information
0022  * @desc: regulator description
0023  * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep
0024  * @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only
0025  */
0026 struct hi6421v530_regulator_info {
0027     struct regulator_desc rdesc;
0028     u8 mode_mask;
0029     u32 eco_microamp;
0030 };
0031 
0032 /* HI6421v530 regulators */
0033 enum hi6421v530_regulator_id {
0034     HI6421V530_LDO3,
0035     HI6421V530_LDO9,
0036     HI6421V530_LDO11,
0037     HI6421V530_LDO15,
0038     HI6421V530_LDO16,
0039 };
0040 
0041 static const unsigned int ldo_3_voltages[] = {
0042     1800000, 1825000, 1850000, 1875000,
0043     1900000, 1925000, 1950000, 1975000,
0044     2000000, 2025000, 2050000, 2075000,
0045     2100000, 2125000, 2150000, 2200000,
0046 };
0047 
0048 static const unsigned int ldo_9_11_voltages[] = {
0049     1750000, 1800000, 1825000, 2800000,
0050     2850000, 2950000, 3000000, 3300000,
0051 };
0052 
0053 static const unsigned int ldo_15_16_voltages[] = {
0054     1750000, 1800000, 2400000, 2600000,
0055     2700000, 2850000, 2950000, 3000000,
0056 };
0057 
0058 static const struct regulator_ops hi6421v530_ldo_ops;
0059 
0060 #define HI6421V530_LDO_ENABLE_TIME (350)
0061 
0062 /*
0063  * _id - LDO id name string
0064  * v_table - voltage table
0065  * vreg - voltage select register
0066  * vmask - voltage select mask
0067  * ereg - enable register
0068  * emask - enable mask
0069  * odelay - off/on delay time in uS
0070  * ecomask - eco mode mask
0071  * ecoamp - eco mode load uppler limit in uA
0072  */
0073 #define HI6421V530_LDO(_ID, v_table, vreg, vmask, ereg, emask,      \
0074            odelay, ecomask, ecoamp) {               \
0075     .rdesc = {                          \
0076         .name        = #_ID,                \
0077         .of_match        = of_match_ptr(#_ID),          \
0078         .regulators_node = of_match_ptr("regulators"),      \
0079         .ops         = &hi6421v530_ldo_ops,         \
0080         .type        = REGULATOR_VOLTAGE,           \
0081         .id      = HI6421V530_##_ID,            \
0082         .owner       = THIS_MODULE,             \
0083         .n_voltages  = ARRAY_SIZE(v_table),         \
0084         .volt_table  = v_table,             \
0085         .vsel_reg    = HI6421_REG_TO_BUS_ADDR(vreg),    \
0086         .vsel_mask   = vmask,               \
0087         .enable_reg  = HI6421_REG_TO_BUS_ADDR(ereg),    \
0088         .enable_mask     = emask,               \
0089         .enable_time     = HI6421V530_LDO_ENABLE_TIME,      \
0090         .off_on_delay    = odelay,              \
0091     },                              \
0092     .mode_mask  = ecomask,                  \
0093     .eco_microamp   = ecoamp,                   \
0094 }
0095 
0096 /* HI6421V530 regulator information */
0097 
0098 static struct hi6421v530_regulator_info hi6421v530_regulator_info[] = {
0099     HI6421V530_LDO(LDO3, ldo_3_voltages, 0x061, 0xf, 0x060, 0x2,
0100            20000, 0x6, 8000),
0101     HI6421V530_LDO(LDO9, ldo_9_11_voltages, 0x06b, 0x7, 0x06a, 0x2,
0102            40000, 0x6, 8000),
0103     HI6421V530_LDO(LDO11, ldo_9_11_voltages, 0x06f, 0x7, 0x06e, 0x2,
0104            40000, 0x6, 8000),
0105     HI6421V530_LDO(LDO15, ldo_15_16_voltages, 0x077, 0x7, 0x076, 0x2,
0106            40000, 0x6, 8000),
0107     HI6421V530_LDO(LDO16, ldo_15_16_voltages, 0x079, 0x7, 0x078, 0x2,
0108            40000, 0x6, 8000),
0109 };
0110 
0111 static unsigned int hi6421v530_regulator_ldo_get_mode(
0112                     struct regulator_dev *rdev)
0113 {
0114     struct hi6421v530_regulator_info *info;
0115     unsigned int reg_val;
0116 
0117     info = rdev_get_drvdata(rdev);
0118     regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
0119 
0120     if (reg_val & (info->mode_mask))
0121         return REGULATOR_MODE_IDLE;
0122 
0123     return REGULATOR_MODE_NORMAL;
0124 }
0125 
0126 static int hi6421v530_regulator_ldo_set_mode(struct regulator_dev *rdev,
0127                         unsigned int mode)
0128 {
0129     struct hi6421v530_regulator_info *info;
0130     unsigned int new_mode;
0131 
0132     info = rdev_get_drvdata(rdev);
0133     switch (mode) {
0134     case REGULATOR_MODE_NORMAL:
0135         new_mode = 0;
0136         break;
0137     case REGULATOR_MODE_IDLE:
0138         new_mode = info->mode_mask;
0139         break;
0140     default:
0141         return -EINVAL;
0142     }
0143 
0144     regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
0145                info->mode_mask, new_mode);
0146 
0147     return 0;
0148 }
0149 
0150 
0151 static const struct regulator_ops hi6421v530_ldo_ops = {
0152     .is_enabled = regulator_is_enabled_regmap,
0153     .enable = regulator_enable_regmap,
0154     .disable = regulator_disable_regmap,
0155     .list_voltage = regulator_list_voltage_table,
0156     .map_voltage = regulator_map_voltage_ascend,
0157     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0158     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0159     .get_mode = hi6421v530_regulator_ldo_get_mode,
0160     .set_mode = hi6421v530_regulator_ldo_set_mode,
0161 };
0162 
0163 static int hi6421v530_regulator_probe(struct platform_device *pdev)
0164 {
0165     struct hi6421_pmic *pmic;
0166     struct regulator_dev *rdev;
0167     struct regulator_config config = { };
0168     unsigned int i;
0169 
0170     pmic = dev_get_drvdata(pdev->dev.parent);
0171     if (!pmic) {
0172         dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
0173         return -ENODEV;
0174     }
0175 
0176     for (i = 0; i < ARRAY_SIZE(hi6421v530_regulator_info); i++) {
0177         config.dev = pdev->dev.parent;
0178         config.regmap = pmic->regmap;
0179         config.driver_data = &hi6421v530_regulator_info[i];
0180 
0181         rdev = devm_regulator_register(&pdev->dev,
0182                 &hi6421v530_regulator_info[i].rdesc,
0183                 &config);
0184         if (IS_ERR(rdev)) {
0185             dev_err(&pdev->dev, "failed to register regulator %s\n",
0186                 hi6421v530_regulator_info[i].rdesc.name);
0187             return PTR_ERR(rdev);
0188         }
0189     }
0190     return 0;
0191 }
0192 
0193 static const struct platform_device_id hi6421v530_regulator_table[] = {
0194     { .name = "hi6421v530-regulator" },
0195     {},
0196 };
0197 MODULE_DEVICE_TABLE(platform, hi6421v530_regulator_table);
0198 
0199 static struct platform_driver hi6421v530_regulator_driver = {
0200     .id_table = hi6421v530_regulator_table,
0201     .driver = {
0202         .name   = "hi6421v530-regulator",
0203     },
0204     .probe  = hi6421v530_regulator_probe,
0205 };
0206 module_platform_driver(hi6421v530_regulator_driver);
0207 
0208 MODULE_AUTHOR("Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>");
0209 MODULE_DESCRIPTION("Hi6421v530 regulator driver");
0210 MODULE_LICENSE("GPL v2");