aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 = {