brintos

brintos / linux-shallow public Read only

0
0
Text · 3.6 KiB · 4b95ca0 Raw
138 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2020 ROHM Semiconductors3 4#include <linux/errno.h>5#include <linux/mfd/rohm-generic.h>6#include <linux/module.h>7#include <linux/of.h>8#include <linux/regmap.h>9#include <linux/regulator/driver.h>10 11static int set_dvs_level(const struct regulator_desc *desc,12			 struct device_node *np, struct regmap *regmap,13			 char *prop, unsigned int reg, unsigned int mask,14			 unsigned int omask, unsigned int oreg)15{16	int ret, i;17	uint32_t uv;18 19	ret = of_property_read_u32(np, prop, &uv);20	if (ret) {21		if (ret != -EINVAL)22			return ret;23		return 0;24	}25	/* If voltage is set to 0 => disable */26	if (uv == 0) {27		if (omask)28			return regmap_update_bits(regmap, oreg, omask, 0);29	}30	/* Some setups don't allow setting own voltage but do allow enabling */31	if (!mask) {32		if (omask)33			return regmap_update_bits(regmap, oreg, omask, omask);34 35		return -EINVAL;36	}37	for (i = 0; i < desc->n_voltages; i++) {38		/* NOTE to next hacker - Does not support pickable ranges */39		if (desc->linear_range_selectors_bitfield)40			return -EINVAL;41		if (desc->n_linear_ranges)42			ret = regulator_desc_list_voltage_linear_range(desc, i);43		else44			ret = regulator_desc_list_voltage_linear(desc, i);45		if (ret < 0)46			continue;47		if (ret == uv) {48			i <<= ffs(desc->vsel_mask) - 1;49 50			ret = regmap_update_bits(regmap, reg, mask, i);51			if (omask && !ret)52				ret = regmap_update_bits(regmap, oreg, omask,53							 omask);54			break;55		}56	}57	if (i == desc->n_voltages)58		pr_warn("Unsupported %s voltage %u\n", prop, uv);59 60	return ret;61}62 63int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,64			  struct device_node *np,65			  const struct regulator_desc *desc,66			  struct regmap *regmap)67{68	int i, ret = 0;69	char *prop;70	unsigned int reg, mask, omask, oreg = desc->enable_reg;71 72	for (i = 0; i < ROHM_DVS_LEVEL_VALID_AMOUNT && !ret; i++) {73		int bit;74 75		bit = BIT(i);76		if (dvs->level_map & bit) {77			switch (bit) {78			case ROHM_DVS_LEVEL_RUN:79				prop = "rohm,dvs-run-voltage";80				reg = dvs->run_reg;81				mask = dvs->run_mask;82				omask = dvs->run_on_mask;83				break;84			case ROHM_DVS_LEVEL_IDLE:85				prop = "rohm,dvs-idle-voltage";86				reg = dvs->idle_reg;87				mask = dvs->idle_mask;88				omask = dvs->idle_on_mask;89				break;90			case ROHM_DVS_LEVEL_SUSPEND:91				prop = "rohm,dvs-suspend-voltage";92				reg = dvs->suspend_reg;93				mask = dvs->suspend_mask;94				omask = dvs->suspend_on_mask;95				break;96			case ROHM_DVS_LEVEL_LPSR:97				prop = "rohm,dvs-lpsr-voltage";98				reg = dvs->lpsr_reg;99				mask = dvs->lpsr_mask;100				omask = dvs->lpsr_on_mask;101				break;102			case ROHM_DVS_LEVEL_SNVS:103				prop = "rohm,dvs-snvs-voltage";104				reg = dvs->snvs_reg;105				mask = dvs->snvs_mask;106				omask = dvs->snvs_on_mask;107				break;108			default:109				return -EINVAL;110			}111			ret = set_dvs_level(desc, np, regmap, prop, reg, mask,112					    omask, oreg);113		}114	}115	return ret;116}117EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);118 119/*120 * Few ROHM PMIC ICs have constrains on voltage changing:121 * BD71837 - only buck 1-4 voltages can be changed when they are enabled.122 * Other bucks and all LDOs must be disabled when voltage is changed.123 * BD96801 - LDO voltage levels can be changed when LDOs are disabled.124 */125int rohm_regulator_set_voltage_sel_restricted(struct regulator_dev *rdev,126					      unsigned int sel)127{128	if (rdev->desc->ops->is_enabled(rdev))129		return -EBUSY;130 131	return regulator_set_voltage_sel_regmap(rdev, sel);132}133EXPORT_SYMBOL_GPL(rohm_regulator_set_voltage_sel_restricted);134 135MODULE_LICENSE("GPL v2");136MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");137MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");138