0001
0002
0003
0004
0005
0006 #include <linux/err.h>
0007 #include <linux/gpio.h>
0008 #include <linux/i2c.h>
0009 #include <linux/init.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/module.h>
0012 #include <linux/regmap.h>
0013 #include <linux/regulator/driver.h>
0014 #include <linux/regulator/machine.h>
0015 #include <linux/regulator/of_regulator.h>
0016 #include <linux/regulator/mt6311.h>
0017 #include <linux/slab.h>
0018 #include "mt6311-regulator.h"
0019
0020 static const struct regmap_config mt6311_regmap_config = {
0021 .reg_bits = 8,
0022 .val_bits = 8,
0023 .max_register = MT6311_FQMTR_CON4,
0024 .cache_type = REGCACHE_RBTREE,
0025 };
0026
0027
0028 #define MT6311_MIN_UV 600000
0029 #define MT6311_MAX_UV 1393750
0030 #define MT6311_STEP_UV 6250
0031
0032 static const struct regulator_ops mt6311_buck_ops = {
0033 .list_voltage = regulator_list_voltage_linear,
0034 .map_voltage = regulator_map_voltage_linear,
0035 .set_voltage_sel = regulator_set_voltage_sel_regmap,
0036 .get_voltage_sel = regulator_get_voltage_sel_regmap,
0037 .set_voltage_time_sel = regulator_set_voltage_time_sel,
0038 .enable = regulator_enable_regmap,
0039 .disable = regulator_disable_regmap,
0040 .is_enabled = regulator_is_enabled_regmap,
0041 };
0042
0043 static const struct regulator_ops mt6311_ldo_ops = {
0044 .enable = regulator_enable_regmap,
0045 .disable = regulator_disable_regmap,
0046 .is_enabled = regulator_is_enabled_regmap,
0047 };
0048
0049 #define MT6311_BUCK(_id) \
0050 {\
0051 .name = #_id,\
0052 .ops = &mt6311_buck_ops,\
0053 .of_match = of_match_ptr(#_id),\
0054 .regulators_node = of_match_ptr("regulators"),\
0055 .type = REGULATOR_VOLTAGE,\
0056 .id = MT6311_ID_##_id,\
0057 .n_voltages = (MT6311_MAX_UV - MT6311_MIN_UV) / MT6311_STEP_UV + 1,\
0058 .min_uV = MT6311_MIN_UV,\
0059 .uV_step = MT6311_STEP_UV,\
0060 .owner = THIS_MODULE,\
0061 .enable_reg = MT6311_VDVFS11_CON9,\
0062 .enable_mask = MT6311_PMIC_VDVFS11_EN_MASK,\
0063 .vsel_reg = MT6311_VDVFS11_CON12,\
0064 .vsel_mask = MT6311_PMIC_VDVFS11_VOSEL_MASK,\
0065 }
0066
0067 #define MT6311_LDO(_id) \
0068 {\
0069 .name = #_id,\
0070 .ops = &mt6311_ldo_ops,\
0071 .of_match = of_match_ptr(#_id),\
0072 .regulators_node = of_match_ptr("regulators"),\
0073 .type = REGULATOR_VOLTAGE,\
0074 .id = MT6311_ID_##_id,\
0075 .owner = THIS_MODULE,\
0076 .enable_reg = MT6311_LDO_CON3,\
0077 .enable_mask = MT6311_PMIC_RG_VBIASN_EN_MASK,\
0078 }
0079
0080 static const struct regulator_desc mt6311_regulators[] = {
0081 MT6311_BUCK(VDVFS),
0082 MT6311_LDO(VBIASN),
0083 };
0084
0085
0086
0087
0088 static int mt6311_i2c_probe(struct i2c_client *i2c)
0089 {
0090 struct regulator_config config = { };
0091 struct regulator_dev *rdev;
0092 struct regmap *regmap;
0093 int i, ret;
0094 unsigned int data;
0095
0096 regmap = devm_regmap_init_i2c(i2c, &mt6311_regmap_config);
0097 if (IS_ERR(regmap)) {
0098 ret = PTR_ERR(regmap);
0099 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
0100 ret);
0101 return ret;
0102 }
0103
0104 ret = regmap_read(regmap, MT6311_SWCID, &data);
0105 if (ret < 0) {
0106 dev_err(&i2c->dev, "Failed to read DEVICE_ID reg: %d\n", ret);
0107 return ret;
0108 }
0109
0110 switch (data) {
0111 case MT6311_E1_CID_CODE:
0112 case MT6311_E2_CID_CODE:
0113 case MT6311_E3_CID_CODE:
0114 break;
0115 default:
0116 dev_err(&i2c->dev, "Unsupported device id = 0x%x.\n", data);
0117 return -ENODEV;
0118 }
0119
0120 for (i = 0; i < MT6311_MAX_REGULATORS; i++) {
0121 config.dev = &i2c->dev;
0122 config.regmap = regmap;
0123
0124 rdev = devm_regulator_register(&i2c->dev,
0125 &mt6311_regulators[i], &config);
0126 if (IS_ERR(rdev)) {
0127 dev_err(&i2c->dev,
0128 "Failed to register MT6311 regulator\n");
0129 return PTR_ERR(rdev);
0130 }
0131 }
0132
0133 return 0;
0134 }
0135
0136 static const struct i2c_device_id mt6311_i2c_id[] = {
0137 {"mt6311", 0},
0138 {},
0139 };
0140 MODULE_DEVICE_TABLE(i2c, mt6311_i2c_id);
0141
0142 #ifdef CONFIG_OF
0143 static const struct of_device_id mt6311_dt_ids[] = {
0144 { .compatible = "mediatek,mt6311-regulator",
0145 .data = &mt6311_i2c_id[0] },
0146 {},
0147 };
0148 MODULE_DEVICE_TABLE(of, mt6311_dt_ids);
0149 #endif
0150
0151 static struct i2c_driver mt6311_regulator_driver = {
0152 .driver = {
0153 .name = "mt6311",
0154 .of_match_table = of_match_ptr(mt6311_dt_ids),
0155 },
0156 .probe_new = mt6311_i2c_probe,
0157 .id_table = mt6311_i2c_id,
0158 };
0159
0160 module_i2c_driver(mt6311_regulator_driver);
0161
0162 MODULE_AUTHOR("Henry Chen <henryc.chen@mediatek.com>");
0163 MODULE_DESCRIPTION("Regulator device driver for Mediatek MT6311");
0164 MODULE_LICENSE("GPL v2");