Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * reg-virtual-consumer.c
0004  *
0005  * Copyright 2008 Wolfson Microelectronics PLC.
0006  *
0007  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
0008  */
0009 
0010 #include <linux/err.h>
0011 #include <linux/mutex.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/regulator/consumer.h>
0014 #include <linux/slab.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 
0018 struct virtual_consumer_data {
0019     struct mutex lock;
0020     struct regulator *regulator;
0021     bool enabled;
0022     int min_uV;
0023     int max_uV;
0024     int min_uA;
0025     int max_uA;
0026     unsigned int mode;
0027 };
0028 
0029 static void update_voltage_constraints(struct device *dev,
0030                        struct virtual_consumer_data *data)
0031 {
0032     int ret;
0033 
0034     if (data->min_uV && data->max_uV
0035         && data->min_uV <= data->max_uV) {
0036         dev_dbg(dev, "Requesting %d-%duV\n",
0037             data->min_uV, data->max_uV);
0038         ret = regulator_set_voltage(data->regulator,
0039                     data->min_uV, data->max_uV);
0040         if (ret != 0) {
0041             dev_err(dev,
0042                 "regulator_set_voltage() failed: %d\n", ret);
0043             return;
0044         }
0045     }
0046 
0047     if (data->min_uV && data->max_uV && !data->enabled) {
0048         dev_dbg(dev, "Enabling regulator\n");
0049         ret = regulator_enable(data->regulator);
0050         if (ret == 0)
0051             data->enabled = true;
0052         else
0053             dev_err(dev, "regulator_enable() failed: %d\n",
0054                 ret);
0055     }
0056 
0057     if (!(data->min_uV && data->max_uV) && data->enabled) {
0058         dev_dbg(dev, "Disabling regulator\n");
0059         ret = regulator_disable(data->regulator);
0060         if (ret == 0)
0061             data->enabled = false;
0062         else
0063             dev_err(dev, "regulator_disable() failed: %d\n",
0064                 ret);
0065     }
0066 }
0067 
0068 static void update_current_limit_constraints(struct device *dev,
0069                       struct virtual_consumer_data *data)
0070 {
0071     int ret;
0072 
0073     if (data->max_uA
0074         && data->min_uA <= data->max_uA) {
0075         dev_dbg(dev, "Requesting %d-%duA\n",
0076             data->min_uA, data->max_uA);
0077         ret = regulator_set_current_limit(data->regulator,
0078                     data->min_uA, data->max_uA);
0079         if (ret != 0) {
0080             dev_err(dev,
0081                 "regulator_set_current_limit() failed: %d\n",
0082                 ret);
0083             return;
0084         }
0085     }
0086 
0087     if (data->max_uA && !data->enabled) {
0088         dev_dbg(dev, "Enabling regulator\n");
0089         ret = regulator_enable(data->regulator);
0090         if (ret == 0)
0091             data->enabled = true;
0092         else
0093             dev_err(dev, "regulator_enable() failed: %d\n",
0094                 ret);
0095     }
0096 
0097     if (!(data->min_uA && data->max_uA) && data->enabled) {
0098         dev_dbg(dev, "Disabling regulator\n");
0099         ret = regulator_disable(data->regulator);
0100         if (ret == 0)
0101             data->enabled = false;
0102         else
0103             dev_err(dev, "regulator_disable() failed: %d\n",
0104                 ret);
0105     }
0106 }
0107 
0108 static ssize_t show_min_uV(struct device *dev,
0109                struct device_attribute *attr, char *buf)
0110 {
0111     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0112     return sprintf(buf, "%d\n", data->min_uV);
0113 }
0114 
0115 static ssize_t set_min_uV(struct device *dev, struct device_attribute *attr,
0116               const char *buf, size_t count)
0117 {
0118     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0119     long val;
0120 
0121     if (kstrtol(buf, 10, &val) != 0)
0122         return count;
0123 
0124     mutex_lock(&data->lock);
0125 
0126     data->min_uV = val;
0127     update_voltage_constraints(dev, data);
0128 
0129     mutex_unlock(&data->lock);
0130 
0131     return count;
0132 }
0133 
0134 static ssize_t show_max_uV(struct device *dev,
0135                struct device_attribute *attr, char *buf)
0136 {
0137     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0138     return sprintf(buf, "%d\n", data->max_uV);
0139 }
0140 
0141 static ssize_t set_max_uV(struct device *dev, struct device_attribute *attr,
0142               const char *buf, size_t count)
0143 {
0144     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0145     long val;
0146 
0147     if (kstrtol(buf, 10, &val) != 0)
0148         return count;
0149 
0150     mutex_lock(&data->lock);
0151 
0152     data->max_uV = val;
0153     update_voltage_constraints(dev, data);
0154 
0155     mutex_unlock(&data->lock);
0156 
0157     return count;
0158 }
0159 
0160 static ssize_t show_min_uA(struct device *dev,
0161                struct device_attribute *attr, char *buf)
0162 {
0163     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0164     return sprintf(buf, "%d\n", data->min_uA);
0165 }
0166 
0167 static ssize_t set_min_uA(struct device *dev, struct device_attribute *attr,
0168               const char *buf, size_t count)
0169 {
0170     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0171     long val;
0172 
0173     if (kstrtol(buf, 10, &val) != 0)
0174         return count;
0175 
0176     mutex_lock(&data->lock);
0177 
0178     data->min_uA = val;
0179     update_current_limit_constraints(dev, data);
0180 
0181     mutex_unlock(&data->lock);
0182 
0183     return count;
0184 }
0185 
0186 static ssize_t show_max_uA(struct device *dev,
0187                struct device_attribute *attr, char *buf)
0188 {
0189     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0190     return sprintf(buf, "%d\n", data->max_uA);
0191 }
0192 
0193 static ssize_t set_max_uA(struct device *dev, struct device_attribute *attr,
0194               const char *buf, size_t count)
0195 {
0196     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0197     long val;
0198 
0199     if (kstrtol(buf, 10, &val) != 0)
0200         return count;
0201 
0202     mutex_lock(&data->lock);
0203 
0204     data->max_uA = val;
0205     update_current_limit_constraints(dev, data);
0206 
0207     mutex_unlock(&data->lock);
0208 
0209     return count;
0210 }
0211 
0212 static ssize_t show_mode(struct device *dev,
0213              struct device_attribute *attr, char *buf)
0214 {
0215     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0216 
0217     switch (data->mode) {
0218     case REGULATOR_MODE_FAST:
0219         return sprintf(buf, "fast\n");
0220     case REGULATOR_MODE_NORMAL:
0221         return sprintf(buf, "normal\n");
0222     case REGULATOR_MODE_IDLE:
0223         return sprintf(buf, "idle\n");
0224     case REGULATOR_MODE_STANDBY:
0225         return sprintf(buf, "standby\n");
0226     default:
0227         return sprintf(buf, "unknown\n");
0228     }
0229 }
0230 
0231 static ssize_t set_mode(struct device *dev, struct device_attribute *attr,
0232             const char *buf, size_t count)
0233 {
0234     struct virtual_consumer_data *data = dev_get_drvdata(dev);
0235     unsigned int mode;
0236     int ret;
0237 
0238     /*
0239      * sysfs_streq() doesn't need the \n's, but we add them so the strings
0240      * will be shared with show_mode(), above.
0241      */
0242     if (sysfs_streq(buf, "fast\n"))
0243         mode = REGULATOR_MODE_FAST;
0244     else if (sysfs_streq(buf, "normal\n"))
0245         mode = REGULATOR_MODE_NORMAL;
0246     else if (sysfs_streq(buf, "idle\n"))
0247         mode = REGULATOR_MODE_IDLE;
0248     else if (sysfs_streq(buf, "standby\n"))
0249         mode = REGULATOR_MODE_STANDBY;
0250     else {
0251         dev_err(dev, "Configuring invalid mode\n");
0252         return count;
0253     }
0254 
0255     mutex_lock(&data->lock);
0256     ret = regulator_set_mode(data->regulator, mode);
0257     if (ret == 0)
0258         data->mode = mode;
0259     else
0260         dev_err(dev, "Failed to configure mode: %d\n", ret);
0261     mutex_unlock(&data->lock);
0262 
0263     return count;
0264 }
0265 
0266 static DEVICE_ATTR(min_microvolts, 0664, show_min_uV, set_min_uV);
0267 static DEVICE_ATTR(max_microvolts, 0664, show_max_uV, set_max_uV);
0268 static DEVICE_ATTR(min_microamps, 0664, show_min_uA, set_min_uA);
0269 static DEVICE_ATTR(max_microamps, 0664, show_max_uA, set_max_uA);
0270 static DEVICE_ATTR(mode, 0664, show_mode, set_mode);
0271 
0272 static struct attribute *regulator_virtual_attributes[] = {
0273     &dev_attr_min_microvolts.attr,
0274     &dev_attr_max_microvolts.attr,
0275     &dev_attr_min_microamps.attr,
0276     &dev_attr_max_microamps.attr,
0277     &dev_attr_mode.attr,
0278     NULL
0279 };
0280 
0281 static const struct attribute_group regulator_virtual_attr_group = {
0282     .attrs  = regulator_virtual_attributes,
0283 };
0284 
0285 #ifdef CONFIG_OF
0286 static const struct of_device_id regulator_virtual_consumer_of_match[] = {
0287     { .compatible = "regulator-virtual-consumer" },
0288     {},
0289 };
0290 MODULE_DEVICE_TABLE(of, regulator_virtual_consumer_of_match);
0291 #endif
0292 
0293 static int regulator_virtual_probe(struct platform_device *pdev)
0294 {
0295     char *reg_id = dev_get_platdata(&pdev->dev);
0296     struct virtual_consumer_data *drvdata;
0297     static bool warned;
0298     int ret;
0299 
0300     if (!warned) {
0301         warned = true;
0302         pr_warn("**********************************************************\n");
0303         pr_warn("**   NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE   **\n");
0304         pr_warn("**                                                      **\n");
0305         pr_warn("** regulator-virtual-consumer is only for testing and   **\n");
0306         pr_warn("** debugging.  Do not use it in a production kernel.    **\n");
0307         pr_warn("**                                                      **\n");
0308         pr_warn("**   NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE   **\n");
0309         pr_warn("**********************************************************\n");
0310     }
0311 
0312     drvdata = devm_kzalloc(&pdev->dev, sizeof(struct virtual_consumer_data),
0313                    GFP_KERNEL);
0314     if (drvdata == NULL)
0315         return -ENOMEM;
0316 
0317     /*
0318      * This virtual consumer does not have any hardware-defined supply
0319      * name, so just allow the regulator to be specified in a property
0320      * named "default-supply" when we're being probed from devicetree.
0321      */
0322     if (!reg_id && pdev->dev.of_node)
0323         reg_id = "default";
0324 
0325     mutex_init(&drvdata->lock);
0326 
0327     drvdata->regulator = devm_regulator_get(&pdev->dev, reg_id);
0328     if (IS_ERR(drvdata->regulator))
0329         return dev_err_probe(&pdev->dev, PTR_ERR(drvdata->regulator),
0330                      "Failed to obtain supply '%s'\n",
0331                      reg_id);
0332 
0333     ret = sysfs_create_group(&pdev->dev.kobj,
0334                  &regulator_virtual_attr_group);
0335     if (ret != 0) {
0336         dev_err(&pdev->dev,
0337             "Failed to create attribute group: %d\n", ret);
0338         return ret;
0339     }
0340 
0341     drvdata->mode = regulator_get_mode(drvdata->regulator);
0342 
0343     platform_set_drvdata(pdev, drvdata);
0344 
0345     return 0;
0346 }
0347 
0348 static int regulator_virtual_remove(struct platform_device *pdev)
0349 {
0350     struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
0351 
0352     sysfs_remove_group(&pdev->dev.kobj, &regulator_virtual_attr_group);
0353 
0354     if (drvdata->enabled)
0355         regulator_disable(drvdata->regulator);
0356 
0357     return 0;
0358 }
0359 
0360 static struct platform_driver regulator_virtual_consumer_driver = {
0361     .probe      = regulator_virtual_probe,
0362     .remove     = regulator_virtual_remove,
0363     .driver     = {
0364         .name       = "reg-virt-consumer",
0365         .of_match_table = of_match_ptr(regulator_virtual_consumer_of_match),
0366     },
0367 };
0368 
0369 module_platform_driver(regulator_virtual_consumer_driver);
0370 
0371 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
0372 MODULE_DESCRIPTION("Virtual regulator consumer");
0373 MODULE_LICENSE("GPL");
0374 MODULE_ALIAS("platform:reg-virt-consumer");