From 6934d084ffb9205ad7c7a504d6a8d38c864a512d Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Fri, 9 Mar 2012 17:53:53 +0900 Subject: [PATCH] --- yaml --- r: 302101 b: refs/heads/master c: 62fe8cd50175ca797dcf3d39a7206da6ac0f6c50 h: refs/heads/master i: 302099: edf20b662ecb4ce5e16f35cf921c1e788608219b v: v3 --- [refs] | 2 +- trunk/drivers/regulator/core.c | 202 +++++++++------------ trunk/include/linux/mfd/s5m87xx/s5m-core.h | 1 + trunk/include/linux/mfd/s5m87xx/s5m-pmic.h | 29 +++ 4 files changed, 112 insertions(+), 122 deletions(-) diff --git a/[refs] b/[refs] index 699a15a37a59..3e9f6ddf9dae 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6492bc1b1a9cb21d28cde3c70d090c7648c8b0ed +refs/heads/master: 62fe8cd50175ca797dcf3d39a7206da6ac0f6c50 diff --git a/trunk/drivers/regulator/core.c b/trunk/drivers/regulator/core.c index 4b2c02c519f0..c056abd7562a 100644 --- a/trunk/drivers/regulator/core.c +++ b/trunk/drivers/regulator/core.c @@ -74,7 +74,6 @@ struct regulator_map { struct regulator { struct device *dev; struct list_head list; - unsigned int always_on:1; int uA_load; int min_uV; int max_uV; @@ -156,17 +155,6 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp return regnode; } -static int _regulator_can_change_status(struct regulator_dev *rdev) -{ - if (!rdev->constraints) - return 0; - - if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) - return 1; - else - return 0; -} - /* Platform voltage constraint check */ static int regulator_check_voltage(struct regulator_dev *rdev, int *min_uV, int *max_uV) @@ -661,7 +649,7 @@ static void drms_uA_update(struct regulator_dev *rdev) /* get input voltage */ input_uV = 0; if (rdev->supply) - input_uV = regulator_get_voltage(rdev->supply); + input_uV = _regulator_get_voltage(rdev); if (input_uV <= 0) input_uV = rdev->constraints->input_uV; if (input_uV <= 0) @@ -685,14 +673,17 @@ 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 implements set_suspend_voltage or - * set_suspend_mode callback. + * only warn if the driver actually makes the suspend mode + * configurable. */ if (!rstate->enabled && !rstate->disabled) { - if (rdev->desc->ops->set_suspend_voltage || - rdev->desc->ops->set_suspend_mode) + if (can_set_state) rdev_warn(rdev, "No configuration\n"); return 0; } @@ -702,13 +693,15 @@ static int suspend_set_state(struct regulator_dev *rdev, return -EINVAL; } - if (rstate->enabled && rdev->desc->ops->set_suspend_enable) + if (!can_set_state) { + rdev_err(rdev, "no way to set suspend state\n"); + return -EINVAL; + } + + if (rstate->enabled) ret = rdev->desc->ops->set_suspend_enable(rdev); - else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) + else ret = rdev->desc->ops->set_suspend_disable(rdev); - else /* OK if set_suspend_enable or set_suspend_disable is NULL */ - ret = 0; - if (ret < 0) { rdev_err(rdev, "failed to enabled/disable\n"); return ret; @@ -1153,15 +1146,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, ®ulator->max_uV); } - /* - * Check now if the regulator is an always on regulator - if - * it is then we don't need to do nearly so much work for - * enable/disable calls. - */ - if (!_regulator_can_change_status(rdev) && - _regulator_is_enabled(rdev)) - regulator->always_on = true; - mutex_unlock(&rdev->mutex); return regulator; link_name_err: @@ -1185,52 +1169,26 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev) } static struct regulator_dev *regulator_dev_lookup(struct device *dev, - const char *supply, - int *ret) + const char *supply) { struct regulator_dev *r; struct device_node *node; - struct regulator_map *map; - const char *devname = NULL; /* first do a dt based lookup */ if (dev && dev->of_node) { node = of_get_regulator(dev, supply); - if (node) { + if (node) list_for_each_entry(r, ®ulator_list, list) if (r->dev.parent && node == r->dev.of_node) return r; - } else { - /* - * If we couldn't even get the node then it's - * not just that the device didn't register - * yet, there's no node and we'll never - * succeed. - */ - *ret = -ENODEV; - } } /* if not found, try doing it non-dt way */ - if (dev) - devname = dev_name(dev); - list_for_each_entry(r, ®ulator_list, list) if (strcmp(rdev_get_name(r), supply) == 0) return r; - list_for_each_entry(map, ®ulator_map_list, list) { - /* If the mapping has a device set up it must match */ - if (map->dev_name && - (!devname || strcmp(map->dev_name, devname))) - continue; - - if (strcmp(map->supply, supply) == 0) - return map->regulator; - } - - return NULL; } @@ -1239,6 +1197,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, int exclusive) { struct regulator_dev *rdev; + struct regulator_map *map; struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); const char *devname = NULL; int ret; @@ -1253,10 +1212,22 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, mutex_lock(®ulator_list_mutex); - rdev = regulator_dev_lookup(dev, id, &ret); + rdev = regulator_dev_lookup(dev, id); if (rdev) goto found; + list_for_each_entry(map, ®ulator_map_list, list) { + /* If the mapping has a device set up it must match */ + if (map->dev_name && + (!devname || strcmp(map->dev_name, devname))) + continue; + + if (strcmp(map->supply, id) == 0) { + rdev = map->regulator; + goto found; + } + } + if (board_wants_dummy_regulator) { rdev = dummy_regulator_rdev; goto found; @@ -1464,6 +1435,17 @@ void devm_regulator_put(struct regulator *regulator) } EXPORT_SYMBOL_GPL(devm_regulator_put); +static int _regulator_can_change_status(struct regulator_dev *rdev) +{ + if (!rdev->constraints) + return 0; + + if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) + return 1; + else + return 0; +} + /* locks held by regulator_enable() */ static int _regulator_enable(struct regulator_dev *rdev) { @@ -1543,9 +1525,6 @@ int regulator_enable(struct regulator *regulator) struct regulator_dev *rdev = regulator->rdev; int ret = 0; - if (regulator->always_on) - return 0; - if (rdev->supply) { ret = regulator_enable(rdev->supply); if (ret != 0) @@ -1624,9 +1603,6 @@ int regulator_disable(struct regulator *regulator) struct regulator_dev *rdev = regulator->rdev; int ret = 0; - if (regulator->always_on) - return 0; - mutex_lock(&rdev->mutex); ret = _regulator_disable(rdev); mutex_unlock(&rdev->mutex); @@ -1735,9 +1711,6 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) struct regulator_dev *rdev = regulator->rdev; int ret; - if (regulator->always_on) - return 0; - mutex_lock(&rdev->mutex); rdev->deferred_disables++; mutex_unlock(&rdev->mutex); @@ -1776,9 +1749,6 @@ int regulator_is_enabled(struct regulator *regulator) { int ret; - if (regulator->always_on) - return 1; - mutex_lock(®ulator->rdev->mutex); ret = _regulator_is_enabled(regulator->rdev); mutex_unlock(®ulator->rdev->mutex); @@ -1873,35 +1843,23 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, int ret; int delay = 0; unsigned int selector; - int old_selector = -1; - int best_val = INT_MAX; trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); min_uV += rdev->constraints->uV_offset; max_uV += rdev->constraints->uV_offset; - /* - * If we can't obtain the old selector there is not enough - * info to call set_voltage_time_sel(). - */ - if (rdev->desc->ops->set_voltage_time_sel && - rdev->desc->ops->get_voltage_sel) { - old_selector = rdev->desc->ops->get_voltage_sel(rdev); - if (old_selector < 0) - return old_selector; - } - if (rdev->desc->ops->set_voltage) { ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, &selector); if (rdev->desc->ops->list_voltage) - best_val = rdev->desc->ops->list_voltage(rdev, + selector = rdev->desc->ops->list_voltage(rdev, selector); else - best_val = -1; + selector = -1; } else if (rdev->desc->ops->set_voltage_sel) { + int best_val = INT_MAX; int i; selector = 0; @@ -1920,27 +1878,36 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } } - if (best_val != INT_MAX) + /* + * If we can't obtain the old selector there is not enough + * info to call set_voltage_time_sel(). + */ + if (rdev->desc->ops->set_voltage_time_sel && + rdev->desc->ops->get_voltage_sel) { + unsigned int old_selector = 0; + + ret = rdev->desc->ops->get_voltage_sel(rdev); + if (ret < 0) + return ret; + old_selector = ret; + ret = rdev->desc->ops->set_voltage_time_sel(rdev, + old_selector, selector); + if (ret < 0) + rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", ret); + else + delay = ret; + } + + if (best_val != INT_MAX) { ret = rdev->desc->ops->set_voltage_sel(rdev, selector); - else + selector = best_val; + } else { ret = -EINVAL; + } } else { ret = -EINVAL; } - /* Call set_voltage_time_sel if successfully obtained old_selector */ - if (ret == 0 && old_selector >= 0 && - rdev->desc->ops->set_voltage_time_sel) { - - delay = rdev->desc->ops->set_voltage_time_sel(rdev, - old_selector, selector); - if (delay < 0) { - rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", - delay); - delay = 0; - } - } - /* Insert any necessary delays */ if (delay >= 1000) { mdelay(delay / 1000); @@ -1953,7 +1920,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL); - trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); + trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector); return ret; } @@ -2357,9 +2324,6 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) */ ret = -EINVAL; - if (!rdev->desc->ops->set_mode) - goto out; - /* get output voltage */ output_uV = _regulator_get_voltage(rdev); if (output_uV <= 0) { @@ -2561,13 +2525,9 @@ int regulator_bulk_enable(int num_consumers, int i; int ret = 0; - for (i = 0; i < num_consumers; i++) { - if (consumers[i].consumer->always_on) - consumers[i].ret = 0; - else - async_schedule_domain(regulator_bulk_enable_async, - &consumers[i], &async_domain); - } + for (i = 0; i < num_consumers; i++) + async_schedule_domain(regulator_bulk_enable_async, + &consumers[i], &async_domain); async_synchronize_full_domain(&async_domain); @@ -2606,7 +2566,7 @@ int regulator_bulk_disable(int num_consumers, struct regulator_bulk_data *consumers) { int i; - int ret, r; + int ret; for (i = num_consumers - 1; i >= 0; --i) { ret = regulator_disable(consumers[i].consumer); @@ -2618,12 +2578,8 @@ int regulator_bulk_disable(int num_consumers, err: pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); - for (++i; i < num_consumers; ++i) { - r = regulator_enable(consumers[i].consumer); - if (r != 0) - pr_err("Failed to reename %s: %d\n", - consumers[i].supply, r); - } + for (++i; i < num_consumers; ++i) + regulator_enable(consumers[i].consumer); return ret; } @@ -2800,6 +2756,10 @@ static int add_regulator_attributes(struct regulator_dev *rdev) return status; } + /* suspend mode constraints need multiple supporting methods */ + if (!(ops->set_suspend_enable && ops->set_suspend_disable)) + return status; + status = device_create_file(dev, &dev_attr_suspend_standby_state); if (status < 0) return status; @@ -2962,7 +2922,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, if (supply) { struct regulator_dev *r; - r = regulator_dev_lookup(dev, supply, &ret); + r = regulator_dev_lookup(dev, supply); if (!r) { dev_err(dev, "Failed to find supply %s\n", supply); diff --git a/trunk/include/linux/mfd/s5m87xx/s5m-core.h b/trunk/include/linux/mfd/s5m87xx/s5m-core.h index a7480b57f92d..21603b42f22f 100644 --- a/trunk/include/linux/mfd/s5m87xx/s5m-core.h +++ b/trunk/include/linux/mfd/s5m87xx/s5m-core.h @@ -335,6 +335,7 @@ extern int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask); struct s5m_platform_data { struct s5m_regulator_data *regulators; + struct s5m_opmode_data *opmode; int device_type; int num_regulators; diff --git a/trunk/include/linux/mfd/s5m87xx/s5m-pmic.h b/trunk/include/linux/mfd/s5m87xx/s5m-pmic.h index a72a5d27e62e..7c719f20f58a 100644 --- a/trunk/include/linux/mfd/s5m87xx/s5m-pmic.h +++ b/trunk/include/linux/mfd/s5m87xx/s5m-pmic.h @@ -58,6 +58,8 @@ enum s5m8767_regulators { S5M8767_REG_MAX, }; +#define S5M8767_ENCTRL_SHIFT 6 + /* S5M8763 regulator ids */ enum s5m8763_regulators { S5M8763_LDO1, @@ -97,4 +99,31 @@ struct s5m_regulator_data { struct regulator_init_data *initdata; }; +/* + * s5m_opmode_data - regulator operation mode data + * @id: regulator id + * @mode: regulator operation mode + */ +struct s5m_opmode_data { + int id; + int mode; +}; + +/* + * s5m regulator operation mode + * S5M_OPMODE_OFF Regulator always OFF + * S5M_OPMODE_ON Regulator always ON + * S5M_OPMODE_LOWPOWER Regulator is on in low-power mode + * S5M_OPMODE_SUSPEND Regulator is changed by PWREN pin + * If PWREN is high, regulator is on + * If PWREN is low, regulator is off + */ + +enum s5m_opmode { + S5M_OPMODE_OFF, + S5M_OPMODE_ON, + S5M_OPMODE_LOWPOWER, + S5M_OPMODE_SUSPEND, +}; + #endif /* __LINUX_MFD_S5M_PMIC_H */