diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2013-06-16 20:57:39 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2013-06-17 00:29:25 +0200 |
commit | 239219ee70aa02a324fb94b6e463781c5c77beea (patch) | |
tree | 4429c2056a5ddd90173a8e132718a2c62019f8d9 | |
parent | 2d0d752bf8aed6bf91cdabd0d4571f336e7370eb (diff) | |
download | rockbox-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.c | 175 | ||||
-rw-r--r-- | firmware/target/arm/imx233/power-imx233.h | 21 |
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 */ |
59 | static struct current_step_bit_t g_4p2_charge_limit_bits[] = | 60 | static 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 | ||
69 | void INT_VDD5V(void) | 87 | void 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 | ||
84 | void imx233_power_init(void) | 116 | void 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 | ||
113 | void power_init(void) | 172 | void power_init(void) |
@@ -143,19 +202,31 @@ bool charging_state(void) | |||
143 | 202 | ||
144 | void imx233_power_set_charge_current(unsigned current) | 203 | void 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 | ||
156 | void imx233_power_set_stop_current(unsigned current) | 223 | void 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 | ||
179 | static struct | 255 | static 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 | ||
232 | void imx233_power_get_regulator(enum imx233_regulator_t reg, unsigned *value_mv, | 328 | void 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 | ||
427 | int 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 | ||
311 | struct imx233_power_info_t imx233_power_get_info(unsigned flags) | 445 | struct 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 | |||
70 | void imx233_power_init(void); | 80 | void imx233_power_init(void); |
71 | 81 | ||
72 | void imx233_power_set_charge_current(unsigned current); /* in mA */ | 82 | void imx233_power_set_charge_current(unsigned current); /* in mA */ |
@@ -75,10 +85,12 @@ void imx233_power_enable_batadj(bool enable); | |||
75 | 85 | ||
76 | enum imx233_regulator_t | 86 | enum 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, | |||
97 | void imx233_power_set_regulator_linreg(enum imx233_regulator_t reg, | 109 | void 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 | ||
100 | static inline void imx233_power_set_dcdc_freq(bool pll, unsigned freq) | 113 | static 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 */ | ||
123 | int imx233_power_sense_die_temperature(int *min, int *max); | ||
124 | #endif | ||
106 | 125 | ||
107 | struct imx233_power_info_t | 126 | struct imx233_power_info_t |
108 | { | 127 | { |