Merge branches 'acpi-cppc', 'acpi-video' and 'acpi-utils'
[linux-2.6-block.git] / drivers / regulator / rohm-regulator.c
CommitLineData
21b72156
MV
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
c2945541
MV
55 for (i = 0; i < ROHM_DVS_LEVEL_VALID_AMOUNT && !ret; i++) {
56 int bit;
57
58 bit = BIT(i);
59 if (dvs->level_map & bit) {
60 switch (bit) {
21b72156
MV
61 case ROHM_DVS_LEVEL_RUN:
62 prop = "rohm,dvs-run-voltage";
63 reg = dvs->run_reg;
64 mask = dvs->run_mask;
65 omask = dvs->run_on_mask;
66 break;
67 case ROHM_DVS_LEVEL_IDLE:
68 prop = "rohm,dvs-idle-voltage";
69 reg = dvs->idle_reg;
70 mask = dvs->idle_mask;
71 omask = dvs->idle_on_mask;
72 break;
73 case ROHM_DVS_LEVEL_SUSPEND:
74 prop = "rohm,dvs-suspend-voltage";
75 reg = dvs->suspend_reg;
76 mask = dvs->suspend_mask;
77 omask = dvs->suspend_on_mask;
78 break;
79 case ROHM_DVS_LEVEL_LPSR:
80 prop = "rohm,dvs-lpsr-voltage";
81 reg = dvs->lpsr_reg;
82 mask = dvs->lpsr_mask;
83 omask = dvs->lpsr_on_mask;
84 break;
85 default:
86 return -EINVAL;
87 }
88 ret = set_dvs_level(desc, np, regmap, prop, reg, mask,
89 omask, oreg);
90 }
91 }
92 return ret;
93}
94EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);
95
96MODULE_LICENSE("GPL v2");
97MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
98MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");