brintos

brintos / linux-shallow public Read only

0
0
Text · 26.2 KiB · 0def82e Raw
1004 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2//3// helpers.c  --  Voltage/Current Regulator framework helper functions.4//5// Copyright 2007, 2008 Wolfson Microelectronics PLC.6// Copyright 2008 SlimLogic Ltd.7 8#include <linux/bitops.h>9#include <linux/delay.h>10#include <linux/err.h>11#include <linux/export.h>12#include <linux/kernel.h>13#include <linux/regmap.h>14#include <linux/regulator/consumer.h>15#include <linux/regulator/driver.h>16 17#include "internal.h"18 19/**20 * regulator_is_enabled_regmap - standard is_enabled() for regmap users21 *22 * @rdev: regulator to operate on23 *24 * Regulators that use regmap for their register I/O can set the25 * enable_reg and enable_mask fields in their descriptor and then use26 * this as their is_enabled operation, saving some code.27 */28int regulator_is_enabled_regmap(struct regulator_dev *rdev)29{30	unsigned int val;31	int ret;32 33	ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);34	if (ret != 0)35		return ret;36 37	val &= rdev->desc->enable_mask;38 39	if (rdev->desc->enable_is_inverted) {40		if (rdev->desc->enable_val)41			return val != rdev->desc->enable_val;42		return val == 0;43	} else {44		if (rdev->desc->enable_val)45			return val == rdev->desc->enable_val;46		return val != 0;47	}48}49EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);50 51/**52 * regulator_enable_regmap - standard enable() for regmap users53 *54 * @rdev: regulator to operate on55 *56 * Regulators that use regmap for their register I/O can set the57 * enable_reg and enable_mask fields in their descriptor and then use58 * this as their enable() operation, saving some code.59 */60int regulator_enable_regmap(struct regulator_dev *rdev)61{62	unsigned int val;63 64	if (rdev->desc->enable_is_inverted) {65		val = rdev->desc->disable_val;66	} else {67		val = rdev->desc->enable_val;68		if (!val)69			val = rdev->desc->enable_mask;70	}71 72	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,73				  rdev->desc->enable_mask, val);74}75EXPORT_SYMBOL_GPL(regulator_enable_regmap);76 77/**78 * regulator_disable_regmap - standard disable() for regmap users79 *80 * @rdev: regulator to operate on81 *82 * Regulators that use regmap for their register I/O can set the83 * enable_reg and enable_mask fields in their descriptor and then use84 * this as their disable() operation, saving some code.85 */86int regulator_disable_regmap(struct regulator_dev *rdev)87{88	unsigned int val;89 90	if (rdev->desc->enable_is_inverted) {91		val = rdev->desc->enable_val;92		if (!val)93			val = rdev->desc->enable_mask;94	} else {95		val = rdev->desc->disable_val;96	}97 98	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,99				  rdev->desc->enable_mask, val);100}101EXPORT_SYMBOL_GPL(regulator_disable_regmap);102 103static int regulator_range_selector_to_index(struct regulator_dev *rdev,104					     unsigned int rval)105{106	int i;107 108	if (!rdev->desc->linear_range_selectors_bitfield)109		return -EINVAL;110 111	rval &= rdev->desc->vsel_range_mask;112	rval >>= ffs(rdev->desc->vsel_range_mask) - 1;113 114	for (i = 0; i < rdev->desc->n_linear_ranges; i++) {115		if (rdev->desc->linear_range_selectors_bitfield[i] == rval)116			return i;117	}118	return -EINVAL;119}120 121/**122 * regulator_get_voltage_sel_pickable_regmap - pickable range get_voltage_sel123 *124 * @rdev: regulator to operate on125 *126 * Regulators that use regmap for their register I/O and use pickable127 * ranges can set the vsel_reg, vsel_mask, vsel_range_reg and vsel_range_mask128 * fields in their descriptor and then use this as their get_voltage_sel129 * operation, saving some code.130 */131int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev)132{133	unsigned int r_val;134	int range;135	unsigned int val;136	int ret;137	unsigned int voltages = 0;138	const struct linear_range *r = rdev->desc->linear_ranges;139 140	if (!r)141		return -EINVAL;142 143	ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);144	if (ret != 0)145		return ret;146 147	ret = regmap_read(rdev->regmap, rdev->desc->vsel_range_reg, &r_val);148	if (ret != 0)149		return ret;150 151	val &= rdev->desc->vsel_mask;152	val >>= ffs(rdev->desc->vsel_mask) - 1;153 154	range = regulator_range_selector_to_index(rdev, r_val);155	if (range < 0)156		return -EINVAL;157 158	voltages = linear_range_values_in_range_array(r, range);159 160	return val + voltages;161}162EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_pickable_regmap);163 164static int write_separate_vsel_and_range(struct regulator_dev *rdev,165					 unsigned int sel, unsigned int range)166{167	bool range_updated;168	int ret;169 170	ret = regmap_update_bits_base(rdev->regmap, rdev->desc->vsel_range_reg,171				      rdev->desc->vsel_range_mask,172				      range, &range_updated, false, false);173	if (ret)174		return ret;175 176	/*177	 * Some PMICs treat the vsel_reg same as apply-bit. Force it to be178	 * written if the range changed, even if the old selector was same as179	 * the new one180	 */181	if (rdev->desc->range_applied_by_vsel && range_updated)182		return regmap_write_bits(rdev->regmap,183					rdev->desc->vsel_reg,184					rdev->desc->vsel_mask, sel);185 186	return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,187				  rdev->desc->vsel_mask, sel);188}189 190/**191 * regulator_set_voltage_sel_pickable_regmap - pickable range set_voltage_sel192 *193 * @rdev: regulator to operate on194 * @sel: Selector to set195 *196 * Regulators that use regmap for their register I/O and use pickable197 * ranges can set the vsel_reg, vsel_mask, vsel_range_reg and vsel_range_mask198 * fields in their descriptor and then use this as their set_voltage_sel199 * operation, saving some code.200 */201int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev,202					      unsigned int sel)203{204	unsigned int range;205	int ret, i;206	unsigned int voltages_in_range = 0;207 208	for (i = 0; i < rdev->desc->n_linear_ranges; i++) {209		const struct linear_range *r;210 211		r = &rdev->desc->linear_ranges[i];212		voltages_in_range = linear_range_values_in_range(r);213 214		if (sel < voltages_in_range)215			break;216		sel -= voltages_in_range;217	}218 219	if (i == rdev->desc->n_linear_ranges)220		return -EINVAL;221 222	sel <<= ffs(rdev->desc->vsel_mask) - 1;223	sel += rdev->desc->linear_ranges[i].min_sel;224 225	range = rdev->desc->linear_range_selectors_bitfield[i];226	range <<= ffs(rdev->desc->vsel_range_mask) - 1;227 228	if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg)229		ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,230					 rdev->desc->vsel_range_mask |231					 rdev->desc->vsel_mask, sel | range);232	else233		ret = write_separate_vsel_and_range(rdev, sel, range);234 235	if (ret)236		return ret;237 238	if (rdev->desc->apply_bit)239		ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,240					 rdev->desc->apply_bit,241					 rdev->desc->apply_bit);242	return ret;243}244EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_pickable_regmap);245 246/**247 * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users248 *249 * @rdev: regulator to operate on250 *251 * Regulators that use regmap for their register I/O can set the252 * vsel_reg and vsel_mask fields in their descriptor and then use this253 * as their get_voltage_sel operation, saving some code.254 */255int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)256{257	unsigned int val;258	int ret;259 260	ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);261	if (ret != 0)262		return ret;263 264	val &= rdev->desc->vsel_mask;265	val >>= ffs(rdev->desc->vsel_mask) - 1;266 267	return val;268}269EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);270 271/**272 * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users273 *274 * @rdev: regulator to operate on275 * @sel: Selector to set276 *277 * Regulators that use regmap for their register I/O can set the278 * vsel_reg and vsel_mask fields in their descriptor and then use this279 * as their set_voltage_sel operation, saving some code.280 */281int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)282{283	int ret;284 285	sel <<= ffs(rdev->desc->vsel_mask) - 1;286 287	ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,288				  rdev->desc->vsel_mask, sel);289	if (ret)290		return ret;291 292	if (rdev->desc->apply_bit)293		ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,294					 rdev->desc->apply_bit,295					 rdev->desc->apply_bit);296	return ret;297}298EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);299 300/**301 * regulator_map_voltage_iterate - map_voltage() based on list_voltage()302 *303 * @rdev: Regulator to operate on304 * @min_uV: Lower bound for voltage305 * @max_uV: Upper bound for voltage306 *307 * Drivers implementing set_voltage_sel() and list_voltage() can use308 * this as their map_voltage() operation.  It will find a suitable309 * voltage by calling list_voltage() until it gets something in bounds310 * for the requested voltages.311 */312int regulator_map_voltage_iterate(struct regulator_dev *rdev,313				  int min_uV, int max_uV)314{315	int best_val = INT_MAX;316	int selector = 0;317	int i, ret;318 319	/* Find the smallest voltage that falls within the specified320	 * range.321	 */322	for (i = 0; i < rdev->desc->n_voltages; i++) {323		ret = rdev->desc->ops->list_voltage(rdev, i);324		if (ret < 0)325			continue;326 327		if (ret < best_val && ret >= min_uV && ret <= max_uV) {328			best_val = ret;329			selector = i;330		}331	}332 333	if (best_val != INT_MAX)334		return selector;335	else336		return -EINVAL;337}338EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);339 340/**341 * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list342 *343 * @rdev: Regulator to operate on344 * @min_uV: Lower bound for voltage345 * @max_uV: Upper bound for voltage346 *347 * Drivers that have ascendant voltage list can use this as their348 * map_voltage() operation.349 */350int regulator_map_voltage_ascend(struct regulator_dev *rdev,351				 int min_uV, int max_uV)352{353	int i, ret;354 355	for (i = 0; i < rdev->desc->n_voltages; i++) {356		ret = rdev->desc->ops->list_voltage(rdev, i);357		if (ret < 0)358			continue;359 360		if (ret > max_uV)361			break;362 363		if (ret >= min_uV && ret <= max_uV)364			return i;365	}366 367	return -EINVAL;368}369EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend);370 371/**372 * regulator_map_voltage_linear - map_voltage() for simple linear mappings373 *374 * @rdev: Regulator to operate on375 * @min_uV: Lower bound for voltage376 * @max_uV: Upper bound for voltage377 *378 * Drivers providing min_uV and uV_step in their regulator_desc can379 * use this as their map_voltage() operation.380 */381int regulator_map_voltage_linear(struct regulator_dev *rdev,382				 int min_uV, int max_uV)383{384	int ret, voltage;385 386	/* Allow uV_step to be 0 for fixed voltage */387	if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {388		if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)389			return 0;390		else391			return -EINVAL;392	}393 394	if (!rdev->desc->uV_step) {395		BUG_ON(!rdev->desc->uV_step);396		return -EINVAL;397	}398 399	if (min_uV < rdev->desc->min_uV)400		min_uV = rdev->desc->min_uV;401 402	ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);403	if (ret < 0)404		return ret;405 406	ret += rdev->desc->linear_min_sel;407 408	/* Map back into a voltage to verify we're still in bounds */409	voltage = rdev->desc->ops->list_voltage(rdev, ret);410	if (voltage < min_uV || voltage > max_uV)411		return -EINVAL;412 413	return ret;414}415EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);416 417/**418 * regulator_map_voltage_linear_range - map_voltage() for multiple linear ranges419 *420 * @rdev: Regulator to operate on421 * @min_uV: Lower bound for voltage422 * @max_uV: Upper bound for voltage423 *424 * Drivers providing linear_ranges in their descriptor can use this as425 * their map_voltage() callback.426 */427int regulator_map_voltage_linear_range(struct regulator_dev *rdev,428				       int min_uV, int max_uV)429{430	const struct linear_range *range;431	int ret = -EINVAL;432	unsigned int sel;433	bool found;434	int voltage, i;435 436	if (!rdev->desc->n_linear_ranges) {437		BUG_ON(!rdev->desc->n_linear_ranges);438		return -EINVAL;439	}440 441	for (i = 0; i < rdev->desc->n_linear_ranges; i++) {442		range = &rdev->desc->linear_ranges[i];443 444		ret = linear_range_get_selector_high(range, min_uV, &sel,445						     &found);446		if (ret)447			continue;448		ret = sel;449 450		/*451		 * Map back into a voltage to verify we're still in bounds.452		 * If we are not, then continue checking rest of the ranges.453		 */454		voltage = rdev->desc->ops->list_voltage(rdev, sel);455		if (voltage >= min_uV && voltage <= max_uV)456			break;457	}458 459	if (i == rdev->desc->n_linear_ranges)460		return -EINVAL;461 462	return ret;463}464EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);465 466/**467 * regulator_map_voltage_pickable_linear_range - map_voltage, pickable ranges468 *469 * @rdev: Regulator to operate on470 * @min_uV: Lower bound for voltage471 * @max_uV: Upper bound for voltage472 *473 * Drivers providing pickable linear_ranges in their descriptor can use474 * this as their map_voltage() callback.475 */476int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,477						int min_uV, int max_uV)478{479	const struct linear_range *range;480	int ret = -EINVAL;481	int voltage, i;482	unsigned int selector = 0;483 484	if (!rdev->desc->n_linear_ranges) {485		BUG_ON(!rdev->desc->n_linear_ranges);486		return -EINVAL;487	}488 489	for (i = 0; i < rdev->desc->n_linear_ranges; i++) {490		int linear_max_uV;491		bool found;492		unsigned int sel;493 494		range = &rdev->desc->linear_ranges[i];495		linear_max_uV = linear_range_get_max_value(range);496 497		if (!(min_uV <= linear_max_uV && max_uV >= range->min)) {498			selector += linear_range_values_in_range(range);499			continue;500		}501 502		ret = linear_range_get_selector_high(range, min_uV, &sel,503						     &found);504		if (ret) {505			selector += linear_range_values_in_range(range);506			continue;507		}508 509		ret = selector + sel - range->min_sel;510 511		voltage = rdev->desc->ops->list_voltage(rdev, ret);512 513		/*514		 * Map back into a voltage to verify we're still in bounds.515		 * We may have overlapping voltage ranges. Hence we don't516		 * exit but retry until we have checked all ranges.517		 */518		if (voltage < min_uV || voltage > max_uV)519			selector += linear_range_values_in_range(range);520		else521			break;522	}523 524	if (i == rdev->desc->n_linear_ranges)525		return -EINVAL;526 527	return ret;528}529EXPORT_SYMBOL_GPL(regulator_map_voltage_pickable_linear_range);530 531/**532 * regulator_desc_list_voltage_linear - List voltages with simple calculation533 *534 * @desc: Regulator desc for regulator which volatges are to be listed535 * @selector: Selector to convert into a voltage536 *537 * Regulators with a simple linear mapping between voltages and538 * selectors can set min_uV and uV_step in the regulator descriptor539 * and then use this function prior regulator registration to list540 * the voltages. This is useful when voltages need to be listed during541 * device-tree parsing.542 */543int regulator_desc_list_voltage_linear(const struct regulator_desc *desc,544				       unsigned int selector)545{546	if (selector >= desc->n_voltages)547		return -EINVAL;548 549	if (selector < desc->linear_min_sel)550		return 0;551 552	selector -= desc->linear_min_sel;553 554	return desc->min_uV + (desc->uV_step * selector);555}556EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear);557 558/**559 * regulator_list_voltage_linear - List voltages with simple calculation560 *561 * @rdev: Regulator device562 * @selector: Selector to convert into a voltage563 *564 * Regulators with a simple linear mapping between voltages and565 * selectors can set min_uV and uV_step in the regulator descriptor566 * and then use this function as their list_voltage() operation,567 */568int regulator_list_voltage_linear(struct regulator_dev *rdev,569				  unsigned int selector)570{571	return regulator_desc_list_voltage_linear(rdev->desc, selector);572}573EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);574 575/**576 * regulator_list_voltage_pickable_linear_range - pickable range list voltages577 *578 * @rdev: Regulator device579 * @selector: Selector to convert into a voltage580 *581 * list_voltage() operation, intended to be used by drivers utilizing pickable582 * ranges helpers.583 */584int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev,585						 unsigned int selector)586{587	const struct linear_range *range;588	int i;589	unsigned int all_sels = 0;590 591	if (!rdev->desc->n_linear_ranges) {592		BUG_ON(!rdev->desc->n_linear_ranges);593		return -EINVAL;594	}595 596	for (i = 0; i < rdev->desc->n_linear_ranges; i++) {597		unsigned int sel_indexes;598 599		range = &rdev->desc->linear_ranges[i];600 601		sel_indexes = linear_range_values_in_range(range) - 1;602 603		if (all_sels + sel_indexes >= selector) {604			selector -= all_sels;605			/*606			 * As we see here, pickable ranges work only as607			 * long as the first selector for each pickable608			 * range is 0, and the each subsequent range for609			 * this 'pick' follow immediately at next unused610			 * selector (Eg. there is no gaps between ranges).611			 * I think this is fine but it probably should be612			 * documented. OTOH, whole pickable range stuff613			 * might benefit from some documentation614			 */615			return range->min + (range->step * selector);616		}617 618		all_sels += (sel_indexes + 1);619	}620 621	return -EINVAL;622}623EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range);624 625/**626 * regulator_desc_list_voltage_linear_range - List voltages for linear ranges627 *628 * @desc: Regulator desc for regulator which volatges are to be listed629 * @selector: Selector to convert into a voltage630 *631 * Regulators with a series of simple linear mappings between voltages632 * and selectors who have set linear_ranges in the regulator descriptor633 * can use this function prior regulator registration to list voltages.634 * This is useful when voltages need to be listed during device-tree635 * parsing.636 */637int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc,638					     unsigned int selector)639{640	unsigned int val;641	int ret;642 643	BUG_ON(!desc->n_linear_ranges);644 645	ret = linear_range_get_value_array(desc->linear_ranges,646					   desc->n_linear_ranges, selector,647					   &val);648	if (ret)649		return ret;650 651	return val;652}653EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range);654 655/**656 * regulator_list_voltage_linear_range - List voltages for linear ranges657 *658 * @rdev: Regulator device659 * @selector: Selector to convert into a voltage660 *661 * Regulators with a series of simple linear mappings between voltages662 * and selectors can set linear_ranges in the regulator descriptor and663 * then use this function as their list_voltage() operation,664 */665int regulator_list_voltage_linear_range(struct regulator_dev *rdev,666					unsigned int selector)667{668	return regulator_desc_list_voltage_linear_range(rdev->desc, selector);669}670EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);671 672/**673 * regulator_list_voltage_table - List voltages with table based mapping674 *675 * @rdev: Regulator device676 * @selector: Selector to convert into a voltage677 *678 * Regulators with table based mapping between voltages and679 * selectors can set volt_table in the regulator descriptor680 * and then use this function as their list_voltage() operation.681 */682int regulator_list_voltage_table(struct regulator_dev *rdev,683				 unsigned int selector)684{685	if (!rdev->desc->volt_table) {686		BUG_ON(!rdev->desc->volt_table);687		return -EINVAL;688	}689 690	if (selector >= rdev->desc->n_voltages)691		return -EINVAL;692	if (selector < rdev->desc->linear_min_sel)693		return 0;694 695	return rdev->desc->volt_table[selector];696}697EXPORT_SYMBOL_GPL(regulator_list_voltage_table);698 699/**700 * regulator_set_bypass_regmap - Default set_bypass() using regmap701 *702 * @rdev: device to operate on.703 * @enable: state to set.704 */705int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)706{707	unsigned int val;708 709	if (enable) {710		val = rdev->desc->bypass_val_on;711		if (!val)712			val = rdev->desc->bypass_mask;713	} else {714		val = rdev->desc->bypass_val_off;715	}716 717	return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg,718				  rdev->desc->bypass_mask, val);719}720EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);721 722/**723 * regulator_set_soft_start_regmap - Default set_soft_start() using regmap724 *725 * @rdev: device to operate on.726 */727int regulator_set_soft_start_regmap(struct regulator_dev *rdev)728{729	unsigned int val;730 731	val = rdev->desc->soft_start_val_on;732	if (!val)733		val = rdev->desc->soft_start_mask;734 735	return regmap_update_bits(rdev->regmap, rdev->desc->soft_start_reg,736				  rdev->desc->soft_start_mask, val);737}738EXPORT_SYMBOL_GPL(regulator_set_soft_start_regmap);739 740/**741 * regulator_set_pull_down_regmap - Default set_pull_down() using regmap742 *743 * @rdev: device to operate on.744 */745int regulator_set_pull_down_regmap(struct regulator_dev *rdev)746{747	unsigned int val;748 749	val = rdev->desc->pull_down_val_on;750	if (!val)751		val = rdev->desc->pull_down_mask;752 753	return regmap_update_bits(rdev->regmap, rdev->desc->pull_down_reg,754				  rdev->desc->pull_down_mask, val);755}756EXPORT_SYMBOL_GPL(regulator_set_pull_down_regmap);757 758/**759 * regulator_get_bypass_regmap - Default get_bypass() using regmap760 *761 * @rdev: device to operate on.762 * @enable: current state.763 */764int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)765{766	unsigned int val;767	unsigned int val_on = rdev->desc->bypass_val_on;768	int ret;769 770	ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val);771	if (ret != 0)772		return ret;773 774	if (!val_on)775		val_on = rdev->desc->bypass_mask;776 777	*enable = (val & rdev->desc->bypass_mask) == val_on;778 779	return 0;780}781EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);782 783/**784 * regulator_set_active_discharge_regmap - Default set_active_discharge()785 *					   using regmap786 *787 * @rdev: device to operate on.788 * @enable: state to set, 0 to disable and 1 to enable.789 */790int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,791					  bool enable)792{793	unsigned int val;794 795	if (enable)796		val = rdev->desc->active_discharge_on;797	else798		val = rdev->desc->active_discharge_off;799 800	return regmap_update_bits(rdev->regmap,801				  rdev->desc->active_discharge_reg,802				  rdev->desc->active_discharge_mask, val);803}804EXPORT_SYMBOL_GPL(regulator_set_active_discharge_regmap);805 806/**807 * regulator_set_current_limit_regmap - set_current_limit for regmap users808 *809 * @rdev: regulator to operate on810 * @min_uA: Lower bound for current limit811 * @max_uA: Upper bound for current limit812 *813 * Regulators that use regmap for their register I/O can set curr_table,814 * csel_reg and csel_mask fields in their descriptor and then use this815 * as their set_current_limit operation, saving some code.816 */817int regulator_set_current_limit_regmap(struct regulator_dev *rdev,818				       int min_uA, int max_uA)819{820	unsigned int n_currents = rdev->desc->n_current_limits;821	int i, sel = -1;822 823	if (n_currents == 0)824		return -EINVAL;825 826	if (rdev->desc->curr_table) {827		const unsigned int *curr_table = rdev->desc->curr_table;828		bool ascend = curr_table[n_currents - 1] > curr_table[0];829 830		/* search for closest to maximum */831		if (ascend) {832			for (i = n_currents - 1; i >= 0; i--) {833				if (min_uA <= curr_table[i] &&834				    curr_table[i] <= max_uA) {835					sel = i;836					break;837				}838			}839		} else {840			for (i = 0; i < n_currents; i++) {841				if (min_uA <= curr_table[i] &&842				    curr_table[i] <= max_uA) {843					sel = i;844					break;845				}846			}847		}848	}849 850	if (sel < 0)851		return -EINVAL;852 853	sel <<= ffs(rdev->desc->csel_mask) - 1;854 855	return regmap_update_bits(rdev->regmap, rdev->desc->csel_reg,856				  rdev->desc->csel_mask, sel);857}858EXPORT_SYMBOL_GPL(regulator_set_current_limit_regmap);859 860/**861 * regulator_get_current_limit_regmap - get_current_limit for regmap users862 *863 * @rdev: regulator to operate on864 *865 * Regulators that use regmap for their register I/O can set the866 * csel_reg and csel_mask fields in their descriptor and then use this867 * as their get_current_limit operation, saving some code.868 */869int regulator_get_current_limit_regmap(struct regulator_dev *rdev)870{871	unsigned int val;872	int ret;873 874	ret = regmap_read(rdev->regmap, rdev->desc->csel_reg, &val);875	if (ret != 0)876		return ret;877 878	val &= rdev->desc->csel_mask;879	val >>= ffs(rdev->desc->csel_mask) - 1;880 881	if (rdev->desc->curr_table) {882		if (val >= rdev->desc->n_current_limits)883			return -EINVAL;884 885		return rdev->desc->curr_table[val];886	}887 888	return -EINVAL;889}890EXPORT_SYMBOL_GPL(regulator_get_current_limit_regmap);891 892/**893 * regulator_bulk_set_supply_names - initialize the 'supply' fields in an array894 *                                   of regulator_bulk_data structs895 *896 * @consumers: array of regulator_bulk_data entries to initialize897 * @supply_names: array of supply name strings898 * @num_supplies: number of supply names to initialize899 *900 * Note: the 'consumers' array must be the size of 'num_supplies'.901 */902void regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers,903				     const char *const *supply_names,904				     unsigned int num_supplies)905{906	unsigned int i;907 908	for (i = 0; i < num_supplies; i++)909		consumers[i].supply = supply_names[i];910}911EXPORT_SYMBOL_GPL(regulator_bulk_set_supply_names);912 913/**914 * regulator_is_equal - test whether two regulators are the same915 *916 * @reg1: first regulator to operate on917 * @reg2: second regulator to operate on918 */919bool regulator_is_equal(struct regulator *reg1, struct regulator *reg2)920{921	return reg1->rdev == reg2->rdev;922}923EXPORT_SYMBOL_GPL(regulator_is_equal);924 925/**926 * regulator_find_closest_bigger - helper to find offset in ramp delay table927 *928 * @target: targeted ramp_delay929 * @table: table with supported ramp delays930 * @num_sel: number of entries in the table931 * @sel: Pointer to store table offset932 *933 * This is the internal helper used by regulator_set_ramp_delay_regmap to934 * map ramp delay to register value. It should only be used directly if935 * regulator_set_ramp_delay_regmap cannot handle a specific device setup936 * (e.g. because the value is split over multiple registers).937 */938int regulator_find_closest_bigger(unsigned int target, const unsigned int *table,939				  unsigned int num_sel, unsigned int *sel)940{941	unsigned int s, tmp, max, maxsel = 0;942	bool found = false;943 944	max = table[0];945 946	for (s = 0; s < num_sel; s++) {947		if (table[s] > max) {948			max = table[s];949			maxsel = s;950		}951		if (table[s] >= target) {952			if (!found || table[s] - target < tmp - target) {953				tmp = table[s];954				*sel = s;955				found = true;956				if (tmp == target)957					break;958			}959		}960	}961 962	if (!found) {963		*sel = maxsel;964		return -EINVAL;965	}966 967	return 0;968}969EXPORT_SYMBOL_GPL(regulator_find_closest_bigger);970 971/**972 * regulator_set_ramp_delay_regmap - set_ramp_delay() helper973 *974 * @rdev: regulator to operate on975 * @ramp_delay: ramp-rate value given in units V/S (uV/uS)976 *977 * Regulators that use regmap for their register I/O can set the ramp_reg978 * and ramp_mask fields in their descriptor and then use this as their979 * set_ramp_delay operation, saving some code.980 */981int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay)982{983	int ret;984	unsigned int sel;985 986	if (WARN_ON(!rdev->desc->n_ramp_values || !rdev->desc->ramp_delay_table))987		return -EINVAL;988 989	ret = regulator_find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table,990					    rdev->desc->n_ramp_values, &sel);991 992	if (ret) {993		dev_warn(rdev_get_dev(rdev),994			 "Can't set ramp-delay %u, setting %u\n", ramp_delay,995			 rdev->desc->ramp_delay_table[sel]);996	}997 998	sel <<= ffs(rdev->desc->ramp_mask) - 1;999 1000	return regmap_update_bits(rdev->regmap, rdev->desc->ramp_reg,1001				  rdev->desc->ramp_mask, sel);1002}1003EXPORT_SYMBOL_GPL(regulator_set_ramp_delay_regmap);1004