summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-12-24 19:20:12 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-12-24 19:20:12 +0000
commitf7f1f7023f94a0c1f00033235f0f9d9ab51a1b3f (patch)
tree394779c4dd8e6df796471346abb5f246aaee18e1
parenta1d3ed25346ab4174cb7fd066158cebc8e29fc79 (diff)
downloadrockbox-f7f1f7023f94a0c1f00033235f0f9d9ab51a1b3f.tar.gz
rockbox-f7f1f7023f94a0c1f00033235f0f9d9ab51a1b3f.zip
imx233/fuze+: implement power management(battery charger), add powermgmt debug info, add power debug info, move target specific powermgmt code to its own files, remove auto-slow setup which was forgotten for debugging
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31424 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/export/imx233.h1
-rw-r--r--firmware/target/arm/imx233/debug-imx233.c68
-rw-r--r--firmware/target/arm/imx233/power-imx233.c123
-rw-r--r--firmware/target/arm/imx233/power-imx233.h71
-rw-r--r--firmware/target/arm/imx233/powermgmt-imx233.c138
-rw-r--r--firmware/target/arm/imx233/sansa-fuzeplus/powermgmt-fuzeplus.c46
-rw-r--r--firmware/target/arm/imx233/sansa-fuzeplus/powermgmt-target.h (renamed from firmware/target/arm/imx233/powermgmt-target.h)24
8 files changed, 432 insertions, 40 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index f59475e27a..e80a7492b1 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1382,6 +1382,7 @@ target/arm/imx233/sansa-fuzeplus/power-fuzeplus.c
1382target/arm/imx233/sansa-fuzeplus/adc-fuzeplus.c 1382target/arm/imx233/sansa-fuzeplus/adc-fuzeplus.c
1383#ifndef BOOTLOADER 1383#ifndef BOOTLOADER
1384target/arm/imx233/sansa-fuzeplus/audio-fuzeplus.c 1384target/arm/imx233/sansa-fuzeplus/audio-fuzeplus.c
1385target/arm/imx233/sansa-fuzeplus/powermgmt-fuzeplus.c
1385#endif 1386#endif
1386#endif 1387#endif
1387 1388
diff --git a/firmware/export/imx233.h b/firmware/export/imx233.h
index 1fa16154c1..a68ca6df13 100644
--- a/firmware/export/imx233.h
+++ b/firmware/export/imx233.h
@@ -90,5 +90,6 @@
90 90
91#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP) 91#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP)
92#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP) 92#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP)
93#define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP)
93 94
94#endif /* __IMX233_H__ */ 95#endif /* __IMX233_H__ */
diff --git a/firmware/target/arm/imx233/debug-imx233.c b/firmware/target/arm/imx233/debug-imx233.c
index e6b07aef58..896c5bf6c3 100644
--- a/firmware/target/arm/imx233/debug-imx233.c
+++ b/firmware/target/arm/imx233/debug-imx233.c
@@ -29,7 +29,7 @@
29#include "adc-imx233.h" 29#include "adc-imx233.h"
30#include "power-imx233.h" 30#include "power-imx233.h"
31#include "clkctrl-imx233.h" 31#include "clkctrl-imx233.h"
32#include "powermgmt.h" 32#include "powermgmt-imx233.h"
33#include "string.h" 33#include "string.h"
34 34
35static struct 35static struct
@@ -107,11 +107,22 @@ bool dbg_hw_info_power(void)
107 lcd_clear_display(); 107 lcd_clear_display();
108 108
109 struct imx233_power_info_t info = imx233_power_get_info(POWER_INFO_ALL); 109 struct imx233_power_info_t info = imx233_power_get_info(POWER_INFO_ALL);
110 lcd_putsf(0, 0, "VDDD: %d mV linreg: %d", info.vddd, info.vddd_linreg); 110 lcd_putsf(0, 0, "VDDD: %d mV linreg: %d offset: %d", info.vddd, info.vddd_linreg,
111 lcd_putsf(0, 1, "VDDA: %d mV linreg: %d", info.vdda, info.vdda_linreg); 111 info.vddd_linreg_offset);
112 lcd_putsf(0, 2, "VDDIO: %d mV", info.vddio); 112 lcd_putsf(0, 1, "VDDA: %d mV linreg: %d offset: %d", info.vdda, info.vdda_linreg,
113 info.vdda_linreg_offset);
114 lcd_putsf(0, 2, "VDDIO: %d mV offset: %d", info.vddio, info.vddio_linreg_offset);
113 lcd_putsf(0, 3, "VDDMEM: %d mV linreg: %d", info.vddmem, info.vddmem_linreg); 115 lcd_putsf(0, 3, "VDDMEM: %d mV linreg: %d", info.vddmem, info.vddmem_linreg);
114 lcd_putsf(0, 4, "DC-DC: pll: %d freq: %d", info.dcdc_sel_pllclk, info.dcdc_freqsel); 116 lcd_putsf(0, 4, "DC-DC: pll: %d freq: %d", info.dcdc_sel_pllclk, info.dcdc_freqsel);
117 lcd_putsf(0, 5, "charge: %d mA stop: %d mA", info.charge_current, info.stop_current);
118 lcd_putsf(0, 6, "charging: %d bat_adj: %d", info.charging, info.batt_adj);
119 lcd_putsf(0, 7, "4.2: en: %d dcdc: %d", info._4p2_enable, info._4p2_dcdc);
120 lcd_putsf(0, 8, "4.2: cmptrip: %d dropout: %d", info._4p2_cmptrip, info._4p2_dropout);
121 lcd_putsf(0, 9, "5V: pwd_4.2_charge: %d", info._5v_pwd_charge_4p2);
122 lcd_putsf(0, 10, "5V: chargelim: %d mA", info._5v_charge_4p2_limit);
123 lcd_putsf(0, 11, "5V: dcdc: %d xfer: %d", info._5v_enable_dcdc, info._5v_dcdc_xfer);
124 lcd_putsf(0, 12, "5V: thr: %d mV use: %d cmps: %d", info._5v_vbusvalid_thr,
125 info._5v_vbusvalid_detect, info._5v_vbus_cmps);
115 126
116 lcd_update(); 127 lcd_update();
117 yield(); 128 yield();
@@ -194,12 +205,6 @@ static struct
194bool dbg_hw_info_clkctrl(void) 205bool dbg_hw_info_clkctrl(void)
195{ 206{
196 lcd_setfont(FONT_SYSFIXED); 207 lcd_setfont(FONT_SYSFIXED);
197 imx233_enable_auto_slow_monitor(AS_CPU_INSTR, true);
198 imx233_enable_auto_slow_monitor(AS_CPU_DATA, true);
199 imx233_enable_auto_slow_monitor(AS_TRAFFIC, true);
200 imx233_enable_auto_slow_monitor(AS_TRAFFIC_JAM, true);
201 imx233_enable_auto_slow_monitor(AS_APBXDMA, true);
202 imx233_enable_auto_slow_monitor(AS_APBHDMA, true);
203 208
204 while(1) 209 while(1)
205 { 210 {
@@ -269,10 +274,49 @@ bool dbg_hw_info_clkctrl(void)
269 } 274 }
270} 275}
271 276
277bool dbg_hw_info_powermgmt(void)
278{
279 lcd_setfont(FONT_SYSFIXED);
280
281 while(1)
282 {
283 int button = get_action(CONTEXT_STD, HZ / 10);
284 switch(button)
285 {
286 case ACTION_STD_NEXT:
287 case ACTION_STD_PREV:
288 case ACTION_STD_OK:
289 case ACTION_STD_MENU:
290 lcd_setfont(FONT_UI);
291 return true;
292 case ACTION_STD_CANCEL:
293 lcd_setfont(FONT_UI);
294 return false;
295 }
296
297 lcd_clear_display();
298 struct imx233_powermgmt_info_t info = imx233_powermgmt_get_info();
299
300 lcd_putsf(0, 0, "state: %s",
301 info.state == CHARGE_STATE_DISABLED ? "disabled" :
302 info.state == CHARGE_STATE_ERROR ? "error" :
303 info.state == DISCHARGING ? "discharging" :
304 info.state == TRICKLE ? "trickle" :
305 info.state == TOPOFF ? "topoff" :
306 info.state == CHARGING ? "charging" : "<unknown>");
307 lcd_putsf(0, 1, "charging tmo: %d", info.charging_timeout);
308 lcd_putsf(0, 2, "topoff tmo: %d", info.topoff_timeout);
309 lcd_putsf(0, 3, "4p2ilimit tmo: %d", info.incr_4p2_ilimit_timeout);
310
311 lcd_update();
312 yield();
313 }
314}
315
272bool dbg_hw_info(void) 316bool dbg_hw_info(void)
273{ 317{
274 return dbg_hw_info_clkctrl() && dbg_hw_info_dma() && dbg_hw_info_adc() && dbg_hw_info_power() && 318 return dbg_hw_info_clkctrl() && dbg_hw_info_dma() && dbg_hw_info_adc() &&
275 dbg_hw_target_info(); 319 dbg_hw_info_power() && dbg_hw_info_powermgmt() && dbg_hw_target_info();
276} 320}
277 321
278bool dbg_ports(void) 322bool dbg_ports(void)
diff --git a/firmware/target/arm/imx233/power-imx233.c b/firmware/target/arm/imx233/power-imx233.c
index 557b8521d5..ac1a407ba0 100644
--- a/firmware/target/arm/imx233/power-imx233.c
+++ b/firmware/target/arm/imx233/power-imx233.c
@@ -26,6 +26,43 @@
26#include "system-target.h" 26#include "system-target.h"
27#include "usb-target.h" 27#include "usb-target.h"
28 28
29struct current_step_bit_t
30{
31 unsigned current;
32 uint32_t bit;
33};
34
35/* in decreasing order */
36static struct current_step_bit_t g_charger_current_bits[] =
37{
38 { 400, HW_POWER_CHARGE__BATTCHRG_I__400mA },
39 { 200, HW_POWER_CHARGE__BATTCHRG_I__200mA },
40 { 100, HW_POWER_CHARGE__BATTCHRG_I__100mA },
41 { 50, HW_POWER_CHARGE__BATTCHRG_I__50mA },
42 { 20, HW_POWER_CHARGE__BATTCHRG_I__20mA },
43 { 10, HW_POWER_CHARGE__BATTCHRG_I__10mA }
44};
45
46/* in decreasing order */
47static struct current_step_bit_t g_charger_stop_current_bits[] =
48{
49 { 100, HW_POWER_CHARGE__STOP_ILIMIT__100mA },
50 { 50, HW_POWER_CHARGE__STOP_ILIMIT__50mA },
51 { 20, HW_POWER_CHARGE__STOP_ILIMIT__20mA },
52 { 10, HW_POWER_CHARGE__STOP_ILIMIT__10mA }
53};
54
55/* in decreasing order */
56static struct current_step_bit_t g_4p2_charge_limit_bits[] =
57{
58 { 400, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__400mA },
59 { 200, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__200mA },
60 { 100, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__100mA },
61 { 50, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__50mA },
62 { 20, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__20mA },
63 { 10, HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__10mA }
64};
65
29void INT_VDD5V(void) 66void INT_VDD5V(void)
30{ 67{
31 if(HW_POWER_CTRL & HW_POWER_CTRL__VBUSVALID_IRQ) 68 if(HW_POWER_CTRL & HW_POWER_CTRL__VBUSVALID_IRQ)
@@ -43,6 +80,12 @@ void INT_VDD5V(void)
43 80
44void power_init(void) 81void power_init(void)
45{ 82{
83 /* setup vbusvalid parameters: set threshold to 4v and power up comparators */
84 __REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_TRSH_BM;
85 __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_TRSH_4V |
86 HW_POWER_5VCTRL__PWRUP_VBUS_CMPS;
87 /* enable vbusvalid detection method for the dcdc (improves efficiency) */
88 __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_5VDETECT;
46 /* clear vbusvalid irq and set correct polarity */ 89 /* clear vbusvalid irq and set correct polarity */
47 __REG_CLR(HW_POWER_CTRL) = HW_POWER_CTRL__VBUSVALID_IRQ; 90 __REG_CLR(HW_POWER_CTRL) = HW_POWER_CTRL__VBUSVALID_IRQ;
48 if(HW_POWER_STS & HW_POWER_STS__VBUSVALID) 91 if(HW_POWER_STS & HW_POWER_STS__VBUSVALID)
@@ -51,6 +94,11 @@ void power_init(void)
51 __REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__POLARITY_VBUSVALID; 94 __REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__POLARITY_VBUSVALID;
52 __REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__ENIRQ_VBUS_VALID; 95 __REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__ENIRQ_VBUS_VALID;
53 imx233_enable_interrupt(INT_SRC_VDD5V, true); 96 imx233_enable_interrupt(INT_SRC_VDD5V, true);
97 /* setup linear regulator offsets to 25 mV below to prevent contention between
98 * linear regulators and DCDC */
99 __FIELD_SET(HW_POWER_VDDDCTRL, LINREG_OFFSET, 2);
100 __FIELD_SET(HW_POWER_VDDACTRL, LINREG_OFFSET, 2);
101 __FIELD_SET(HW_POWER_VDDIOCTRL, LINREG_OFFSET, 2);
54} 102}
55 103
56void power_off(void) 104void power_off(void)
@@ -64,12 +112,42 @@ void power_off(void)
64 112
65unsigned int power_input_status(void) 113unsigned int power_input_status(void)
66{ 114{
67 return POWER_INPUT_NONE; 115 return usb_plugged() ? POWER_INPUT_MAIN_CHARGER : POWER_INPUT_NONE;
68} 116}
69 117
70bool charging_state(void) 118bool charging_state(void)
71{ 119{
72 return false; 120 return HW_POWER_STS & HW_POWER_STS__CHRGSTS;
121}
122
123void imx233_power_set_charge_current(unsigned current)
124{
125 __REG_CLR(HW_POWER_CHARGE) = HW_POWER_CHARGE__BATTCHRG_I_BM;
126 /* find closest current LOWER THAN OR EQUAL TO the expected current */
127 for(unsigned i = 0; i < ARRAYLEN(g_charger_current_bits); i++)
128 if(current >= g_charger_current_bits[i].current)
129 {
130 current -= g_charger_current_bits[i].current;
131 __REG_SET(HW_POWER_CHARGE) = g_charger_current_bits[i].bit;
132 }
133}
134
135void imx233_power_set_stop_current(unsigned current)
136{
137 __REG_CLR(HW_POWER_CHARGE) = HW_POWER_CHARGE__STOP_ILIMIT_BM;
138 /* find closest current GREATHER THAN OR EQUAL TO the expected current */
139 unsigned sum = 0;
140 for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++)
141 sum += g_charger_stop_current_bits[i].current;
142 for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++)
143 {
144 sum -= g_charger_stop_current_bits[i].current;
145 if(current > sum)
146 {
147 current -= g_charger_stop_current_bits[i].current;
148 __REG_SET(HW_POWER_CHARGE) = g_charger_stop_current_bits[i].bit;
149 }
150 }
73} 151}
74 152
75struct imx233_power_info_t imx233_power_get_info(unsigned flags) 153struct imx233_power_info_t imx233_power_get_info(unsigned flags)
@@ -91,14 +169,22 @@ struct imx233_power_info_t imx233_power_get_info(unsigned flags)
91 { 169 {
92 s.vddd = HW_POWER_VDDDCTRL__TRG_MIN + HW_POWER_VDDDCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDDCTRL, TRG); 170 s.vddd = HW_POWER_VDDDCTRL__TRG_MIN + HW_POWER_VDDDCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDDCTRL, TRG);
93 s.vddd_linreg = HW_POWER_VDDDCTRL & HW_POWER_VDDDCTRL__ENABLE_LINREG; 171 s.vddd_linreg = HW_POWER_VDDDCTRL & HW_POWER_VDDDCTRL__ENABLE_LINREG;
172 s.vddd_linreg_offset = __XTRACT(HW_POWER_VDDDCTRL, LINREG_OFFSET) == 0 ? 0 :
173 __XTRACT(HW_POWER_VDDDCTRL, LINREG_OFFSET) == 1 ? 25 : -25;
94 } 174 }
95 if(flags & POWER_INFO_VDDA) 175 if(flags & POWER_INFO_VDDA)
96 { 176 {
97 s.vdda = HW_POWER_VDDACTRL__TRG_MIN + HW_POWER_VDDACTRL__TRG_STEP * __XTRACT(HW_POWER_VDDACTRL, TRG); 177 s.vdda = HW_POWER_VDDACTRL__TRG_MIN + HW_POWER_VDDACTRL__TRG_STEP * __XTRACT(HW_POWER_VDDACTRL, TRG);
98 s.vdda_linreg = HW_POWER_VDDACTRL & HW_POWER_VDDACTRL__ENABLE_LINREG; 178 s.vdda_linreg = HW_POWER_VDDACTRL & HW_POWER_VDDACTRL__ENABLE_LINREG;
179 s.vdda_linreg_offset = __XTRACT(HW_POWER_VDDACTRL, LINREG_OFFSET) == 0 ? 0 :
180 __XTRACT(HW_POWER_VDDACTRL, LINREG_OFFSET) == 1 ? 25 : -25;
99 } 181 }
100 if(flags & POWER_INFO_VDDIO) 182 if(flags & POWER_INFO_VDDIO)
183 {
101 s.vddio = HW_POWER_VDDIOCTRL__TRG_MIN + HW_POWER_VDDIOCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDIOCTRL, TRG); 184 s.vddio = HW_POWER_VDDIOCTRL__TRG_MIN + HW_POWER_VDDIOCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDIOCTRL, TRG);
185 s.vddio_linreg_offset = __XTRACT(HW_POWER_VDDIOCTRL, LINREG_OFFSET) == 0 ? 0 :
186 __XTRACT(HW_POWER_VDDIOCTRL, LINREG_OFFSET) == 1 ? 25 : -25;
187 }
102 if(flags & POWER_INFO_VDDMEM) 188 if(flags & POWER_INFO_VDDMEM)
103 { 189 {
104 s.vddmem = HW_POWER_VDDMEMCTRL__TRG_MIN + HW_POWER_VDDMEMCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDMEMCTRL, TRG); 190 s.vddmem = HW_POWER_VDDMEMCTRL__TRG_MIN + HW_POWER_VDDMEMCTRL__TRG_STEP * __XTRACT(HW_POWER_VDDMEMCTRL, TRG);
@@ -109,5 +195,38 @@ struct imx233_power_info_t imx233_power_get_info(unsigned flags)
109 s.dcdc_sel_pllclk = HW_POWER_MISC & HW_POWER_MISC__SEL_PLLCLK; 195 s.dcdc_sel_pllclk = HW_POWER_MISC & HW_POWER_MISC__SEL_PLLCLK;
110 s.dcdc_freqsel = dcdc_freqsel[__XTRACT(HW_POWER_MISC, FREQSEL)]; 196 s.dcdc_freqsel = dcdc_freqsel[__XTRACT(HW_POWER_MISC, FREQSEL)];
111 } 197 }
198 if(flags & POWER_INFO_CHARGE)
199 {
200 for(unsigned i = 0; i < ARRAYLEN(g_charger_current_bits); i++)
201 if(HW_POWER_CHARGE & g_charger_current_bits[i].bit)
202 s.charge_current += g_charger_current_bits[i].current;
203 for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++)
204 if(HW_POWER_CHARGE & g_charger_stop_current_bits[i].bit)
205 s.stop_current += g_charger_stop_current_bits[i].current;
206 s.charging = HW_POWER_STS & HW_POWER_STS__CHRGSTS;
207 s.batt_adj = HW_POWER_BATTMONITOR & HW_POWER_BATTMONITOR__ENBATADJ;
208 }
209 if(flags & POWER_INFO_4P2)
210 {
211 s._4p2_enable = HW_POWER_DCDC4P2 & HW_POWER_DCDC4P2__ENABLE_4P2;
212 s._4p2_dcdc = HW_POWER_DCDC4P2 & HW_POWER_DCDC4P2__ENABLE_DCDC;
213 s._4p2_cmptrip = __XTRACT(HW_POWER_DCDC4P2, CMPTRIP);
214 s._4p2_dropout = __XTRACT(HW_POWER_DCDC4P2, DROPOUT_CTRL);
215 }
216 if(flags & POWER_INFO_5V)
217 {
218 s._5v_pwd_charge_4p2 = HW_POWER_5VCTRL & HW_POWER_5VCTRL__PWD_CHARGE_4P2;
219 s._5v_dcdc_xfer = HW_POWER_5VCTRL & HW_POWER_5VCTRL__DCDC_XFER;
220 s._5v_enable_dcdc = HW_POWER_5VCTRL & HW_POWER_5VCTRL__ENABLE_DCDC;
221 for(unsigned i = 0; i < ARRAYLEN(g_4p2_charge_limit_bits); i++)
222 if(HW_POWER_5VCTRL & g_4p2_charge_limit_bits[i].bit)
223 s._5v_charge_4p2_limit += g_4p2_charge_limit_bits[i].current;
224 s._5v_vbusvalid_detect = HW_POWER_5VCTRL & HW_POWER_5VCTRL__VBUSVALID_5VDETECT;
225 s._5v_vbus_cmps = HW_POWER_5VCTRL & HW_POWER_5VCTRL__PWRUP_VBUS_CMPS;
226 s._5v_vbusvalid_thr =
227 __XTRACT(HW_POWER_5VCTRL, VBUSVALID_TRSH) == 0 ?
228 2900
229 : 3900 + __XTRACT(HW_POWER_5VCTRL, VBUSVALID_TRSH) * 100;
230 }
112 return s; 231 return s;
113} 232}
diff --git a/firmware/target/arm/imx233/power-imx233.h b/firmware/target/arm/imx233/power-imx233.h
index a546b96117..368ca719da 100644
--- a/firmware/target/arm/imx233/power-imx233.h
+++ b/firmware/target/arm/imx233/power-imx233.h
@@ -33,25 +33,52 @@
33#define HW_POWER_CTRL__POLARITY_VBUSVALID (1 << 5) 33#define HW_POWER_CTRL__POLARITY_VBUSVALID (1 << 5)
34 34
35#define HW_POWER_5VCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x10)) 35#define HW_POWER_5VCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x10))
36#define HW_POWER_5VCTRL__ENABLE_DCDC (1 << 0)
37#define HW_POWER_5VCTRL__PWRUP_VBUS_CMPS (1 << 1)
36#define HW_POWER_5VCTRL__VBUSVALID_5VDETECT (1 << 4) 38#define HW_POWER_5VCTRL__VBUSVALID_5VDETECT (1 << 4)
39#define HW_POWER_5VCTRL__DCDC_XFER (1 << 5)
37#define HW_POWER_5VCTRL__VBUSVALID_TRSH_BP 8 40#define HW_POWER_5VCTRL__VBUSVALID_TRSH_BP 8
38#define HW_POWER_5VCTRL__VBUSVALID_TRSH_BM (0x7 << 8) 41#define HW_POWER_5VCTRL__VBUSVALID_TRSH_BM (0x7 << 8)
42#define HW_POWER_5VCTRL__VBUSVALID_TRSH_2p9 (0 << 8)
43#define HW_POWER_5VCTRL__VBUSVALID_TRSH_4V (1 << 8)
44#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT_BP 12
45#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT_BM (0x3f << 12)
46#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__10mA (1 << 12)
47#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__20mA (1 << 13)
48#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__50mA (1 << 14)
49#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__100mA (1 << 15)
50#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__200mA (1 << 16)
51#define HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT__400mA (1 << 17)
52#define HW_POWER_5VCTRL__PWD_CHARGE_4P2 (1 << 20)
39 53
40#define HW_POWER_MINPWR (*(volatile uint32_t *)(HW_POWER_BASE + 0x20)) 54#define HW_POWER_MINPWR (*(volatile uint32_t *)(HW_POWER_BASE + 0x20))
41 55
42#define HW_POWER_CHARGE (*(volatile uint32_t *)(HW_POWER_BASE + 0x30)) 56#define HW_POWER_CHARGE (*(volatile uint32_t *)(HW_POWER_BASE + 0x30))
43#define HW_POWER_CHARGE__BATTCHRG_I_BP 0 57#define HW_POWER_CHARGE__BATTCHRG_I_BP 0
44#define HW_POWER_CHARGE__BATTCHRG_I_BM 0x3f 58#define HW_POWER_CHARGE__BATTCHRG_I_BM 0x3f
59#define HW_POWER_CHARGE__BATTCHRG_I__10mA (1 << 0)
60#define HW_POWER_CHARGE__BATTCHRG_I__20mA (1 << 1)
61#define HW_POWER_CHARGE__BATTCHRG_I__50mA (1 << 2)
62#define HW_POWER_CHARGE__BATTCHRG_I__100mA (1 << 3)
63#define HW_POWER_CHARGE__BATTCHRG_I__200mA (1 << 4)
64#define HW_POWER_CHARGE__BATTCHRG_I__400mA (1 << 5)
45#define HW_POWER_CHARGE__STOP_ILIMIT_BP 8 65#define HW_POWER_CHARGE__STOP_ILIMIT_BP 8
46#define HW_POWER_CHARGE__STOP_ILIMIT_BM 0xf00 66#define HW_POWER_CHARGE__STOP_ILIMIT_BM 0xf00
67#define HW_POWER_CHARGE__STOP_ILIMIT__10mA (1 << 8)
68#define HW_POWER_CHARGE__STOP_ILIMIT__20mA (1 << 9)
69#define HW_POWER_CHARGE__STOP_ILIMIT__50mA (1 << 10)
70#define HW_POWER_CHARGE__STOP_ILIMIT__100mA (1 << 11)
47#define HW_POWER_CHARGE__PWD_BATTCHRG (1 << 16) 71#define HW_POWER_CHARGE__PWD_BATTCHRG (1 << 16)
48#define HW_POWER_CHARGE__CHRG_STS_OFF (1 << 19) 72#define HW_POWER_CHARGE__CHRG_STS_OFF (1 << 19)
73#define HW_POWER_CHARGE__ENABLE_LOAD (1 << 22)
49 74
50#define HW_POWER_VDDDCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x40)) 75#define HW_POWER_VDDDCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x40))
51#define HW_POWER_VDDDCTRL__TRG_BP 0 76#define HW_POWER_VDDDCTRL__TRG_BP 0
52#define HW_POWER_VDDDCTRL__TRG_BM 0x1f 77#define HW_POWER_VDDDCTRL__TRG_BM 0x1f
53#define HW_POWER_VDDDCTRL__TRG_STEP 25 /* mV */ 78#define HW_POWER_VDDDCTRL__TRG_STEP 25 /* mV */
54#define HW_POWER_VDDDCTRL__TRG_MIN 800 /* mV */ 79#define HW_POWER_VDDDCTRL__TRG_MIN 800 /* mV */
80#define HW_POWER_VDDDCTRL__LINREG_OFFSET_BP 16
81#define HW_POWER_VDDDCTRL__LINREG_OFFSET_BM (0x3 << 16)
55#define HW_POWER_VDDDCTRL__ENABLE_LINREG (1 << 21) 82#define HW_POWER_VDDDCTRL__ENABLE_LINREG (1 << 21)
56 83
57#define HW_POWER_VDDACTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x50)) 84#define HW_POWER_VDDACTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x50))
@@ -59,6 +86,8 @@
59#define HW_POWER_VDDACTRL__TRG_BM 0x1f 86#define HW_POWER_VDDACTRL__TRG_BM 0x1f
60#define HW_POWER_VDDACTRL__TRG_STEP 25 /* mV */ 87#define HW_POWER_VDDACTRL__TRG_STEP 25 /* mV */
61#define HW_POWER_VDDACTRL__TRG_MIN 1500 /* mV */ 88#define HW_POWER_VDDACTRL__TRG_MIN 1500 /* mV */
89#define HW_POWER_VDDACTRL__LINREG_OFFSET_BP 12
90#define HW_POWER_VDDACTRL__LINREG_OFFSET_BM (0x3 << 12)
62#define HW_POWER_VDDACTRL__ENABLE_LINREG (1 << 17) 91#define HW_POWER_VDDACTRL__ENABLE_LINREG (1 << 17)
63 92
64#define HW_POWER_VDDIOCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x60)) 93#define HW_POWER_VDDIOCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x60))
@@ -66,6 +95,8 @@
66#define HW_POWER_VDDIOCTRL__TRG_BM 0x1f 95#define HW_POWER_VDDIOCTRL__TRG_BM 0x1f
67#define HW_POWER_VDDIOCTRL__TRG_STEP 25 /* mV */ 96#define HW_POWER_VDDIOCTRL__TRG_STEP 25 /* mV */
68#define HW_POWER_VDDIOCTRL__TRG_MIN 2800 /* mV */ 97#define HW_POWER_VDDIOCTRL__TRG_MIN 2800 /* mV */
98#define HW_POWER_VDDIOCTRL__LINREG_OFFSET_BP 12
99#define HW_POWER_VDDIOCTRL__LINREG_OFFSET_BM (0x3 << 12)
69 100
70#define HW_POWER_VDDMEMCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x70)) 101#define HW_POWER_VDDMEMCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x70))
71#define HW_POWER_VDDMEMCTRL__TRG_BP 0 102#define HW_POWER_VDDMEMCTRL__TRG_BP 0
@@ -74,6 +105,17 @@
74#define HW_POWER_VDDMEMCTRL__TRG_MIN 1700 /* mV */ 105#define HW_POWER_VDDMEMCTRL__TRG_MIN 1700 /* mV */
75#define HW_POWER_VDDMEMCTRL__ENABLE_LINREG (1 << 8) 106#define HW_POWER_VDDMEMCTRL__ENABLE_LINREG (1 << 8)
76 107
108#define HW_POWER_DCDC4P2 (*(volatile uint32_t *)(HW_POWER_BASE + 0x80))
109#define HW_POWER_DCDC4P2__CMPTRIP_BP 0
110#define HW_POWER_DCDC4P2__CMPTRIP_BM 0x1f
111#define HW_POWER_DCDC4P2__CMPTRIP__0p85 0
112#define HW_POWER_DCDC4P2__ENABLE_DCDC (1 << 22)
113#define HW_POWER_DCDC4P2__ENABLE_4P2 (1 << 23)
114#define HW_POWER_DCDC4P2__DROPOUT_CTRL_BP 28
115#define HW_POWER_DCDC4P2__DROPOUT_CTRL_BM (0xf << 28)
116#define HW_POWER_DCDC4P2__DROPOUT_CTRL__200mV (3 << 30)
117#define HW_POWER_DCDC4P2__DROPOUT_CTRL__HIGHER (2 << 28)
118
77#define HW_POWER_MISC (*(volatile uint32_t *)(HW_POWER_BASE + 0x90)) 119#define HW_POWER_MISC (*(volatile uint32_t *)(HW_POWER_BASE + 0x90))
78#define HW_POWER_MISC__SEL_PLLCLK 1 120#define HW_POWER_MISC__SEL_PLLCLK 1
79#define HW_POWER_MISC__FREQSEL_BP 4 121#define HW_POWER_MISC__FREQSEL_BP 4
@@ -89,10 +131,12 @@
89 131
90#define HW_POWER_STS (*(volatile uint32_t *)(HW_POWER_BASE + 0xc0)) 132#define HW_POWER_STS (*(volatile uint32_t *)(HW_POWER_BASE + 0xc0))
91#define HW_POWER_STS__VBUSVALID (1 << 1) 133#define HW_POWER_STS__VBUSVALID (1 << 1)
134#define HW_POWER_STS__CHRGSTS (1 << 11)
92#define HW_POWER_STS__PSWITCH_BP 20 135#define HW_POWER_STS__PSWITCH_BP 20
93#define HW_POWER_STS__PSWITCH_BM (3 << 20) 136#define HW_POWER_STS__PSWITCH_BM (3 << 20)
94 137
95#define HW_POWER_BATTMONITOR (*(volatile uint32_t *)(HW_POWER_BASE + 0xe0)) 138#define HW_POWER_BATTMONITOR (*(volatile uint32_t *)(HW_POWER_BASE + 0xe0))
139#define HW_POWER_BATTMONITOR__ENBATADJ (1 << 10)
96#define HW_POWER_BATTMONITOR__BATT_VAL_BP 16 140#define HW_POWER_BATTMONITOR__BATT_VAL_BP 16
97#define HW_POWER_BATTMONITOR__BATT_VAL_BM (0x3ff << 16) 141#define HW_POWER_BATTMONITOR__BATT_VAL_BM (0x3ff << 16)
98 142
@@ -100,17 +144,39 @@
100#define HW_POWER_RESET__UNLOCK 0x3E770000 144#define HW_POWER_RESET__UNLOCK 0x3E770000
101#define HW_POWER_RESET__PWD 0x1 145#define HW_POWER_RESET__PWD 0x1
102 146
147void imx233_power_set_charge_current(unsigned current); /* in mA */
148void imx233_power_set_stop_current(unsigned current); /* in mA */
149void imx233_power_enable_batadj(bool enable);
150
103struct imx233_power_info_t 151struct imx233_power_info_t
104{ 152{
105 int vddd; /* in mV */ 153 int vddd; /* in mV */
106 bool vddd_linreg; /* VDDD source: linreg from VDDA or DC-DC */ 154 bool vddd_linreg; /* VDDD source: linreg from VDDA or DC-DC */
155 int vddd_linreg_offset;
107 int vdda; /* in mV */ 156 int vdda; /* in mV */
108 bool vdda_linreg; /* VDDA source: linreg from VDDIO or DC-DC */ 157 bool vdda_linreg; /* VDDA source: linreg from VDDIO or DC-DC */
158 int vdda_linreg_offset;
109 int vddio; /* in mV */ 159 int vddio; /* in mV */
160 int vddio_linreg_offset;
110 int vddmem; /* in mV */ 161 int vddmem; /* in mV */
111 bool vddmem_linreg; /* VDDMEM source: linreg from VDDIO or off */ 162 bool vddmem_linreg; /* VDDMEM source: linreg from VDDIO or off */
112 bool dcdc_sel_pllclk; /* clock source of DC-DC: pll or 24MHz xtal */ 163 bool dcdc_sel_pllclk; /* clock source of DC-DC: pll or 24MHz xtal */
113 int dcdc_freqsel; 164 int dcdc_freqsel;
165 int charge_current;
166 int stop_current;
167 bool charging;
168 bool batt_adj;
169 bool _4p2_enable;
170 bool _4p2_dcdc;
171 int _4p2_cmptrip;
172 int _4p2_dropout;
173 bool _5v_pwd_charge_4p2;
174 int _5v_charge_4p2_limit;
175 bool _5v_dcdc_xfer;
176 bool _5v_enable_dcdc;
177 int _5v_vbusvalid_thr;
178 bool _5v_vbusvalid_detect;
179 bool _5v_vbus_cmps;
114}; 180};
115 181
116#define POWER_INFO_VDDD (1 << 0) 182#define POWER_INFO_VDDD (1 << 0)
@@ -118,7 +184,10 @@ struct imx233_power_info_t
118#define POWER_INFO_VDDIO (1 << 2) 184#define POWER_INFO_VDDIO (1 << 2)
119#define POWER_INFO_VDDMEM (1 << 3) 185#define POWER_INFO_VDDMEM (1 << 3)
120#define POWER_INFO_DCDC (1 << 4) 186#define POWER_INFO_DCDC (1 << 4)
121#define POWER_INFO_ALL 0x1f 187#define POWER_INFO_CHARGE (1 << 5)
188#define POWER_INFO_4P2 (1 << 6)
189#define POWER_INFO_5V (1 << 7)
190#define POWER_INFO_ALL 0xff
122 191
123struct imx233_power_info_t imx233_power_get_info(unsigned flags); 192struct imx233_power_info_t imx233_power_get_info(unsigned flags);
124 193
diff --git a/firmware/target/arm/imx233/powermgmt-imx233.c b/firmware/target/arm/imx233/powermgmt-imx233.c
index 0f24fa41ff..97f6e08e12 100644
--- a/firmware/target/arm/imx233/powermgmt-imx233.c
+++ b/firmware/target/arm/imx233/powermgmt-imx233.c
@@ -21,30 +21,21 @@
21 21
22#include "powermgmt.h" 22#include "powermgmt.h"
23#include "power-imx233.h" 23#include "power-imx233.h"
24#include "usb-target.h"
25#include "string.h"
26//#define LOGF_ENABLE
27#include "logf.h"
24 28
25const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = 29#if !defined(IMX233_CHARGE_CURRENT) || !defined(IMX233_STOP_CURRENT) \
26{ 30 || !defined(IMX233_CHARGING_TIMEOUT) || !defined(IMX233_TOPOFF_TIMEOUT)
27 3659 31#error You must define IMX233_CHARGE_CURRENT, IMX233_STOP_CURRENT, \
28}; 32 IMX233_CHARGING_TIMEOUT and IMX233_TOPOFF_TIMEOUT !
29 33#endif
30const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
31{
32 3630
33};
34
35/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
36const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
37{
38 /* Toshiba Gigabeat S Li Ion 700mAH figured from discharge curve */
39 { 3659, 3719, 3745, 3761, 3785, 3813, 3856, 3926, 3984, 4040, 4121 },
40};
41 34
42/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ 35/* charger state is maintained in charge_state (see powermgmt.h) */
43const unsigned short percent_to_volt_charge[11] = 36static int timeout_charging; /* timeout before charging will be declared broken */
44{ 37static int timeout_topping_off; /* timeout before stopping charging after topping off */
45 /* Toshiba Gigabeat S Li Ion 700mAH figured from charge curve */ 38static int timeout_4p2_ilimit_increase; /* timeout before increasing 4p2 ilimit */
46 4028, 4063, 4087, 4111, 4135, 4156, 4173, 4185, 4194, 4202, 4208
47};
48 39
49/* Returns battery voltage from ADC [millivolts] */ 40/* Returns battery voltage from ADC [millivolts] */
50unsigned int battery_adc_voltage(void) 41unsigned int battery_adc_voltage(void)
@@ -55,12 +46,115 @@ unsigned int battery_adc_voltage(void)
55 46
56void powermgmt_init_target(void) 47void powermgmt_init_target(void)
57{ 48{
49 imx233_power_set_charge_current(IMX233_CHARGE_CURRENT);
50 imx233_power_set_stop_current(IMX233_STOP_CURRENT);
51 /* assume that adc_init was called and battery monitoring via LRADC setup */
52 __REG_SET(HW_POWER_BATTMONITOR) = HW_POWER_BATTMONITOR__ENBATADJ;
53 /* make sure we are in a known state: disable charger and 4p2 */
54 __REG_SET(HW_POWER_CHARGE) = HW_POWER_CHARGE__PWD_BATTCHRG;
55 __REG_CLR(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_DCDC |
56 HW_POWER_DCDC4P2__ENABLE_4P2;
57 __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
58 charge_state = DISCHARGING;
58} 59}
59 60
60void charging_algorithm_step(void) 61void charging_algorithm_step(void)
61{ 62{
63 bool is_5v_present = usb_plugged();
64
65 /* initial state & 5v -> battery transition */
66 if(!is_5v_present && charge_state != DISCHARGING)
67 {
68 logf("pwrmgmt: * -> discharging");
69 logf("pwrmgmt: disable charger and 4p2");
70 /* 5V has been lost: disable 4p2 power rail */
71 __REG_SET(HW_POWER_CHARGE) = HW_POWER_CHARGE__PWD_BATTCHRG;
72 __REG_CLR(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_DCDC |
73 HW_POWER_DCDC4P2__ENABLE_4P2;
74 __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
75 charge_state = DISCHARGING;
76 }
77 /* battery -> 5v transition */
78 else if(is_5v_present && charge_state == DISCHARGING)
79 {
80 logf("pwrmgmt: discharging -> trickle");
81 logf("pwrmgmt: begin charging 4p2");
82 /* 5V has been detected: prepare 4.2V power rail for activation */
83 __REG_SET(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_4P2;
84 __REG_SET(HW_POWER_CHARGE) = HW_POWER_CHARGE__ENABLE_LOAD;
85 __FIELD_SET(HW_POWER_5VCTRL, CHARGE_4P2_ILIMIT, 1);
86 __REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;// FIXME: manual error ?
87 __REG_SET(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_DCDC;
88 timeout_4p2_ilimit_increase = current_tick + HZ / 100;
89 charge_state = TRICKLE;
90 }
91 else if(charge_state == TRICKLE && TIME_AFTER(current_tick, timeout_4p2_ilimit_increase))
92 {
93 /* if 4.2V current limit has not reached 780mA, increase it slowly to
94 * charge the 4.2V capacitance */
95 if(__XTRACT(HW_POWER_5VCTRL, CHARGE_4P2_ILIMIT) != 0x3f)
96 {
97 //logf("pwrmgmt: incr 4.2 ilimit");
98 HW_POWER_5VCTRL += 1 << HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT_BP;
99 timeout_4p2_ilimit_increase = current_tick + HZ / 100;
100 }
101 /* we've reached the maximum, take action */
102 else
103 {
104 logf("pwrmgmt: enable dcdc and charger");
105 logf("pwrmgmt: trickle -> charging");
106 /* adjust arbitration between 4.2 and battery */
107 __FIELD_SET(HW_POWER_DCDC4P2, CMPTRIP, 0); /* 85% */
108 __FIELD_SET(HW_POWER_DCDC4P2, DROPOUT_CTRL, 0xe); /* select greater, 200 mV drop */
109 __REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__DCDC_XFER;
110 __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__ENABLE_DCDC;
111 /* enable battery charging */
112 __REG_CLR(HW_POWER_CHARGE) = HW_POWER_CHARGE__PWD_BATTCHRG;
113 charge_state = CHARGING;
114 timeout_charging = current_tick + IMX233_CHARGING_TIMEOUT;
115 }
116 }
117 else if(charge_state == CHARGING && TIME_AFTER(current_tick, timeout_charging))
118 {
119 /* we have charged for a too long time, declare charger broken */
120 logf("pwrmgmt: charging timeout exceeded!");
121 logf("pwrmgmt: charging -> error");
122 /* stop charging */
123 __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
124 /* goto error state */
125 charge_state = CHARGE_STATE_ERROR;
126 }
127 else if(charge_state == CHARGING && !(HW_POWER_STS & HW_POWER_STS__CHRGSTS))
128 {
129 logf("pwrmgmt: topping off");
130 logf("pwrmgmt: charging -> topoff");
131 charge_state = TOPOFF;
132 timeout_topping_off = current_tick + IMX233_TOPOFF_TIMEOUT;
133 }
134 else if(charge_state == TOPOFF && TIME_AFTER(current_tick, timeout_topping_off))
135 {
136 logf("pwrmgmt: charging finished");
137 logf("pwrmgmt: topoff -> disabled");
138 /* stop charging */
139 __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
140 charge_state = CHARGE_STATE_DISABLED;
141 }
62} 142}
63 143
64void charging_algorithm_close(void) 144void charging_algorithm_close(void)
65{ 145{
66} 146}
147
148struct imx233_powermgmt_info_t imx233_powermgmt_get_info(void)
149{
150 struct imx233_powermgmt_info_t info;
151 memset(&info, 0, sizeof(info));
152 info.state = charge_state;
153 info.charging_timeout =
154 charge_state == CHARGING ? timeout_charging - current_tick : 0;
155 info.topoff_timeout =
156 charge_state == TOPOFF ? timeout_topping_off - current_tick : 0;
157 info.incr_4p2_ilimit_timeout =
158 charge_state == TRICKLE ? timeout_4p2_ilimit_increase - current_tick : 0;
159 return info;
160}
diff --git a/firmware/target/arm/imx233/sansa-fuzeplus/powermgmt-fuzeplus.c b/firmware/target/arm/imx233/sansa-fuzeplus/powermgmt-fuzeplus.c
new file mode 100644
index 0000000000..3e068f007d
--- /dev/null
+++ b/firmware/target/arm/imx233/sansa-fuzeplus/powermgmt-fuzeplus.c
@@ -0,0 +1,46 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "powermgmt-target.h"
23
24const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
25{
26 3659
27};
28
29const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
30{
31 3630
32};
33
34/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
35const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
36{
37 /* Toshiba Gigabeat S Li Ion 700mAH figured from discharge curve */
38 { 3659, 3719, 3745, 3761, 3785, 3813, 3856, 3926, 3984, 4040, 4121 },
39};
40
41/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
42const unsigned short percent_to_volt_charge[11] =
43{
44 /* Toshiba Gigabeat S Li Ion 700mAH figured from charge curve */
45 4028, 4063, 4087, 4111, 4135, 4156, 4173, 4185, 4194, 4202, 4208
46};
diff --git a/firmware/target/arm/imx233/powermgmt-target.h b/firmware/target/arm/imx233/sansa-fuzeplus/powermgmt-target.h
index d539a66d16..34d1d00e1d 100644
--- a/firmware/target/arm/imx233/powermgmt-target.h
+++ b/firmware/target/arm/imx233/sansa-fuzeplus/powermgmt-target.h
@@ -22,9 +22,27 @@
22#define POWERMGMT_TARGET_H 22#define POWERMGMT_TARGET_H
23 23
24#include "config.h" 24#include "config.h"
25#include "powermgmt-imx233.h"
25 26
26void powermgmt_init_target(void); 27/* Fuze+ OF settings:
27void charging_algorithm_step(void); 28 * - current ramp slope: 50 mA/s
28void charging_algorithm_close(void); 29 * - conditioning threshold voltage: 3 V
30 * - conditioning max voltage: 3.1 V
31 * - conditioning current: 60 mA
32 * - conditioning timeout: 1 h
33 * - charging voltage: 4.2 V
34 * - charging current: 200 mA
35 * - charging threshold current: 30 mA
36 * - charging timeout: 4 h
37 * - top off period: 30 min
38 * - high die temperature: 71 °C
39 * - low die temperature: 56 °C
40 * - safe temperature current: 30 mA
41 */
42
43#define IMX233_CHARGE_CURRENT 200
44#define IMX233_STOP_CURRENT 30
45#define IMX233_TOPOFF_TIMEOUT (30 * 60 * HZ)
46#define IMX233_CHARGING_TIMEOUT (4 * 3600 * HZ)
29 47
30#endif /* POWERMGMT_TARGET_H */ 48#endif /* POWERMGMT_TARGET_H */