aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Andersson <bjorn.andersson@linaro.org>2019-01-22 14:01:47 -0500
committerMark Brown <broonie@kernel.org>2019-01-22 14:15:37 -0500
commitfd805d99352c89b5cc1ca62ca5644840c9f02f07 (patch)
tree8ef72737022214f05db1cb77bea654fa6650fd26
parentccffcb8e9a11fe91f3577cefeed00b1f58d51671 (diff)
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>
-rw-r--r--drivers/regulator/qcom_smd-regulator.c104
1 files changed, 69 insertions, 35 deletions
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
index f5bca77d67c1..68bc23df4213 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -31,6 +31,11 @@ struct qcom_rpm_reg {
31 31
32 int is_enabled; 32 int is_enabled;
33 int uV; 33 int uV;
34 u32 load;
35
36 unsigned int enabled_updated:1;
37 unsigned int uv_updated:1;
38 unsigned int load_updated:1;
34}; 39};
35 40
36struct rpm_regulator_req { 41struct rpm_regulator_req {
@@ -43,30 +48,59 @@ struct rpm_regulator_req {
43#define RPM_KEY_UV 0x00007675 /* "uv" */ 48#define RPM_KEY_UV 0x00007675 /* "uv" */
44#define RPM_KEY_MA 0x0000616d /* "ma" */ 49#define RPM_KEY_MA 0x0000616d /* "ma" */
45 50
46static int rpm_reg_write_active(struct qcom_rpm_reg *vreg, 51static int rpm_reg_write_active(struct qcom_rpm_reg *vreg)
47 struct rpm_regulator_req *req,
48 size_t size)
49{ 52{
50 return qcom_rpm_smd_write(vreg->rpm, 53 struct rpm_regulator_req req[3];
51 QCOM_SMD_RPM_ACTIVE_STATE, 54 int reqlen = 0;
52 vreg->type, 55 int ret;
53 vreg->id, 56
54 req, size); 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;
55} 91}
56 92
57static int rpm_reg_enable(struct regulator_dev *rdev) 93static int rpm_reg_enable(struct regulator_dev *rdev)
58{ 94{
59 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); 95 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
60 struct rpm_regulator_req req;
61 int ret; 96 int ret;
62 97
63 req.key = cpu_to_le32(RPM_KEY_SWEN); 98 vreg->is_enabled = 1;
64 req.nbytes = cpu_to_le32(sizeof(u32)); 99 vreg->enabled_updated = 1;
65 req.value = cpu_to_le32(1);
66 100
67 ret = rpm_reg_write_active(vreg, &req, sizeof(req)); 101 ret = rpm_reg_write_active(vreg);
68 if (!ret) 102 if (ret)
69 vreg->is_enabled = 1; 103 vreg->is_enabled = 0;
70 104
71 return ret; 105 return ret;
72} 106}
@@ -81,16 +115,14 @@ static int rpm_reg_is_enabled(struct regulator_dev *rdev)
81static int rpm_reg_disable(struct regulator_dev *rdev) 115static int rpm_reg_disable(struct regulator_dev *rdev)
82{ 116{
83 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); 117 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
84 struct rpm_regulator_req req;
85 int ret; 118 int ret;
86 119
87 req.key = cpu_to_le32(RPM_KEY_SWEN); 120 vreg->is_enabled = 0;
88 req.nbytes = cpu_to_le32(sizeof(u32)); 121 vreg->enabled_updated = 1;
89 req.value = 0;
90 122
91 ret = rpm_reg_write_active(vreg, &req, sizeof(req)); 123 ret = rpm_reg_write_active(vreg);
92 if (!ret) 124 if (ret)
93 vreg->is_enabled = 0; 125 vreg->is_enabled = 1;
94 126
95 return ret; 127 return ret;
96} 128}
@@ -108,16 +140,15 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev,
108 unsigned *selector) 140 unsigned *selector)
109{ 141{
110 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); 142 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
111 struct rpm_regulator_req req; 143 int ret;
112 int ret = 0; 144 int old_uV = vreg->uV;
113 145
114 req.key = cpu_to_le32(RPM_KEY_UV); 146 vreg->uV = min_uV;
115 req.nbytes = cpu_to_le32(sizeof(u32)); 147 vreg->uv_updated = 1;
116 req.value = cpu_to_le32(min_uV);
117 148
118 ret = rpm_reg_write_active(vreg, &req, sizeof(req)); 149 ret = rpm_reg_write_active(vreg);
119 if (!ret) 150 if (ret)
120 vreg->uV = min_uV; 151 vreg->uV = old_uV;
121 152
122 return ret; 153 return ret;
123} 154}
@@ -125,13 +156,16 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev,
125static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA) 156static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
126{ 157{
127 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); 158 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
128 struct rpm_regulator_req req; 159 u32 old_load = vreg->load;
160 int ret;
129 161
130 req.key = cpu_to_le32(RPM_KEY_MA); 162 vreg->load = load_uA;
131 req.nbytes = cpu_to_le32(sizeof(u32)); 163 vreg->load_updated = 1;
132 req.value = cpu_to_le32(load_uA / 1000); 164 ret = rpm_reg_write_active(vreg);
165 if (ret)
166 vreg->load = old_load;
133 167
134 return rpm_reg_write_active(vreg, &req, sizeof(req)); 168 return ret;
135} 169}
136 170
137static const struct regulator_ops rpm_smps_ldo_ops = { 171static const struct regulator_ops rpm_smps_ldo_ops = {