Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Bjorn Andersson and committed by
Mark Brown
fd805d99 ccffcb8e

+69 -35
+69 -35
drivers/regulator/qcom_smd-regulator.c
··· 31 31 32 32 int is_enabled; 33 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 36 41 struct rpm_regulator_req { ··· 48 43 #define RPM_KEY_UV 0x00007675 /* "uv" */ 49 44 #define RPM_KEY_MA 0x0000616d /* "ma" */ 50 45 51 - static int rpm_reg_write_active(struct qcom_rpm_reg *vreg, 52 - struct rpm_regulator_req *req, 53 - size_t size) 46 + static int rpm_reg_write_active(struct qcom_rpm_reg *vreg) 54 47 { 55 - return qcom_rpm_smd_write(vreg->rpm, 56 - QCOM_SMD_RPM_ACTIVE_STATE, 57 - vreg->type, 58 - vreg->id, 59 - req, size); 48 + struct rpm_regulator_req req[3]; 49 + int reqlen = 0; 50 + int ret; 51 + 52 + if (vreg->enabled_updated) { 53 + req[reqlen].key = cpu_to_le32(RPM_KEY_SWEN); 54 + req[reqlen].nbytes = cpu_to_le32(sizeof(u32)); 55 + req[reqlen].value = cpu_to_le32(vreg->is_enabled); 56 + reqlen++; 57 + } 58 + 59 + if (vreg->uv_updated && vreg->is_enabled) { 60 + req[reqlen].key = cpu_to_le32(RPM_KEY_UV); 61 + req[reqlen].nbytes = cpu_to_le32(sizeof(u32)); 62 + req[reqlen].value = cpu_to_le32(vreg->uV); 63 + reqlen++; 64 + } 65 + 66 + if (vreg->load_updated && vreg->is_enabled) { 67 + req[reqlen].key = cpu_to_le32(RPM_KEY_MA); 68 + req[reqlen].nbytes = cpu_to_le32(sizeof(u32)); 69 + req[reqlen].value = cpu_to_le32(vreg->load / 1000); 70 + reqlen++; 71 + } 72 + 73 + if (!reqlen) 74 + return 0; 75 + 76 + ret = qcom_rpm_smd_write(vreg->rpm, QCOM_SMD_RPM_ACTIVE_STATE, 77 + vreg->type, vreg->id, 78 + req, sizeof(req[0]) * reqlen); 79 + if (!ret) { 80 + vreg->enabled_updated = 0; 81 + vreg->uv_updated = 0; 82 + vreg->load_updated = 0; 83 + } 84 + 85 + return ret; 60 86 } 61 87 62 88 static int rpm_reg_enable(struct regulator_dev *rdev) 63 89 { 64 90 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); 65 - struct rpm_regulator_req req; 66 91 int ret; 67 92 68 - req.key = cpu_to_le32(RPM_KEY_SWEN); 69 - req.nbytes = cpu_to_le32(sizeof(u32)); 70 - req.value = cpu_to_le32(1); 93 + vreg->is_enabled = 1; 94 + vreg->enabled_updated = 1; 71 95 72 - ret = rpm_reg_write_active(vreg, &req, sizeof(req)); 73 - if (!ret) 74 - vreg->is_enabled = 1; 96 + ret = rpm_reg_write_active(vreg); 97 + if (ret) 98 + vreg->is_enabled = 0; 75 99 76 100 return ret; 77 101 } ··· 115 81 static int rpm_reg_disable(struct regulator_dev *rdev) 116 82 { 117 83 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); 118 - struct rpm_regulator_req req; 119 84 int ret; 120 85 121 - req.key = cpu_to_le32(RPM_KEY_SWEN); 122 - req.nbytes = cpu_to_le32(sizeof(u32)); 123 - req.value = 0; 86 + vreg->is_enabled = 0; 87 + vreg->enabled_updated = 1; 124 88 125 - ret = rpm_reg_write_active(vreg, &req, sizeof(req)); 126 - if (!ret) 127 - vreg->is_enabled = 0; 89 + ret = rpm_reg_write_active(vreg); 90 + if (ret) 91 + vreg->is_enabled = 1; 128 92 129 93 return ret; 130 94 } ··· 140 108 unsigned *selector) 141 109 { 142 110 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); 143 - struct rpm_regulator_req req; 144 - int ret = 0; 111 + int ret; 112 + int old_uV = vreg->uV; 145 113 146 - req.key = cpu_to_le32(RPM_KEY_UV); 147 - req.nbytes = cpu_to_le32(sizeof(u32)); 148 - req.value = cpu_to_le32(min_uV); 114 + vreg->uV = min_uV; 115 + vreg->uv_updated = 1; 149 116 150 - ret = rpm_reg_write_active(vreg, &req, sizeof(req)); 151 - if (!ret) 152 - vreg->uV = min_uV; 117 + ret = rpm_reg_write_active(vreg); 118 + if (ret) 119 + vreg->uV = old_uV; 153 120 154 121 return ret; 155 122 } ··· 156 125 static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA) 157 126 { 158 127 struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); 159 - struct rpm_regulator_req req; 128 + u32 old_load = vreg->load; 129 + int ret; 160 130 161 - req.key = cpu_to_le32(RPM_KEY_MA); 162 - req.nbytes = cpu_to_le32(sizeof(u32)); 163 - req.value = cpu_to_le32(load_uA / 1000); 131 + vreg->load = load_uA; 132 + vreg->load_updated = 1; 133 + ret = rpm_reg_write_active(vreg); 134 + if (ret) 135 + vreg->load = old_load; 164 136 165 - return rpm_reg_write_active(vreg, &req, sizeof(req)); 137 + return ret; 166 138 } 167 139 168 140 static const struct regulator_ops rpm_smps_ldo_ops = {