Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright (c) 2019 five technologies GmbH
0004 // Author: Markus Reichl <m.reichl@fivetechno.de>
0005 
0006 #include <linux/module.h>
0007 #include <linux/i2c.h>
0008 #include <linux/of.h>
0009 #include <linux/regulator/driver.h>
0010 #include <linux/regmap.h>
0011 
0012 
0013 #define VOL_MIN_IDX         0x00
0014 #define VOL_MAX_IDX         0x7ff
0015 
0016 /* Register definitions */
0017 #define MP8859_VOUT_L_REG       0    //3 lo Bits
0018 #define MP8859_VOUT_H_REG       1    //8 hi Bits
0019 #define MP8859_VOUT_GO_REG      2
0020 #define MP8859_IOUT_LIM_REG     3
0021 #define MP8859_CTL1_REG         4
0022 #define MP8859_CTL2_REG         5
0023 #define MP8859_RESERVED1_REG        6
0024 #define MP8859_RESERVED2_REG        7
0025 #define MP8859_RESERVED3_REG        8
0026 #define MP8859_STATUS_REG       9
0027 #define MP8859_INTERRUPT_REG        0x0A
0028 #define MP8859_MASK_REG         0x0B
0029 #define MP8859_ID1_REG          0x0C
0030 #define MP8859_MFR_ID_REG       0x27
0031 #define MP8859_DEV_ID_REG       0x28
0032 #define MP8859_IC_REV_REG       0x29
0033 
0034 #define MP8859_MAX_REG          0x29
0035 
0036 #define MP8859_GO_BIT           0x01
0037 
0038 
0039 static int mp8859_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
0040 {
0041     int ret;
0042 
0043     ret = regmap_write(rdev->regmap, MP8859_VOUT_L_REG, sel & 0x7);
0044 
0045     if (ret)
0046         return ret;
0047     ret = regmap_write(rdev->regmap, MP8859_VOUT_H_REG, sel >> 3);
0048 
0049     if (ret)
0050         return ret;
0051     ret = regmap_update_bits(rdev->regmap, MP8859_VOUT_GO_REG,
0052                     MP8859_GO_BIT, 1);
0053     return ret;
0054 }
0055 
0056 static int mp8859_get_voltage_sel(struct regulator_dev *rdev)
0057 {
0058     unsigned int val_tmp;
0059     unsigned int val;
0060     int ret;
0061 
0062     ret = regmap_read(rdev->regmap, MP8859_VOUT_H_REG, &val_tmp);
0063 
0064     if (ret)
0065         return ret;
0066     val = val_tmp << 3;
0067 
0068     ret = regmap_read(rdev->regmap, MP8859_VOUT_L_REG, &val_tmp);
0069 
0070     if (ret)
0071         return ret;
0072     val |= val_tmp & 0x07;
0073     return val;
0074 }
0075 
0076 static const struct linear_range mp8859_dcdc_ranges[] = {
0077     REGULATOR_LINEAR_RANGE(0, VOL_MIN_IDX, VOL_MAX_IDX, 10000),
0078 };
0079 
0080 static const struct regmap_config mp8859_regmap = {
0081     .reg_bits = 8,
0082     .val_bits = 8,
0083     .max_register = MP8859_MAX_REG,
0084     .cache_type = REGCACHE_RBTREE,
0085 };
0086 
0087 static const struct regulator_ops mp8859_ops = {
0088     .set_voltage_sel = mp8859_set_voltage_sel,
0089     .get_voltage_sel = mp8859_get_voltage_sel,
0090     .list_voltage = regulator_list_voltage_linear_range,
0091 };
0092 
0093 static const struct regulator_desc mp8859_regulators[] = {
0094     {
0095         .id = 0,
0096         .type = REGULATOR_VOLTAGE,
0097         .name = "mp8859_dcdc",
0098         .supply_name = "vin",
0099         .of_match = of_match_ptr("mp8859_dcdc"),
0100         .n_voltages = VOL_MAX_IDX + 1,
0101         .linear_ranges = mp8859_dcdc_ranges,
0102         .n_linear_ranges = 1,
0103         .ops = &mp8859_ops,
0104         .owner = THIS_MODULE,
0105     },
0106 };
0107 
0108 static int mp8859_i2c_probe(struct i2c_client *i2c)
0109 {
0110     int ret;
0111     struct regulator_config config = {.dev = &i2c->dev};
0112     struct regmap *regmap = devm_regmap_init_i2c(i2c, &mp8859_regmap);
0113     struct regulator_dev *rdev;
0114 
0115     if (IS_ERR(regmap)) {
0116         ret = PTR_ERR(regmap);
0117         dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
0118         return ret;
0119     }
0120     rdev = devm_regulator_register(&i2c->dev, &mp8859_regulators[0],
0121                     &config);
0122 
0123     if (IS_ERR(rdev)) {
0124         ret = PTR_ERR(rdev);
0125         dev_err(&i2c->dev, "failed to register %s: %d\n",
0126             mp8859_regulators[0].name, ret);
0127         return ret;
0128     }
0129     return 0;
0130 }
0131 
0132 static const struct of_device_id mp8859_dt_id[] = {
0133     {.compatible =  "mps,mp8859"},
0134     {},
0135 };
0136 MODULE_DEVICE_TABLE(of, mp8859_dt_id);
0137 
0138 static const struct i2c_device_id mp8859_i2c_id[] = {
0139     { "mp8859", },
0140     {  },
0141 };
0142 MODULE_DEVICE_TABLE(i2c, mp8859_i2c_id);
0143 
0144 static struct i2c_driver mp8859_regulator_driver = {
0145     .driver = {
0146         .name = "mp8859",
0147         .of_match_table = of_match_ptr(mp8859_dt_id),
0148     },
0149     .probe_new = mp8859_i2c_probe,
0150     .id_table = mp8859_i2c_id,
0151 };
0152 
0153 module_i2c_driver(mp8859_regulator_driver);
0154 
0155 MODULE_DESCRIPTION("Monolithic Power Systems MP8859 voltage regulator driver");
0156 MODULE_AUTHOR("Markus Reichl <m.reichl@fivetechno.de>");
0157 MODULE_LICENSE("GPL v2");