Skip to content

Commit fd805d9

Browse files
anderssonbroonie
authored andcommitted
regulator: qcom-smd: Batch up requests for disabled regulators
In some scenarios the early stages of the boot chain has configured regulators to be in a required state, but the later stages has skipped to inform the RPM about it's requirements. But as the SMD RPM regulators are being initialized voltage change requests will be issued to align the voltage with the valid ranges. The RPM aggregates all parameters for the specific regulator, the voltage will be adjusted and the "enabled" state will be "off" - and the regulator is turned off. This patch addresses this problem by caching the requested enable state, voltage and load and send the parameters in a batch, depending on the enable state - effectively delaying the voltage request for disabled regulators. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent ccffcb8 commit fd805d9

File tree

1 file changed

+69
-35
lines changed

1 file changed

+69
-35
lines changed

drivers/regulator/qcom_smd-regulator.c

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ struct qcom_rpm_reg {
3131

3232
int is_enabled;
3333
int uV;
34+
u32 load;
35+
36+
unsigned int enabled_updated:1;
37+
unsigned int uv_updated:1;
38+
unsigned int load_updated:1;
3439
};
3540

3641
struct rpm_regulator_req {
@@ -43,30 +48,59 @@ struct rpm_regulator_req {
4348
#define RPM_KEY_UV 0x00007675 /* "uv" */
4449
#define RPM_KEY_MA 0x0000616d /* "ma" */
4550

46-
static int rpm_reg_write_active(struct qcom_rpm_reg *vreg,
47-
struct rpm_regulator_req *req,
48-
size_t size)
51+
static int rpm_reg_write_active(struct qcom_rpm_reg *vreg)
4952
{
50-
return qcom_rpm_smd_write(vreg->rpm,
51-
QCOM_SMD_RPM_ACTIVE_STATE,
52-
vreg->type,
53-
vreg->id,
54-
req, size);
53+
struct rpm_regulator_req req[3];
54+
int reqlen = 0;
55+
int ret;
56+
57+
if (vreg->enabled_updated) {
58+
req[reqlen].key = cpu_to_le32(RPM_KEY_SWEN);
59+
req[reqlen].nbytes = cpu_to_le32(sizeof(u32));
60+
req[reqlen].value = cpu_to_le32(vreg->is_enabled);
61+
reqlen++;
62+
}
63+
64+
if (vreg->uv_updated && vreg->is_enabled) {
65+
req[reqlen].key = cpu_to_le32(RPM_KEY_UV);
66+
req[reqlen].nbytes = cpu_to_le32(sizeof(u32));
67+
req[reqlen].value = cpu_to_le32(vreg->uV);
68+
reqlen++;
69+
}
70+
71+
if (vreg->load_updated && vreg->is_enabled) {
72+
req[reqlen].key = cpu_to_le32(RPM_KEY_MA);
73+
req[reqlen].nbytes = cpu_to_le32(sizeof(u32));
74+
req[reqlen].value = cpu_to_le32(vreg->load / 1000);
75+
reqlen++;
76+
}
77+
78+
if (!reqlen)
79+
return 0;
80+
81+
ret = qcom_rpm_smd_write(vreg->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
82+
vreg->type, vreg->id,
83+
req, sizeof(req[0]) * reqlen);
84+
if (!ret) {
85+
vreg->enabled_updated = 0;
86+
vreg->uv_updated = 0;
87+
vreg->load_updated = 0;
88+
}
89+
90+
return ret;
5591
}
5692

5793
static int rpm_reg_enable(struct regulator_dev *rdev)
5894
{
5995
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
60-
struct rpm_regulator_req req;
6196
int ret;
6297

63-
req.key = cpu_to_le32(RPM_KEY_SWEN);
64-
req.nbytes = cpu_to_le32(sizeof(u32));
65-
req.value = cpu_to_le32(1);
98+
vreg->is_enabled = 1;
99+
vreg->enabled_updated = 1;
66100

67-
ret = rpm_reg_write_active(vreg, &req, sizeof(req));
68-
if (!ret)
69-
vreg->is_enabled = 1;
101+
ret = rpm_reg_write_active(vreg);
102+
if (ret)
103+
vreg->is_enabled = 0;
70104

71105
return ret;
72106
}
@@ -81,16 +115,14 @@ static int rpm_reg_is_enabled(struct regulator_dev *rdev)
81115
static int rpm_reg_disable(struct regulator_dev *rdev)
82116
{
83117
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
84-
struct rpm_regulator_req req;
85118
int ret;
86119

87-
req.key = cpu_to_le32(RPM_KEY_SWEN);
88-
req.nbytes = cpu_to_le32(sizeof(u32));
89-
req.value = 0;
120+
vreg->is_enabled = 0;
121+
vreg->enabled_updated = 1;
90122

91-
ret = rpm_reg_write_active(vreg, &req, sizeof(req));
92-
if (!ret)
93-
vreg->is_enabled = 0;
123+
ret = rpm_reg_write_active(vreg);
124+
if (ret)
125+
vreg->is_enabled = 1;
94126

95127
return ret;
96128
}
@@ -108,30 +140,32 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev,
108140
unsigned *selector)
109141
{
110142
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
111-
struct rpm_regulator_req req;
112-
int ret = 0;
143+
int ret;
144+
int old_uV = vreg->uV;
113145

114-
req.key = cpu_to_le32(RPM_KEY_UV);
115-
req.nbytes = cpu_to_le32(sizeof(u32));
116-
req.value = cpu_to_le32(min_uV);
146+
vreg->uV = min_uV;
147+
vreg->uv_updated = 1;
117148

118-
ret = rpm_reg_write_active(vreg, &req, sizeof(req));
119-
if (!ret)
120-
vreg->uV = min_uV;
149+
ret = rpm_reg_write_active(vreg);
150+
if (ret)
151+
vreg->uV = old_uV;
121152

122153
return ret;
123154
}
124155

125156
static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
126157
{
127158
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
128-
struct rpm_regulator_req req;
159+
u32 old_load = vreg->load;
160+
int ret;
129161

130-
req.key = cpu_to_le32(RPM_KEY_MA);
131-
req.nbytes = cpu_to_le32(sizeof(u32));
132-
req.value = cpu_to_le32(load_uA / 1000);
162+
vreg->load = load_uA;
163+
vreg->load_updated = 1;
164+
ret = rpm_reg_write_active(vreg);
165+
if (ret)
166+
vreg->load = old_load;
133167

134-
return rpm_reg_write_active(vreg, &req, sizeof(req));
168+
return ret;
135169
}
136170

137171
static const struct regulator_ops rpm_smps_ldo_ops = {

0 commit comments

Comments
 (0)