diff options
Diffstat (limited to 'firmware/target/arm/imx233/power-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/power-imx233.c | 149 |
1 files changed, 124 insertions, 25 deletions
diff --git a/firmware/target/arm/imx233/power-imx233.c b/firmware/target/arm/imx233/power-imx233.c index 6ba08ae394..c02d6ddb77 100644 --- a/firmware/target/arm/imx233/power-imx233.c +++ b/firmware/target/arm/imx233/power-imx233.c | |||
@@ -165,6 +165,130 @@ void imx233_power_set_stop_current(unsigned current) | |||
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
168 | /* regulator info */ | ||
169 | #define HAS_BO (1 << 0) | ||
170 | #define HAS_LINREG (1 << 1) | ||
171 | #define HAS_LINREG_OFFSET (1 << 2) | ||
172 | |||
173 | static struct | ||
174 | { | ||
175 | unsigned min, step; | ||
176 | volatile uint32_t *reg; | ||
177 | uint32_t trg_bm, trg_bp; // bitmask and bitpos | ||
178 | unsigned flags; | ||
179 | uint32_t bo_bm, bo_bp; // bitmask and bitpos | ||
180 | uint32_t linreg_bm; | ||
181 | uint32_t linreg_offset_bm, linreg_offset_bp; // bitmask and bitpos | ||
182 | } regulator_info[] = | ||
183 | { | ||
184 | #define ADD_REGULATOR(name, mask) \ | ||
185 | .min = HW_POWER_##name##CTRL__TRG_MIN, \ | ||
186 | .step = HW_POWER_##name##CTRL__TRG_STEP, \ | ||
187 | .reg = &HW_POWER_##name##CTRL, \ | ||
188 | .trg_bm = HW_POWER_##name##CTRL__TRG_BM, \ | ||
189 | .trg_bp = HW_POWER_##name##CTRL__TRG_BP, \ | ||
190 | .flags = mask | ||
191 | #define ADD_REGULATOR_BO(name) \ | ||
192 | .bo_bm = HW_POWER_##name##CTRL__BO_OFFSET_BM, \ | ||
193 | .bo_bp = HW_POWER_##name##CTRL__BO_OFFSET_BP | ||
194 | #define ADD_REGULATOR_LINREG(name) \ | ||
195 | .linreg_bm = HW_POWER_##name##CTRL__ENABLE_LINREG | ||
196 | #define ADD_REGULATOR_LINREG_OFFSET(name) \ | ||
197 | .linreg_offset_bm = HW_POWER_##name##CTRL__LINREG_OFFSET_BM, \ | ||
198 | .linreg_offset_bp = HW_POWER_##name##CTRL__LINREG_OFFSET_BP | ||
199 | [REGULATOR_VDDD] = | ||
200 | { | ||
201 | ADD_REGULATOR(VDDD, HAS_BO|HAS_LINREG|HAS_LINREG_OFFSET), | ||
202 | ADD_REGULATOR_BO(VDDD), | ||
203 | ADD_REGULATOR_LINREG(VDDD), | ||
204 | ADD_REGULATOR_LINREG_OFFSET(VDDD) | ||
205 | }, | ||
206 | [REGULATOR_VDDA] = | ||
207 | { | ||
208 | ADD_REGULATOR(VDDA, HAS_BO|HAS_LINREG|HAS_LINREG_OFFSET), | ||
209 | ADD_REGULATOR_BO(VDDA), | ||
210 | ADD_REGULATOR_LINREG(VDDA), | ||
211 | ADD_REGULATOR_LINREG_OFFSET(VDDA) | ||
212 | }, | ||
213 | [REGULATOR_VDDIO] = | ||
214 | { | ||
215 | ADD_REGULATOR(VDDIO, HAS_BO|HAS_LINREG_OFFSET), | ||
216 | ADD_REGULATOR_BO(VDDIO), | ||
217 | ADD_REGULATOR_LINREG_OFFSET(VDDIO) | ||
218 | }, | ||
219 | [REGULATOR_VDDMEM] = | ||
220 | { | ||
221 | ADD_REGULATOR(VDDMEM, HAS_LINREG), | ||
222 | ADD_REGULATOR_LINREG(VDDMEM), | ||
223 | }, | ||
224 | }; | ||
225 | |||
226 | void imx233_power_get_regulator(enum imx233_regulator_t reg, unsigned *value_mv, | ||
227 | unsigned *brownout_mv) | ||
228 | { | ||
229 | uint32_t reg_val = *regulator_info[reg].reg; | ||
230 | /* read target value */ | ||
231 | unsigned raw_val = (reg_val & regulator_info[reg].trg_bm) >> regulator_info[reg].trg_bp; | ||
232 | /* convert it to mv */ | ||
233 | if(value_mv) | ||
234 | *value_mv = regulator_info[reg].min + regulator_info[reg].step * raw_val; | ||
235 | if(regulator_info[reg].flags & HAS_BO) | ||
236 | { | ||
237 | /* read brownout offset */ | ||
238 | unsigned raw_bo = (reg_val & regulator_info[reg].bo_bm) >> regulator_info[reg].bo_bp; | ||
239 | /* convert it to mv */ | ||
240 | if(brownout_mv) | ||
241 | *brownout_mv = regulator_info[reg].min + regulator_info[reg].step * (raw_val - raw_bo); | ||
242 | } | ||
243 | else if(brownout_mv) | ||
244 | *brownout_mv = 0; | ||
245 | } | ||
246 | |||
247 | void imx233_power_set_regulator(enum imx233_regulator_t reg, unsigned value_mv, | ||
248 | unsigned brownout_mv) | ||
249 | { | ||
250 | // compute raw values | ||
251 | unsigned raw_val = (value_mv - regulator_info[reg].min) / regulator_info[reg].step; | ||
252 | unsigned raw_bo_offset = (value_mv - brownout_mv) / regulator_info[reg].step; | ||
253 | // update | ||
254 | uint32_t reg_val = (*regulator_info[reg].reg) & ~regulator_info[reg].trg_bm; | ||
255 | reg_val |= raw_val << regulator_info[reg].trg_bp; | ||
256 | if(regulator_info[reg].flags & HAS_BO) | ||
257 | { | ||
258 | reg_val &= ~regulator_info[reg].bo_bm; | ||
259 | reg_val |= raw_bo_offset << regulator_info[reg].bo_bp; | ||
260 | } | ||
261 | *regulator_info[reg].reg = reg_val; | ||
262 | } | ||
263 | |||
264 | // offset is -1,0 or 1 | ||
265 | void imx233_power_get_regulator_linreg(enum imx233_regulator_t reg, | ||
266 | bool *enabled, int *linreg_offset) | ||
267 | { | ||
268 | if(enabled && regulator_info[reg].flags & HAS_LINREG) | ||
269 | *enabled = !!(*regulator_info[reg].reg & regulator_info[reg].linreg_bm); | ||
270 | else if(enabled) | ||
271 | *enabled = true; | ||
272 | if(regulator_info[reg].flags & HAS_LINREG_OFFSET) | ||
273 | { | ||
274 | unsigned v = (*regulator_info[reg].reg & regulator_info[reg].linreg_offset_bm); | ||
275 | v >>= regulator_info[reg].linreg_offset_bp; | ||
276 | if(linreg_offset) | ||
277 | *linreg_offset = (v == 0) ? 0 : (v == 1) ? 1 : -1; | ||
278 | } | ||
279 | else if(linreg_offset) | ||
280 | *linreg_offset = 0; | ||
281 | } | ||
282 | |||
283 | // offset is -1,0 or 1 | ||
284 | /* | ||
285 | void imx233_power_set_regulator_linreg(enum imx233_regulator_t reg, | ||
286 | bool enabled, int linreg_offset) | ||
287 | { | ||
288 | } | ||
289 | */ | ||
290 | |||
291 | |||
168 | struct imx233_power_info_t imx233_power_get_info(unsigned flags) | 292 | struct imx233_power_info_t imx233_power_get_info(unsigned flags) |
169 | { | 293 | { |
170 | static int dcdc_freqsel[8] = { | 294 | static int dcdc_freqsel[8] = { |
@@ -180,31 +304,6 @@ struct imx233_power_info_t imx233_power_get_info(unsigned flags) | |||
180 | 304 | ||
181 | struct imx233_power_info_t s; | 305 | struct imx233_power_info_t s; |
182 | memset(&s, 0, sizeof(s)); | 306 | memset(&s, 0, sizeof(s)); |
183 | if(flags & POWER_INFO_VDDD) | ||
184 | { | ||
185 | s.vddd = HW_POWER_VDDDCTRL__TRG_MIN + HW_POWER_VDDDCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDDCTRL, TRG); | ||
186 | s.vddd_linreg = HW_POWER_VDDDCTRL & HW_POWER_VDDDCTRL__ENABLE_LINREG; | ||
187 | s.vddd_linreg_offset = __XTRACT(HW_POWER_VDDDCTRL, LINREG_OFFSET) == 0 ? 0 : | ||
188 | __XTRACT(HW_POWER_VDDDCTRL, LINREG_OFFSET) == 1 ? 25 : -25; | ||
189 | } | ||
190 | if(flags & POWER_INFO_VDDA) | ||
191 | { | ||
192 | s.vdda = HW_POWER_VDDACTRL__TRG_MIN + HW_POWER_VDDACTRL__TRG_STEP * __XTRACT(HW_POWER_VDDACTRL, TRG); | ||
193 | s.vdda_linreg = HW_POWER_VDDACTRL & HW_POWER_VDDACTRL__ENABLE_LINREG; | ||
194 | s.vdda_linreg_offset = __XTRACT(HW_POWER_VDDACTRL, LINREG_OFFSET) == 0 ? 0 : | ||
195 | __XTRACT(HW_POWER_VDDACTRL, LINREG_OFFSET) == 1 ? 25 : -25; | ||
196 | } | ||
197 | if(flags & POWER_INFO_VDDIO) | ||
198 | { | ||
199 | s.vddio = HW_POWER_VDDIOCTRL__TRG_MIN + HW_POWER_VDDIOCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDIOCTRL, TRG); | ||
200 | s.vddio_linreg_offset = __XTRACT(HW_POWER_VDDIOCTRL, LINREG_OFFSET) == 0 ? 0 : | ||
201 | __XTRACT(HW_POWER_VDDIOCTRL, LINREG_OFFSET) == 1 ? 25 : -25; | ||
202 | } | ||
203 | if(flags & POWER_INFO_VDDMEM) | ||
204 | { | ||
205 | s.vddmem = HW_POWER_VDDMEMCTRL__TRG_MIN + HW_POWER_VDDMEMCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDMEMCTRL, TRG); | ||
206 | s.vddmem_linreg = HW_POWER_VDDMEMCTRL & HW_POWER_VDDMEMCTRL__ENABLE_LINREG; | ||
207 | } | ||
208 | if(flags & POWER_INFO_DCDC) | 307 | if(flags & POWER_INFO_DCDC) |
209 | { | 308 | { |
210 | s.dcdc_sel_pllclk = HW_POWER_MISC & HW_POWER_MISC__SEL_PLLCLK; | 309 | s.dcdc_sel_pllclk = HW_POWER_MISC & HW_POWER_MISC__SEL_PLLCLK; |