X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fregulator%2Fcore.c;h=2b4e40d311902c3a05061aa99e4d4fd65b38a167;hb=d71f4cece4bd97d05592836202fc04ff2e7817e3;hp=1848a3f0980ee7b5614ec69a4f5714a41dfec587;hpb=af5866c9cdc9e43ef775a14765fd8eab95c7fd20;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 1848a3f..2b4e40d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -16,13 +16,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include "dummy.h" + #define REGULATOR_VERSION "0.5" static DEFINE_MUTEX(regulator_list_mutex); @@ -66,6 +70,16 @@ static unsigned int _regulator_get_mode(struct regulator_dev *rdev); static void _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data); +static const char *rdev_get_name(struct regulator_dev *rdev) +{ + if (rdev->constraints && rdev->constraints->name) + return rdev->constraints->name; + else if (rdev->desc->name) + return rdev->desc->name; + else + return ""; +} + /* gets the regulator for a given consumer device */ static struct regulator *get_device_regulator(struct device *dev) { @@ -96,12 +110,12 @@ static int regulator_check_voltage(struct regulator_dev *rdev, if (!rdev->constraints) { printk(KERN_ERR "%s: no constraints for %s\n", __func__, - rdev->desc->name); + rdev_get_name(rdev)); return -ENODEV; } if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { printk(KERN_ERR "%s: operation not allowed for %s\n", - __func__, rdev->desc->name); + __func__, rdev_get_name(rdev)); return -EPERM; } @@ -124,12 +138,12 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, if (!rdev->constraints) { printk(KERN_ERR "%s: no constraints for %s\n", __func__, - rdev->desc->name); + rdev_get_name(rdev)); return -ENODEV; } if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { printk(KERN_ERR "%s: operation not allowed for %s\n", - __func__, rdev->desc->name); + __func__, rdev_get_name(rdev)); return -EPERM; } @@ -159,17 +173,17 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode) if (!rdev->constraints) { printk(KERN_ERR "%s: no constraints for %s\n", __func__, - rdev->desc->name); + rdev_get_name(rdev)); return -ENODEV; } if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { printk(KERN_ERR "%s: operation not allowed for %s\n", - __func__, rdev->desc->name); + __func__, rdev_get_name(rdev)); return -EPERM; } if (!(rdev->constraints->valid_modes_mask & mode)) { printk(KERN_ERR "%s: invalid mode %x for %s\n", - __func__, mode, rdev->desc->name); + __func__, mode, rdev_get_name(rdev)); return -EINVAL; } return 0; @@ -180,12 +194,12 @@ static int regulator_check_drms(struct regulator_dev *rdev) { if (!rdev->constraints) { printk(KERN_ERR "%s: no constraints for %s\n", __func__, - rdev->desc->name); + rdev_get_name(rdev)); return -ENODEV; } if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { printk(KERN_ERR "%s: operation not allowed for %s\n", - __func__, rdev->desc->name); + __func__, rdev_get_name(rdev)); return -EPERM; } return 0; @@ -230,16 +244,8 @@ static ssize_t regulator_name_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - const char *name; - if (rdev->constraints && rdev->constraints->name) - name = rdev->constraints->name; - else if (rdev->desc->name) - name = rdev->desc->name; - else - name = ""; - - return sprintf(buf, "%s\n", name); + return sprintf(buf, "%s\n", rdev_get_name(rdev)); } static ssize_t regulator_print_opmode(char *buf, int mode) @@ -388,7 +394,7 @@ static ssize_t regulator_total_uA_show(struct device *dev, mutex_lock(&rdev->mutex); list_for_each_entry(regulator, &rdev->consumer_list, list) - uA += regulator->uA_load; + uA += regulator->uA_load; mutex_unlock(&rdev->mutex); return sprintf(buf, "%d\n", uA); } @@ -563,7 +569,7 @@ static void drms_uA_update(struct regulator_dev *rdev) /* calc total requested load */ list_for_each_entry(sibling, &rdev->consumer_list, list) - current_uA += sibling->uA_load; + current_uA += sibling->uA_load; /* now get the optimum mode for our new total regulator load */ mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, @@ -579,10 +585,29 @@ static int suspend_set_state(struct regulator_dev *rdev, struct regulator_state *rstate) { int ret = 0; + bool can_set_state; + + can_set_state = rdev->desc->ops->set_suspend_enable && + rdev->desc->ops->set_suspend_disable; + + /* If we have no suspend mode configration don't set anything; + * only warn if the driver actually makes the suspend mode + * configurable. + */ + if (!rstate->enabled && !rstate->disabled) { + if (can_set_state) + printk(KERN_WARNING "%s: No configuration for %s\n", + __func__, rdev_get_name(rdev)); + return 0; + } - /* enable & disable are mandatory for suspend control */ - if (!rdev->desc->ops->set_suspend_enable || - !rdev->desc->ops->set_suspend_disable) { + if (rstate->enabled && rstate->disabled) { + printk(KERN_ERR "%s: invalid configuration for %s\n", + __func__, rdev_get_name(rdev)); + return -EINVAL; + } + + if (!can_set_state) { printk(KERN_ERR "%s: no way to set suspend state\n", __func__); return -EINVAL; @@ -640,26 +665,44 @@ static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) static void print_constraints(struct regulator_dev *rdev) { struct regulation_constraints *constraints = rdev->constraints; - char buf[80]; - int count; + char buf[80] = ""; + int count = 0; + int ret; - if (rdev->desc->type == REGULATOR_VOLTAGE) { + if (constraints->min_uV && constraints->max_uV) { if (constraints->min_uV == constraints->max_uV) - count = sprintf(buf, "%d mV ", - constraints->min_uV / 1000); + count += sprintf(buf + count, "%d mV ", + constraints->min_uV / 1000); else - count = sprintf(buf, "%d <--> %d mV ", - constraints->min_uV / 1000, - constraints->max_uV / 1000); - } else { + count += sprintf(buf + count, "%d <--> %d mV ", + constraints->min_uV / 1000, + constraints->max_uV / 1000); + } + + if (!constraints->min_uV || + constraints->min_uV != constraints->max_uV) { + ret = _regulator_get_voltage(rdev); + if (ret > 0) + count += sprintf(buf + count, "at %d mV ", ret / 1000); + } + + if (constraints->min_uA && constraints->max_uA) { if (constraints->min_uA == constraints->max_uA) - count = sprintf(buf, "%d mA ", - constraints->min_uA / 1000); + count += sprintf(buf + count, "%d mA ", + constraints->min_uA / 1000); else - count = sprintf(buf, "%d <--> %d mA ", - constraints->min_uA / 1000, - constraints->max_uA / 1000); + count += sprintf(buf + count, "%d <--> %d mA ", + constraints->min_uA / 1000, + constraints->max_uA / 1000); + } + + if (!constraints->min_uA || + constraints->min_uA != constraints->max_uA) { + ret = _regulator_get_current_limit(rdev); + if (ret > 0) + count += sprintf(buf + count, "at %d uA ", ret / 1000); } + if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) count += sprintf(buf + count, "fast "); if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) @@ -669,13 +712,14 @@ static void print_constraints(struct regulator_dev *rdev) if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) count += sprintf(buf + count, "standby"); - printk(KERN_INFO "regulator: %s: %s\n", rdev->desc->name, buf); + printk(KERN_INFO "regulator: %s: %s\n", rdev_get_name(rdev), buf); } static int machine_constraints_voltage(struct regulator_dev *rdev, - const char *name, struct regulation_constraints *constraints) + struct regulation_constraints *constraints) { struct regulator_ops *ops = rdev->desc->ops; + const char *name = rdev_get_name(rdev); int ret; /* do we need to apply the constraint voltage */ @@ -782,16 +826,11 @@ static int set_machine_constraints(struct regulator_dev *rdev, const char *name; struct regulator_ops *ops = rdev->desc->ops; - if (constraints->name) - name = constraints->name; - else if (rdev->desc->name) - name = rdev->desc->name; - else - name = "regulator"; - rdev->constraints = constraints; - ret = machine_constraints_voltage(rdev, name, constraints); + name = rdev_get_name(rdev); + + ret = machine_constraints_voltage(rdev, constraints); if (ret != 0) goto out; @@ -914,7 +953,7 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, dev_name(&node->regulator->dev), node->regulator->desc->name, supply, - dev_name(&rdev->dev), rdev->desc->name); + dev_name(&rdev->dev), rdev_get_name(rdev)); return -EBUSY; } @@ -1000,6 +1039,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, goto overflow_err; regulator->dev = dev; + sysfs_attr_init(®ulator->dev_attr.attr); regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL); if (regulator->dev_attr.attr.name == NULL) goto attr_name_err; @@ -1049,6 +1089,13 @@ overflow_err: return NULL; } +static int _regulator_get_enable_time(struct regulator_dev *rdev) +{ + if (!rdev->desc->ops->enable_time) + return 0; + return rdev->desc->ops->enable_time(rdev); +} + /* Internal regulator request function */ static struct regulator *_regulator_get(struct device *dev, const char *id, int exclusive) @@ -1080,6 +1127,22 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, goto found; } } + +#ifdef CONFIG_REGULATOR_DUMMY + if (!devname) + devname = "deviceless"; + + /* If the board didn't flag that it was fully constrained then + * substitute in a dummy regulator so consumers can continue. + */ + if (!has_full_constraints) { + pr_warning("%s supply %s not found, using dummy regulator\n", + devname, id); + rdev = dummy_regulator_rdev; + goto found; + } +#endif + mutex_unlock(®ulator_list_mutex); return regulator; @@ -1216,14 +1279,14 @@ static int _regulator_can_change_status(struct regulator_dev *rdev) /* locks held by regulator_enable() */ static int _regulator_enable(struct regulator_dev *rdev) { - int ret; + int ret, delay; /* do we need to enable the supply regulator first */ if (rdev->supply) { ret = _regulator_enable(rdev->supply); if (ret < 0) { printk(KERN_ERR "%s: failed to enable %s: %d\n", - __func__, rdev->desc->name, ret); + __func__, rdev_get_name(rdev), ret); return ret; } } @@ -1240,16 +1303,37 @@ static int _regulator_enable(struct regulator_dev *rdev) if (!_regulator_can_change_status(rdev)) return -EPERM; - if (rdev->desc->ops->enable) { - ret = rdev->desc->ops->enable(rdev); - if (ret < 0) - return ret; - } else { + if (!rdev->desc->ops->enable) return -EINVAL; + + /* Query before enabling in case configuration + * dependant. */ + ret = _regulator_get_enable_time(rdev); + if (ret >= 0) { + delay = ret; + } else { + printk(KERN_WARNING + "%s: enable_time() failed for %s: %d\n", + __func__, rdev_get_name(rdev), + ret); + delay = 0; } + + /* Allow the regulator to ramp; it would be useful + * to extend this for bulk operations so that the + * regulators can ramp together. */ + ret = rdev->desc->ops->enable(rdev); + if (ret < 0) + return ret; + + if (delay >= 1000) + mdelay(delay / 1000); + else if (delay) + udelay(delay); + } else if (ret < 0) { printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", - __func__, rdev->desc->name, ret); + __func__, rdev_get_name(rdev), ret); return ret; } /* Fallthrough on positive return values - already enabled */ @@ -1290,7 +1374,7 @@ static int _regulator_disable(struct regulator_dev *rdev) if (WARN(rdev->use_count <= 0, "unbalanced disables for %s\n", - rdev->desc->name)) + rdev_get_name(rdev))) return -EIO; /* are we the last user and permitted to disable ? */ @@ -1303,9 +1387,12 @@ static int _regulator_disable(struct regulator_dev *rdev) ret = rdev->desc->ops->disable(rdev); if (ret < 0) { printk(KERN_ERR "%s: failed to disable %s\n", - __func__, rdev->desc->name); + __func__, rdev_get_name(rdev)); return ret; } + + _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, + NULL); } /* decrease our supplies ref count and disable if required */ @@ -1360,12 +1447,12 @@ static int _regulator_force_disable(struct regulator_dev *rdev) ret = rdev->desc->ops->disable(rdev); if (ret < 0) { printk(KERN_ERR "%s: failed to force disable %s\n", - __func__, rdev->desc->name); + __func__, rdev_get_name(rdev)); return ret; } /* notify other consumers that power has been forced off */ - _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE, - NULL); + _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | + REGULATOR_EVENT_DISABLE, NULL); } /* decrease our supplies ref count and disable if required */ @@ -1399,9 +1486,9 @@ EXPORT_SYMBOL_GPL(regulator_force_disable); static int _regulator_is_enabled(struct regulator_dev *rdev) { - /* sanity check */ + /* If we don't know then assume that the regulator is always on */ if (!rdev->desc->ops->is_enabled) - return -EINVAL; + return 1; return rdev->desc->ops->is_enabled(rdev); } @@ -1777,7 +1864,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) output_uV = rdev->desc->ops->get_voltage(rdev); if (output_uV <= 0) { printk(KERN_ERR "%s: invalid output voltage found for %s\n", - __func__, rdev->desc->name); + __func__, rdev_get_name(rdev)); goto out; } @@ -1788,13 +1875,13 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) input_uV = rdev->constraints->input_uV; if (input_uV <= 0) { printk(KERN_ERR "%s: invalid input voltage found for %s\n", - __func__, rdev->desc->name); + __func__, rdev_get_name(rdev)); goto out; } /* calc total requested load for this regulator */ list_for_each_entry(consumer, &rdev->consumer_list, list) - total_uA_load += consumer->uA_load; + total_uA_load += consumer->uA_load; mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, output_uV, @@ -1802,7 +1889,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) ret = regulator_check_mode(rdev, mode); if (ret < 0) { printk(KERN_ERR "%s: failed to get optimum mode for %s @" - " %d uA %d -> %d uV\n", __func__, rdev->desc->name, + " %d uA %d -> %d uV\n", __func__, rdev_get_name(rdev), total_uA_load, input_uV, output_uV); goto out; } @@ -1810,7 +1897,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) ret = rdev->desc->ops->set_mode(rdev, mode); if (ret < 0) { printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n", - __func__, mode, rdev->desc->name); + __func__, mode, rdev_get_name(rdev)); goto out; } ret = mode; @@ -1863,9 +1950,9 @@ static void _notifier_call_chain(struct regulator_dev *rdev, /* now notify regulator we supply */ list_for_each_entry(_rdev, &rdev->supply_list, slist) { - mutex_lock(&_rdev->mutex); - _notifier_call_chain(_rdev, event, data); - mutex_unlock(&_rdev->mutex); + mutex_lock(&_rdev->mutex); + _notifier_call_chain(_rdev, event, data); + mutex_unlock(&_rdev->mutex); } } @@ -1942,7 +2029,7 @@ int regulator_bulk_enable(int num_consumers, err: printk(KERN_ERR "Failed to enable %s: %d\n", consumers[i].supply, ret); - for (i = 0; i < num_consumers; i++) + for (--i; i >= 0; --i) regulator_disable(consumers[i].consumer); return ret; @@ -1978,7 +2065,7 @@ int regulator_bulk_disable(int num_consumers, err: printk(KERN_ERR "Failed to disable %s: %d\n", consumers[i].supply, ret); - for (i = 0; i < num_consumers; i++) + for (--i; i >= 0; --i) regulator_enable(consumers[i].consumer); return ret; @@ -2328,7 +2415,7 @@ int regulator_suspend_prepare(suspend_state_t state) if (ret < 0) { printk(KERN_ERR "%s: failed to prepare %s\n", - __func__, rdev->desc->name); + __func__, rdev_get_name(rdev)); goto out; } } @@ -2416,8 +2503,15 @@ EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); static int __init regulator_init(void) { + int ret; + printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION); - return class_register(®ulator_class); + + ret = class_register(®ulator_class); + + regulator_dummy_init(); + + return ret; } /* init early to allow our consumers to complete system booting */ @@ -2441,12 +2535,7 @@ static int __init regulator_init_complete(void) ops = rdev->desc->ops; c = rdev->constraints; - if (c && c->name) - name = c->name; - else if (rdev->desc->name) - name = rdev->desc->name; - else - name = "regulator"; + name = rdev_get_name(rdev); if (!ops->disable || (c && c->always_on)) continue;