diff options
-rw-r--r-- | drivers/regulator/qcom_smd-regulator.c | 104 |
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 | ||
36 | struct rpm_regulator_req { | 41 | struct 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 | ||
46 | static int rpm_reg_write_active(struct qcom_rpm_reg *vreg, | 51 | static 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 | ||
57 | static int rpm_reg_enable(struct regulator_dev *rdev) | 93 | static 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) | |||
81 | static int rpm_reg_disable(struct regulator_dev *rdev) | 115 | static 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, | |||
125 | static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA) | 156 | static 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 | ||
137 | static const struct regulator_ops rpm_smps_ldo_ops = { | 171 | static const struct regulator_ops rpm_smps_ldo_ops = { |