diff options
Diffstat (limited to 'firmware/target/arm/imx233/power-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/power-imx233.c | 123 |
1 files changed, 121 insertions, 2 deletions
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 | ||
29 | struct current_step_bit_t | ||
30 | { | ||
31 | unsigned current; | ||
32 | uint32_t bit; | ||
33 | }; | ||
34 | |||
35 | /* in decreasing order */ | ||
36 | static 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 */ | ||
47 | static 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 */ | ||
56 | static 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 | |||
29 | void INT_VDD5V(void) | 66 | void 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 | ||
44 | void power_init(void) | 81 | void 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 | ||
56 | void power_off(void) | 104 | void power_off(void) |
@@ -64,12 +112,42 @@ void power_off(void) | |||
64 | 112 | ||
65 | unsigned int power_input_status(void) | 113 | unsigned 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 | ||
70 | bool charging_state(void) | 118 | bool charging_state(void) |
71 | { | 119 | { |
72 | return false; | 120 | return HW_POWER_STS & HW_POWER_STS__CHRGSTS; |
121 | } | ||
122 | |||
123 | void 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 | |||
135 | void 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 | ||
75 | struct imx233_power_info_t imx233_power_get_info(unsigned flags) | 153 | struct 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 | } |