^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (c) 2019 five technologies GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // Author: Markus Reichl <m.reichl@fivetechno.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/regulator/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define VOL_MIN_IDX 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define VOL_MAX_IDX 0x7ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define MP8859_VOUT_L_REG 0 //3 lo Bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define MP8859_VOUT_H_REG 1 //8 hi Bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define MP8859_VOUT_GO_REG 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define MP8859_IOUT_LIM_REG 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define MP8859_CTL1_REG 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MP8859_CTL2_REG 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MP8859_RESERVED1_REG 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define MP8859_RESERVED2_REG 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define MP8859_RESERVED3_REG 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MP8859_STATUS_REG 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define MP8859_INTERRUPT_REG 0x0A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MP8859_MASK_REG 0x0B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MP8859_ID1_REG 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MP8859_MFR_ID_REG 0x27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define MP8859_DEV_ID_REG 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MP8859_IC_REV_REG 0x29
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define MP8859_MAX_REG 0x29
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define MP8859_GO_BIT 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int mp8859_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ret = regmap_write(rdev->regmap, MP8859_VOUT_L_REG, sel & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ret = regmap_write(rdev->regmap, MP8859_VOUT_H_REG, sel >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) ret = regmap_update_bits(rdev->regmap, MP8859_VOUT_GO_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) MP8859_GO_BIT, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static int mp8859_get_voltage_sel(struct regulator_dev *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned int val_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ret = regmap_read(rdev->regmap, MP8859_VOUT_H_REG, &val_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) val = val_tmp << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ret = regmap_read(rdev->regmap, MP8859_VOUT_L_REG, &val_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) val |= val_tmp & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static const struct linear_range mp8859_dcdc_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) REGULATOR_LINEAR_RANGE(0, VOL_MIN_IDX, VOL_MAX_IDX, 10000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static const struct regmap_config mp8859_regmap = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .max_register = MP8859_MAX_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .cache_type = REGCACHE_RBTREE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static const struct regulator_ops mp8859_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .set_voltage_sel = mp8859_set_voltage_sel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .get_voltage_sel = mp8859_get_voltage_sel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .list_voltage = regulator_list_voltage_linear_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static const struct regulator_desc mp8859_regulators[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .type = REGULATOR_VOLTAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .name = "mp8859_dcdc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .supply_name = "vin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .of_match = of_match_ptr("mp8859_dcdc"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .n_voltages = VOL_MAX_IDX + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .linear_ranges = mp8859_dcdc_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .n_linear_ranges = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .ops = &mp8859_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int mp8859_i2c_probe(struct i2c_client *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct regulator_config config = {.dev = &i2c->dev};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct regmap *regmap = devm_regmap_init_i2c(i2c, &mp8859_regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct regulator_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (IS_ERR(regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ret = PTR_ERR(regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) rdev = devm_regulator_register(&i2c->dev, &mp8859_regulators[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (IS_ERR(rdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ret = PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) dev_err(&i2c->dev, "failed to register %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) mp8859_regulators[0].name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static const struct of_device_id mp8859_dt_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {.compatible = "mps,mp8859"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) MODULE_DEVICE_TABLE(of, mp8859_dt_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static const struct i2c_device_id mp8859_i2c_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) { "mp8859", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) MODULE_DEVICE_TABLE(i2c, mp8859_i2c_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static struct i2c_driver mp8859_regulator_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .name = "mp8859",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .of_match_table = of_match_ptr(mp8859_dt_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .probe_new = mp8859_i2c_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .id_table = mp8859_i2c_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) module_i2c_driver(mp8859_regulator_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) MODULE_DESCRIPTION("Monolithic Power Systems MP8859 voltage regulator driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) MODULE_AUTHOR("Markus Reichl <m.reichl@fivetechno.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) MODULE_LICENSE("GPL v2");