summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2016-05-22 02:33:58 +0200
committerCástor Muñoz <cmvidal@gmail.com>2016-05-25 12:45:34 +0200
commit98bd2231eca3e6cb015fa58877d648857cb816e6 (patch)
treee5d5e2bd16eadd658093eb025cf8c5f037fc0ba2
parent88caf222ed1da8f88114b4aa3a615e72e3649ca1 (diff)
downloadrockbox-98bd2231eca3e6cb015fa58877d648857cb816e6.tar.gz
rockbox-98bd2231eca3e6cb015fa58877d648857cb816e6.zip
iPod Classic: introduce PMU interrupts
PMU interrupts are used to detect USB Vbus, wall adaptor, accessories and holdswitch. A thread is needed to poll the PMU throught I2C, ATM it does nothing but showing the state of the inputs on the HW debug menu, funcionallity for each individual input will be added in next patches. Change-Id: If93bf2044d1052729237a7fd1431c8493e09f1c7
-rw-r--r--firmware/export/pcf5063x.h11
-rw-r--r--firmware/target/arm/s5l8702/debug-s5l8702.c29
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c162
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-target.h25
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c2
-rw-r--r--firmware/target/arm/s5l8702/system-s5l8702.c1
6 files changed, 214 insertions, 16 deletions
diff --git a/firmware/export/pcf5063x.h b/firmware/export/pcf5063x.h
index 164417f483..f5f177ace7 100644
--- a/firmware/export/pcf5063x.h
+++ b/firmware/export/pcf5063x.h
@@ -159,6 +159,17 @@ enum pcf5063X_reg_oocwake {
159 PCF5063X_OOCWAKE_ADP = 0x80, 159 PCF5063X_OOCWAKE_ADP = 0x80,
160}; 160};
161 161
162enum pcf5063X_reg_oocstat {
163 PCF5063X_OOCSTAT_ONKEY = 0x01,
164 PCF5063X_OOCSTAT_EXTON1 = 0x02,
165 PCF5063X_OOCSTAT_EXTON2 = 0x04,
166 PCF5063X_OOCSTAT_EXTON3 = 0x08,
167 PCF5063X_OOCSTAT_BUBPRES = 0x10,
168 PCF5063X_OOCSTAT_SYSOK = 0x20,
169 PCF5063X_OOCSTAT_BATOK = 0x40,
170 PCF5063X_OOCSTAT_TMPOK = 0x80,
171};
172
162enum pcf5063X_reg_mbcc1 { 173enum pcf5063X_reg_mbcc1 {
163 PCF5063X_MBCC1_CHGENA = 0x01, /* Charger enable */ 174 PCF5063X_MBCC1_CHGENA = 0x01, /* Charger enable */
164 PCF5063X_MBCC1_AUTOSTOP = 0x02, 175 PCF5063X_MBCC1_AUTOSTOP = 0x02,
diff --git a/firmware/target/arm/s5l8702/debug-s5l8702.c b/firmware/target/arm/s5l8702/debug-s5l8702.c
index 614019bac1..48a20a97c2 100644
--- a/firmware/target/arm/s5l8702/debug-s5l8702.c
+++ b/firmware/target/arm/s5l8702/debug-s5l8702.c
@@ -102,14 +102,14 @@ bool dbg_hw_info(void)
102 _DEBUG_PRINTF("PMU:"); 102 _DEBUG_PRINTF("PMU:");
103 for(i=0;i<7;i++) 103 for(i=0;i<7;i++)
104 { 104 {
105 char *device[] = {"(unknown)", 105 char *device[] = {"unknown",
106 "(unknown)", 106 "unknown",
107 "(unknown)", 107 "LCD",
108 "(unknown)", 108 "AUDIO",
109 "(unknown)", 109 "unknown",
110 "(unknown)", 110 "CLICKWHEEL",
111 "(unknown)"}; 111 "ACCESSORY"};
112 _DEBUG_PRINTF("ldo%d %s: %dmV %s",i, 112 _DEBUG_PRINTF("ldo%d %s: %dmV (%s)",i,
113 pmu_read(0x2e + (i << 1))?" on":"off", 113 pmu_read(0x2e + (i << 1))?" on":"off",
114 900 + pmu_read(0x2d + (i << 1))*100, 114 900 + pmu_read(0x2d + (i << 1))*100,
115 device[i]); 115 device[i]);
@@ -120,6 +120,19 @@ bool dbg_hw_info(void)
120 _DEBUG_PRINTF("charging: %s", charging_state() ? "true" : "false"); 120 _DEBUG_PRINTF("charging: %s", charging_state() ? "true" : "false");
121 _DEBUG_PRINTF("backlight: %s", pmu_read(0x29) ? "on" : "off"); 121 _DEBUG_PRINTF("backlight: %s", pmu_read(0x29) ? "on" : "off");
122 _DEBUG_PRINTF("brightness value: %d", pmu_read(0x28)); 122 _DEBUG_PRINTF("brightness value: %d", pmu_read(0x28));
123 line++;
124 _DEBUG_PRINTF("USB present: %s",
125 pmu_usb_present() ? "true" : "false");
126#if CONFIG_CHARGING
127 _DEBUG_PRINTF("FW present: %s",
128 pmu_firewire_present() ? "true" : "false");
129#endif
130 _DEBUG_PRINTF("holdswitch locked: %s",
131 pmu_holdswitch_locked() ? "true" : "false");
132#ifdef IPOD_ACCESSORY_PROTOCOL
133 _DEBUG_PRINTF("accessory present: %s",
134 pmu_accessory_present() ? "true" : "false");
135#endif
123 } 136 }
124#ifdef UC870X_DEBUG 137#ifdef UC870X_DEBUG
125 else if(state==2) 138 else if(state==2)
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)
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
index d090f72a67..2274b4061f 100644
--- a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
+++ b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
@@ -30,7 +30,21 @@
30/* undocummented PMU registers */ 30/* undocummented PMU registers */
31#define PCF50635_REG_INT6 0x85 31#define PCF50635_REG_INT6 0x85
32#define PCF50635_REG_INT6M 0x86 32#define PCF50635_REG_INT6M 0x86
33#define PCF50635_REG_GPIOSTAT 0x87 /* bit1: GPIO2 status (TBC) */ 33#define PCF50635_REG_GPIOSTAT 0x87
34
35enum pcf50635_reg_int6 {
36 PCF50635_INT6_GPIO1 = 0x01, /* TBC */
37 PCF50635_INT6_GPIO2 = 0x02,
38};
39
40enum pcf50635_reg_gpiostat {
41 PCF50635_GPIOSTAT_GPIO1 = 0x01, /* TBC */
42 PCF50635_GPIOSTAT_GPIO2 = 0x02,
43};
44
45
46/* GPIO for external PMU interrupt */
47#define GPIO_EINT_PMU 0x7b
34 48
35/* LDOs */ 49/* LDOs */
36#define LDO_UNK1 1 /* TBC: SoC voltage (USB) */ 50#define LDO_UNK1 1 /* TBC: SoC voltage (USB) */
@@ -77,6 +91,15 @@ void pmu_read_rtc(unsigned char* buffer);
77void pmu_write_rtc(unsigned char* buffer); 91void pmu_write_rtc(unsigned char* buffer);
78void pmu_hdd_power(bool on); 92void pmu_hdd_power(bool on);
79 93
94int pmu_holdswitch_locked(void);
95int pmu_usb_present(void);
96#if CONFIG_CHARGING
97int pmu_firewire_present(void);
98#endif
99#ifdef IPOD_ACCESSORY_PROTOCOL
100int pmu_accessory_present(void);
101#endif
102
80void pmu_preinit(void); 103void pmu_preinit(void);
81#ifdef BOOTLOADER 104#ifdef BOOTLOADER
82unsigned char pmu_rd(int address); 105unsigned char pmu_rd(int address);
diff --git a/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c
index 57358b8cb6..d3224d2a66 100644
--- a/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c
@@ -41,6 +41,8 @@ void power_off(void)
41 41
42void power_init(void) 42void power_init(void)
43{ 43{
44 pmu_init();
45
44 idepowered = false; 46 idepowered = false;
45 47
46 /* DOWN1CTL: CPU DVM step time = 30us (default: no DVM) */ 48 /* DOWN1CTL: CPU DVM step time = 30us (default: no DVM) */
diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c
index cbe8bfcaf7..459f4c36c6 100644
--- a/firmware/target/arm/s5l8702/system-s5l8702.c
+++ b/firmware/target/arm/s5l8702/system-s5l8702.c
@@ -207,7 +207,6 @@ void system_init(void)
207#endif 207#endif
208 gpio_init(); 208 gpio_init();
209 eint_init(); 209 eint_init();
210 pmu_init();
211 dma_init(); 210 dma_init();
212#ifdef HAVE_SERIAL 211#ifdef HAVE_SERIAL
213 uart_init(); 212 uart_init();