summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-16 20:57:39 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-17 00:29:25 +0200
commit239219ee70aa02a324fb94b6e463781c5c77beea (patch)
tree4429c2056a5ddd90173a8e132718a2c62019f8d9
parent2d0d752bf8aed6bf91cdabd0d4571f336e7370eb (diff)
downloadrockbox-239219ee70aa02a324fb94b6e463781c5c77beea.tar.gz
rockbox-239219ee70aa02a324fb94b6e463781c5c77beea.zip
imx233: fix power for stmp3600 and stmp3700
There are many small differences between them. In particular some regulators are not available on stmp3600. Also the vbusvalid detect method is not available as an irq on stmp3600 and seems broken on stmp3700. Finally die temperature is handled by the power block on stmp3600. Change-Id: I2c68b418738f15564e445d3a1496018cef97fff7
-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{