0001
0002
0003
0004
0005
0006
0007
0008
0009
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
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 *) ®ulators[i];
0186
0187 rdev = devm_regulator_register(&pdev->dev,
0188 ®ulators[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");