1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Device driver for regulators in Hisi IC 4 // 5 // Copyright (c) 2013 Linaro Ltd. 6 // Copyright (c) 2011 Hisilicon. 7 // Copyright (c) 2020-2021 Huawei Technologies Co., Ltd 8 // 9 // Guodong Xu <guodong.xu@linaro.org> 10 11 #include <linux/delay.h> 12 #include <linux/mfd/hi6421-spmi-pmic.h> 13 #include <linux/module.h> 14 #include <linux/platform_device.h> 15 #include <linux/regmap.h> 16 #include <linux/regulator/driver.h> 17 #include <linux/spmi.h> 18 19 struct hi6421_spmi_reg_info { 20 struct regulator_desc desc; 21 struct hi6421_spmi_pmic *pmic; 22 u8 eco_mode_mask; 23 u32 eco_uA; 24 25 /* Serialize regulator enable logic */ 26 struct mutex enable_mutex; 27 }; 28 29 static const unsigned int ldo3_voltages[] = { 30 1500000, 1550000, 1600000, 1650000, 31 1700000, 1725000, 1750000, 1775000, 32 1800000, 1825000, 1850000, 1875000, 33 1900000, 1925000, 1950000, 2000000 34 }; 35 36 static const unsigned int ldo4_voltages[] = { 37 1725000, 1750000, 1775000, 1800000, 38 1825000, 1850000, 1875000, 1900000 39 }; 40 41 static const unsigned int ldo9_voltages[] = { 42 1750000, 1800000, 1825000, 2800000, 43 2850000, 2950000, 3000000, 3300000 44 }; 45 46 static const unsigned int ldo15_voltages[] = { 47 1800000, 1850000, 2400000, 2600000, 48 2700000, 2850000, 2950000, 3000000 49 }; 50 51 static const unsigned int ldo17_voltages[] = { 52 2500000, 2600000, 2700000, 2800000, 53 3000000, 3100000, 3200000, 3300000 54 }; 55 56 static const unsigned int ldo34_voltages[] = { 57 2600000, 2700000, 2800000, 2900000, 58 3000000, 3100000, 3200000, 3300000 59 }; 60 61 /** 62 * HI6421V600_LDO() - specify a LDO power line 63 * @_id: LDO id name string 64 * @vtable: voltage table 65 * @ereg: enable register 66 * @emask: enable mask 67 * @vreg: voltage select register 68 * @odelay: off/on delay time in uS 69 * @etime: enable time in uS 70 * @ecomask: eco mode mask 71 * @ecoamp: eco mode load uppler limit in uA 72 */ 73 #define HI6421V600_LDO(_id, vtable, ereg, emask, vreg, \ 74 odelay, etime, ecomask, ecoamp) \ 75 [HI6421V600_##_id] = { \ 76 .desc = { \ 77 .name = #_id, \ 78 .of_match = of_match_ptr(#_id), \ 79 .regulators_node = of_match_ptr("regulators"), \ 80 .ops = &hi6421_spmi_ldo_rops, \ 81 .type = REGULATOR_VOLTAGE, \ 82 .id = HI6421V600_##_id, \ 83 .owner = THIS_MODULE, \ 84 .volt_table = vtable, \ 85 .n_voltages = ARRAY_SIZE(vtable), \ 86 .vsel_mask = (1 << (ARRAY_SIZE(vtable) - 1)) - 1, \ 87 .vsel_reg = vreg, \ 88 .enable_reg = ereg, \ 89 .enable_mask = emask, \ 90 .enable_time = etime, \ 91 .ramp_delay = etime, \ 92 .off_on_delay = odelay, \ 93 }, \ 94 .eco_mode_mask = ecomask, \ 95 .eco_uA = ecoamp, \ 96 } 97 98 static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev) 99 { 100 struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev); 101 struct hi6421_spmi_pmic *pmic = sreg->pmic; 102 int ret; 103 104 /* cannot enable more than one regulator at one time */ 105 mutex_lock(&sreg->enable_mutex); 106 107 ret = regmap_update_bits(pmic->regmap, rdev->desc->enable_reg, 108 rdev->desc->enable_mask, 109 rdev->desc->enable_mask); 110 111 /* Avoid powering up multiple devices at the same time */ 112 usleep_range(rdev->desc->off_on_delay, rdev->desc->off_on_delay + 60); 113 114 mutex_unlock(&sreg->enable_mutex); 115 116 return ret; 117 } 118 119 static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev) 120 { 121 struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev); 122 struct hi6421_spmi_pmic *pmic = sreg->pmic; 123 124 return regmap_update_bits(pmic->regmap, rdev->desc->enable_reg, 125 rdev->desc->enable_mask, 0); 126 } 127 128 static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) 129 { 130 struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev); 131 struct hi6421_spmi_pmic *pmic = sreg->pmic; 132 u32 reg_val; 133 134 regmap_read(pmic->regmap, rdev->desc->enable_reg, ®_val); 135 136 if (reg_val & sreg->eco_mode_mask) 137 return REGULATOR_MODE_IDLE; 138 139 return REGULATOR_MODE_NORMAL; 140 } 141 142 static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev, 143 unsigned int mode) 144 { 145 struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev); 146 struct hi6421_spmi_pmic *pmic = sreg->pmic; 147 u32 val; 148 149 switch (mode) { 150 case REGULATOR_MODE_NORMAL: 151 val = 0; 152 break; 153 case REGULATOR_MODE_IDLE: 154 val = sreg->eco_mode_mask << (ffs(sreg->eco_mode_mask) - 1); 155 break; 156 default: 157 return -EINVAL; 158 } 159 160 return regmap_update_bits(pmic->regmap, rdev->desc->enable_reg, 161 sreg->eco_mode_mask, val); 162 } 163 164 static unsigned int 165 hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev, 166 int input_uV, int output_uV, 167 int load_uA) 168 { 169 struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev); 170 171 if (!sreg->eco_uA || ((unsigned int)load_uA > sreg->eco_uA)) 172 return REGULATOR_MODE_NORMAL; 173 174 return REGULATOR_MODE_IDLE; 175 } 176 177 static const struct regulator_ops hi6421_spmi_ldo_rops = { 178 .is_enabled = regulator_is_enabled_regmap, 179 .enable = hi6421_spmi_regulator_enable, 180 .disable = hi6421_spmi_regulator_disable, 181 .list_voltage = regulator_list_voltage_table, 182 .map_voltage = regulator_map_voltage_iterate, 183 .get_voltage_sel = regulator_get_voltage_sel_regmap, 184 .set_voltage_sel = regulator_set_voltage_sel_regmap, 185 .get_mode = hi6421_spmi_regulator_get_mode, 186 .set_mode = hi6421_spmi_regulator_set_mode, 187 .get_optimum_mode = hi6421_spmi_regulator_get_optimum_mode, 188 }; 189 190 /* HI6421v600 regulators with known registers */ 191 enum hi6421_spmi_regulator_id { 192 HI6421V600_LDO3, 193 HI6421V600_LDO4, 194 HI6421V600_LDO9, 195 HI6421V600_LDO15, 196 HI6421V600_LDO16, 197 HI6421V600_LDO17, 198 HI6421V600_LDO33, 199 HI6421V600_LDO34, 200 }; 201 202 static struct hi6421_spmi_reg_info regulator_info[] = { 203 HI6421V600_LDO(LDO3, ldo3_voltages, 204 0x16, 0x01, 0x51, 205 20000, 120, 206 0, 0), 207 HI6421V600_LDO(LDO4, ldo4_voltages, 208 0x17, 0x01, 0x52, 209 20000, 120, 210 0x10, 10000), 211 HI6421V600_LDO(LDO9, ldo9_voltages, 212 0x1c, 0x01, 0x57, 213 20000, 360, 214 0x10, 10000), 215 HI6421V600_LDO(LDO15, ldo15_voltages, 216 0x21, 0x01, 0x5c, 217 20000, 360, 218 0x10, 10000), 219 HI6421V600_LDO(LDO16, ldo15_voltages, 220 0x22, 0x01, 0x5d, 221 20000, 360, 222 0x10, 10000), 223 HI6421V600_LDO(LDO17, ldo17_voltages, 224 0x23, 0x01, 0x5e, 225 20000, 120, 226 0x10, 10000), 227 HI6421V600_LDO(LDO33, ldo17_voltages, 228 0x32, 0x01, 0x6d, 229 20000, 120, 230 0, 0), 231 HI6421V600_LDO(LDO34, ldo34_voltages, 232 0x33, 0x01, 0x6e, 233 20000, 120, 234 0, 0), 235 }; 236 237 static int hi6421_spmi_regulator_probe(struct platform_device *pdev) 238 { 239 struct device *pmic_dev = pdev->dev.parent; 240 struct regulator_config config = { }; 241 struct hi6421_spmi_reg_info *sreg; 242 struct hi6421_spmi_reg_info *info; 243 struct device *dev = &pdev->dev; 244 struct hi6421_spmi_pmic *pmic; 245 struct regulator_dev *rdev; 246 int i; 247 248 /* 249 * This driver is meant to be called by hi6421-spmi-core, 250 * which should first set drvdata. If this doesn't happen, hit 251 * a warn on and return. 252 */ 253 pmic = dev_get_drvdata(pmic_dev); 254 if (WARN_ON(!pmic)) 255 return -ENODEV; 256 257 sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL); 258 if (!sreg) 259 return -ENOMEM; 260 261 sreg->pmic = pmic; 262 mutex_init(&sreg->enable_mutex); 263 264 for (i = 0; i < ARRAY_SIZE(regulator_info); i++) { 265 info = ®ulator_info[i]; 266 267 config.dev = pdev->dev.parent; 268 config.driver_data = sreg; 269 config.regmap = pmic->regmap; 270 271 rdev = devm_regulator_register(dev, &info->desc, &config); 272 if (IS_ERR(rdev)) { 273 dev_err(dev, "failed to register %s\n", 274 info->desc.name); 275 return PTR_ERR(rdev); 276 } 277 } 278 279 return 0; 280 } 281 282 static const struct platform_device_id hi6421_spmi_regulator_table[] = { 283 { .name = "hi6421v600-regulator" }, 284 {}, 285 }; 286 MODULE_DEVICE_TABLE(platform, hi6421_spmi_regulator_table); 287 288 static struct platform_driver hi6421_spmi_regulator_driver = { 289 .id_table = hi6421_spmi_regulator_table, 290 .driver = { 291 .name = "hi6421v600-regulator", 292 }, 293 .probe = hi6421_spmi_regulator_probe, 294 }; 295 module_platform_driver(hi6421_spmi_regulator_driver); 296 297 MODULE_DESCRIPTION("Hi6421v600 SPMI regulator driver"); 298 MODULE_LICENSE("GPL v2"); 299 300