Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
 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
26	if (uv == 0) {
27		if (omask)
28			return regmap_update_bits(regmap, oreg, omask, 0);
29	}
30	for (i = 0; i < desc->n_voltages; i++) {
31		ret = regulator_desc_list_voltage_linear_range(desc, i);
32		if (ret < 0)
33			continue;
34		if (ret == uv) {
35			i <<= ffs(desc->vsel_mask) - 1;
36			ret = regmap_update_bits(regmap, reg, mask, i);
37			if (omask && !ret)
38				ret = regmap_update_bits(regmap, oreg, omask,
39							 omask);
40			break;
41		}
42	}
43	return ret;
44}
45
46int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
47			  struct device_node *np,
48			  const struct regulator_desc *desc,
49			  struct regmap *regmap)
50{
51	int i, ret = 0;
52	char *prop;
53	unsigned int reg, mask, omask, oreg = desc->enable_reg;
54
55	for (i = 0; i < ROHM_DVS_LEVEL_MAX && !ret; i++) {
56		if (dvs->level_map & (1 << i)) {
57			switch (i + 1) {
58			case ROHM_DVS_LEVEL_RUN:
59				prop = "rohm,dvs-run-voltage";
60				reg = dvs->run_reg;
61				mask = dvs->run_mask;
62				omask = dvs->run_on_mask;
63				break;
64			case ROHM_DVS_LEVEL_IDLE:
65				prop = "rohm,dvs-idle-voltage";
66				reg = dvs->idle_reg;
67				mask = dvs->idle_mask;
68				omask = dvs->idle_on_mask;
69				break;
70			case ROHM_DVS_LEVEL_SUSPEND:
71				prop = "rohm,dvs-suspend-voltage";
72				reg = dvs->suspend_reg;
73				mask = dvs->suspend_mask;
74				omask = dvs->suspend_on_mask;
75				break;
76			case ROHM_DVS_LEVEL_LPSR:
77				prop = "rohm,dvs-lpsr-voltage";
78				reg = dvs->lpsr_reg;
79				mask = dvs->lpsr_mask;
80				omask = dvs->lpsr_on_mask;
81				break;
82			default:
83				return -EINVAL;
84			}
85			ret = set_dvs_level(desc, np, regmap, prop, reg, mask,
86					    omask, oreg);
87		}
88	}
89	return ret;
90}
91EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);
92
93MODULE_LICENSE("GPL v2");
94MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
95MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");