diff options
Diffstat (limited to 'firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c')
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c | 162 |
1 files changed, 156 insertions, 6 deletions
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c index 920c93ad5d..4200308861 100644 --- a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c +++ b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c | |||
@@ -21,8 +21,12 @@ | |||
21 | 21 | ||
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "kernel.h" | 23 | #include "kernel.h" |
24 | #include "i2c-s5l8702.h" | 24 | #include "thread.h" |
25 | |||
25 | #include "pmu-target.h" | 26 | #include "pmu-target.h" |
27 | #include "i2c-s5l8702.h" | ||
28 | #include "gpio-s5l8702.h" | ||
29 | |||
26 | 30 | ||
27 | static struct mutex pmu_adc_mutex; | 31 | static struct mutex pmu_adc_mutex; |
28 | 32 | ||
@@ -50,11 +54,6 @@ int pmu_write(int address, unsigned char val) | |||
50 | return pmu_write_multiple(address, 1, &val); | 54 | return pmu_write_multiple(address, 1, &val); |
51 | } | 55 | } |
52 | 56 | ||
53 | void pmu_init(void) | ||
54 | { | ||
55 | mutex_init(&pmu_adc_mutex); | ||
56 | } | ||
57 | |||
58 | int pmu_read_adc(unsigned int adc) | 57 | int pmu_read_adc(unsigned int adc) |
59 | { | 58 | { |
60 | int data = 0; | 59 | int data = 0; |
@@ -144,6 +143,157 @@ void pmu_write_rtc(unsigned char* buffer) | |||
144 | } | 143 | } |
145 | 144 | ||
146 | /* | 145 | /* |
146 | * eINT | ||
147 | */ | ||
148 | #define Q_EINT 0 | ||
149 | |||
150 | static char pmu_thread_stack[DEFAULT_STACK_SIZE/4]; | ||
151 | static struct event_queue pmu_queue; | ||
152 | static unsigned char ints_msk[6]; | ||
153 | |||
154 | static void pmu_eint_isr(struct eint_handler*); | ||
155 | |||
156 | static struct eint_handler pmu_eint = { | ||
157 | .gpio_n = GPIO_EINT_PMU, | ||
158 | .type = EIC_INTTYPE_LEVEL, | ||
159 | .level = EIC_INTLEVEL_LOW, | ||
160 | .isr = pmu_eint_isr, | ||
161 | }; | ||
162 | |||
163 | static int pmu_input_holdswitch; | ||
164 | static int pmu_input_usb; | ||
165 | |||
166 | int pmu_holdswitch_locked(void) | ||
167 | { | ||
168 | return pmu_input_holdswitch; | ||
169 | } | ||
170 | |||
171 | int pmu_usb_present(void) | ||
172 | { | ||
173 | return pmu_input_usb; | ||
174 | } | ||
175 | |||
176 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
177 | static int pmu_input_accessory; | ||
178 | |||
179 | int pmu_accessory_present(void) | ||
180 | { | ||
181 | return pmu_input_accessory; | ||
182 | } | ||
183 | #endif | ||
184 | |||
185 | #if CONFIG_CHARGING | ||
186 | static int pmu_input_firewire; | ||
187 | |||
188 | int pmu_firewire_present(void) | ||
189 | { | ||
190 | return pmu_input_firewire; | ||
191 | } | ||
192 | |||
193 | static void pmu_read_inputs_mbcs(void) | ||
194 | { | ||
195 | pmu_input_firewire = !!(pmu_read(PCF5063X_REG_MBCS1) | ||
196 | & PCF5063X_MBCS1_ADAPTPRES); | ||
197 | } | ||
198 | #endif | ||
199 | |||
200 | static void pmu_read_inputs_gpio(void) | ||
201 | { | ||
202 | pmu_input_holdswitch = !(pmu_read(PCF50635_REG_GPIOSTAT) | ||
203 | & PCF50635_GPIOSTAT_GPIO2); | ||
204 | } | ||
205 | |||
206 | static void pmu_read_inputs_ooc(void) | ||
207 | { | ||
208 | unsigned char oocstat = pmu_read(PCF5063X_REG_OOCSTAT); | ||
209 | pmu_input_usb = !!(oocstat & PCF5063X_OOCSTAT_EXTON2); | ||
210 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
211 | pmu_input_accessory = !(oocstat & PCF5063X_OOCSTAT_EXTON3); | ||
212 | #endif | ||
213 | } | ||
214 | |||
215 | static void pmu_eint_isr(struct eint_handler *h) | ||
216 | { | ||
217 | eint_unregister(h); | ||
218 | queue_post(&pmu_queue, Q_EINT, 0); | ||
219 | } | ||
220 | |||
221 | static void NORETURN_ATTR pmu_thread(void) | ||
222 | { | ||
223 | struct queue_event ev; | ||
224 | unsigned char ints[6]; | ||
225 | |||
226 | while (true) | ||
227 | { | ||
228 | queue_wait_w_tmo(&pmu_queue, &ev, TIMEOUT_BLOCK); | ||
229 | switch (ev.id) | ||
230 | { | ||
231 | case Q_EINT: | ||
232 | /* read (clear) PMU interrupts, this will also | ||
233 | raise the PMU IRQ pin */ | ||
234 | pmu_read_multiple(PCF5063X_REG_INT1, 2, ints); | ||
235 | ints[5] = pmu_read(PCF50635_REG_INT6); | ||
236 | |||
237 | #if CONFIG_CHARGING | ||
238 | if (ints[0] & ~ints_msk[0]) pmu_read_inputs_mbcs(); | ||
239 | #endif | ||
240 | if (ints[1] & ~ints_msk[1]) pmu_read_inputs_ooc(); | ||
241 | if (ints[5] & ~ints_msk[5]) pmu_read_inputs_gpio(); | ||
242 | |||
243 | eint_register(&pmu_eint); | ||
244 | break; | ||
245 | |||
246 | case SYS_TIMEOUT: | ||
247 | break; | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | |||
252 | /* main init */ | ||
253 | void pmu_init(void) | ||
254 | { | ||
255 | mutex_init(&pmu_adc_mutex); | ||
256 | queue_init(&pmu_queue, false); | ||
257 | |||
258 | create_thread(pmu_thread, | ||
259 | pmu_thread_stack, sizeof(pmu_thread_stack), 0, | ||
260 | "PMU" IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU)); | ||
261 | |||
262 | /* configure PMU interrutps */ | ||
263 | for (int i = 0; i < 6; i++) | ||
264 | ints_msk[i] = 0xff; | ||
265 | |||
266 | #if CONFIG_CHARGING | ||
267 | ints_msk[0] &= ~PCF5063X_INT1_ADPINS & /* FireWire */ | ||
268 | ~PCF5063X_INT1_ADPREM; | ||
269 | #endif | ||
270 | ints_msk[1] &= ~PCF5063X_INT2_EXTON2R & /* USB */ | ||
271 | ~PCF5063X_INT2_EXTON2F; | ||
272 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
273 | ints_msk[1] &= ~PCF5063X_INT2_EXTON3R & /* Accessory */ | ||
274 | ~PCF5063X_INT2_EXTON3F; | ||
275 | #endif | ||
276 | ints_msk[5] &= ~PCF50635_INT6_GPIO2; /* Holdswitch */ | ||
277 | |||
278 | pmu_write_multiple(PCF5063X_REG_INT1M, 5, ints_msk); | ||
279 | pmu_write(PCF50635_REG_INT6M, ints_msk[5]); | ||
280 | |||
281 | /* clear all */ | ||
282 | unsigned char ints[5]; | ||
283 | pmu_read_multiple(PCF5063X_REG_INT1, 5, ints); | ||
284 | pmu_read(PCF50635_REG_INT6); | ||
285 | |||
286 | /* get initial values */ | ||
287 | #if CONFIG_CHARGING | ||
288 | pmu_read_inputs_mbcs(); | ||
289 | #endif | ||
290 | pmu_read_inputs_ooc(); | ||
291 | pmu_read_inputs_gpio(); | ||
292 | |||
293 | eint_register(&pmu_eint); | ||
294 | } | ||
295 | |||
296 | /* | ||
147 | * preinit | 297 | * preinit |
148 | */ | 298 | */ |
149 | int pmu_rd_multiple(int address, int count, unsigned char* buffer) | 299 | int pmu_rd_multiple(int address, int count, unsigned char* buffer) |