Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Device driver for regulators in Hi655x IC
0004 //
0005 // Copyright (c) 2016 HiSilicon Ltd.
0006 //
0007 // Authors:
0008 // Chen Feng <puck.chen@hisilicon.com>
0009 // Fei  Wang <w.f@huawei.com>
0010 
0011 #include <linux/bitops.h>
0012 #include <linux/device.h>
0013 #include <linux/err.h>
0014 #include <linux/module.h>
0015 #include <linux/io.h>
0016 #include <linux/of.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/regmap.h>
0019 #include <linux/regulator/driver.h>
0020 #include <linux/regulator/machine.h>
0021 #include <linux/regulator/of_regulator.h>
0022 #include <linux/mfd/hi655x-pmic.h>
0023 
0024 struct hi655x_regulator {
0025     unsigned int disable_reg;
0026     unsigned int status_reg;
0027     struct regulator_desc rdesc;
0028 };
0029 
0030 /* LDO7 & LDO10 */
0031 static const unsigned int ldo7_voltages[] = {
0032     1800000, 1850000, 2850000, 2900000,
0033     3000000, 3100000, 3200000, 3300000,
0034 };
0035 
0036 static const unsigned int ldo19_voltages[] = {
0037     1800000, 1850000, 1900000, 1750000,
0038     2800000, 2850000, 2900000, 3000000,
0039 };
0040 
0041 static const unsigned int ldo22_voltages[] = {
0042      900000, 1000000, 1050000, 1100000,
0043     1150000, 1175000, 1185000, 1200000,
0044 };
0045 
0046 enum hi655x_regulator_id {
0047     HI655X_LDO0,
0048     HI655X_LDO1,
0049     HI655X_LDO2,
0050     HI655X_LDO3,
0051     HI655X_LDO4,
0052     HI655X_LDO5,
0053     HI655X_LDO6,
0054     HI655X_LDO7,
0055     HI655X_LDO8,
0056     HI655X_LDO9,
0057     HI655X_LDO10,
0058     HI655X_LDO11,
0059     HI655X_LDO12,
0060     HI655X_LDO13,
0061     HI655X_LDO14,
0062     HI655X_LDO15,
0063     HI655X_LDO16,
0064     HI655X_LDO17,
0065     HI655X_LDO18,
0066     HI655X_LDO19,
0067     HI655X_LDO20,
0068     HI655X_LDO21,
0069     HI655X_LDO22,
0070 };
0071 
0072 static int hi655x_is_enabled(struct regulator_dev *rdev)
0073 {
0074     unsigned int value = 0;
0075     const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
0076 
0077     regmap_read(rdev->regmap, regulator->status_reg, &value);
0078     return (value & rdev->desc->enable_mask);
0079 }
0080 
0081 static int hi655x_disable(struct regulator_dev *rdev)
0082 {
0083     const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
0084 
0085     return regmap_write(rdev->regmap, regulator->disable_reg,
0086                 rdev->desc->enable_mask);
0087 }
0088 
0089 static const struct regulator_ops hi655x_regulator_ops = {
0090     .enable = regulator_enable_regmap,
0091     .disable = hi655x_disable,
0092     .is_enabled = hi655x_is_enabled,
0093     .list_voltage = regulator_list_voltage_table,
0094     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0095     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0096 };
0097 
0098 static const struct regulator_ops hi655x_ldo_linear_ops = {
0099     .enable = regulator_enable_regmap,
0100     .disable = hi655x_disable,
0101     .is_enabled = hi655x_is_enabled,
0102     .list_voltage = regulator_list_voltage_linear,
0103     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0104     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0105 };
0106 
0107 #define HI655X_LDO(_ID, vreg, vmask, ereg, dreg,                 \
0108            sreg, cmask, vtable) {                        \
0109     .rdesc = {                                               \
0110         .name            = #_ID,                         \
0111         .of_match        = of_match_ptr(#_ID),           \
0112         .ops             = &hi655x_regulator_ops,        \
0113         .regulators_node = of_match_ptr("regulators"),   \
0114         .type            = REGULATOR_VOLTAGE,            \
0115         .id              = HI655X_##_ID,                 \
0116         .owner           = THIS_MODULE,                  \
0117         .n_voltages      = ARRAY_SIZE(vtable),           \
0118         .volt_table      = vtable,                       \
0119         .vsel_reg        = HI655X_BUS_ADDR(vreg),        \
0120         .vsel_mask       = vmask,                        \
0121         .enable_reg      = HI655X_BUS_ADDR(ereg),        \
0122         .enable_mask     = BIT(cmask),                   \
0123     },                                                       \
0124     .disable_reg = HI655X_BUS_ADDR(dreg),                    \
0125     .status_reg = HI655X_BUS_ADDR(sreg),                     \
0126 }
0127 
0128 #define HI655X_LDO_LINEAR(_ID, vreg, vmask, ereg, dreg,          \
0129               sreg, cmask, minv, nvolt, vstep) {     \
0130     .rdesc = {                                               \
0131         .name            = #_ID,                         \
0132         .of_match        = of_match_ptr(#_ID),           \
0133         .ops             = &hi655x_ldo_linear_ops,       \
0134         .regulators_node = of_match_ptr("regulators"),   \
0135         .type            = REGULATOR_VOLTAGE,            \
0136         .id              = HI655X_##_ID,                 \
0137         .owner           = THIS_MODULE,                  \
0138         .min_uV          = minv,                         \
0139         .n_voltages      = nvolt,                        \
0140         .uV_step         = vstep,                        \
0141         .vsel_reg        = HI655X_BUS_ADDR(vreg),        \
0142         .vsel_mask       = vmask,                        \
0143         .enable_reg      = HI655X_BUS_ADDR(ereg),        \
0144         .enable_mask     = BIT(cmask),                   \
0145     },                                                       \
0146     .disable_reg = HI655X_BUS_ADDR(dreg),                    \
0147     .status_reg = HI655X_BUS_ADDR(sreg),                     \
0148 }
0149 
0150 static const struct hi655x_regulator regulators[] = {
0151     HI655X_LDO_LINEAR(LDO2, 0x72, 0x07, 0x29, 0x2a, 0x2b, 0x01,
0152               2500000, 8, 100000),
0153     HI655X_LDO(LDO7, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x06, ldo7_voltages),
0154     HI655X_LDO(LDO10, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x01, ldo7_voltages),
0155     HI655X_LDO_LINEAR(LDO13, 0x7e, 0x07, 0x2c, 0x2d, 0x2e, 0x04,
0156               1600000, 8, 50000),
0157     HI655X_LDO_LINEAR(LDO14, 0x7f, 0x07, 0x2c, 0x2d, 0x2e, 0x05,
0158               2500000, 8, 100000),
0159     HI655X_LDO_LINEAR(LDO15, 0x80, 0x07, 0x2c, 0x2d, 0x2e, 0x06,
0160               1600000, 8, 50000),
0161     HI655X_LDO_LINEAR(LDO17, 0x82, 0x07, 0x2f, 0x30, 0x31, 0x00,
0162               2500000, 8, 100000),
0163     HI655X_LDO(LDO19, 0x84, 0x07, 0x2f, 0x30, 0x31, 0x02, ldo19_voltages),
0164     HI655X_LDO_LINEAR(LDO21, 0x86, 0x07, 0x2f, 0x30, 0x31, 0x04,
0165               1650000, 8, 50000),
0166     HI655X_LDO(LDO22, 0x87, 0x07, 0x2f, 0x30, 0x31, 0x05, ldo22_voltages),
0167 };
0168 
0169 static int hi655x_regulator_probe(struct platform_device *pdev)
0170 {
0171     unsigned int i;
0172     struct hi655x_pmic *pmic;
0173     struct regulator_config config = { };
0174     struct regulator_dev *rdev;
0175 
0176     pmic = dev_get_drvdata(pdev->dev.parent);
0177     if (!pmic) {
0178         dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
0179         return -ENODEV;
0180     }
0181 
0182     config.dev = pdev->dev.parent;
0183     config.regmap = pmic->regmap;
0184     for (i = 0; i < ARRAY_SIZE(regulators); i++) {
0185         config.driver_data = (void *) &regulators[i];
0186 
0187         rdev = devm_regulator_register(&pdev->dev,
0188                            &regulators[i].rdesc,
0189                            &config);
0190         if (IS_ERR(rdev)) {
0191             dev_err(&pdev->dev, "failed to register regulator %s\n",
0192                 regulators[i].rdesc.name);
0193             return PTR_ERR(rdev);
0194         }
0195     }
0196     return 0;
0197 }
0198 
0199 static const struct platform_device_id hi655x_regulator_table[] = {
0200     { .name = "hi655x-regulator" },
0201     {},
0202 };
0203 MODULE_DEVICE_TABLE(platform, hi655x_regulator_table);
0204 
0205 static struct platform_driver hi655x_regulator_driver = {
0206     .id_table = hi655x_regulator_table,
0207     .driver = {
0208         .name   = "hi655x-regulator",
0209     },
0210     .probe  = hi655x_regulator_probe,
0211 };
0212 module_platform_driver(hi655x_regulator_driver);
0213 
0214 MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
0215 MODULE_DESCRIPTION("Hisilicon Hi655x regulator driver");
0216 MODULE_LICENSE("GPL v2");