Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 
0003 #include <linux/bits.h>
0004 #include <linux/gpio/consumer.h>
0005 #include <linux/interrupt.h>
0006 #include <linux/kernel.h>
0007 #include <linux/mod_devicetable.h>
0008 #include <linux/module.h>
0009 #include <linux/of.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/regmap.h>
0012 #include <linux/regulator/driver.h>
0013 #include <linux/regulator/machine.h>
0014 
0015 enum {
0016     MT6370_IDX_DSVBOOST = 0,
0017     MT6370_IDX_DSVPOS,
0018     MT6370_IDX_DSVNEG,
0019     MT6370_IDX_VIBLDO,
0020     MT6370_MAX_IDX
0021 };
0022 
0023 #define MT6370_REG_LDO_CFG  0x180
0024 #define MT6370_REG_LDO_VOUT 0x181
0025 #define MT6370_REG_DB_CTRL1 0x1B0
0026 #define MT6370_REG_DB_CTRL2 0x1B1
0027 #define MT6370_REG_DB_VBST  0x1B2
0028 #define MT6370_REG_DB_VPOS  0x1B3
0029 #define MT6370_REG_DB_VNEG  0x1B4
0030 #define MT6370_REG_LDO_STAT 0x1DC
0031 #define MT6370_REG_DB_STAT  0x1DF
0032 
0033 #define MT6370_LDOOMS_MASK  BIT(7)
0034 #define MT6370_LDOEN_MASK   BIT(7)
0035 #define MT6370_LDOVOUT_MASK GENMASK(3, 0)
0036 #define MT6370_DBPERD_MASK  (BIT(7) | BIT(4))
0037 #define MT6370_DBEXTEN_MASK BIT(0)
0038 #define MT6370_DBVPOSEN_MASK    BIT(6)
0039 #define MT6370_DBVPOSDISG_MASK  BIT(5)
0040 #define MT6370_DBVNEGEN_MASK    BIT(3)
0041 #define MT6370_DBVNEGDISG_MASK  BIT(2)
0042 #define MT6370_DBALLON_MASK (MT6370_DBVPOSEN_MASK | MT6370_DBVNEGEN_MASK)
0043 #define MT6370_DBSLEW_MASK  GENMASK(7, 6)
0044 #define MT6370_DBVOUT_MASK  GENMASK(5, 0)
0045 #define MT6370_LDOOC_EVT_MASK   BIT(7)
0046 #define MT6370_POSSCP_EVT_MASK  BIT(7)
0047 #define MT6370_NEGSCP_EVT_MASK  BIT(6)
0048 #define MT6370_BSTOCP_EVT_MASK  BIT(5)
0049 #define MT6370_POSOCP_EVT_MASK  BIT(4)
0050 #define MT6370_NEGOCP_EVT_MASK  BIT(3)
0051 
0052 #define MT6370_LDO_MINUV    1600000
0053 #define MT6370_LDO_STPUV    200000
0054 #define MT6370_LDO_N_VOLT   13
0055 #define MT6370_DBVBOOST_MINUV   4000000
0056 #define MT6370_DBVBOOST_STPUV   50000
0057 #define MT6370_DBVBOOST_N_VOLT  45
0058 #define MT6370_DBVOUT_MINUV 4000000
0059 #define MT6370_DBVOUT_STPUV 50000
0060 #define MT6370_DBVOUT_N_VOLT    41
0061 
0062 struct mt6370_priv {
0063     struct device *dev;
0064     struct regmap *regmap;
0065     struct regulator_dev *rdev[MT6370_MAX_IDX];
0066     bool use_external_ctrl;
0067 };
0068 
0069 static const unsigned int mt6370_vpos_ramp_tbl[] = { 8540, 5840, 4830, 3000 };
0070 static const unsigned int mt6370_vneg_ramp_tbl[] = { 10090, 6310, 5050, 3150 };
0071 
0072 static int mt6370_get_error_flags(struct regulator_dev *rdev,
0073                   unsigned int *flags)
0074 {
0075     struct regmap *regmap = rdev_get_regmap(rdev);
0076     unsigned int stat_reg, stat, rpt_flags = 0;
0077     int rid = rdev_get_id(rdev), ret;
0078 
0079     if (rid == MT6370_IDX_VIBLDO)
0080         stat_reg = MT6370_REG_LDO_STAT;
0081     else
0082         stat_reg = MT6370_REG_DB_STAT;
0083 
0084     ret = regmap_read(regmap, stat_reg, &stat);
0085     if (ret)
0086         return ret;
0087 
0088     switch (rid) {
0089     case MT6370_IDX_DSVBOOST:
0090         if (stat & MT6370_BSTOCP_EVT_MASK)
0091             rpt_flags |= REGULATOR_ERROR_OVER_CURRENT;
0092         break;
0093     case MT6370_IDX_DSVPOS:
0094         if (stat & MT6370_POSSCP_EVT_MASK)
0095             rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE;
0096 
0097         if (stat & MT6370_POSOCP_EVT_MASK)
0098             rpt_flags |= REGULATOR_ERROR_OVER_CURRENT;
0099         break;
0100     case MT6370_IDX_DSVNEG:
0101         if (stat & MT6370_NEGSCP_EVT_MASK)
0102             rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE;
0103 
0104         if (stat & MT6370_NEGOCP_EVT_MASK)
0105             rpt_flags |= REGULATOR_ERROR_OVER_CURRENT;
0106         break;
0107     default:
0108         if (stat & MT6370_LDOOC_EVT_MASK)
0109             rpt_flags |= REGULATOR_ERROR_OVER_CURRENT;
0110         break;
0111     }
0112 
0113     *flags = rpt_flags;
0114     return 0;
0115 }
0116 
0117 static const struct regulator_ops mt6370_dbvboost_ops = {
0118     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0119     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0120     .list_voltage = regulator_list_voltage_linear,
0121     .get_bypass = regulator_get_bypass_regmap,
0122     .set_bypass = regulator_set_bypass_regmap,
0123     .get_error_flags = mt6370_get_error_flags,
0124 };
0125 
0126 static const struct regulator_ops mt6370_dbvout_ops = {
0127     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0128     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0129     .list_voltage = regulator_list_voltage_linear,
0130     .is_enabled = regulator_is_enabled_regmap,
0131     .enable = regulator_enable_regmap,
0132     .disable = regulator_disable_regmap,
0133     .set_active_discharge = regulator_set_active_discharge_regmap,
0134     .set_ramp_delay = regulator_set_ramp_delay_regmap,
0135     .get_error_flags = mt6370_get_error_flags,
0136 };
0137 
0138 static const struct regulator_ops mt6370_ldo_ops = {
0139     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0140     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0141     .list_voltage = regulator_list_voltage_linear,
0142     .is_enabled = regulator_is_enabled_regmap,
0143     .enable = regulator_enable_regmap,
0144     .disable = regulator_disable_regmap,
0145     .set_active_discharge = regulator_set_active_discharge_regmap,
0146     .get_error_flags = mt6370_get_error_flags,
0147 };
0148 
0149 static int mt6370_of_parse_cb(struct device_node *np,
0150                   const struct regulator_desc *desc,
0151                   struct regulator_config *config)
0152 {
0153     struct mt6370_priv *priv = config->driver_data;
0154     struct gpio_desc *enable_gpio;
0155     int ret;
0156 
0157     enable_gpio = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0,
0158                          GPIOD_OUT_HIGH |
0159                          GPIOD_FLAGS_BIT_NONEXCLUSIVE,
0160                          desc->name);
0161     if (IS_ERR(enable_gpio)) {
0162         config->ena_gpiod = NULL;
0163         return 0;
0164     }
0165 
0166     /*
0167      * RG control by default
0168      * Only if all are using external pin, change all by external control
0169      */
0170     if (priv->use_external_ctrl) {
0171         ret = regmap_update_bits(priv->regmap, MT6370_REG_DB_CTRL1,
0172                      MT6370_DBEXTEN_MASK,
0173                      MT6370_DBEXTEN_MASK);
0174         if (ret)
0175             return ret;
0176     }
0177 
0178     config->ena_gpiod = enable_gpio;
0179     priv->use_external_ctrl = true;
0180     return 0;
0181 }
0182 
0183 static const struct regulator_desc mt6370_regulator_descs[] = {
0184     {
0185         .name = "mt6370-dsv-vbst",
0186         .of_match = of_match_ptr("dsvbst"),
0187         .regulators_node = of_match_ptr("regulators"),
0188         .id = MT6370_IDX_DSVBOOST,
0189         .type = REGULATOR_VOLTAGE,
0190         .owner = THIS_MODULE,
0191         .ops = &mt6370_dbvboost_ops,
0192         .min_uV = MT6370_DBVBOOST_MINUV,
0193         .uV_step = MT6370_DBVBOOST_STPUV,
0194         .n_voltages = MT6370_DBVBOOST_N_VOLT,
0195         .vsel_reg = MT6370_REG_DB_VBST,
0196         .vsel_mask = MT6370_DBVOUT_MASK,
0197         .bypass_reg = MT6370_REG_DB_CTRL1,
0198         .bypass_mask = MT6370_DBPERD_MASK,
0199         .bypass_val_on = MT6370_DBPERD_MASK,
0200     },
0201     {
0202         .name = "mt6370-dsv-vpos",
0203         .of_match = of_match_ptr("dsvpos"),
0204         .regulators_node = of_match_ptr("regulators"),
0205         .id = MT6370_IDX_DSVPOS,
0206         .type = REGULATOR_VOLTAGE,
0207         .owner = THIS_MODULE,
0208         .of_parse_cb = mt6370_of_parse_cb,
0209         .ops = &mt6370_dbvout_ops,
0210         .min_uV = MT6370_DBVOUT_MINUV,
0211         .uV_step = MT6370_DBVOUT_STPUV,
0212         .n_voltages = MT6370_DBVOUT_N_VOLT,
0213         .vsel_reg = MT6370_REG_DB_VPOS,
0214         .vsel_mask = MT6370_DBVOUT_MASK,
0215         .enable_reg = MT6370_REG_DB_CTRL2,
0216         .enable_mask = MT6370_DBVPOSEN_MASK,
0217         .ramp_reg = MT6370_REG_DB_VPOS,
0218         .ramp_mask = MT6370_DBSLEW_MASK,
0219         .ramp_delay_table = mt6370_vpos_ramp_tbl,
0220         .n_ramp_values = ARRAY_SIZE(mt6370_vpos_ramp_tbl),
0221         .active_discharge_reg = MT6370_REG_DB_CTRL2,
0222         .active_discharge_mask = MT6370_DBVPOSDISG_MASK,
0223         .active_discharge_on = MT6370_DBVPOSDISG_MASK,
0224     },
0225     {
0226         .name = "mt6370-dsv-vneg",
0227         .of_match = of_match_ptr("dsvneg"),
0228         .regulators_node = of_match_ptr("regulators"),
0229         .id = MT6370_IDX_DSVNEG,
0230         .type = REGULATOR_VOLTAGE,
0231         .owner = THIS_MODULE,
0232         .of_parse_cb = mt6370_of_parse_cb,
0233         .ops = &mt6370_dbvout_ops,
0234         .min_uV = MT6370_DBVOUT_MINUV,
0235         .uV_step = MT6370_DBVOUT_STPUV,
0236         .n_voltages = MT6370_DBVOUT_N_VOLT,
0237         .vsel_reg = MT6370_REG_DB_VNEG,
0238         .vsel_mask = MT6370_DBVOUT_MASK,
0239         .enable_reg = MT6370_REG_DB_CTRL2,
0240         .enable_mask = MT6370_DBVNEGEN_MASK,
0241         .ramp_reg = MT6370_REG_DB_VNEG,
0242         .ramp_mask = MT6370_DBSLEW_MASK,
0243         .ramp_delay_table = mt6370_vneg_ramp_tbl,
0244         .n_ramp_values = ARRAY_SIZE(mt6370_vneg_ramp_tbl),
0245         .active_discharge_reg = MT6370_REG_DB_CTRL2,
0246         .active_discharge_mask = MT6370_DBVNEGDISG_MASK,
0247         .active_discharge_on = MT6370_DBVNEGDISG_MASK,
0248     },
0249     {
0250         .name = "mt6370-vib-ldo",
0251         .of_match = of_match_ptr("vibldo"),
0252         .regulators_node = of_match_ptr("regulators"),
0253         .id = MT6370_IDX_VIBLDO,
0254         .type = REGULATOR_VOLTAGE,
0255         .owner = THIS_MODULE,
0256         .ops = &mt6370_ldo_ops,
0257         .min_uV = MT6370_LDO_MINUV,
0258         .uV_step = MT6370_LDO_STPUV,
0259         .n_voltages = MT6370_LDO_N_VOLT,
0260         .vsel_reg = MT6370_REG_LDO_VOUT,
0261         .vsel_mask = MT6370_LDOVOUT_MASK,
0262         .enable_reg = MT6370_REG_LDO_VOUT,
0263         .enable_mask = MT6370_LDOEN_MASK,
0264         .active_discharge_reg = MT6370_REG_LDO_CFG,
0265         .active_discharge_mask = MT6370_LDOOMS_MASK,
0266         .active_discharge_on = MT6370_LDOOMS_MASK,
0267     }
0268 };
0269 
0270 static irqreturn_t mt6370_scp_handler(int irq, void *data)
0271 {
0272     struct regulator_dev *rdev = data;
0273 
0274     regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE,
0275                       NULL);
0276     return IRQ_HANDLED;
0277 }
0278 
0279 static irqreturn_t mt6370_ocp_handler(int irq, void *data)
0280 {
0281     struct regulator_dev *rdev = data;
0282 
0283     regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL);
0284     return IRQ_HANDLED;
0285 }
0286 
0287 static int mt6370_regulator_irq_register(struct mt6370_priv *priv)
0288 {
0289     struct platform_device *pdev = to_platform_device(priv->dev);
0290     static const struct {
0291         const char *name;
0292         int rid;
0293         irq_handler_t handler;
0294     } mt6370_irqs[] = {
0295         { "db_vpos_scp", MT6370_IDX_DSVPOS, mt6370_scp_handler },
0296         { "db_vneg_scp", MT6370_IDX_DSVNEG, mt6370_scp_handler },
0297         { "db_vbst_ocp", MT6370_IDX_DSVBOOST, mt6370_ocp_handler },
0298         { "db_vpos_ocp", MT6370_IDX_DSVPOS,  mt6370_ocp_handler },
0299         { "db_vneg_ocp", MT6370_IDX_DSVNEG, mt6370_ocp_handler },
0300         { "ldo_oc", MT6370_IDX_VIBLDO, mt6370_ocp_handler }
0301     };
0302     struct regulator_dev *rdev;
0303     int i, irq, ret;
0304 
0305     for (i = 0; i < ARRAY_SIZE(mt6370_irqs); i++) {
0306         irq = platform_get_irq_byname(pdev, mt6370_irqs[i].name);
0307 
0308         rdev = priv->rdev[mt6370_irqs[i].rid];
0309 
0310         ret = devm_request_threaded_irq(priv->dev, irq, NULL,
0311                         mt6370_irqs[i].handler, 0,
0312                         mt6370_irqs[i].name, rdev);
0313         if (ret) {
0314             dev_err(priv->dev,
0315                 "Failed to register (%d) interrupt\n", i);
0316             return ret;
0317         }
0318     }
0319 
0320     return 0;
0321 }
0322 
0323 static int mt6370_regualtor_register(struct mt6370_priv *priv)
0324 {
0325     struct regulator_dev *rdev;
0326     struct regulator_config cfg = {};
0327     struct device *parent = priv->dev->parent;
0328     int i;
0329 
0330     cfg.dev = parent;
0331     cfg.driver_data = priv;
0332 
0333     for (i = 0; i < MT6370_MAX_IDX; i++) {
0334         rdev = devm_regulator_register(priv->dev,
0335                            mt6370_regulator_descs + i,
0336                            &cfg);
0337         if (IS_ERR(rdev)) {
0338             dev_err(priv->dev,
0339                 "Failed to register (%d) regulator\n", i);
0340             return PTR_ERR(rdev);
0341         }
0342 
0343         priv->rdev[i] = rdev;
0344     }
0345 
0346     return 0;
0347 }
0348 
0349 static int mt6370_regulator_probe(struct platform_device *pdev)
0350 {
0351     struct mt6370_priv *priv;
0352     int ret;
0353 
0354     priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0355     if (!priv)
0356         return -ENOMEM;
0357 
0358     priv->dev = &pdev->dev;
0359 
0360     priv->regmap = dev_get_regmap(pdev->dev.parent, NULL);
0361     if (!priv->regmap) {
0362         dev_err(&pdev->dev, "Failed to init regmap\n");
0363         return -ENODEV;
0364     }
0365 
0366     ret = mt6370_regualtor_register(priv);
0367     if (ret)
0368         return ret;
0369 
0370     return mt6370_regulator_irq_register(priv);
0371 }
0372 
0373 static const struct platform_device_id mt6370_devid_table[] = {
0374     { "mt6370-regulator", 0},
0375     {}
0376 };
0377 MODULE_DEVICE_TABLE(platform, mt6370_devid_table);
0378 
0379 static struct platform_driver mt6370_regulator_driver = {
0380     .driver = {
0381         .name = "mt6370-regulator",
0382     },
0383     .id_table = mt6370_devid_table,
0384     .probe = mt6370_regulator_probe,
0385 };
0386 module_platform_driver(mt6370_regulator_driver);
0387 
0388 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
0389 MODULE_DESCRIPTION("Mediatek MT6370 Regulator Driver");
0390 MODULE_LICENSE("GPL v2");