Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright (c) 2015 MediaTek Inc.
0004 // Author: Henry Chen <henryc.chen@mediatek.com>
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 /* Default limits measured in millivolts and milliamps */
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  * I2C driver interface functions
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");