1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // MP8867/MP8869 regulator driver 4 // 5 // Copyright (C) 2020 Synaptics Incorporated 6 // 7 // Author: Jisheng Zhang <jszhang@kernel.org> 8 9 #include <linux/gpio/consumer.h> 10 #include <linux/i2c.h> 11 #include <linux/module.h> 12 #include <linux/of_device.h> 13 #include <linux/regmap.h> 14 #include <linux/regulator/driver.h> 15 #include <linux/regulator/of_regulator.h> 16 17 #define MP886X_VSEL 0x00 18 #define MP886X_V_BOOT (1 << 7) 19 #define MP886X_SYSCNTLREG1 0x01 20 #define MP886X_MODE (1 << 0) 21 #define MP886X_SLEW_SHIFT 3 22 #define MP886X_SLEW_MASK (0x7 << MP886X_SLEW_SHIFT) 23 #define MP886X_GO (1 << 6) 24 #define MP886X_EN (1 << 7) 25 26 struct mp886x_cfg_info { 27 const struct regulator_ops *rops; 28 const int slew_rates[8]; 29 }; 30 31 struct mp886x_device_info { 32 struct device *dev; 33 struct regulator_desc desc; 34 struct regulator_init_data *regulator; 35 struct gpio_desc *en_gpio; 36 const struct mp886x_cfg_info *ci; 37 u32 r[2]; 38 unsigned int sel; 39 }; 40 41 static int mp886x_set_ramp(struct regulator_dev *rdev, int ramp) 42 { 43 struct mp886x_device_info *di = rdev_get_drvdata(rdev); 44 const struct mp886x_cfg_info *ci = di->ci; 45 int reg = -1, i; 46 47 for (i = 0; i < ARRAY_SIZE(ci->slew_rates); i++) { 48 if (ramp <= ci->slew_rates[i]) 49 reg = i; 50 else 51 break; 52 } 53 54 if (reg < 0) { 55 dev_err(di->dev, "unsupported ramp value %d\n", ramp); 56 return -EINVAL; 57 } 58 59 return regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, 60 MP886X_SLEW_MASK, reg << MP886X_SLEW_SHIFT); 61 } 62 63 static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode) 64 { 65 switch (mode) { 66 case REGULATOR_MODE_FAST: 67 regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, 68 MP886X_MODE, MP886X_MODE); 69 break; 70 case REGULATOR_MODE_NORMAL: 71 regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, 72 MP886X_MODE, 0); 73 break; 74 default: 75 return -EINVAL; 76 } 77 return 0; 78 } 79 80 static unsigned int mp886x_get_mode(struct regulator_dev *rdev) 81 { 82 u32 val; 83 int ret; 84 85 ret = regmap_read(rdev->regmap, MP886X_SYSCNTLREG1, &val); 86 if (ret < 0) 87 return ret; 88 if (val & MP886X_MODE) 89 return REGULATOR_MODE_FAST; 90 else 91 return REGULATOR_MODE_NORMAL; 92 } 93 94 static int mp8869_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) 95 { 96 int ret; 97 98 ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, 99 MP886X_GO, MP886X_GO); 100 if (ret < 0) 101 return ret; 102 103 sel <<= ffs(rdev->desc->vsel_mask) - 1; 104 return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, 105 MP886X_V_BOOT | rdev->desc->vsel_mask, sel); 106 } 107 108 static inline unsigned int mp8869_scale(unsigned int uv, u32 r1, u32 r2) 109 { 110 u32 tmp = uv * r1 / r2; 111 112 return uv + tmp; 113 } 114 115 static int mp8869_get_voltage_sel(struct regulator_dev *rdev) 116 { 117 struct mp886x_device_info *di = rdev_get_drvdata(rdev); 118 int ret, uv; 119 unsigned int val; 120 bool fbloop; 121 122 ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); 123 if (ret) 124 return ret; 125 126 fbloop = val & MP886X_V_BOOT; 127 if (fbloop) { 128 uv = rdev->desc->min_uV; 129 uv = mp8869_scale(uv, di->r[0], di->r[1]); 130 return regulator_map_voltage_linear(rdev, uv, uv); 131 } 132 133 val &= rdev->desc->vsel_mask; 134 val >>= ffs(rdev->desc->vsel_mask) - 1; 135 136 return val; 137 } 138 139 static const struct regulator_ops mp8869_regulator_ops = { 140 .set_voltage_sel = mp8869_set_voltage_sel, 141 .get_voltage_sel = mp8869_get_voltage_sel, 142 .set_voltage_time_sel = regulator_set_voltage_time_sel, 143 .map_voltage = regulator_map_voltage_linear, 144 .list_voltage = regulator_list_voltage_linear, 145 .enable = regulator_enable_regmap, 146 .disable = regulator_disable_regmap, 147 .is_enabled = regulator_is_enabled_regmap, 148 .set_mode = mp886x_set_mode, 149 .get_mode = mp886x_get_mode, 150 .set_ramp_delay = mp886x_set_ramp, 151 }; 152 153 static const struct mp886x_cfg_info mp8869_ci = { 154 .rops = &mp8869_regulator_ops, 155 .slew_rates = { 156 40000, 157 30000, 158 20000, 159 10000, 160 5000, 161 2500, 162 1250, 163 625, 164 }, 165 }; 166 167 static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) 168 { 169 struct mp886x_device_info *di = rdev_get_drvdata(rdev); 170 int ret, delta; 171 172 ret = mp8869_set_voltage_sel(rdev, sel); 173 if (ret < 0) 174 return ret; 175 176 delta = di->sel - sel; 177 if (abs(delta) <= 5) 178 ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, 179 MP886X_GO, 0); 180 di->sel = sel; 181 182 return ret; 183 } 184 185 static int mp8867_get_voltage_sel(struct regulator_dev *rdev) 186 { 187 struct mp886x_device_info *di = rdev_get_drvdata(rdev); 188 int ret, uv; 189 unsigned int val; 190 bool fbloop; 191 192 ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); 193 if (ret) 194 return ret; 195 196 fbloop = val & MP886X_V_BOOT; 197 198 val &= rdev->desc->vsel_mask; 199 val >>= ffs(rdev->desc->vsel_mask) - 1; 200 201 if (fbloop) { 202 uv = regulator_list_voltage_linear(rdev, val); 203 uv = mp8869_scale(uv, di->r[0], di->r[1]); 204 return regulator_map_voltage_linear(rdev, uv, uv); 205 } 206 207 return val; 208 } 209 210 static const struct regulator_ops mp8867_regulator_ops = { 211 .set_voltage_sel = mp8867_set_voltage_sel, 212 .get_voltage_sel = mp8867_get_voltage_sel, 213 .set_voltage_time_sel = regulator_set_voltage_time_sel, 214 .map_voltage = regulator_map_voltage_linear, 215 .list_voltage = regulator_list_voltage_linear, 216 .enable = regulator_enable_regmap, 217 .disable = regulator_disable_regmap, 218 .is_enabled = regulator_is_enabled_regmap, 219 .set_mode = mp886x_set_mode, 220 .get_mode = mp886x_get_mode, 221 .set_ramp_delay = mp886x_set_ramp, 222 }; 223 224 static const struct mp886x_cfg_info mp8867_ci = { 225 .rops = &mp8867_regulator_ops, 226 .slew_rates = { 227 64000, 228 32000, 229 16000, 230 8000, 231 4000, 232 2000, 233 1000, 234 500, 235 }, 236 }; 237 238 static int mp886x_regulator_register(struct mp886x_device_info *di, 239 struct regulator_config *config) 240 { 241 struct regulator_desc *rdesc = &di->desc; 242 struct regulator_dev *rdev; 243 244 rdesc->name = "mp886x-reg"; 245 rdesc->supply_name = "vin"; 246 rdesc->ops = di->ci->rops; 247 rdesc->type = REGULATOR_VOLTAGE; 248 rdesc->n_voltages = 128; 249 rdesc->enable_reg = MP886X_SYSCNTLREG1; 250 rdesc->enable_mask = MP886X_EN; 251 rdesc->min_uV = 600000; 252 rdesc->uV_step = 10000; 253 rdesc->vsel_reg = MP886X_VSEL; 254 rdesc->vsel_mask = 0x3f; 255 rdesc->owner = THIS_MODULE; 256 257 rdev = devm_regulator_register(di->dev, &di->desc, config); 258 if (IS_ERR(rdev)) 259 return PTR_ERR(rdev); 260 di->sel = rdesc->ops->get_voltage_sel(rdev); 261 return 0; 262 } 263 264 static const struct regmap_config mp886x_regmap_config = { 265 .reg_bits = 8, 266 .val_bits = 8, 267 }; 268 269 static int mp886x_i2c_probe(struct i2c_client *client) 270 { 271 struct device *dev = &client->dev; 272 struct device_node *np = dev->of_node; 273 struct mp886x_device_info *di; 274 struct regulator_config config = { }; 275 struct regmap *regmap; 276 int ret; 277 278 di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL); 279 if (!di) 280 return -ENOMEM; 281 282 di->regulator = of_get_regulator_init_data(dev, np, &di->desc); 283 if (!di->regulator) { 284 dev_err(dev, "Platform data not found!\n"); 285 return -EINVAL; 286 } 287 288 ret = of_property_read_u32_array(np, "mps,fb-voltage-divider", 289 di->r, 2); 290 if (ret) 291 return ret; 292 293 di->en_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); 294 if (IS_ERR(di->en_gpio)) 295 return PTR_ERR(di->en_gpio); 296 297 di->ci = of_device_get_match_data(dev); 298 di->dev = dev; 299 300 regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config); 301 if (IS_ERR(regmap)) { 302 dev_err(dev, "Failed to allocate regmap!\n"); 303 return PTR_ERR(regmap); 304 } 305 i2c_set_clientdata(client, di); 306 307 config.dev = di->dev; 308 config.init_data = di->regulator; 309 config.regmap = regmap; 310 config.driver_data = di; 311 config.of_node = np; 312 313 ret = mp886x_regulator_register(di, &config); 314 if (ret < 0) 315 dev_err(dev, "Failed to register regulator!\n"); 316 return ret; 317 } 318 319 static const struct of_device_id mp886x_dt_ids[] = { 320 { 321 .compatible = "mps,mp8867", 322 .data = &mp8867_ci 323 }, 324 { 325 .compatible = "mps,mp8869", 326 .data = &mp8869_ci 327 }, 328 { } 329 }; 330 MODULE_DEVICE_TABLE(of, mp886x_dt_ids); 331 332 static const struct i2c_device_id mp886x_id[] = { 333 { "mp886x", }, 334 { }, 335 }; 336 MODULE_DEVICE_TABLE(i2c, mp886x_id); 337 338 static struct i2c_driver mp886x_regulator_driver = { 339 .driver = { 340 .name = "mp886x-regulator", 341 .of_match_table = of_match_ptr(mp886x_dt_ids), 342 }, 343 .probe_new = mp886x_i2c_probe, 344 .id_table = mp886x_id, 345 }; 346 module_i2c_driver(mp886x_regulator_driver); 347 348 MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>"); 349 MODULE_DESCRIPTION("MP886x regulator driver"); 350 MODULE_LICENSE("GPL v2"); 351