diff options
Diffstat (limited to 'firmware/target/arm/imx233')
-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 | { |