cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rohm-regulator.c (3580B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (C) 2020 ROHM Semiconductors
      3
      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)
     40			return -EINVAL;
     41		if (desc->n_linear_ranges)
     42			ret = regulator_desc_list_voltage_linear_range(desc, i);
     43		else
     44			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			ret = regmap_update_bits(regmap, reg, mask, i);
     50			if (omask && !ret)
     51				ret = regmap_update_bits(regmap, oreg, omask,
     52							 omask);
     53			break;
     54		}
     55	}
     56	return ret;
     57}
     58
     59int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
     60			  struct device_node *np,
     61			  const struct regulator_desc *desc,
     62			  struct regmap *regmap)
     63{
     64	int i, ret = 0;
     65	char *prop;
     66	unsigned int reg, mask, omask, oreg = desc->enable_reg;
     67
     68	for (i = 0; i < ROHM_DVS_LEVEL_VALID_AMOUNT && !ret; i++) {
     69		int bit;
     70
     71		bit = BIT(i);
     72		if (dvs->level_map & bit) {
     73			switch (bit) {
     74			case ROHM_DVS_LEVEL_RUN:
     75				prop = "rohm,dvs-run-voltage";
     76				reg = dvs->run_reg;
     77				mask = dvs->run_mask;
     78				omask = dvs->run_on_mask;
     79				break;
     80			case ROHM_DVS_LEVEL_IDLE:
     81				prop = "rohm,dvs-idle-voltage";
     82				reg = dvs->idle_reg;
     83				mask = dvs->idle_mask;
     84				omask = dvs->idle_on_mask;
     85				break;
     86			case ROHM_DVS_LEVEL_SUSPEND:
     87				prop = "rohm,dvs-suspend-voltage";
     88				reg = dvs->suspend_reg;
     89				mask = dvs->suspend_mask;
     90				omask = dvs->suspend_on_mask;
     91				break;
     92			case ROHM_DVS_LEVEL_LPSR:
     93				prop = "rohm,dvs-lpsr-voltage";
     94				reg = dvs->lpsr_reg;
     95				mask = dvs->lpsr_mask;
     96				omask = dvs->lpsr_on_mask;
     97				break;
     98			case ROHM_DVS_LEVEL_SNVS:
     99				prop = "rohm,dvs-snvs-voltage";
    100				reg = dvs->snvs_reg;
    101				mask = dvs->snvs_mask;
    102				omask = dvs->snvs_on_mask;
    103				break;
    104			default:
    105				return -EINVAL;
    106			}
    107			ret = set_dvs_level(desc, np, regmap, prop, reg, mask,
    108					    omask, oreg);
    109		}
    110	}
    111	return ret;
    112}
    113EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);
    114
    115/*
    116 * Few ROHM PMIC ICs have constrains on voltage changing:
    117 * BD71837 - only buck 1-4 voltages can be changed when they are enabled.
    118 * Other bucks and all LDOs must be disabled when voltage is changed.
    119 * BD96801 - LDO voltage levels can be changed when LDOs are disabled.
    120 */
    121int rohm_regulator_set_voltage_sel_restricted(struct regulator_dev *rdev,
    122					      unsigned int sel)
    123{
    124	if (rdev->desc->ops->is_enabled(rdev))
    125		return -EBUSY;
    126
    127	return regulator_set_voltage_sel_regmap(rdev, sel);
    128}
    129EXPORT_SYMBOL_GPL(rohm_regulator_set_voltage_sel_restricted);
    130
    131MODULE_LICENSE("GPL v2");
    132MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
    133MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");