|
35 | 35 |
|
36 | 36 | #define MP8859_GO_BIT 0x01
|
37 | 37 |
|
| 38 | +#define MP8859_IOUT_LIM_MASK 0x7f |
| 39 | + |
38 | 40 | #define MP8859_ENABLE_MASK 0x80
|
39 | 41 | #define MP8859_DISCHG_EN_MASK 0x10
|
40 | 42 | #define MP8859_MODE_MASK 0x08
|
@@ -131,6 +133,58 @@ static int mp8859_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
131 | 133 | MP8859_MODE_MASK, val);
|
132 | 134 | }
|
133 | 135 |
|
| 136 | +static int mp8859_set_current_limit(struct regulator_dev *rdev, |
| 137 | + int min_uA, int max_uA) |
| 138 | +{ |
| 139 | + unsigned int cur_val, new_val; |
| 140 | + int ret, i; |
| 141 | + |
| 142 | + /* Steps of 50mA */ |
| 143 | + new_val = max_uA / 50000; |
| 144 | + if (new_val > MP8859_IOUT_LIM_MASK) |
| 145 | + return -EINVAL; |
| 146 | + if (new_val == 0) |
| 147 | + return -EINVAL; |
| 148 | + |
| 149 | + /* |
| 150 | + * If the regulator is limiting then ramp gradually as per |
| 151 | + * datasheet, otherwise just set the value directly. |
| 152 | + */ |
| 153 | + ret = regmap_read(rdev->regmap, MP8859_STATUS_REG, &cur_val); |
| 154 | + if (ret != 0) |
| 155 | + return ret; |
| 156 | + if (!(cur_val & MP8859_CC_CV_MASK)) { |
| 157 | + return regmap_update_bits(rdev->regmap, MP8859_IOUT_LIM_REG, |
| 158 | + MP8859_IOUT_LIM_MASK, new_val); |
| 159 | + } |
| 160 | + |
| 161 | + ret = regmap_read(rdev->regmap, MP8859_IOUT_LIM_REG, &cur_val); |
| 162 | + if (ret != 0) |
| 163 | + return ret; |
| 164 | + |
| 165 | + if (cur_val >= new_val) { |
| 166 | + for (i = cur_val; i >= new_val; i--) { |
| 167 | + ret = regmap_update_bits(rdev->regmap, |
| 168 | + MP8859_IOUT_LIM_REG, |
| 169 | + MP8859_IOUT_LIM_MASK, |
| 170 | + cur_val - i); |
| 171 | + if (ret != 0) |
| 172 | + return ret; |
| 173 | + } |
| 174 | + } else { |
| 175 | + for (i = cur_val; i <= new_val; i++) { |
| 176 | + ret = regmap_update_bits(rdev->regmap, |
| 177 | + MP8859_IOUT_LIM_REG, |
| 178 | + MP8859_IOUT_LIM_MASK, |
| 179 | + cur_val + i); |
| 180 | + if (ret != 0) |
| 181 | + return ret; |
| 182 | + } |
| 183 | + } |
| 184 | + |
| 185 | + return 0; |
| 186 | +} |
| 187 | + |
134 | 188 | static int mp8859_get_status(struct regulator_dev *rdev)
|
135 | 189 | {
|
136 | 190 | unsigned int val;
|
@@ -241,6 +295,7 @@ static const struct regulator_ops mp8859_ops = {
|
241 | 295 | .set_mode = mp8859_set_mode,
|
242 | 296 | .get_mode = mp8859_get_mode,
|
243 | 297 | .set_active_discharge = regulator_set_active_discharge_regmap,
|
| 298 | + .set_current_limit = mp8859_set_current_limit, |
244 | 299 | .get_status = mp8859_get_status,
|
245 | 300 | .get_error_flags = mp8859_get_error_flags,
|
246 | 301 | };
|
|
0 commit comments