mp886x.c (8756B)
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#define MP8869_SYSCNTLREG2 0x02 26 27struct mp886x_cfg_info { 28 const struct regulator_ops *rops; 29 const unsigned int slew_rates[8]; 30 const int switch_freq[4]; 31 const u8 fs_reg; 32 const u8 fs_shift; 33}; 34 35struct mp886x_device_info { 36 struct device *dev; 37 struct regulator_desc desc; 38 struct regulator_init_data *regulator; 39 struct gpio_desc *en_gpio; 40 const struct mp886x_cfg_info *ci; 41 u32 r[2]; 42 unsigned int sel; 43}; 44 45static void mp886x_set_switch_freq(struct mp886x_device_info *di, 46 struct regmap *regmap, 47 u32 freq) 48{ 49 const struct mp886x_cfg_info *ci = di->ci; 50 int i; 51 52 for (i = 0; i < ARRAY_SIZE(ci->switch_freq); i++) { 53 if (freq == ci->switch_freq[i]) { 54 regmap_update_bits(regmap, ci->fs_reg, 55 0x3 << ci->fs_shift, i << ci->fs_shift); 56 return; 57 } 58 } 59 60 dev_err(di->dev, "invalid frequency %d\n", freq); 61} 62 63static 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 80static 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 94static 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 108static 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 115static 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 139static 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 = regulator_set_ramp_delay_regmap, 151}; 152 153static 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 .switch_freq = { 166 500000, 167 750000, 168 1000000, 169 1250000, 170 }, 171 .fs_reg = MP8869_SYSCNTLREG2, 172 .fs_shift = 4, 173}; 174 175static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) 176{ 177 struct mp886x_device_info *di = rdev_get_drvdata(rdev); 178 int ret, delta; 179 180 ret = mp8869_set_voltage_sel(rdev, sel); 181 if (ret < 0) 182 return ret; 183 184 delta = di->sel - sel; 185 if (abs(delta) <= 5) 186 ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, 187 MP886X_GO, 0); 188 di->sel = sel; 189 190 return ret; 191} 192 193static int mp8867_get_voltage_sel(struct regulator_dev *rdev) 194{ 195 struct mp886x_device_info *di = rdev_get_drvdata(rdev); 196 int ret, uv; 197 unsigned int val; 198 bool fbloop; 199 200 ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); 201 if (ret) 202 return ret; 203 204 fbloop = val & MP886X_V_BOOT; 205 206 val &= rdev->desc->vsel_mask; 207 val >>= ffs(rdev->desc->vsel_mask) - 1; 208 209 if (fbloop) { 210 uv = regulator_list_voltage_linear(rdev, val); 211 uv = mp8869_scale(uv, di->r[0], di->r[1]); 212 return regulator_map_voltage_linear(rdev, uv, uv); 213 } 214 215 return val; 216} 217 218static const struct regulator_ops mp8867_regulator_ops = { 219 .set_voltage_sel = mp8867_set_voltage_sel, 220 .get_voltage_sel = mp8867_get_voltage_sel, 221 .set_voltage_time_sel = regulator_set_voltage_time_sel, 222 .map_voltage = regulator_map_voltage_linear, 223 .list_voltage = regulator_list_voltage_linear, 224 .enable = regulator_enable_regmap, 225 .disable = regulator_disable_regmap, 226 .is_enabled = regulator_is_enabled_regmap, 227 .set_mode = mp886x_set_mode, 228 .get_mode = mp886x_get_mode, 229 .set_ramp_delay = regulator_set_ramp_delay_regmap, 230}; 231 232static const struct mp886x_cfg_info mp8867_ci = { 233 .rops = &mp8867_regulator_ops, 234 .slew_rates = { 235 64000, 236 32000, 237 16000, 238 8000, 239 4000, 240 2000, 241 1000, 242 500, 243 }, 244 .switch_freq = { 245 500000, 246 750000, 247 1000000, 248 1500000, 249 }, 250 .fs_reg = MP886X_SYSCNTLREG1, 251 .fs_shift = 1, 252}; 253 254static int mp886x_regulator_register(struct mp886x_device_info *di, 255 struct regulator_config *config) 256{ 257 struct regulator_desc *rdesc = &di->desc; 258 struct regulator_dev *rdev; 259 260 rdesc->name = "mp886x-reg"; 261 rdesc->supply_name = "vin"; 262 rdesc->ops = di->ci->rops; 263 rdesc->type = REGULATOR_VOLTAGE; 264 rdesc->n_voltages = 128; 265 rdesc->enable_reg = MP886X_SYSCNTLREG1; 266 rdesc->enable_mask = MP886X_EN; 267 rdesc->min_uV = 600000; 268 rdesc->uV_step = 10000; 269 rdesc->vsel_reg = MP886X_VSEL; 270 rdesc->vsel_mask = 0x3f; 271 rdesc->ramp_reg = MP886X_SYSCNTLREG1; 272 rdesc->ramp_mask = MP886X_SLEW_MASK; 273 rdesc->ramp_delay_table = di->ci->slew_rates; 274 rdesc->n_ramp_values = ARRAY_SIZE(di->ci->slew_rates); 275 rdesc->owner = THIS_MODULE; 276 277 rdev = devm_regulator_register(di->dev, &di->desc, config); 278 if (IS_ERR(rdev)) 279 return PTR_ERR(rdev); 280 di->sel = rdesc->ops->get_voltage_sel(rdev); 281 return 0; 282} 283 284static const struct regmap_config mp886x_regmap_config = { 285 .reg_bits = 8, 286 .val_bits = 8, 287}; 288 289static int mp886x_i2c_probe(struct i2c_client *client) 290{ 291 struct device *dev = &client->dev; 292 struct device_node *np = dev->of_node; 293 struct mp886x_device_info *di; 294 struct regulator_config config = { }; 295 struct regmap *regmap; 296 u32 freq; 297 int ret; 298 299 di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL); 300 if (!di) 301 return -ENOMEM; 302 303 di->regulator = of_get_regulator_init_data(dev, np, &di->desc); 304 if (!di->regulator) { 305 dev_err(dev, "Platform data not found!\n"); 306 return -EINVAL; 307 } 308 309 ret = of_property_read_u32_array(np, "mps,fb-voltage-divider", 310 di->r, 2); 311 if (ret) 312 return ret; 313 314 di->en_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); 315 if (IS_ERR(di->en_gpio)) 316 return PTR_ERR(di->en_gpio); 317 318 di->ci = of_device_get_match_data(dev); 319 di->dev = dev; 320 321 regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config); 322 if (IS_ERR(regmap)) { 323 dev_err(dev, "Failed to allocate regmap!\n"); 324 return PTR_ERR(regmap); 325 } 326 i2c_set_clientdata(client, di); 327 328 config.dev = di->dev; 329 config.init_data = di->regulator; 330 config.regmap = regmap; 331 config.driver_data = di; 332 config.of_node = np; 333 334 if (!of_property_read_u32(np, "mps,switch-frequency-hz", &freq)) 335 mp886x_set_switch_freq(di, regmap, freq); 336 337 ret = mp886x_regulator_register(di, &config); 338 if (ret < 0) 339 dev_err(dev, "Failed to register regulator!\n"); 340 return ret; 341} 342 343static const struct of_device_id mp886x_dt_ids[] = { 344 { 345 .compatible = "mps,mp8867", 346 .data = &mp8867_ci 347 }, 348 { 349 .compatible = "mps,mp8869", 350 .data = &mp8869_ci 351 }, 352 { } 353}; 354MODULE_DEVICE_TABLE(of, mp886x_dt_ids); 355 356static const struct i2c_device_id mp886x_id[] = { 357 { "mp886x", }, 358 { }, 359}; 360MODULE_DEVICE_TABLE(i2c, mp886x_id); 361 362static struct i2c_driver mp886x_regulator_driver = { 363 .driver = { 364 .name = "mp886x-regulator", 365 .of_match_table = of_match_ptr(mp886x_dt_ids), 366 }, 367 .probe_new = mp886x_i2c_probe, 368 .id_table = mp886x_id, 369}; 370module_i2c_driver(mp886x_regulator_driver); 371 372MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>"); 373MODULE_DESCRIPTION("MP886x regulator driver"); 374MODULE_LICENSE("GPL v2");