summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-05-21 08:42:11 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-05-21 08:42:11 +0000
commita9c20f5789c13b486d217024a020f9d6163e2d51 (patch)
tree5da52ca9cc7a28ba21ced042cb739e6160d5f87b
parent5f796087b009fee1ae60904b0355cc7febe3330f (diff)
downloadrockbox-a9c20f5789c13b486d217024a020f9d6163e2d51.tar.gz
rockbox-a9c20f5789c13b486d217024a020f9d6163e2d51.zip
Gigabeat S:
1) Rework event handling and static registration mechanism. No target- specific code in mc13783 driver. GPIO event driver interfaces more cleanly. 2) Somewhat related - enable thread priority for bootloader which is desireable here (ffs is used for GPIO event enabling anyway and that goes along with priority). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17593 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES3
-rw-r--r--firmware/drivers/rtc/rtc_mc13783.c16
-rw-r--r--firmware/export/config-gigabeat-s.h1
-rw-r--r--firmware/export/config.h9
-rw-r--r--firmware/export/mc13783.h27
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/adc-imx31.c11
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-imx31.c123
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-target.h4
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c21
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c68
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h56
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/gpio-target.h17
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c72
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c161
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-target.h36
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/power-imx31.c18
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/power-imx31.h2
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-imx31.c11
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-target.h2
19 files changed, 433 insertions, 225 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index bbdd0bc5a2..88e48bb226 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -679,12 +679,13 @@ target/arm/imx31/gigabeat-s/backlight-imx31.c
679target/arm/imx31/gigabeat-s/button-imx31.c 679target/arm/imx31/gigabeat-s/button-imx31.c
680target/arm/imx31/gigabeat-s/clkctl-imx31.c 680target/arm/imx31/gigabeat-s/clkctl-imx31.c
681target/arm/imx31/gigabeat-s/dma_start.c 681target/arm/imx31/gigabeat-s/dma_start.c
682target/arm/imx31/gigabeat-s/gpio-imx31.c
683target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c 682target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c
683target/arm/imx31/gigabeat-s/gpio-imx31.c
684target/arm/imx31/gigabeat-s/kernel-imx31.c 684target/arm/imx31/gigabeat-s/kernel-imx31.c
685target/arm/imx31/gigabeat-s/i2c-imx31.c 685target/arm/imx31/gigabeat-s/i2c-imx31.c
686target/arm/imx31/gigabeat-s/i2s-imx31.c 686target/arm/imx31/gigabeat-s/i2s-imx31.c
687target/arm/imx31/gigabeat-s/lcd-imx31.c 687target/arm/imx31/gigabeat-s/lcd-imx31.c
688target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c
688target/arm/imx31/gigabeat-s/mc13783-imx31.c 689target/arm/imx31/gigabeat-s/mc13783-imx31.c
689target/arm/imx31/gigabeat-s/mmu-imx31.c 690target/arm/imx31/gigabeat-s/mmu-imx31.c
690target/arm/imx31/gigabeat-s/power-imx31.c 691target/arm/imx31/gigabeat-s/power-imx31.c
diff --git a/firmware/drivers/rtc/rtc_mc13783.c b/firmware/drivers/rtc/rtc_mc13783.c
index 9d2c50cf11..325a496646 100644
--- a/firmware/drivers/rtc/rtc_mc13783.c
+++ b/firmware/drivers/rtc/rtc_mc13783.c
@@ -67,11 +67,6 @@ enum rtc_registers_indexes
67/* was it an alarm that triggered power on ? */ 67/* was it an alarm that triggered power on ? */
68static bool alarm_start = false; 68static bool alarm_start = false;
69 69
70void mc13783_alarm_start(void)
71{
72 alarm_start = true;
73}
74
75static const unsigned char rtc_registers[RTC_NUM_REGS] = 70static const unsigned char rtc_registers[RTC_NUM_REGS] =
76{ 71{
77 [RTC_REG_TIME] = MC13783_RTC_TIME, 72 [RTC_REG_TIME] = MC13783_RTC_TIME,
@@ -122,7 +117,12 @@ static int is_leap_year(int y)
122/** Public APIs **/ 117/** Public APIs **/
123void rtc_init(void) 118void rtc_init(void)
124{ 119{
125 /* Nothing to do */ 120 /* only needs to be polled on startup */
121 if (mc13783_read(MC13783_INTERRUPT_STATUS1) & MC13783_TODAI)
122 {
123 alarm_start = true;
124 mc13783_write(MC13783_INTERRUPT_STATUS1, MC13783_TODAI);
125 }
126} 126}
127 127
128int rtc_read_datetime(unsigned char* buf) 128int rtc_read_datetime(unsigned char* buf)
@@ -264,7 +264,9 @@ bool rtc_enable_alarm(bool enable)
264bool rtc_check_alarm_started(bool release_alarm) 264bool rtc_check_alarm_started(bool release_alarm)
265{ 265{
266 bool rc = alarm_start; 266 bool rc = alarm_start;
267 alarm_start &= ~release_alarm; 267
268 if (release_alarm)
269 alarm_start = false;
268 270
269 return rc; 271 return rc;
270} 272}
diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h
index a0c05dad45..cafb202ebe 100644
--- a/firmware/export/config-gigabeat-s.h
+++ b/firmware/export/config-gigabeat-s.h
@@ -97,6 +97,7 @@
97/* Define the bitmask of modules used */ 97/* Define the bitmask of modules used */
98#define SPI_MODULE_MASK (USE_CSPI2_MODULE) 98#define SPI_MODULE_MASK (USE_CSPI2_MODULE)
99#define I2C_MODULE_MASK (USE_I2C1_MODULE) 99#define I2C_MODULE_MASK (USE_I2C1_MODULE)
100#define GPIO_EVENT_MASK (USE_GPIO1_EVENTS)
100 101
101/* Define this if target has an additional number of threads specific to it */ 102/* Define this if target has an additional number of threads specific to it */
102#define TARGET_EXTRA_THREADS 1 103#define TARGET_EXTRA_THREADS 1
diff --git a/firmware/export/config.h b/firmware/export/config.h
index c200355872..c7e204c5df 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -341,7 +341,14 @@
341#endif 341#endif
342 342
343#if (CONFIG_CODEC == SWCODEC) 343#if (CONFIG_CODEC == SWCODEC)
344#ifndef BOOTLOADER 344#ifdef BOOTLOADER
345
346#if CONFIG_CPU == IMX31L
347/* Priority in bootloader is wanted */
348#define HAVE_PRIORITY_SCHEDULING
349#endif
350
351#else /* !BOOTLOADER */
345 352
346#define HAVE_EXTENDED_MESSAGING_AND_NAME 353#define HAVE_EXTENDED_MESSAGING_AND_NAME
347 354
diff --git a/firmware/export/mc13783.h b/firmware/export/mc13783.h
index 6ed1cb46be..1f6fee8c44 100644
--- a/firmware/export/mc13783.h
+++ b/firmware/export/mc13783.h
@@ -1270,6 +1270,9 @@ enum mc13783_regs_enum
1270 #define MC13783_TC3PERIODr(x) (((x) & MC13783_TC3PERIOD) >> 21) 1270 #define MC13783_TC3PERIODr(x) (((x) & MC13783_TC3PERIOD) >> 21)
1271#define MC13783_TC3TRIODE (0x1 << 23) 1271#define MC13783_TC3TRIODE (0x1 << 23)
1272 1272
1273/* For event enum values which are target-defined */
1274#include "mc13783-target.h"
1275
1273void mc13783_init(void); 1276void mc13783_init(void);
1274void mc13783_close(void); 1277void mc13783_close(void);
1275uint32_t mc13783_set(unsigned address, uint32_t bits); 1278uint32_t mc13783_set(unsigned address, uint32_t bits);
@@ -1281,6 +1284,28 @@ int mc13783_write_regset(const unsigned char *regs, const uint32_t *data, int co
1281uint32_t mc13783_read(unsigned address); 1284uint32_t mc13783_read(unsigned address);
1282int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count); 1285int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count);
1283int mc13783_read_regset(const unsigned char *regs, uint32_t *buffer, int count); 1286int mc13783_read_regset(const unsigned char *regs, uint32_t *buffer, int count);
1284void mc13783_alarm_start(void); 1287
1288/* Statically-registered event enable/disable */
1289enum mc13783_event_sets
1290{
1291 MC13783_EVENT_SET0 = 0,
1292 MC13783_EVENT_SET1 = 1,
1293};
1294
1295struct mc13783_event
1296{
1297 enum mc13783_event_sets set : 8;
1298 uint32_t mask : 24;
1299 void (*callback)(void);
1300};
1301
1302struct mc13783_event_list
1303{
1304 unsigned count;
1305 const struct mc13783_event *events;
1306};
1307
1308bool mc13783_enable_event(enum mc13783_event_ids event);
1309void mc13783_disable_event(enum mc13783_event_ids event);
1285 1310
1286#endif /* _MC13783_H_ */ 1311#endif /* _MC13783_H_ */
diff --git a/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c b/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c
index d26d708da1..2f4e45c3b1 100644
--- a/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c
@@ -77,11 +77,11 @@ unsigned short adc_read(int channel)
77 77
78 mutex_unlock(&adc_mtx); 78 mutex_unlock(&adc_mtx);
79 79
80 /* Channels 0-3/8-11 in ADD1, 0-4/12-15 in ADD2 */ 80 /* Channels 0-3/8-11 in ADD1, 4-7/12-15 in ADD2 */
81 return (channel & 4) ? MC13783_ADD2r(data) : MC13783_ADD1r(data); 81 return (channel & 4) ? MC13783_ADD2r(data) : MC13783_ADD1r(data);
82} 82}
83 83
84/* Called when conversion is complete */ 84/* Called by mc13783 interrupt thread when conversion is complete */
85void adc_done(void) 85void adc_done(void)
86{ 86{
87 wakeup_signal(&adc_wake); 87 wakeup_signal(&adc_wake);
@@ -100,7 +100,8 @@ void adc_init(void)
100 MC13783_RTHEN | MC13783_CHRGICON); 100 MC13783_RTHEN | MC13783_CHRGICON);
101 /* Enable ADC, set multi-channel mode */ 101 /* Enable ADC, set multi-channel mode */
102 mc13783_write(MC13783_ADC1, MC13783_ADEN); 102 mc13783_write(MC13783_ADC1, MC13783_ADEN);
103 /* Enable the ADCDONE interrupt - notifications are dispatched by 103
104 * event handler. */ 104 /* Enable ADCDONE event */
105 mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_ADCDONEM); 105 mc13783_write(MC13783_INTERRUPT_STATUS0, MC13783_ADCDONEI);
106 mc13783_enable_event(MC13783_ADCDONE_EVENT);
106} 107}
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
index 746883d010..ad1e2b7e49 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
@@ -26,6 +26,7 @@
26#include "backlight-target.h" 26#include "backlight-target.h"
27#include "avic-imx31.h" 27#include "avic-imx31.h"
28#include "clkctl-imx31.h" 28#include "clkctl-imx31.h"
29#include "mc13783.h"
29 30
30/* Most code in here is taken from the Linux BSP provided by Freescale 31/* Most code in here is taken from the Linux BSP provided by Freescale
31 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */ 32 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */
@@ -119,56 +120,6 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
119 int_btn = button; 120 int_btn = button;
120} 121}
121 122
122void button_init_device(void)
123{
124#ifdef BOOTLOADER
125 /* Can be called more than once in the bootloader */
126 if (initialized)
127 return;
128
129 initialized = true;
130#endif
131
132 /* Enable keypad clock */
133 imx31_clkctl_module_clock_gating(CG_KPP, CGM_ON_ALL);
134
135 /* 1. Enable number of rows in keypad (KPCR[4:0])
136 *
137 * Configure the rows/cols in KPP
138 * LSB nybble in KPP is for 5 rows
139 * MSB nybble in KPP is for 3 cols */
140 KPP_KPCR |= 0x1f;
141
142 /* 2. Write 0's to KPDR[10:8] */
143 KPP_KPDR &= ~(0x7 << 8);
144
145 /* 3. Configure the keypad columns as open-drain (KPCR[10:8]). */
146 KPP_KPCR |= (0x7 << 8);
147
148 /* 4. Configure columns as output, rows as input (KDDR[10:8,4:0]) */
149 KPP_KDDR = (KPP_KDDR | (0x7 << 8)) & ~0x1f;
150
151 /* 5. Clear the KPKD Status Flag and Synchronizer chain.
152 * 6. Set the KDIE control bit bit. */
153 KPP_KPSR = KPP_KPSR_KDIE | KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD;
154
155 /* KPP IRQ at priority 3 */
156 avic_enable_int(KPP, IRQ, 3, KPP_HANDLER);
157}
158
159#ifdef BUTTON_DRIVER_CLOSE
160void button_close_device(void)
161{
162 int oldlevel = disable_irq_save();
163
164 avic_disable_int(KPP);
165 KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE);
166 int_btn = BUTTON_NONE;
167
168 restore_irq(oldlevel);
169}
170#endif /* BUTTON_DRIVER_CLOSE */
171
172bool button_hold(void) 123bool button_hold(void)
173{ 124{
174 return _button_hold(); 125 return _button_hold();
@@ -199,8 +150,11 @@ int button_read_device(void)
199} 150}
200 151
201/* This is called from the mc13783 interrupt thread */ 152/* This is called from the mc13783 interrupt thread */
202void button_power_set_state(bool pressed) 153void button_power_event(void)
203{ 154{
155 bool pressed =
156 (mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD1S) == 0;
157
204 /* Prevent KPP_HANDLER from changing things */ 158 /* Prevent KPP_HANDLER from changing things */
205 int oldlevel = disable_irq_save(); 159 int oldlevel = disable_irq_save();
206 160
@@ -218,16 +172,73 @@ void button_power_set_state(bool pressed)
218 172
219#ifdef HAVE_HEADPHONE_DETECTION 173#ifdef HAVE_HEADPHONE_DETECTION
220/* This is called from the mc13783 interrupt thread */ 174/* This is called from the mc13783 interrupt thread */
221void set_headphones_inserted(bool inserted) 175void headphone_detect_event(void)
222{ 176{
223 headphones_detect = inserted; 177 /* FIXME: Not really the correct method */
178 headphones_detect =
179 (mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD2S) == 0;
224} 180}
225 181
226/* This is called from the mc13783 interrupt thread */
227/* TODO: Just do a post to the button queue directly - implement the
228 * appropriate variant in the driver. */
229bool headphones_inserted(void) 182bool headphones_inserted(void)
230{ 183{
231 return headphones_detect; 184 return headphones_detect;
232} 185}
233#endif /* HAVE_HEADPHONE_DETECTION */ 186#endif /* HAVE_HEADPHONE_DETECTION */
187
188void button_init_device(void)
189{
190#ifdef BOOTLOADER
191 /* Can be called more than once in the bootloader */
192 if (initialized)
193 return;
194
195 initialized = true;
196#endif
197
198 /* Enable keypad clock */
199 imx31_clkctl_module_clock_gating(CG_KPP, CGM_ON_ALL);
200
201 /* 1. Enable number of rows in keypad (KPCR[4:0])
202 *
203 * Configure the rows/cols in KPP
204 * LSB nybble in KPP is for 5 rows
205 * MSB nybble in KPP is for 3 cols */
206 KPP_KPCR |= 0x1f;
207
208 /* 2. Write 0's to KPDR[10:8] */
209 KPP_KPDR &= ~(0x7 << 8);
210
211 /* 3. Configure the keypad columns as open-drain (KPCR[10:8]). */
212 KPP_KPCR |= (0x7 << 8);
213
214 /* 4. Configure columns as output, rows as input (KDDR[10:8,4:0]) */
215 KPP_KDDR = (KPP_KDDR | (0x7 << 8)) & ~0x1f;
216
217 /* 5. Clear the KPKD Status Flag and Synchronizer chain.
218 * 6. Set the KDIE control bit bit. */
219 KPP_KPSR = KPP_KPSR_KDIE | KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD;
220
221 /* KPP IRQ at priority 3 */
222 avic_enable_int(KPP, IRQ, 3, KPP_HANDLER);
223
224 button_power_event();
225 mc13783_enable_event(MC13783_ONOFD1_EVENT);
226
227#ifdef HAVE_HEADPHONE_DETECTION
228 headphone_detect_event();
229 mc13783_enable_event(MC13783_ONOFD2_EVENT);
230#endif
231}
232
233#ifdef BUTTON_DRIVER_CLOSE
234void button_close_device(void)
235{
236 int oldlevel = disable_irq_save();
237
238 avic_disable_int(KPP);
239 KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE);
240 int_btn = BUTTON_NONE;
241
242 restore_irq(oldlevel);
243}
244#endif /* BUTTON_DRIVER_CLOSE */
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-target.h b/firmware/target/arm/imx31/gigabeat-s/button-target.h
index 61d33f8e70..28c14f358c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/button-target.h
@@ -32,8 +32,8 @@ bool button_hold(void);
32void button_init_device(void); 32void button_init_device(void);
33void button_close_device(void); 33void button_close_device(void);
34int button_read_device(void); 34int button_read_device(void);
35void button_power_set_state(bool pressed); 35void button_power_event(void);
36void set_headphones_inserted(bool inserted); 36void headphone_detect_event(void);
37bool headphones_inserted(void); 37bool headphones_inserted(void);
38 38
39/* Toshiba Gigabeat S-specific button codes */ 39/* Toshiba Gigabeat S-specific button codes */
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c
index cfbb7fcc4c..64d156407e 100644
--- a/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c
@@ -22,18 +22,23 @@
22#include "system.h" 22#include "system.h"
23#include "gpio-imx31.h" 23#include "gpio-imx31.h"
24 24
25extern int mc13783_event(void); 25/* Gigabeat S definitions for static GPIO event registration */
26 26
27static const struct gpio_event gpio1_events = 27/* Describes single events for each GPIO1 pin */
28static const struct gpio_event gpio1_events[] =
28{ 29{
29 .line = MC13783_GPIO_LINE, 30 [MC13783_EVENT_ID-GPIO1_EVENT_FIRST] =
30 .sense = GPIO_SENSE_RISING, 31 {
31 .callback = mc13783_event, 32 .mask = 1 << MC13783_GPIO_LINE,
33 .sense = GPIO_SENSE_RISING,
34 .callback = mc13783_event,
35 }
32}; 36};
33 37
38/* Describes the events attached to GPIO1 port */
34const struct gpio_event_list gpio1_event_list = 39const struct gpio_event_list gpio1_event_list =
35{ 40{
36 .priority = 7, 41 .ints_priority = 7,
37 .count = 1, 42 .count = ARRAYLEN(gpio1_events),
38 .events = &gpio1_events, 43 .events = gpio1_events,
39}; 44};
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c
index 0b76b84d36..2a83b5ca73 100644
--- a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c
@@ -73,29 +73,38 @@ static struct gpio_module_descriptor
73#endif 73#endif
74}; 74};
75 75
76static void gpio_call_events(enum gpio_module_number gpio) 76static void gpio_call_events(const struct gpio_module_descriptor * const desc)
77{ 77{
78 const struct gpio_module_descriptor * const desc = &gpio_descs[gpio];
79 const struct gpio_event_list * const list = desc->list; 78 const struct gpio_event_list * const list = desc->list;
80 struct gpio_map * const base = desc->base; 79 struct gpio_map * const base = desc->base;
81 unsigned i; 80 const struct gpio_event * event, *event_last;
82 81
83 /* Intersect pending and unmasked bits */ 82 /* Intersect pending and unmasked bits */
84 uint32_t pending = base->isr & base->imr; 83 uint32_t pnd = base->isr & base->imr;
84
85 event = list->events;
86 event_last = event + list->count;
85 87
86 /* Call each event handler in order */ 88 /* Call each event handler in order */
87 for (i = 0; i < list->count; i++) 89 /* .count is surely expected to be > 0 */
90 do
88 { 91 {
89 const struct gpio_event * const event = &list->events[i]; 92 uint32_t mask = event->mask;
90 uint32_t bit = 1ul << event->line; 93
94 if (pnd & mask)
95 {
96 event->callback();
97 pnd &= ~mask;
98 }
91 99
92 if ((pending & bit) && event->callback()) 100 if (pnd == 0)
93 pending &= ~bit; 101 break; /* Teminate early if nothing more to service */
94 } 102 }
103 while (++event < event_last);
95 104
96 if (pending != 0) 105 if (pnd != 0)
97 { 106 {
98 /* Wasn't handled */ 107 /* One or more weren't handled */
99 UIE_VECTOR(); 108 UIE_VECTOR();
100 } 109 }
101} 110}
@@ -103,21 +112,21 @@ static void gpio_call_events(enum gpio_module_number gpio)
103#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) 112#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
104static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void) 113static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void)
105{ 114{
106 gpio_call_events(GPIO1_NUM); 115 gpio_call_events(&gpio_descs[GPIO1_NUM]);
107} 116}
108#endif 117#endif
109 118
110#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) 119#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
111static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void) 120static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void)
112{ 121{
113 gpio_call_events(GPIO2_NUM); 122 gpio_call_events(&gpio_descs[GPIO2_NUM]);
114} 123}
115#endif 124#endif
116 125
117#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) 126#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
118static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void) 127static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void)
119{ 128{
120 gpio_call_events(GPIO3_NUM); 129 gpio_call_events(&gpio_descs[GPIO3_NUM]);
121} 130}
122#endif 131#endif
123 132
@@ -140,19 +149,16 @@ void gpio_init(void)
140#endif 149#endif
141} 150}
142 151
143bool gpio_enable_event(enum gpio_module_number gpio, unsigned id) 152bool gpio_enable_event(enum gpio_event_ids id)
144{ 153{
145 const struct gpio_module_descriptor * const desc = &gpio_descs[gpio]; 154 const struct gpio_module_descriptor * const desc = &gpio_descs[id >> 5];
146 const struct gpio_event * const event = &desc->list->events[id]; 155 const struct gpio_event * const event = &desc->list->events[id & 31];
147 struct gpio_map * const base = desc->base; 156 struct gpio_map * const base = desc->base;
148 volatile uint32_t *icr; 157 volatile uint32_t *icr;
149 uint32_t mask; 158 uint32_t mask, line;
150 uint32_t imr; 159 uint32_t imr;
151 int shift; 160 int shift;
152 161
153 if (id >= desc->list->count)
154 return false;
155
156 int oldlevel = disable_irq_save(); 162 int oldlevel = disable_irq_save();
157 163
158 imr = base->imr; 164 imr = base->imr;
@@ -160,39 +166,37 @@ bool gpio_enable_event(enum gpio_module_number gpio, unsigned id)
160 if (imr == 0) 166 if (imr == 0)
161 { 167 {
162 /* First enabled interrupt for this GPIO */ 168 /* First enabled interrupt for this GPIO */
163 avic_enable_int(desc->ints, IRQ, desc->list->priority, 169 avic_enable_int(desc->ints, IRQ, desc->list->ints_priority,
164 desc->handler); 170 desc->handler);
165 } 171 }
166 172
167 /* Set the line sense */ 173 /* Set the line sense */
168 icr = &base->icr[event->line >> 4]; 174 line = find_first_set_bit(event->mask);
169 shift = (event->line & 15) << 1; 175 icr = &base->icr[line >> 4];
176 shift = (line & 15) << 1;
170 mask = GPIO_SENSE_CONFIG_MASK << shift; 177 mask = GPIO_SENSE_CONFIG_MASK << shift;
171 178
172 *icr = (*icr & ~mask) | ((event->sense << shift) & mask); 179 *icr = (*icr & ~mask) | ((event->sense << shift) & mask);
173 180
174 /* Unmask the line */ 181 /* Unmask the line */
175 base->imr = imr | (1ul << event->line); 182 base->imr = imr | event->mask;
176 183
177 restore_irq(oldlevel); 184 restore_irq(oldlevel);
178 185
179 return true; 186 return true;
180} 187}
181 188
182void gpio_disable_event(enum gpio_module_number gpio, unsigned id) 189void gpio_disable_event(enum gpio_event_ids id)
183{ 190{
184 const struct gpio_module_descriptor * const desc = &gpio_descs[gpio]; 191 const struct gpio_module_descriptor * const desc = &gpio_descs[id >> 5];
185 const struct gpio_event * const event = &desc->list->events[id]; 192 const struct gpio_event * const event = &desc->list->events[id & 31];
186 struct gpio_map * const base = desc->base; 193 struct gpio_map * const base = desc->base;
187 uint32_t imr; 194 uint32_t imr;
188 195
189 if (id >= desc->list->count)
190 return;
191
192 int oldlevel = disable_irq_save(); 196 int oldlevel = disable_irq_save();
193 197
194 /* Remove bit from mask */ 198 /* Remove bit from mask */
195 imr = base->imr & ~(1ul << event->line); 199 imr = base->imr & ~event->mask;
196 200
197 /* Mask the line */ 201 /* Mask the line */
198 base->imr = imr; 202 base->imr = imr;
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h
index 34d3e72f8e..c3c3e1f63b 100644
--- a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h
+++ b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h
@@ -19,12 +19,12 @@
19#ifndef GPIO_IMX31_H 19#ifndef GPIO_IMX31_H
20#define GPIO_IMX31_H 20#define GPIO_IMX31_H
21 21
22#include "gpio-target.h" 22/* Static registration mechanism for imx31 GPIO interrupts */
23
24#define USE_GPIO1_EVENTS (1 << 0) 23#define USE_GPIO1_EVENTS (1 << 0)
25#define USE_GPIO2_EVENTS (1 << 1) 24#define USE_GPIO2_EVENTS (1 << 1)
26#define USE_GPIO3_EVENTS (1 << 2) 25#define USE_GPIO3_EVENTS (1 << 2)
27 26
27/* Module indexes defined by which GPIO modules are used */
28enum gpio_module_number 28enum gpio_module_number
29{ 29{
30 __GPIO_NUM_START = -1, 30 __GPIO_NUM_START = -1,
@@ -40,6 +40,22 @@ enum gpio_module_number
40 GPIO_NUM_GPIO, 40 GPIO_NUM_GPIO,
41}; 41};
42 42
43/* Module corresponding to the event ID is identified by range */
44enum gpio_event_bases
45{
46#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
47 GPIO1_EVENT_FIRST = 32*GPIO1_NUM,
48#endif
49#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
50 GPIO2_EVENT_FIRST = 32*GPIO2_NUM,
51#endif
52#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
53 GPIO3_EVENT_FIRST = 32*GPIO3_NUM,
54#endif
55};
56
57#include "gpio-target.h"
58
43/* Possible values for gpio interrupt line config */ 59/* Possible values for gpio interrupt line config */
44enum gpio_int_sense_enum 60enum gpio_int_sense_enum
45{ 61{
@@ -54,35 +70,43 @@ enum gpio_int_sense_enum
54/* Register map for each module */ 70/* Register map for each module */
55struct gpio_map 71struct gpio_map
56{ 72{
57 volatile uint32_t dr; /* 00h */ 73 volatile uint32_t dr; /* 00h */
58 volatile uint32_t gdir; /* 04h */ 74 volatile uint32_t gdir; /* 04h */
59 volatile uint32_t psr; /* 08h */ 75 volatile uint32_t psr; /* 08h */
60 volatile uint32_t icr[2]; /* 0Ch */ 76 union
61 volatile uint32_t imr; /* 14h */ 77 {
62 volatile uint32_t isr; /* 18h */ 78 struct
79 {
80 volatile uint32_t icr1; /* 0Ch */
81 volatile uint32_t icr2; /* 10h */
82 };
83 volatile uint32_t icr[2]; /* 0Ch */
84 };
85 volatile uint32_t imr; /* 14h */
86 volatile uint32_t isr; /* 18h */
63}; 87};
64 88
65/* Pending events will be called in array order */ 89/* Pending events will be called in array order which allows easy
90 * pioritization */
66 91
67/* Describes a single event for a pin */ 92/* Describes a single event for a pin */
68struct gpio_event 93struct gpio_event
69{ 94{
70 int line; /* Line number (0-31) */ 95 uint32_t mask; /* mask: 1 << (0...31) */
71 enum gpio_int_sense_enum sense; /* Type of sense */ 96 enum gpio_int_sense_enum sense; /* Type of sense */
72 int (*callback)(void); /* Callback function (return nonzero 97 void (*callback)(void); /* Callback function */
73 * to indicate this event was handled) */
74}; 98};
75 99
76/* Describes the events attached to a port */ 100/* Describes the events attached to a port */
77struct gpio_event_list 101struct gpio_event_list
78{ 102{
79 int priority; /* Interrupt priority for this GPIO */ 103 int ints_priority; /* Interrupt priority for this GPIO */
80 unsigned count; /* Count of events */ 104 unsigned count; /* Count of events for the module */
81 const struct gpio_event *events; /* List of events */ 105 const struct gpio_event *events; /* List of events */
82}; 106};
83 107
84void gpio_init(void); 108void gpio_init(void);
85bool gpio_enable_event(enum gpio_module_number gpio, unsigned id); 109bool gpio_enable_event(enum gpio_event_ids id);
86void gpio_disable_event(enum gpio_module_number gpio, unsigned id); 110void gpio_disable_event(enum gpio_event_ids id);
87 111
88#endif /* GPIO_IMX31_H */ 112#endif /* GPIO_IMX31_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-target.h b/firmware/target/arm/imx31/gigabeat-s/gpio-target.h
index 46e43af28d..797f9f4552 100644
--- a/firmware/target/arm/imx31/gigabeat-s/gpio-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/gpio-target.h
@@ -21,11 +21,22 @@
21#ifndef GPIO_TARGET_H 21#ifndef GPIO_TARGET_H
22#define GPIO_TARGET_H 22#define GPIO_TARGET_H
23 23
24#define GPIO_EVENT_MASK (USE_GPIO1_EVENTS) 24/* MC13783 GPIO pin info for this target */
25
26#define MC13783_GPIO_NUM GPIO1_NUM 25#define MC13783_GPIO_NUM GPIO1_NUM
27#define MC13783_GPIO_ISR GPIO1_ISR 26#define MC13783_GPIO_ISR GPIO1_ISR
28#define MC13783_GPIO_LINE 31 27#define MC13783_GPIO_LINE 31
29#define MC13783_EVENT_ID 0 28
29/* Declare event indexes in priority order in a packed array */
30enum gpio_event_ids
31{
32 /* GPIO1 event IDs */
33 MC13783_EVENT_ID = GPIO1_EVENT_FIRST,
34 /* GPIO2 event IDs */
35 /* none defined */
36 /* GPIO3 event IDs */
37 /* none defined */
38};
39
40void mc13783_event(void);
30 41
31#endif /* GPIO_TARGET_H */ 42#endif /* GPIO_TARGET_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c
new file mode 100644
index 0000000000..67cfc2d886
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c
@@ -0,0 +1,72 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2008 by Michael Sevakis
11 *
12 * Gigabeat S MC13783 event descriptions
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
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 "system.h"
23#include "mc13783.h"
24#include "mc13783-target.h"
25#include "adc-target.h"
26#include "button-target.h"
27#include "usb-target.h"
28#include "power-imx31.h"
29
30/* Gigabeat S definitions for static MC13783 event registration */
31
32static const struct mc13783_event mc13783_events[] =
33{
34 [MC13783_ADCDONE_EVENT] = /* ADC conversion complete */
35 {
36 .set = MC13783_EVENT_SET0,
37 .mask = MC13783_ADCDONEM,
38 .callback = adc_done,
39 },
40 [MC13783_ONOFD1_EVENT] = /* Power button */
41 {
42 .set = MC13783_EVENT_SET1,
43 .mask = MC13783_ONOFD1M,
44 .callback = button_power_event,
45 },
46#ifdef HAVE_HEADPHONE_DETECTION
47 [MC13783_ONOFD2_EVENT] = /* Headphone jack */
48 {
49 .set = MC13783_EVENT_SET1,
50 .mask = MC13783_ONOFD2M,
51 .callback = headphone_detect_event,
52 },
53#endif
54 [MC13783_CHGDET_EVENT] = /* Charger detection */
55 {
56 .set = MC13783_EVENT_SET0,
57 .mask = MC13783_CHGDETM,
58 .callback = charger_detect_event,
59 },
60 [MC13783_USB4V4_EVENT] = /* USB insertion */
61 {
62 .set = MC13783_EVENT_SET0,
63 .mask = MC13783_USB4V4M,
64 .callback = usb_connect_event,
65 },
66};
67
68const struct mc13783_event_list mc13783_event_list =
69{
70 .count = ARRAYLEN(mc13783_events),
71 .events = mc13783_events
72};
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
index 4f2bd9d931..097e81d7a3 100644
--- a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
@@ -49,121 +49,86 @@ static struct spi_node mc13783_spi =
49 0, /* SPI clock - no wait states */ 49 0, /* SPI clock - no wait states */
50}; 50};
51 51
52static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; 52extern const struct mc13783_event_list mc13783_event_list;
53
54static int mc13783_thread_stack[3*DEFAULT_STACK_SIZE/sizeof(int)];
53static const char *mc13783_thread_name = "pmic"; 55static const char *mc13783_thread_name = "pmic";
54static struct wakeup mc13783_wake; 56static struct wakeup mc13783_wake;
57
58/* Tracking for which interrupts are enabled */
59static uint32_t pmic_int_enabled[2] =
60 { 0x00000000, 0x00000000 };
61
62static const unsigned char pmic_intm_regs[2] =
63 { MC13783_INTERRUPT_MASK0, MC13783_INTERRUPT_MASK1 };
64
65static const unsigned char pmic_ints_regs[2] =
66 { MC13783_INTERRUPT_STATUS0, MC13783_INTERRUPT_STATUS1 };
67
55#ifdef PMIC_DRIVER_CLOSE 68#ifdef PMIC_DRIVER_CLOSE
56static bool pmic_close = false; 69static bool pmic_close = false;
57static struct thread_entry *mc13783_thread_p = NULL; 70static struct thread_entry *mc13783_thread_p = NULL;
58#endif 71#endif
59 72
60/* The next two functions are rather target-specific but they'll just be left
61 * here for the moment */
62static void mc13783_interrupt_thread(void) 73static void mc13783_interrupt_thread(void)
63{ 74{
64 const unsigned char status_regs[2] =
65 {
66 MC13783_INTERRUPT_STATUS0,
67 MC13783_INTERRUPT_STATUS1,
68 };
69 uint32_t pending[2]; 75 uint32_t pending[2];
70 uint32_t value;
71
72 mc13783_read_regset(status_regs, pending, 2);
73 mc13783_write_regset(status_regs, pending, 2);
74
75 gpio_enable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID);
76
77 if (pending[1] & MC13783_TODAI) /* only needs to be polled on startup */
78 mc13783_alarm_start();
79
80 /* Check initial states for events with a sense bit */
81 value = mc13783_read(MC13783_INTERRUPT_SENSE0);
82 usb_set_status(value & MC13783_USB4V4S);
83 set_charger_inserted(value & MC13783_CHGDETS);
84
85 value = mc13783_read(MC13783_INTERRUPT_SENSE1);
86 button_power_set_state((value & MC13783_ONOFD1S) == 0);
87#ifdef HAVE_HEADPHONE_DETECTION
88 set_headphones_inserted((value & MC13783_ONOFD2S) == 0);
89#endif
90 76
91 pending[0] = pending[1] = 0xffffff; 77 /* Enable mc13783 GPIO event */
92 mc13783_write_regset(status_regs, pending, 2); 78 gpio_enable_event(MC13783_EVENT_ID);
93 79
94 /* Enable desired PMIC interrupts - some are unmasked in the drivers that
95 * handle a specific task */
96 mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_CHGDETM);
97 mc13783_clear(MC13783_INTERRUPT_MASK1, MC13783_ONOFD1M |
98 MC13783_ONOFD2M);
99
100 while (1) 80 while (1)
101 { 81 {
82 const struct mc13783_event *event, *event_last;
83
102 wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK); 84 wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK);
103 85
104#ifdef PMIC_DRIVER_CLOSE 86#ifdef PMIC_DRIVER_CLOSE
105 if (pmic_close) 87 if (pmic_close)
106 { 88 break;
107 gpio_disable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID);
108 return;
109 }
110#endif 89#endif
111 90
112 mc13783_read_regset(status_regs, pending, 2); 91 mc13783_read_regset(pmic_ints_regs, pending, 2);
113 mc13783_write_regset(status_regs, pending, 2);
114
115 if (pending[0])
116 {
117 /* Handle ...PENDING0 */
118
119 /* Handle interrupts without a sense bit */
120 if (pending[0] & MC13783_ADCDONEI)
121 adc_done();
122 92
123 /* Handle interrupts that have a sense bit that needs to 93 /* Only clear interrupts being dispatched */
124 * be checked */ 94 pending[0] &= pmic_int_enabled[0];
125 if (pending[0] & (MC13783_CHGDETI | MC13783_USB4V4I)) 95 pending[1] &= pmic_int_enabled[1];
126 {
127 value = mc13783_read(MC13783_INTERRUPT_SENSE0);
128 96
129 if (pending[0] & MC13783_CHGDETI) 97 mc13783_write_regset(pmic_ints_regs, pending, 2);
130 set_charger_inserted(value & MC13783_CHGDETS);
131 98
132 if (pending[0] & MC13783_USB4V4I) 99 event = mc13783_event_list.events;
133 usb_set_status(value & MC13783_USB4V4S); 100 event_last = event + mc13783_event_list.count;
134 }
135 }
136 101
137 if (pending[1]) 102 /* .count is surely expected to be > 0 */
103 do
138 { 104 {
139 /* Handle ...PENDING1 */ 105 enum mc13783_event_sets set = event->set;
140 106 uint32_t pnd = pending[set];
141 /* Handle interrupts without a sense bit */ 107 uint32_t mask = event->mask;
142 /* ... */
143 108
144 /* Handle interrupts that have a sense bit that needs to 109 if (pnd & mask)
145 * be checked */
146 if (pending[1] & (MC13783_ONOFD1I | MC13783_ONOFD2I))
147 { 110 {
148 value = mc13783_read(MC13783_INTERRUPT_SENSE1); 111 event->callback();
149 112 pnd &= ~mask;
150 if (pending[1] & MC13783_ONOFD1I) 113 pending[set] = pnd;
151 button_power_set_state((value & MC13783_ONOFD1S) == 0);
152#ifdef HAVE_HEADPHONE_DETECTION
153 if (pending[1] & MC13783_ONOFD2I)
154 set_headphones_inserted((value & MC13783_ONOFD2S) == 0);
155#endif
156 } 114 }
115
116 if ((pending[0] | pending[1]) == 0)
117 break; /* Teminate early if nothing more to service */
157 } 118 }
119 while (++event < event_last);
158 } 120 }
121
122#ifdef PMIC_DRIVER_CLOSE
123 gpio_disable_event(MC13783_EVENT_ID);
124#endif
159} 125}
160 126
161/* GPIO interrupt handler for mc13783 */ 127/* GPIO interrupt handler for mc13783 */
162int mc13783_event(void) 128void mc13783_event(void)
163{ 129{
164 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); 130 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE);
165 wakeup_signal(&mc13783_wake); 131 wakeup_signal(&mc13783_wake);
166 return 1; /* Yes, it's handled */
167} 132}
168 133
169void mc13783_init(void) 134void mc13783_init(void)
@@ -174,8 +139,8 @@ void mc13783_init(void)
174 /* Enable the PMIC SPI module */ 139 /* Enable the PMIC SPI module */
175 spi_enable_module(&mc13783_spi); 140 spi_enable_module(&mc13783_spi);
176 141
177 /* Mask any PMIC interrupts for now - poll initial status in thread 142 /* Mask any PMIC interrupts for now - modules will enable them as
178 * and enable them there */ 143 * required */
179 mc13783_write(MC13783_INTERRUPT_MASK0, 0xffffff); 144 mc13783_write(MC13783_INTERRUPT_MASK0, 0xffffff);
180 mc13783_write(MC13783_INTERRUPT_MASK1, 0xffffff); 145 mc13783_write(MC13783_INTERRUPT_MASK1, 0xffffff);
181 146
@@ -203,7 +168,39 @@ void mc13783_close(void)
203 wakeup_signal(&mc13783_wake); 168 wakeup_signal(&mc13783_wake);
204 thread_wait(thread); 169 thread_wait(thread);
205} 170}
206#endif 171#endif /* PMIC_DRIVER_CLOSE */
172
173bool mc13783_enable_event(enum mc13783_event_ids id)
174{
175 const struct mc13783_event * const event =
176 &mc13783_event_list.events[id];
177 int set = event->set;
178 uint32_t mask = event->mask;
179
180 spi_lock(&mc13783_spi);
181
182 pmic_int_enabled[set] |= mask;
183 mc13783_clear(pmic_intm_regs[set], mask);
184
185 spi_unlock(&mc13783_spi);
186
187 return true;
188}
189
190void mc13783_disable_event(enum mc13783_event_ids id)
191{
192 const struct mc13783_event * const event =
193 &mc13783_event_list.events[id];
194 int set = event->set;
195 uint32_t mask = event->mask;
196
197 spi_lock(&mc13783_spi);
198
199 pmic_int_enabled[set] &= ~mask;
200 mc13783_set(pmic_intm_regs[set], mask);
201
202 spi_unlock(&mc13783_spi);
203}
207 204
208uint32_t mc13783_set(unsigned address, uint32_t bits) 205uint32_t mc13783_set(unsigned address, uint32_t bits)
209{ 206{
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h b/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h
new file mode 100644
index 0000000000..a74a229f04
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h
@@ -0,0 +1,36 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2008 by Michael Sevakis
11 *
12 * Gigabeat S mc13783 event descriptions
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef MC13783_TARGET_H
22#define MC13783_TARGET_H
23
24/* Declare event indexes in priority order in a packed array */
25enum mc13783_event_ids
26{
27 MC13783_ADCDONE_EVENT = 0, /* ADC conversion complete */
28 MC13783_ONOFD1_EVENT, /* Power button */
29#ifdef HAVE_HEADPHONE_DETECTION
30 MC13783_ONOFD2_EVENT, /* Headphone jack */
31#endif
32 MC13783_CHGDET_EVENT, /* Charger detection */
33 MC13783_USB4V4_EVENT, /* USB insertion */
34};
35
36#endif /* MC13783_TARGET_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
index 53cdb7c315..8db59bdf0e 100644
--- a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
@@ -28,14 +28,11 @@
28 28
29static bool charger_detect = false; 29static bool charger_detect = false;
30 30
31void power_init(void)
32{
33}
34
35/* This is called from the mc13783 interrupt thread */ 31/* This is called from the mc13783 interrupt thread */
36void set_charger_inserted(bool inserted) 32void charger_detect_event(void)
37{ 33{
38 charger_detect = inserted; 34 charger_detect =
35 mc13783_read(MC13783_INTERRUPT_SENSE0) & MC13783_CHGDETS;
39} 36}
40 37
41bool charger_inserted(void) 38bool charger_inserted(void)
@@ -81,6 +78,15 @@ void power_off(void)
81 while (1); 78 while (1);
82} 79}
83 80
81void power_init(void)
82{
83 /* Poll initial state */
84 charger_detect_event();
85
86 /* Enable detect event */
87 mc13783_enable_event(MC13783_CHGDET_EVENT);
88}
89
84#else /* SIMULATOR */ 90#else /* SIMULATOR */
85 91
86bool charger_inserted(void) 92bool charger_inserted(void)
diff --git a/firmware/target/arm/imx31/gigabeat-s/power-imx31.h b/firmware/target/arm/imx31/gigabeat-s/power-imx31.h
index bb0a7614d8..b949d41d35 100644
--- a/firmware/target/arm/imx31/gigabeat-s/power-imx31.h
+++ b/firmware/target/arm/imx31/gigabeat-s/power-imx31.h
@@ -19,6 +19,6 @@
19#ifndef POWER_IMX31_H 19#ifndef POWER_IMX31_H
20#define POWER_IMX31_H 20#define POWER_IMX31_H
21 21
22void set_charger_inserted(bool inserted); 22void charger_detect_event(void);
23 23
24#endif /* POWER_IMX31_H */ 24#endif /* POWER_IMX31_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c b/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c
index f12fd8f0b1..ad6c77138c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c
@@ -48,9 +48,10 @@ static void enable_transceiver(bool enable)
48 } 48 }
49} 49}
50 50
51void usb_set_status(bool plugged) 51void usb_connect_event(void)
52{ 52{
53 usb_status = plugged ? USB_INSERTED : USB_EXTRACTED; 53 uint32_t status = mc13783_read(MC13783_INTERRUPT_SENSE0);
54 usb_status = (status & MC13783_USB4V4S) ? USB_INSERTED : USB_EXTRACTED;
54} 55}
55 56
56int usb_detect(void) 57int usb_detect(void)
@@ -73,7 +74,11 @@ void usb_init_device(void)
73 /* Module will be turned off later after firmware init */ 74 /* Module will be turned off later after firmware init */
74 usb_drv_startup(); 75 usb_drv_startup();
75 76
76 mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_USB4V4M); 77 /* Initially poll */
78 usb_connect_event();
79
80 /* Enable PMIC event */
81 mc13783_enable_event(MC13783_USB4V4_EVENT);
77} 82}
78 83
79void usb_enable(bool on) 84void usb_enable(bool on)
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-target.h b/firmware/target/arm/imx31/gigabeat-s/usb-target.h
index c6e2850b9d..0af740ac7c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/usb-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/usb-target.h
@@ -23,7 +23,7 @@
23#define USB_DRIVER_CLOSE 23#define USB_DRIVER_CLOSE
24#endif 24#endif
25 25
26void usb_set_status(bool plugged); 26void usb_connect_event(void);
27bool usb_init_device(void); 27bool usb_init_device(void);
28int usb_detect(void); 28int usb_detect(void);
29/* Read the immediate state of the cable from the PMIC */ 29/* Read the immediate state of the cable from the PMIC */