summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/imx233/power-imx233.c175
-rw-r--r--firmware/target/arm/imx233/power-imx233.h21
2 files changed, 188 insertions, 8 deletions
diff --git a/firmware/target/arm/imx233/power-imx233.c b/firmware/target/arm/imx233/power-imx233.c
index 7829fd79ce..5041c3b7fc 100644
--- a/firmware/target/arm/imx233/power-imx233.c
+++ b/firmware/target/arm/imx233/power-imx233.c
@@ -55,6 +55,7 @@ static struct current_step_bit_t g_charger_stop_current_bits[] =
55 { 10, BV_POWER_CHARGE_STOP_ILIMIT__10mA } 55 { 10, BV_POWER_CHARGE_STOP_ILIMIT__10mA }
56}; 56};
57 57
58#if IMX233_SUBTARGET >= 3780
58/* in decreasing order */ 59/* in decreasing order */
59static struct current_step_bit_t g_4p2_charge_limit_bits[] = 60static struct current_step_bit_t g_4p2_charge_limit_bits[] =
60{ 61{
@@ -65,9 +66,27 @@ static struct current_step_bit_t g_4p2_charge_limit_bits[] =
65 { 20, BV_POWER_5VCTRL_CHARGE_4P2_ILIMIT__20mA }, 66 { 20, BV_POWER_5VCTRL_CHARGE_4P2_ILIMIT__20mA },
66 { 10, BV_POWER_5VCTRL_CHARGE_4P2_ILIMIT__10mA } 67 { 10, BV_POWER_5VCTRL_CHARGE_4P2_ILIMIT__10mA }
67}; 68};
69#endif
70
71/* FIXME
72 * POWER_STS.VBUSVALID does not reflect the actual vbusvalid value, only
73 * VBUSVALID_STATUS does. Indeed the VBUSVALID field can be locked using
74 * VBUSVALIDPIOLOCK. Some Freescale code suggests locking is required for
75 * proper operation of the USB ARC core. This is problematic though
76 * because it prevents proper usage of the VDD5V irq.
77 * Since we didn't encounter this problem, we never lock VBUSVALID
78 *
79 * WARNING
80 * Using VBUSVALID irq on STMP3700 seems broken, once the irq is fired,
81 * it cannot be acked. Currently fallback to the VDD5V>VDDIO method.
82 */
83#if IMX233_SUBTARGET >= 3780
84#define USE_VBUSVALID
85#endif
68 86
69void INT_VDD5V(void) 87void INT_VDD5V(void)
70{ 88{
89#ifdef USE_VBUSVALID
71 if(BF_RD(POWER_CTRL, VBUSVALID_IRQ)) 90 if(BF_RD(POWER_CTRL, VBUSVALID_IRQ))
72 { 91 {
73 if(BF_RD(POWER_STS, VBUSVALID)) 92 if(BF_RD(POWER_STS, VBUSVALID))
@@ -76,9 +95,22 @@ void INT_VDD5V(void)
76 usb_remove_int(); 95 usb_remove_int();
77 /* reverse polarity */ 96 /* reverse polarity */
78 BF_TOG(POWER_CTRL, POLARITY_VBUSVALID); 97 BF_TOG(POWER_CTRL, POLARITY_VBUSVALID);
79 /* enable int */ 98 /* clear int */
80 BF_CLR(POWER_CTRL, VBUSVALID_IRQ); 99 BF_CLR(POWER_CTRL, VBUSVALID_IRQ);
81 } 100 }
101#else
102 if(BF_RD(POWER_CTRL, VDD5V_GT_VDDIO_IRQ))
103 {
104 if(BF_RD(POWER_STS, VDD5V_GT_VDDIO))
105 usb_insert_int();
106 else
107 usb_remove_int();
108 /* reverse polarity */
109 BF_TOG(POWER_CTRL, POLARITY_VDD5V_GT_VDDIO);
110 /* clear int */
111 BF_CLR(POWER_CTRL, VDD5V_GT_VDDIO_IRQ);
112 }
113#endif
82} 114}
83 115
84void imx233_power_init(void) 116void imx233_power_init(void)
@@ -86,28 +118,55 @@ void imx233_power_init(void)
86 /* setup vbusvalid parameters: set threshold to 4v and power up comparators */ 118 /* setup vbusvalid parameters: set threshold to 4v and power up comparators */
87 BF_CLR(POWER_5VCTRL, VBUSVALID_TRSH); 119 BF_CLR(POWER_5VCTRL, VBUSVALID_TRSH);
88 BF_SETV(POWER_5VCTRL, VBUSVALID_TRSH, 1); 120 BF_SETV(POWER_5VCTRL, VBUSVALID_TRSH, 1);
121#if IMX233_SUBTARGET >= 3780
89 BF_SET(POWER_5VCTRL, PWRUP_VBUS_CMPS); 122 BF_SET(POWER_5VCTRL, PWRUP_VBUS_CMPS);
123#else
124 BF_SET(POWER_5VCTRL, OTG_PWRUP_CMPS);
125#endif
90 /* enable vbusvalid detection method for the dcdc (improves efficiency) */ 126 /* enable vbusvalid detection method for the dcdc (improves efficiency) */
91 BF_SET(POWER_5VCTRL, VBUSVALID_5VDETECT); 127 BF_SET(POWER_5VCTRL, VBUSVALID_5VDETECT);
128#ifdef USE_VBUSVALID
129 /* make sure VBUSVALID is unlocked */
130 BF_CLR(POWER_DEBUG, VBUSVALIDPIOLOCK);
131 /* clear vbusvalid irq and set correct polarity */
92 BF_CLR(POWER_CTRL, VBUSVALID_IRQ); 132 BF_CLR(POWER_CTRL, VBUSVALID_IRQ);
93 if(BF_RD(POWER_STS, VBUSVALID)) 133 if(BF_RD(POWER_STS, VBUSVALID))
94 BF_CLR(POWER_CTRL, POLARITY_VBUSVALID); 134 BF_CLR(POWER_CTRL, POLARITY_VBUSVALID);
95 else 135 else
96 BF_SET(POWER_CTRL, POLARITY_VBUSVALID); 136 BF_SET(POWER_CTRL, POLARITY_VBUSVALID);
97 BF_SET(POWER_CTRL, ENIRQ_VBUS_VALID); 137 BF_SET(POWER_CTRL, ENIRQ_VBUS_VALID);
138 /* make sure old detection way is not enabled */
139 BF_CLR(POWER_CTRL, ENIRQ_VDD5V_GT_VDDIO);
140#else
141 BF_CLR(POWER_CTRL, VDD5V_GT_VDDIO_IRQ);
142 if(BF_RD(POWER_STS, VDD5V_GT_VDDIO))
143 BF_CLR(POWER_CTRL, POLARITY_VDD5V_GT_VDDIO);
144 else
145 BF_SET(POWER_CTRL, POLARITY_VDD5V_GT_VDDIO);
146 BF_SET(POWER_CTRL, ENIRQ_VDD5V_GT_VDDIO);
147#endif
98 imx233_icoll_enable_interrupt(INT_SRC_VDD5V, true); 148 imx233_icoll_enable_interrupt(INT_SRC_VDD5V, true);
99 /* setup linear regulator offsets to 25 mV below to prevent contention between 149 /* setup linear regulator offsets to 25 mV below to prevent contention between
100 * linear regulators and DCDC */ 150 * linear regulators and DCDC */
151#if IMX233_SUBTARGET >= 3700
101 BF_WR(POWER_VDDDCTRL, LINREG_OFFSET, 2); 152 BF_WR(POWER_VDDDCTRL, LINREG_OFFSET, 2);
102 BF_WR(POWER_VDDACTRL, LINREG_OFFSET, 2); 153 BF_WR(POWER_VDDACTRL, LINREG_OFFSET, 2);
103 BF_WR(POWER_VDDIOCTRL, LINREG_OFFSET, 2); 154 BF_WR(POWER_VDDIOCTRL, LINREG_OFFSET, 2);
104 /* enable DCDC (more efficient) */ 155 /* enable DCDC (more efficient) */
105 BF_SET(POWER_5VCTRL, ENABLE_DCDC); 156 BF_SET(POWER_5VCTRL, ENABLE_DCDC);
157#else
158 BF_SET(POWER_5VCTRL, LINREG_OFFSET);
159 BF_SET(POWER_5VCTRL, EN_DCDC1);
160 BF_SET(POWER_5VCTRL, EN_DCDC2);
161#endif
162
163#if IMX233_SUBTARGET >= 3780
106 /* enable a few bits controlling the DC-DC as recommended by Freescale */ 164 /* enable a few bits controlling the DC-DC as recommended by Freescale */
107 BF_SET(POWER_LOOPCTRL, TOGGLE_DIF); 165 BF_SET(POWER_LOOPCTRL, TOGGLE_DIF);
108 BF_SET(POWER_LOOPCTRL, EN_CM_HYST); 166 BF_SET(POWER_LOOPCTRL, EN_CM_HYST);
109 BF_CLR(POWER_LOOPCTRL, EN_RCSCALE); 167 BF_CLR(POWER_LOOPCTRL, EN_RCSCALE);
110 BF_SETV(POWER_LOOPCTRL, EN_RCSCALE, 1); 168 BF_SETV(POWER_LOOPCTRL, EN_RCSCALE, 1);
169#endif
111} 170}
112 171
113void power_init(void) 172void power_init(void)
@@ -143,19 +202,31 @@ bool charging_state(void)
143 202
144void imx233_power_set_charge_current(unsigned current) 203void imx233_power_set_charge_current(unsigned current)
145{ 204{
205#if IMX233_SUBTARGET >= 3700
146 BF_CLR(POWER_CHARGE, BATTCHRG_I); 206 BF_CLR(POWER_CHARGE, BATTCHRG_I);
207#else
208 BF_CLR(POWER_BATTCHRG, BATTCHRG_I);
209#endif
147 /* find closest current LOWER THAN OR EQUAL TO the expected current */ 210 /* find closest current LOWER THAN OR EQUAL TO the expected current */
148 for(unsigned i = 0; i < ARRAYLEN(g_charger_current_bits); i++) 211 for(unsigned i = 0; i < ARRAYLEN(g_charger_current_bits); i++)
149 if(current >= g_charger_current_bits[i].current) 212 if(current >= g_charger_current_bits[i].current)
150 { 213 {
151 current -= g_charger_current_bits[i].current; 214 current -= g_charger_current_bits[i].current;
215#if IMX233_SUBTARGET >= 3700
152 BF_SETV(POWER_CHARGE, BATTCHRG_I, g_charger_current_bits[i].bit); 216 BF_SETV(POWER_CHARGE, BATTCHRG_I, g_charger_current_bits[i].bit);
217#else
218 BF_SETV(POWER_BATTCHRG, BATTCHRG_I, g_charger_current_bits[i].bit);
219#endif
153 } 220 }
154} 221}
155 222
156void imx233_power_set_stop_current(unsigned current) 223void imx233_power_set_stop_current(unsigned current)
157{ 224{
225#if IMX233_SUBTARGET >= 3700
158 BF_CLR(POWER_CHARGE, STOP_ILIMIT); 226 BF_CLR(POWER_CHARGE, STOP_ILIMIT);
227#else
228 BF_CLR(POWER_BATTCHRG, STOP_ILIMIT);
229#endif
159 /* find closest current GREATHER THAN OR EQUAL TO the expected current */ 230 /* find closest current GREATHER THAN OR EQUAL TO the expected current */
160 unsigned sum = 0; 231 unsigned sum = 0;
161 for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++) 232 for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++)
@@ -166,7 +237,11 @@ void imx233_power_set_stop_current(unsigned current)
166 if(current > sum) 237 if(current > sum)
167 { 238 {
168 current -= g_charger_stop_current_bits[i].current; 239 current -= g_charger_stop_current_bits[i].current;
240#if IMX233_SUBTARGET >= 3700
169 BF_SETV(POWER_CHARGE, STOP_ILIMIT, g_charger_stop_current_bits[i].bit); 241 BF_SETV(POWER_CHARGE, STOP_ILIMIT, g_charger_stop_current_bits[i].bit);
242#else
243 BF_SETV(POWER_BATTCHRG, STOP_ILIMIT, g_charger_stop_current_bits[i].bit);
244#endif
170 } 245 }
171 } 246 }
172} 247}
@@ -175,10 +250,12 @@ void imx233_power_set_stop_current(unsigned current)
175#define HAS_BO (1 << 0) 250#define HAS_BO (1 << 0)
176#define HAS_LINREG (1 << 1) 251#define HAS_LINREG (1 << 1)
177#define HAS_LINREG_OFFSET (1 << 2) 252#define HAS_LINREG_OFFSET (1 << 2)
253#define HAS_ABS_BO (1 << 3)
178 254
179static struct 255static struct
180{ 256{
181 unsigned min, step; 257 unsigned min, step;
258 int off; // offset in the register value
182 volatile uint32_t *reg; 259 volatile uint32_t *reg;
183 uint32_t trg_bm, trg_bp; // bitmask and bitpos 260 uint32_t trg_bm, trg_bp; // bitmask and bitpos
184 unsigned flags; 261 unsigned flags;
@@ -193,15 +270,18 @@ static struct
193 .reg = &HW_POWER_##name##CTRL, \ 270 .reg = &HW_POWER_##name##CTRL, \
194 .trg_bm = BM_POWER_##name##CTRL_TRG, \ 271 .trg_bm = BM_POWER_##name##CTRL_TRG, \
195 .trg_bp = BP_POWER_##name##CTRL_TRG, \ 272 .trg_bp = BP_POWER_##name##CTRL_TRG, \
196 .flags = mask 273 .flags = mask, \
274 .off = 0
197#define ADD_REGULATOR_BO(name) \ 275#define ADD_REGULATOR_BO(name) \
198 .bo_bm = BM_POWER_##name##CTRL_BO_OFFSET, \ 276 .bo_bm = BM_POWER_##name##CTRL_BO_OFFSET, \
199 .bo_bp = BP_POWER_##name##CTRL_BO_OFFSET 277 .bo_bp = BP_POWER_##name##CTRL_BO_OFFSET
200#define ADD_REGULATOR_LINREG(name) \ 278#define ADD_REGULATOR_LINREG(name) \
201 .linreg_bm = BM_POWER_##name##CTRL_ENABLE_LINREG 279 .linreg_bm = BM_POWER_##name##CTRL_ENABLE_LINREG
202#define ADD_REGULATOR_LINREG_OFFSET(name) \ 280#define ADD_REGULATOR_LINREG_OFFSET(name) \
203 .linreg_offset_bm = BM_POWER_##name##CTRL_LINREG_OFFSET, \ 281 .linreg_offset_bm = BP_POWER_##name##CTRL_LINREG_OFFSET, \
204 .linreg_offset_bp = BP_POWER_##name##CTRL_LINREG_OFFSET 282 .linreg_offset_bp = BM_POWER_##name##CTRL_LINREG_OFFSET
283
284#if IMX233_SUBTARGET >= 3700
205 [REGULATOR_VDDD] = 285 [REGULATOR_VDDD] =
206 { 286 {
207 ADD_REGULATOR(VDDD, HAS_BO|HAS_LINREG|HAS_LINREG_OFFSET), 287 ADD_REGULATOR(VDDD, HAS_BO|HAS_LINREG|HAS_LINREG_OFFSET),
@@ -222,11 +302,27 @@ static struct
222 ADD_REGULATOR_BO(VDDIO), 302 ADD_REGULATOR_BO(VDDIO),
223 ADD_REGULATOR_LINREG_OFFSET(VDDIO) 303 ADD_REGULATOR_LINREG_OFFSET(VDDIO)
224 }, 304 },
305#if IMX233_SUBTARGET >= 3780
225 [REGULATOR_VDDMEM] = 306 [REGULATOR_VDDMEM] =
226 { 307 {
227 ADD_REGULATOR(VDDMEM, HAS_LINREG), 308 ADD_REGULATOR(VDDMEM, HAS_LINREG),
228 ADD_REGULATOR_LINREG(VDDMEM), 309 ADD_REGULATOR_LINREG(VDDMEM),
229 }, 310 },
311#endif
312#else
313 [REGULATOR_VDDD] =
314 {
315 .min = HW_POWER_VDDDCTRL__TRG_MIN,
316 .step = HW_POWER_VDDDCTRL__TRG_STEP,
317 .off = HW_POWER_VDDDCTRL__TRG_OFF,
318 .reg = &HW_POWER_VDDCTRL,
319 .flags = HAS_BO | HAS_ABS_BO,
320 .trg_bm = BM_POWER_VDDCTRL_VDDD_TRG,
321 .trg_bp = BP_POWER_VDDCTRL_VDDD_TRG,
322 .bo_bm = BM_POWER_VDDCTRL_VDDD_BO,
323 .bo_bp = BP_POWER_VDDCTRL_VDDD_BO,
324 },
325#endif
230}; 326};
231 327
232void imx233_power_get_regulator(enum imx233_regulator_t reg, unsigned *value_mv, 328void imx233_power_get_regulator(enum imx233_regulator_t reg, unsigned *value_mv,
@@ -235,6 +331,7 @@ void imx233_power_get_regulator(enum imx233_regulator_t reg, unsigned *value_mv,
235 uint32_t reg_val = *regulator_info[reg].reg; 331 uint32_t reg_val = *regulator_info[reg].reg;
236 /* read target value */ 332 /* read target value */
237 unsigned raw_val = (reg_val & regulator_info[reg].trg_bm) >> regulator_info[reg].trg_bp; 333 unsigned raw_val = (reg_val & regulator_info[reg].trg_bm) >> regulator_info[reg].trg_bp;
334 raw_val -= regulator_info[reg].off;
238 /* convert it to mv */ 335 /* convert it to mv */
239 if(value_mv) 336 if(value_mv)
240 *value_mv = regulator_info[reg].min + regulator_info[reg].step * raw_val; 337 *value_mv = regulator_info[reg].min + regulator_info[reg].step * raw_val;
@@ -242,9 +339,12 @@ void imx233_power_get_regulator(enum imx233_regulator_t reg, unsigned *value_mv,
242 { 339 {
243 /* read brownout offset */ 340 /* read brownout offset */
244 unsigned raw_bo = (reg_val & regulator_info[reg].bo_bm) >> regulator_info[reg].bo_bp; 341 unsigned raw_bo = (reg_val & regulator_info[reg].bo_bm) >> regulator_info[reg].bo_bp;
342 raw_bo -= regulator_info[reg].off;
343 if(!(regulator_info[reg].flags & HAS_ABS_BO))
344 raw_bo = raw_val - raw_bo;
245 /* convert it to mv */ 345 /* convert it to mv */
246 if(brownout_mv) 346 if(brownout_mv)
247 *brownout_mv = regulator_info[reg].min + regulator_info[reg].step * (raw_val - raw_bo); 347 *brownout_mv = regulator_info[reg].min + regulator_info[reg].step * raw_bo;
248 } 348 }
249 else if(brownout_mv) 349 else if(brownout_mv)
250 *brownout_mv = 0; 350 *brownout_mv = 0;
@@ -255,9 +355,15 @@ void imx233_power_set_regulator(enum imx233_regulator_t reg, unsigned value_mv,
255{ 355{
256 // compute raw values 356 // compute raw values
257 unsigned raw_val = (value_mv - regulator_info[reg].min) / regulator_info[reg].step; 357 unsigned raw_val = (value_mv - regulator_info[reg].min) / regulator_info[reg].step;
258 unsigned raw_bo_offset = (value_mv - brownout_mv) / regulator_info[reg].step; 358 raw_val += regulator_info[reg].off;
359 if(!(regulator_info[reg].flags & HAS_ABS_BO))
360 brownout_mv = value_mv - brownout_mv;
361 unsigned raw_bo_offset = brownout_mv/ regulator_info[reg].step;
362 raw_bo_offset += regulator_info[reg].off;
259 // clear dc-dc ok flag 363 // clear dc-dc ok flag
364#if IMX233_SUBTARGET >= 3700
260 BF_SET(POWER_CTRL, DC_OK_IRQ); 365 BF_SET(POWER_CTRL, DC_OK_IRQ);
366#endif
261 // update 367 // update
262 uint32_t reg_val = (*regulator_info[reg].reg) & ~regulator_info[reg].trg_bm; 368 uint32_t reg_val = (*regulator_info[reg].reg) & ~regulator_info[reg].trg_bm;
263 reg_val |= raw_val << regulator_info[reg].trg_bp; 369 reg_val |= raw_val << regulator_info[reg].trg_bp;
@@ -271,6 +377,7 @@ void imx233_power_set_regulator(enum imx233_regulator_t reg, unsigned value_mv,
271 * If DC-DC is used, we can use the DCDC_OK irq 377 * If DC-DC is used, we can use the DCDC_OK irq
272 * Otherwise it is unreliable (doesn't work when lowering voltage on linregs) 378 * Otherwise it is unreliable (doesn't work when lowering voltage on linregs)
273 * It usually takes between 0.5ms and 2.5ms */ 379 * It usually takes between 0.5ms and 2.5ms */
380#if IMX233_SUBTARGET >= 3700
274 if(!BF_RD(POWER_5VCTRL, ENABLE_DCDC)) 381 if(!BF_RD(POWER_5VCTRL, ENABLE_DCDC))
275 panicf("regulator %d: wait for voltage stabilize in linreg mode !", reg); 382 panicf("regulator %d: wait for voltage stabilize in linreg mode !", reg);
276 unsigned timeout = current_tick + (HZ * 20) / 1000; 383 unsigned timeout = current_tick + (HZ * 20) / 1000;
@@ -278,6 +385,15 @@ void imx233_power_set_regulator(enum imx233_regulator_t reg, unsigned value_mv,
278 yield(); 385 yield();
279 if(!BF_RD(POWER_CTRL, DC_OK_IRQ)) 386 if(!BF_RD(POWER_CTRL, DC_OK_IRQ))
280 panicf("regulator %d: failed to stabilize", reg); 387 panicf("regulator %d: failed to stabilize", reg);
388#else
389 if(!BF_RD(POWER_5VCTRL, EN_DCDC1) || !BF_RD(POWER_5VCTRL, EN_DCDC2))
390 panicf("regulator %d: wait for voltage stabilize in linreg mode !", reg);
391 unsigned timeout = current_tick + (HZ * 20) / 1000;
392 while(!BF_RD(POWER_STS, DC1_OK) || !BF_RD(POWER_STS, DC2_OK) || !TIME_AFTER(current_tick, timeout))
393 yield();
394 if(!BF_RD(POWER_STS, DC1_OK) || !BF_RD(POWER_STS, DC2_OK))
395 panicf("regulator %d: failed to stabilize", reg);
396#endif
281} 397}
282 398
283// offset is -1,0 or 1 399// offset is -1,0 or 1
@@ -307,9 +423,28 @@ void imx233_power_set_regulator_linreg(enum imx233_regulator_t reg,
307} 423}
308*/ 424*/
309 425
426#if IMX233_SUBTARGET < 3700
427int imx233_power_sense_die_temperature(int *min, int *max)
428{
429 static int die_temp[] =
430 {
431 -50, -40, -30, -20, -10, 0, 15, 25, 35, 45, 55, 70, 85, 95, 105, 115, 130
432 };
433 /* power up temperature sensor */
434 BF_CLRV(POWER_SPEEDTEMP, TEMP_CTRL, 1 << 3);
435 /* read temp */
436 int sense = BF_RD(POWER_SPEEDTEMP, TEMP_STS);
437 *min = die_temp[sense];
438 *max = die_temp[sense + 1];
439 /* power down temperature sensor */
440 BF_SETV(POWER_SPEEDTEMP, TEMP_CTRL, 1 << 3);
441 return 0;
442}
443#endif
310 444
311struct imx233_power_info_t imx233_power_get_info(unsigned flags) 445struct imx233_power_info_t imx233_power_get_info(unsigned flags)
312{ 446{
447#if IMX233_SUBTARGET >= 3700
313 static int dcdc_freqsel[8] = { 448 static int dcdc_freqsel[8] = {
314 [BV_POWER_MISC_FREQSEL__RES] = 0, 449 [BV_POWER_MISC_FREQSEL__RES] = 0,
315 [BV_POWER_MISC_FREQSEL__20MHz] = 20000, 450 [BV_POWER_MISC_FREQSEL__20MHz] = 20000,
@@ -320,18 +455,25 @@ struct imx233_power_info_t imx233_power_get_info(unsigned flags)
320 [BV_POWER_MISC_FREQSEL__21p6MHz] = 21600, 455 [BV_POWER_MISC_FREQSEL__21p6MHz] = 21600,
321 [BV_POWER_MISC_FREQSEL__17p28MHz] = 17280, 456 [BV_POWER_MISC_FREQSEL__17p28MHz] = 17280,
322 }; 457 };
323 458#endif
324 struct imx233_power_info_t s; 459 struct imx233_power_info_t s;
325 memset(&s, 0, sizeof(s)); 460 memset(&s, 0, sizeof(s));
461#if IMX233_SUBTARGET >= 3700
326 if(flags & POWER_INFO_DCDC) 462 if(flags & POWER_INFO_DCDC)
327 { 463 {
328 s.dcdc_sel_pllclk = BF_RD(POWER_MISC, SEL_PLLCLK); 464 s.dcdc_sel_pllclk = BF_RD(POWER_MISC, SEL_PLLCLK);
329 s.dcdc_freqsel = dcdc_freqsel[BF_RD(POWER_MISC, FREQSEL)]; 465 s.dcdc_freqsel = dcdc_freqsel[BF_RD(POWER_MISC, FREQSEL)];
330 } 466 }
467#endif
331 if(flags & POWER_INFO_CHARGE) 468 if(flags & POWER_INFO_CHARGE)
332 { 469 {
470#if IMX233_SUBTARGET >= 3700
333 uint32_t current = BF_RD(POWER_CHARGE, BATTCHRG_I); 471 uint32_t current = BF_RD(POWER_CHARGE, BATTCHRG_I);
334 uint32_t stop_current = BF_RD(POWER_CHARGE, STOP_ILIMIT); 472 uint32_t stop_current = BF_RD(POWER_CHARGE, STOP_ILIMIT);
473#else
474 uint32_t current = BF_RD(POWER_BATTCHRG, BATTCHRG_I);
475 uint32_t stop_current = BF_RD(POWER_BATTCHRG, STOP_ILIMIT);
476#endif
335 for(unsigned i = 0; i < ARRAYLEN(g_charger_current_bits); i++) 477 for(unsigned i = 0; i < ARRAYLEN(g_charger_current_bits); i++)
336 if(current & g_charger_current_bits[i].bit) 478 if(current & g_charger_current_bits[i].bit)
337 s.charge_current += g_charger_current_bits[i].current; 479 s.charge_current += g_charger_current_bits[i].current;
@@ -339,8 +481,13 @@ struct imx233_power_info_t imx233_power_get_info(unsigned flags)
339 if(stop_current & g_charger_stop_current_bits[i].bit) 481 if(stop_current & g_charger_stop_current_bits[i].bit)
340 s.stop_current += g_charger_stop_current_bits[i].current; 482 s.stop_current += g_charger_stop_current_bits[i].current;
341 s.charging = BF_RD(POWER_STS, CHRGSTS); 483 s.charging = BF_RD(POWER_STS, CHRGSTS);
484#if IMX233_SUBTARGET >= 3700
342 s.batt_adj = BF_RD(POWER_BATTMONITOR, EN_BATADJ); 485 s.batt_adj = BF_RD(POWER_BATTMONITOR, EN_BATADJ);
486#else
487 s.batt_adj = BF_RD(POWER_DC1MULTOUT, EN_BATADJ);
488#endif
343 } 489 }
490#if IMX233_SUBTARGET >= 3780
344 if(flags & POWER_INFO_4P2) 491 if(flags & POWER_INFO_4P2)
345 { 492 {
346 s._4p2_enable = BF_RD(POWER_DCDC4P2, ENABLE_4P2); 493 s._4p2_enable = BF_RD(POWER_DCDC4P2, ENABLE_4P2);
@@ -348,16 +495,30 @@ struct imx233_power_info_t imx233_power_get_info(unsigned flags)
348 s._4p2_cmptrip = BF_RD(POWER_DCDC4P2, CMPTRIP); 495 s._4p2_cmptrip = BF_RD(POWER_DCDC4P2, CMPTRIP);
349 s._4p2_dropout = BF_RD(POWER_DCDC4P2, DROPOUT_CTRL); 496 s._4p2_dropout = BF_RD(POWER_DCDC4P2, DROPOUT_CTRL);
350 } 497 }
498#endif
351 if(flags & POWER_INFO_5V) 499 if(flags & POWER_INFO_5V)
352 { 500 {
501#if IMX233_SUBTARGET >= 3780
353 s._5v_pwd_charge_4p2 = BF_RD(POWER_5VCTRL, PWD_CHARGE_4P2); 502 s._5v_pwd_charge_4p2 = BF_RD(POWER_5VCTRL, PWD_CHARGE_4P2);
503#endif
504 s._5v_dcdc_xfer = BF_RD(POWER_5VCTRL, DCDC_XFER);
505#if IMX233_SUBTARGET >= 3700
354 s._5v_enable_dcdc = BF_RD(POWER_5VCTRL, ENABLE_DCDC); 506 s._5v_enable_dcdc = BF_RD(POWER_5VCTRL, ENABLE_DCDC);
507#else
508 s._5v_enable_dcdc = BF_RD(POWER_5VCTRL, EN_DCDC1) && BF_RD(POWER_5VCTRL, EN_DCDC2);
509#endif
510#if IMX233_SUBTARGET >= 3780
355 uint32_t charge_4p2_ilimit = BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT); 511 uint32_t charge_4p2_ilimit = BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT);
356 for(unsigned i = 0; i < ARRAYLEN(g_4p2_charge_limit_bits); i++) 512 for(unsigned i = 0; i < ARRAYLEN(g_4p2_charge_limit_bits); i++)
357 if(charge_4p2_ilimit & g_4p2_charge_limit_bits[i].bit) 513 if(charge_4p2_ilimit & g_4p2_charge_limit_bits[i].bit)
358 s._5v_charge_4p2_limit += g_4p2_charge_limit_bits[i].current; 514 s._5v_charge_4p2_limit += g_4p2_charge_limit_bits[i].current;
515#endif
359 s._5v_vbusvalid_detect = BF_RD(POWER_5VCTRL, VBUSVALID_5VDETECT); 516 s._5v_vbusvalid_detect = BF_RD(POWER_5VCTRL, VBUSVALID_5VDETECT);
517#if IMX233_SUBTARGET >= 3780
360 s._5v_vbus_cmps = BF_RD(POWER_5VCTRL, PWRUP_VBUS_CMPS); 518 s._5v_vbus_cmps = BF_RD(POWER_5VCTRL, PWRUP_VBUS_CMPS);
519#else
520 s._5v_vbus_cmps = BF_RD(POWER_5VCTRL, OTG_PWRUP_CMPS);
521#endif
361 s._5v_vbusvalid_thr = 522 s._5v_vbusvalid_thr =
362 BF_RD(POWER_5VCTRL, VBUSVALID_TRSH) == 0 ? 523 BF_RD(POWER_5VCTRL, VBUSVALID_TRSH) == 0 ?
363 2900 524 2900
diff --git a/firmware/target/arm/imx233/power-imx233.h b/firmware/target/arm/imx233/power-imx233.h
index e6bd02525b..d33ca20333 100644
--- a/firmware/target/arm/imx233/power-imx233.h
+++ b/firmware/target/arm/imx233/power-imx233.h
@@ -34,6 +34,7 @@
34#define BV_POWER_5VCTRL_CHARGE_4P2_ILIMIT__200mA (1 << 4) 34#define BV_POWER_5VCTRL_CHARGE_4P2_ILIMIT__200mA (1 << 4)
35#define BV_POWER_5VCTRL_CHARGE_4P2_ILIMIT__400mA (1 << 5) 35#define BV_POWER_5VCTRL_CHARGE_4P2_ILIMIT__400mA (1 << 5)
36 36
37
37#define BV_POWER_CHARGE_BATTCHRG_I__10mA (1 << 0) 38#define BV_POWER_CHARGE_BATTCHRG_I__10mA (1 << 0)
38#define BV_POWER_CHARGE_BATTCHRG_I__20mA (1 << 1) 39#define BV_POWER_CHARGE_BATTCHRG_I__20mA (1 << 1)
39#define BV_POWER_CHARGE_BATTCHRG_I__50mA (1 << 2) 40#define BV_POWER_CHARGE_BATTCHRG_I__50mA (1 << 2)
@@ -46,6 +47,7 @@
46#define BV_POWER_CHARGE_STOP_ILIMIT__50mA (1 << 2) 47#define BV_POWER_CHARGE_STOP_ILIMIT__50mA (1 << 2)
47#define BV_POWER_CHARGE_STOP_ILIMIT__100mA (1 << 3) 48#define BV_POWER_CHARGE_STOP_ILIMIT__100mA (1 << 3)
48 49
50#if IMX233_SUBTARGET >= 3700
49#define HW_POWER_VDDDCTRL__TRG_STEP 25 /* mV */ 51#define HW_POWER_VDDDCTRL__TRG_STEP 25 /* mV */
50#define HW_POWER_VDDDCTRL__TRG_MIN 800 /* mV */ 52#define HW_POWER_VDDDCTRL__TRG_MIN 800 /* mV */
51 53
@@ -57,6 +59,13 @@
57 59
58#define HW_POWER_VDDMEMCTRL__TRG_STEP 50 /* mV */ 60#define HW_POWER_VDDMEMCTRL__TRG_STEP 50 /* mV */
59#define HW_POWER_VDDMEMCTRL__TRG_MIN 1700 /* mV */ 61#define HW_POWER_VDDMEMCTRL__TRG_MIN 1700 /* mV */
62#else
63/* don't use the full available range because of the weird encodings for
64 * extreme values which are useless anyway */
65#define HW_POWER_VDDDCTRL__TRG_STEP 32 /* mV */
66#define HW_POWER_VDDDCTRL__TRG_MIN 1280 /* mV */
67#define HW_POWER_VDDDCTRL__TRG_OFF 8 /* below 8, the register value doesn't encode linearly */
68#endif
60 69
61#define BV_POWER_MISC_FREQSEL__RES 0 70#define BV_POWER_MISC_FREQSEL__RES 0
62#define BV_POWER_MISC_FREQSEL__20MHz 1 71#define BV_POWER_MISC_FREQSEL__20MHz 1
@@ -67,6 +76,7 @@
67#define BV_POWER_MISC_FREQSEL__21p6MHz 6 76#define BV_POWER_MISC_FREQSEL__21p6MHz 6
68#define BV_POWER_MISC_FREQSEL__17p28MHz 7 77#define BV_POWER_MISC_FREQSEL__17p28MHz 7
69 78
79
70void imx233_power_init(void); 80void imx233_power_init(void);
71 81
72void imx233_power_set_charge_current(unsigned current); /* in mA */ 82void imx233_power_set_charge_current(unsigned current); /* in mA */
@@ -75,10 +85,12 @@ void imx233_power_enable_batadj(bool enable);
75 85
76enum imx233_regulator_t 86enum imx233_regulator_t
77{ 87{
78 REGULATOR_VDDD, /* target, brownout, linreg, linreg offset */ 88 REGULATOR_VDDD, /* target, brownout, linreg[3700+], linreg offset[3700+] */
89#if IMX233_SUBTARGET >= 3700
79 REGULATOR_VDDA, /* target, brownout, linreg, linreg offset */ 90 REGULATOR_VDDA, /* target, brownout, linreg, linreg offset */
80 REGULATOR_VDDIO, /* target, brownout, linreg offset */ 91 REGULATOR_VDDIO, /* target, brownout, linreg offset */
81 REGULATOR_VDDMEM, /* target, linreg */ 92 REGULATOR_VDDMEM, /* target, linreg */
93#endif
82 REGULATOR_COUNT, 94 REGULATOR_COUNT,
83}; 95};
84 96
@@ -97,12 +109,19 @@ void imx233_power_get_regulator_linreg(enum imx233_regulator_t reg,
97void imx233_power_set_regulator_linreg(enum imx233_regulator_t reg, 109void imx233_power_set_regulator_linreg(enum imx233_regulator_t reg,
98 bool enabled, int linreg_offset); 110 bool enabled, int linreg_offset);
99 111
112#if IMX233_SUBTARGET >= 3700
100static inline void imx233_power_set_dcdc_freq(bool pll, unsigned freq) 113static inline void imx233_power_set_dcdc_freq(bool pll, unsigned freq)
101{ 114{
102 if(pll) 115 if(pll)
103 BF_WR(POWER_MISC, FREQSEL, freq); 116 BF_WR(POWER_MISC, FREQSEL, freq);
104 BF_WR(POWER_MISC, SEL_PLLCLK, pll); 117 BF_WR(POWER_MISC, SEL_PLLCLK, pll);
105} 118}
119#endif
120
121#if IMX233_SUBTARGET < 3700
122/* return -1 on error */
123int imx233_power_sense_die_temperature(int *min, int *max);
124#endif
106 125
107struct imx233_power_info_t 126struct imx233_power_info_t
108{ 127{