^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * reg-virtual-consumer.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2008 Wolfson Microelectronics PLC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct virtual_consumer_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct regulator *regulator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int min_uV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int max_uV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) int min_uA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int max_uA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static void update_voltage_constraints(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct virtual_consumer_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (data->min_uV && data->max_uV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) && data->min_uV <= data->max_uV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) dev_dbg(dev, "Requesting %d-%duV\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) data->min_uV, data->max_uV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ret = regulator_set_voltage(data->regulator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) data->min_uV, data->max_uV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) "regulator_set_voltage() failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (data->min_uV && data->max_uV && !data->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) dev_dbg(dev, "Enabling regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ret = regulator_enable(data->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) data->enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) dev_err(dev, "regulator_enable() failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!(data->min_uV && data->max_uV) && data->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) dev_dbg(dev, "Disabling regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ret = regulator_disable(data->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) data->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) dev_err(dev, "regulator_disable() failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void update_current_limit_constraints(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct virtual_consumer_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (data->max_uA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) && data->min_uA <= data->max_uA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dev_dbg(dev, "Requesting %d-%duA\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) data->min_uA, data->max_uA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ret = regulator_set_current_limit(data->regulator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) data->min_uA, data->max_uA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "regulator_set_current_limit() failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (data->max_uA && !data->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dev_dbg(dev, "Enabling regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ret = regulator_enable(data->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) data->enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dev_err(dev, "regulator_enable() failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!(data->min_uA && data->max_uA) && data->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) dev_dbg(dev, "Disabling regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ret = regulator_disable(data->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) data->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) dev_err(dev, "regulator_disable() failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static ssize_t show_min_uV(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return sprintf(buf, "%d\n", data->min_uV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static ssize_t set_min_uV(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (kstrtol(buf, 10, &val) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) data->min_uV = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) update_voltage_constraints(dev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static ssize_t show_max_uV(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return sprintf(buf, "%d\n", data->max_uV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static ssize_t set_max_uV(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (kstrtol(buf, 10, &val) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) data->max_uV = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) update_voltage_constraints(dev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static ssize_t show_min_uA(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return sprintf(buf, "%d\n", data->min_uA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static ssize_t set_min_uA(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (kstrtol(buf, 10, &val) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) data->min_uA = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) update_current_limit_constraints(dev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static ssize_t show_max_uA(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return sprintf(buf, "%d\n", data->max_uA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static ssize_t set_max_uA(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (kstrtol(buf, 10, &val) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) data->max_uA = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) update_current_limit_constraints(dev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static ssize_t show_mode(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) switch (data->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) case REGULATOR_MODE_FAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return sprintf(buf, "fast\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case REGULATOR_MODE_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return sprintf(buf, "normal\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) case REGULATOR_MODE_IDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return sprintf(buf, "idle\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) case REGULATOR_MODE_STANDBY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return sprintf(buf, "standby\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return sprintf(buf, "unknown\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static ssize_t set_mode(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct virtual_consumer_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) unsigned int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * sysfs_streq() doesn't need the \n's, but we add them so the strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * will be shared with show_mode(), above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (sysfs_streq(buf, "fast\n"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) mode = REGULATOR_MODE_FAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) else if (sysfs_streq(buf, "normal\n"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mode = REGULATOR_MODE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) else if (sysfs_streq(buf, "idle\n"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) mode = REGULATOR_MODE_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) else if (sysfs_streq(buf, "standby\n"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) mode = REGULATOR_MODE_STANDBY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) dev_err(dev, "Configuring invalid mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ret = regulator_set_mode(data->regulator, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) data->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dev_err(dev, "Failed to configure mode: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static DEVICE_ATTR(min_microvolts, 0664, show_min_uV, set_min_uV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static DEVICE_ATTR(max_microvolts, 0664, show_max_uV, set_max_uV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static DEVICE_ATTR(min_microamps, 0664, show_min_uA, set_min_uA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static DEVICE_ATTR(max_microamps, 0664, show_max_uA, set_max_uA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static DEVICE_ATTR(mode, 0664, show_mode, set_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static struct attribute *regulator_virtual_attributes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) &dev_attr_min_microvolts.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) &dev_attr_max_microvolts.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) &dev_attr_min_microamps.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) &dev_attr_max_microamps.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) &dev_attr_mode.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static const struct attribute_group regulator_virtual_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .attrs = regulator_virtual_attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int regulator_virtual_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) char *reg_id = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct virtual_consumer_data *drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) drvdata = devm_kzalloc(&pdev->dev, sizeof(struct virtual_consumer_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (drvdata == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) mutex_init(&drvdata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) drvdata->regulator = devm_regulator_get(&pdev->dev, reg_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (IS_ERR(drvdata->regulator)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ret = PTR_ERR(drvdata->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) dev_err(&pdev->dev, "Failed to obtain supply '%s': %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) reg_id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ret = sysfs_create_group(&pdev->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ®ulator_virtual_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) "Failed to create attribute group: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) drvdata->mode = regulator_get_mode(drvdata->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) platform_set_drvdata(pdev, drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int regulator_virtual_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) sysfs_remove_group(&pdev->dev.kobj, ®ulator_virtual_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (drvdata->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) regulator_disable(drvdata->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static struct platform_driver regulator_virtual_consumer_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .probe = regulator_virtual_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .remove = regulator_virtual_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .name = "reg-virt-consumer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) module_platform_driver(regulator_virtual_consumer_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) MODULE_DESCRIPTION("Virtual regulator consumer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) MODULE_ALIAS("platform:reg-virt-consumer");