summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c')
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c162
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
27static struct mutex pmu_adc_mutex; 31static 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
53void pmu_init(void)
54{
55 mutex_init(&pmu_adc_mutex);
56}
57
58int pmu_read_adc(unsigned int adc) 57int 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
150static char pmu_thread_stack[DEFAULT_STACK_SIZE/4];
151static struct event_queue pmu_queue;
152static unsigned char ints_msk[6];
153
154static void pmu_eint_isr(struct eint_handler*);
155
156static 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
163static int pmu_input_holdswitch;
164static int pmu_input_usb;
165
166int pmu_holdswitch_locked(void)
167{
168 return pmu_input_holdswitch;
169}
170
171int pmu_usb_present(void)
172{
173 return pmu_input_usb;
174}
175
176#ifdef IPOD_ACCESSORY_PROTOCOL
177static int pmu_input_accessory;
178
179int pmu_accessory_present(void)
180{
181 return pmu_input_accessory;
182}
183#endif
184
185#if CONFIG_CHARGING
186static int pmu_input_firewire;
187
188int pmu_firewire_present(void)
189{
190 return pmu_input_firewire;
191}
192
193static void pmu_read_inputs_mbcs(void)
194{
195 pmu_input_firewire = !!(pmu_read(PCF5063X_REG_MBCS1)
196 & PCF5063X_MBCS1_ADAPTPRES);
197}
198#endif
199
200static void pmu_read_inputs_gpio(void)
201{
202 pmu_input_holdswitch = !(pmu_read(PCF50635_REG_GPIOSTAT)
203 & PCF50635_GPIOSTAT_GPIO2);
204}
205
206static 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
215static void pmu_eint_isr(struct eint_handler *h)
216{
217 eint_unregister(h);
218 queue_post(&pmu_queue, Q_EINT, 0);
219}
220
221static 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 */
253void 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 */
149int pmu_rd_multiple(int address, int count, unsigned char* buffer) 299int pmu_rd_multiple(int address, int count, unsigned char* buffer)