]> Git Repo - J-linux.git/blob - drivers/regulator/rohm-regulator.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / regulator / rohm-regulator.c
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
11 static 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                 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
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
63 int 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 }
117 EXPORT_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  */
125 int 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 }
133 EXPORT_SYMBOL_GPL(rohm_regulator_set_voltage_sel_restricted);
134
135 MODULE_LICENSE("GPL v2");
136 MODULE_AUTHOR("Matti Vaittinen <[email protected]>");
137 MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");
This page took 0.029959 seconds and 4 git commands to generate.