1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Copyright (c) 2019 five technologies GmbH 4 // Author: Markus Reichl <m.reichl@fivetechno.de> 5 6 #include <linux/module.h> 7 #include <linux/i2c.h> 8 #include <linux/of.h> 9 #include <linux/regulator/driver.h> 10 #include <linux/regmap.h> 11 12 13 #define VOL_MIN_IDX 0x00 14 #define VOL_MAX_IDX 0x7ff 15 16 /* Register definitions */ 17 #define MP8859_VOUT_L_REG 0 //3 lo Bits 18 #define MP8859_VOUT_H_REG 1 //8 hi Bits 19 #define MP8859_VOUT_GO_REG 2 20 #define MP8859_IOUT_LIM_REG 3 21 #define MP8859_CTL1_REG 4 22 #define MP8859_CTL2_REG 5 23 #define MP8859_RESERVED1_REG 6 24 #define MP8859_RESERVED2_REG 7 25 #define MP8859_RESERVED3_REG 8 26 #define MP8859_STATUS_REG 9 27 #define MP8859_INTERRUPT_REG 0x0A 28 #define MP8859_MASK_REG 0x0B 29 #define MP8859_ID1_REG 0x0C 30 #define MP8859_MFR_ID_REG 0x27 31 #define MP8859_DEV_ID_REG 0x28 32 #define MP8859_IC_REV_REG 0x29 33 34 #define MP8859_MAX_REG 0x29 35 36 #define MP8859_GO_BIT 0x01 37 38 #define MP8859_IOUT_LIM_MASK 0x7f 39 40 #define MP8859_ENABLE_MASK 0x80 41 #define MP8859_DISCHG_EN_MASK 0x10 42 #define MP8859_MODE_MASK 0x08 43 44 #define MP8859_PG_MASK 0x80 45 #define MP8859_OTP_MASK 0x40 46 #define MP8859_OTW_MASK 0x20 47 #define MP8859_CC_CV_MASK 0x10 48 49 static int mp8859_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) 50 { 51 int ret; 52 53 ret = regmap_write(rdev->regmap, MP8859_VOUT_L_REG, sel & 0x7); 54 55 if (ret) 56 return ret; 57 ret = regmap_write(rdev->regmap, MP8859_VOUT_H_REG, sel >> 3); 58 59 if (ret) 60 return ret; 61 ret = regmap_update_bits(rdev->regmap, MP8859_VOUT_GO_REG, 62 MP8859_GO_BIT, 1); 63 return ret; 64 } 65 66 static int mp8859_get_voltage_sel(struct regulator_dev *rdev) 67 { 68 unsigned int val_tmp; 69 unsigned int val; 70 int ret; 71 72 ret = regmap_read(rdev->regmap, MP8859_VOUT_H_REG, &val_tmp); 73 74 if (ret) 75 return ret; 76 val = val_tmp << 3; 77 78 ret = regmap_read(rdev->regmap, MP8859_VOUT_L_REG, &val_tmp); 79 80 if (ret) 81 return ret; 82 val |= val_tmp & 0x07; 83 return val; 84 } 85 86 static int mp8859_set_voltage_time_sel(struct regulator_dev *rdev, 87 unsigned int from, unsigned int to) 88 { 89 int change; 90 91 /* The voltage ramps at 1mV/uS, selectors are 10mV */ 92 if (from > to) 93 change = from - to; 94 else 95 change = to - from; 96 97 return change * 10 * 1000; 98 } 99 100 static unsigned int mp8859_get_mode(struct regulator_dev *rdev) 101 { 102 unsigned int val; 103 int ret; 104 105 ret = regmap_read(rdev->regmap, MP8859_CTL1_REG, &val); 106 if (ret != 0) { 107 dev_err(&rdev->dev, "Failed to read mode: %d\n", ret); 108 return 0; 109 } 110 111 if (val & MP8859_MODE_MASK) 112 return REGULATOR_MODE_FAST; 113 else 114 return REGULATOR_MODE_NORMAL; 115 } 116 117 static int mp8859_set_mode(struct regulator_dev *rdev, unsigned int mode) 118 { 119 unsigned int val; 120 121 switch (mode) { 122 case REGULATOR_MODE_FAST: 123 val = MP8859_MODE_MASK; 124 break; 125 case REGULATOR_MODE_NORMAL: 126 val = 0; 127 break; 128 default: 129 return -EINVAL; 130 } 131 132 return regmap_update_bits(rdev->regmap, MP8859_CTL1_REG, 133 MP8859_MODE_MASK, val); 134 } 135 136 static int mp8859_set_current_limit(struct regulator_dev *rdev, 137 int min_uA, int max_uA) 138 { 139 unsigned int cur_val, new_val; 140 int ret, i; 141 142 /* Steps of 50mA */ 143 new_val = max_uA / 50000; 144 if (new_val > MP8859_IOUT_LIM_MASK) 145 return -EINVAL; 146 if (new_val == 0) 147 return -EINVAL; 148 149 /* 150 * If the regulator is limiting then ramp gradually as per 151 * datasheet, otherwise just set the value directly. 152 */ 153 ret = regmap_read(rdev->regmap, MP8859_STATUS_REG, &cur_val); 154 if (ret != 0) 155 return ret; 156 if (!(cur_val & MP8859_CC_CV_MASK)) { 157 return regmap_update_bits(rdev->regmap, MP8859_IOUT_LIM_REG, 158 MP8859_IOUT_LIM_MASK, new_val); 159 } 160 161 ret = regmap_read(rdev->regmap, MP8859_IOUT_LIM_REG, &cur_val); 162 if (ret != 0) 163 return ret; 164 165 if (cur_val >= new_val) { 166 for (i = cur_val; i >= new_val; i--) { 167 ret = regmap_update_bits(rdev->regmap, 168 MP8859_IOUT_LIM_REG, 169 MP8859_IOUT_LIM_MASK, 170 cur_val - i); 171 if (ret != 0) 172 return ret; 173 } 174 } else { 175 for (i = cur_val; i <= new_val; i++) { 176 ret = regmap_update_bits(rdev->regmap, 177 MP8859_IOUT_LIM_REG, 178 MP8859_IOUT_LIM_MASK, 179 cur_val + i); 180 if (ret != 0) 181 return ret; 182 } 183 } 184 185 return 0; 186 } 187 188 static int mp8859_get_status(struct regulator_dev *rdev) 189 { 190 unsigned int val; 191 int ret; 192 193 /* Output status is only meaingful when enabled */ 194 ret = regmap_read(rdev->regmap, MP8859_CTL1_REG, &val); 195 if (ret != 0) 196 return ret; 197 if (!(val & MP8859_ENABLE_MASK)) 198 return REGULATOR_STATUS_UNDEFINED; 199 200 ret = regmap_read(rdev->regmap, MP8859_STATUS_REG, &val); 201 if (ret != 0) 202 return ret; 203 204 if (val & MP8859_PG_MASK) 205 return REGULATOR_STATUS_ON; 206 else 207 return REGULATOR_STATUS_ERROR; 208 } 209 210 static int mp8859_get_error_flags(struct regulator_dev *rdev, 211 unsigned int *flags) 212 { 213 unsigned int status, enabled; 214 int ret; 215 216 *flags = 0; 217 218 /* Output status is only meaingful when enabled */ 219 ret = regmap_read(rdev->regmap, MP8859_CTL1_REG, &enabled); 220 if (ret != 0) 221 return ret; 222 enabled &= MP8859_ENABLE_MASK; 223 224 ret = regmap_read(rdev->regmap, MP8859_STATUS_REG, &status); 225 if (ret != 0) 226 return ret; 227 228 if (enabled && !(status & MP8859_PG_MASK)) 229 status |= REGULATOR_ERROR_FAIL; 230 if (status & MP8859_OTP_MASK) 231 status |= REGULATOR_ERROR_OVER_TEMP; 232 if (status & MP8859_OTW_MASK) 233 status |= REGULATOR_ERROR_OVER_TEMP_WARN; 234 if (status & MP8859_CC_CV_MASK) 235 status |= REGULATOR_ERROR_OVER_CURRENT; 236 237 return 0; 238 } 239 240 static const struct linear_range mp8859_dcdc_ranges[] = { 241 REGULATOR_LINEAR_RANGE(0, VOL_MIN_IDX, VOL_MAX_IDX, 10000), 242 }; 243 244 static bool mp8859_readable(struct device *dev, unsigned int reg) 245 { 246 switch (reg) { 247 case MP8859_VOUT_L_REG: 248 case MP8859_VOUT_H_REG: 249 case MP8859_VOUT_GO_REG: 250 case MP8859_IOUT_LIM_REG: 251 case MP8859_CTL1_REG: 252 case MP8859_CTL2_REG: 253 case MP8859_STATUS_REG: 254 case MP8859_INTERRUPT_REG: 255 case MP8859_MASK_REG: 256 case MP8859_ID1_REG: 257 case MP8859_MFR_ID_REG: 258 case MP8859_DEV_ID_REG: 259 case MP8859_IC_REV_REG: 260 return true; 261 default: 262 return false; 263 } 264 } 265 266 static bool mp8859_volatile(struct device *dev, unsigned int reg) 267 { 268 switch (reg) { 269 case MP8859_VOUT_GO_REG: 270 case MP8859_STATUS_REG: 271 case MP8859_INTERRUPT_REG: 272 return true; 273 default: 274 return false; 275 } 276 } 277 278 static const struct regmap_config mp8859_regmap = { 279 .reg_bits = 8, 280 .val_bits = 8, 281 .max_register = MP8859_MAX_REG, 282 .cache_type = REGCACHE_MAPLE, 283 .readable_reg = mp8859_readable, 284 .volatile_reg = mp8859_volatile, 285 }; 286 287 static const struct regulator_ops mp8859_ops = { 288 .set_voltage_sel = mp8859_set_voltage_sel, 289 .get_voltage_sel = mp8859_get_voltage_sel, 290 .list_voltage = regulator_list_voltage_linear_range, 291 .set_voltage_time_sel = mp8859_set_voltage_time_sel, 292 .enable = regulator_enable_regmap, 293 .disable = regulator_disable_regmap, 294 .is_enabled = regulator_is_enabled_regmap, 295 .set_mode = mp8859_set_mode, 296 .get_mode = mp8859_get_mode, 297 .set_active_discharge = regulator_set_active_discharge_regmap, 298 .set_current_limit = mp8859_set_current_limit, 299 .get_status = mp8859_get_status, 300 .get_error_flags = mp8859_get_error_flags, 301 }; 302 303 static const struct regulator_desc mp8859_regulators[] = { 304 { 305 .id = 0, 306 .type = REGULATOR_VOLTAGE, 307 .name = "mp8859_dcdc", 308 .supply_name = "vin", 309 .of_match = of_match_ptr("mp8859_dcdc"), 310 .n_voltages = VOL_MAX_IDX + 1, 311 .linear_ranges = mp8859_dcdc_ranges, 312 .n_linear_ranges = 1, 313 .enable_reg = MP8859_CTL1_REG, 314 .enable_mask = MP8859_ENABLE_MASK, 315 .enable_val = MP8859_ENABLE_MASK, 316 .active_discharge_reg = MP8859_CTL1_REG, 317 .active_discharge_on = MP8859_DISCHG_EN_MASK, 318 .active_discharge_mask = MP8859_DISCHG_EN_MASK, 319 .ops = &mp8859_ops, 320 .owner = THIS_MODULE, 321 }, 322 }; 323 324 static int mp8859_i2c_probe(struct i2c_client *i2c) 325 { 326 int ret; 327 struct regulator_config config = {.dev = &i2c->dev}; 328 struct regmap *regmap = devm_regmap_init_i2c(i2c, &mp8859_regmap); 329 struct regulator_dev *rdev; 330 unsigned int val, rev; 331 332 if (IS_ERR(regmap)) { 333 ret = PTR_ERR(regmap); 334 dev_err(&i2c->dev, "regmap init failed: %d\n", ret); 335 return ret; 336 } 337 338 ret = regmap_read(regmap, MP8859_MFR_ID_REG, &val); 339 if (ret != 0) { 340 dev_err(&i2c->dev, "Failed to read manufacturer ID: %d\n", ret); 341 return ret; 342 } 343 if (val != 0x9) { 344 dev_err(&i2c->dev, "Manufacturer ID %x != 9\n", val); 345 return -EINVAL; 346 } 347 348 ret = regmap_read(regmap, MP8859_DEV_ID_REG, &val); 349 if (ret != 0) { 350 dev_err(&i2c->dev, "Failed to read device ID: %d\n", ret); 351 return ret; 352 } 353 if (val != 0x58) { 354 dev_err(&i2c->dev, "Manufacturer ID %x != 0x58\n", val); 355 return -EINVAL; 356 } 357 358 ret = regmap_read(regmap, MP8859_IC_REV_REG, &rev); 359 if (ret != 0) { 360 dev_err(&i2c->dev, "Failed to read device revision: %d\n", ret); 361 return ret; 362 } 363 ret = regmap_read(regmap, MP8859_ID1_REG, &val); 364 if (ret != 0) { 365 dev_err(&i2c->dev, "Failed to read device ID1: %d\n", ret); 366 return ret; 367 } 368 dev_info(&i2c->dev, "MP8859-%04d revision %d\n", val, rev); 369 370 rdev = devm_regulator_register(&i2c->dev, &mp8859_regulators[0], 371 &config); 372 373 if (IS_ERR(rdev)) { 374 ret = PTR_ERR(rdev); 375 dev_err(&i2c->dev, "failed to register %s: %d\n", 376 mp8859_regulators[0].name, ret); 377 return ret; 378 } 379 return 0; 380 } 381 382 static const struct of_device_id mp8859_dt_id[] __maybe_unused = { 383 {.compatible = "mps,mp8859"}, 384 {}, 385 }; 386 MODULE_DEVICE_TABLE(of, mp8859_dt_id); 387 388 static const struct i2c_device_id mp8859_i2c_id[] = { 389 { "mp8859", }, 390 { }, 391 }; 392 MODULE_DEVICE_TABLE(i2c, mp8859_i2c_id); 393 394 static struct i2c_driver mp8859_regulator_driver = { 395 .driver = { 396 .name = "mp8859", 397 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 398 .of_match_table = of_match_ptr(mp8859_dt_id), 399 }, 400 .probe = mp8859_i2c_probe, 401 .id_table = mp8859_i2c_id, 402 }; 403 404 module_i2c_driver(mp8859_regulator_driver); 405 406 MODULE_DESCRIPTION("Monolithic Power Systems MP8859 voltage regulator driver"); 407 MODULE_AUTHOR("Markus Reichl <m.reichl@fivetechno.de>"); 408 MODULE_LICENSE("GPL v2"); 409