diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/imx31/debug-imx31.c | 48 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/avic-imx31.c | 2 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c | 4 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/button-imx31.c | 38 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/button-target.h | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c | 39 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c | 207 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h | 77 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/gpio-target.h | 31 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c | 151 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/power-imx31.c | 10 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/system-imx31.c | 2 |
12 files changed, 593 insertions, 19 deletions
diff --git a/firmware/target/arm/imx31/debug-imx31.c b/firmware/target/arm/imx31/debug-imx31.c index ab8db78063..7f1c9166d6 100644 --- a/firmware/target/arm/imx31/debug-imx31.c +++ b/firmware/target/arm/imx31/debug-imx31.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "sprintf.h" | 24 | #include "sprintf.h" |
25 | #include "font.h" | 25 | #include "font.h" |
26 | #include "debug-target.h" | 26 | #include "debug-target.h" |
27 | #include "mc13783.h" | ||
27 | 28 | ||
28 | bool __dbg_hw_info(void) | 29 | bool __dbg_hw_info(void) |
29 | { | 30 | { |
@@ -34,6 +35,43 @@ bool __dbg_ports(void) | |||
34 | { | 35 | { |
35 | char buf[50]; | 36 | char buf[50]; |
36 | int line; | 37 | int line; |
38 | int i; | ||
39 | |||
40 | static const char pmic_regset[] = | ||
41 | { | ||
42 | MC13783_INTERRUPT_STATUS0, | ||
43 | MC13783_INTERRUPT_SENSE0, | ||
44 | MC13783_INTERRUPT_STATUS1, | ||
45 | MC13783_INTERRUPT_SENSE1, | ||
46 | MC13783_RTC_TIME, | ||
47 | MC13783_RTC_ALARM, | ||
48 | MC13783_RTC_DAY, | ||
49 | MC13783_RTC_DAY_ALARM, | ||
50 | MC13783_ADC0, | ||
51 | MC13783_ADC1, | ||
52 | MC13783_ADC2, | ||
53 | MC13783_ADC3, | ||
54 | MC13783_ADC4, | ||
55 | }; | ||
56 | |||
57 | static const char *pmic_regnames[ARRAYLEN(pmic_regset)] = | ||
58 | { | ||
59 | "Int Stat0 ", | ||
60 | "Int Sense0", | ||
61 | "Int Stat1 ", | ||
62 | "Int Sense1", | ||
63 | "RTC Time ", | ||
64 | "RTC Alarm ", | ||
65 | "RTC Day ", | ||
66 | "RTC Day Al", | ||
67 | "ADC0 ", | ||
68 | "ADC1 ", | ||
69 | "ADC2 ", | ||
70 | "ADC3 ", | ||
71 | "ADC4 ", | ||
72 | }; | ||
73 | |||
74 | uint32_t pmic_regs[ARRAYLEN(pmic_regset)]; | ||
37 | 75 | ||
38 | lcd_setmargins(0, 0); | 76 | lcd_setmargins(0, 0); |
39 | lcd_clear_display(); | 77 | lcd_clear_display(); |
@@ -84,6 +122,16 @@ bool __dbg_ports(void) | |||
84 | snprintf(buf, sizeof(buf), " ISR: %08lx", GPIO3_ISR); | 122 | snprintf(buf, sizeof(buf), " ISR: %08lx", GPIO3_ISR); |
85 | lcd_puts(0, line++, buf); line++; | 123 | lcd_puts(0, line++, buf); line++; |
86 | 124 | ||
125 | lcd_puts(0, line++, "PMIC Registers"); line++; | ||
126 | |||
127 | mc13783_read_regset(pmic_regset, pmic_regs, ARRAYLEN(pmic_regs)); | ||
128 | |||
129 | for (i = 0; i < (int)ARRAYLEN(pmic_regs); i++) | ||
130 | { | ||
131 | snprintf(buf, sizeof(buf), "%s: %08lx", pmic_regnames[i], pmic_regs[i]); | ||
132 | lcd_puts(0, line++, buf); | ||
133 | } | ||
134 | |||
87 | lcd_update(); | 135 | lcd_update(); |
88 | if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL)) | 136 | if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL)) |
89 | return false; | 137 | return false; |
diff --git a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c index 194bc11ed6..6b64bfad77 100644 --- a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c | |||
@@ -43,7 +43,7 @@ static const char * avic_int_names[64] = | |||
43 | "EXT_SENS1", "EXT_SENS2", "EXT_WDOG", "EXT_TV" | 43 | "EXT_SENS1", "EXT_SENS2", "EXT_WDOG", "EXT_TV" |
44 | }; | 44 | }; |
45 | 45 | ||
46 | static void UIE_VECTOR(void) | 46 | void UIE_VECTOR(void) |
47 | { | 47 | { |
48 | int mode; | 48 | int mode; |
49 | long offset; | 49 | long offset; |
diff --git a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c b/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c index 051b1c8479..1a41f0c53e 100644 --- a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c | |||
@@ -34,13 +34,13 @@ bool _backlight_init(void) | |||
34 | void _backlight_on(void) | 34 | void _backlight_on(void) |
35 | { | 35 | { |
36 | /* LEDEN=1 */ | 36 | /* LEDEN=1 */ |
37 | mc13783_set(MC13783_LED_CONTROL0, (1 << 0)); | 37 | mc13783_set(MC13783_LED_CONTROL0, MC13783_LEDEN); |
38 | } | 38 | } |
39 | 39 | ||
40 | void _backlight_off(void) | 40 | void _backlight_off(void) |
41 | { | 41 | { |
42 | /* LEDEN=0 */ | 42 | /* LEDEN=0 */ |
43 | mc13783_clear(MC13783_LED_CONTROL0, (1 << 0)); | 43 | mc13783_clear(MC13783_LED_CONTROL0, MC13783_LEDEN); |
44 | } | 44 | } |
45 | 45 | ||
46 | /* Assumes that the backlight has been initialized */ | 46 | /* Assumes that the backlight has been initialized */ |
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c index 602f41abb9..c85fe5e37e 100644 --- a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c | |||
@@ -29,7 +29,8 @@ | |||
29 | /* Most code in here is taken from the Linux BSP provided by Freescale | 29 | /* Most code in here is taken from the Linux BSP provided by Freescale |
30 | * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */ | 30 | * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */ |
31 | 31 | ||
32 | static uint32_t int_btn = BUTTON_NONE; | 32 | static bool headphones_detect = false; |
33 | static uint32_t int_btn = BUTTON_NONE; | ||
33 | static bool hold_button = false; | 34 | static bool hold_button = false; |
34 | static bool hold_button_old = false; | 35 | static bool hold_button_old = false; |
35 | #define _button_hold() (GPIO3_DR & 0x10) | 36 | #define _button_hold() (GPIO3_DR & 0x10) |
@@ -48,7 +49,8 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void) | |||
48 | unsigned short reg_val; | 49 | unsigned short reg_val; |
49 | int col, row; | 50 | int col, row; |
50 | int i; | 51 | int i; |
51 | int button = BUTTON_NONE; | 52 | /* Power button is handled separately on PMIC */ |
53 | int button = int_btn & BUTTON_POWER; | ||
52 | 54 | ||
53 | /* 1. Disable both (depress and release) keypad interrupts. */ | 55 | /* 1. Disable both (depress and release) keypad interrupts. */ |
54 | KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE); | 56 | KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE); |
@@ -161,3 +163,35 @@ int button_read_device(void) | |||
161 | /* If hold, ignore any pressed button */ | 163 | /* If hold, ignore any pressed button */ |
162 | return hold_button ? BUTTON_NONE : int_btn; | 164 | return hold_button ? BUTTON_NONE : int_btn; |
163 | } | 165 | } |
166 | |||
167 | /* This is called from the mc13783 interrupt thread */ | ||
168 | void button_power_set_state(bool pressed) | ||
169 | { | ||
170 | /* Prevent KPP_HANDLER from changing things */ | ||
171 | int oldlevel = disable_irq_save(); | ||
172 | |||
173 | if (pressed) | ||
174 | { | ||
175 | int_btn |= BUTTON_POWER; | ||
176 | } | ||
177 | else | ||
178 | { | ||
179 | int_btn &= ~BUTTON_POWER; | ||
180 | } | ||
181 | |||
182 | restore_irq(oldlevel); | ||
183 | } | ||
184 | |||
185 | /* This is called from the mc13783 interrupt thread */ | ||
186 | void set_headphones_inserted(bool inserted) | ||
187 | { | ||
188 | headphones_detect = inserted; | ||
189 | } | ||
190 | |||
191 | /* This is called from the mc13783 interrupt thread */ | ||
192 | /* TODO: Just do a post to the button queue directly - implement the | ||
193 | * appropriate variant in the driver. */ | ||
194 | bool headphones_inserted(void) | ||
195 | { | ||
196 | return headphones_detect; | ||
197 | } | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-target.h b/firmware/target/arm/imx31/gigabeat-s/button-target.h index 33f018e0bf..836a4c02cd 100644 --- a/firmware/target/arm/imx31/gigabeat-s/button-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/button-target.h | |||
@@ -27,6 +27,9 @@ | |||
27 | bool button_hold(void); | 27 | bool button_hold(void); |
28 | void button_init_device(void); | 28 | void button_init_device(void); |
29 | int button_read_device(void); | 29 | int button_read_device(void); |
30 | void button_power_set_state(bool pressed); | ||
31 | void set_headphones_inserted(bool inserted); | ||
32 | bool headphones_inserted(void); | ||
30 | 33 | ||
31 | /* Toshiba Gigabeat specific button codes */ | 34 | /* Toshiba Gigabeat specific button codes */ |
32 | 35 | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c new file mode 100644 index 0000000000..cfbb7fcc4c --- /dev/null +++ b/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c | |||
@@ -0,0 +1,39 @@ | |||
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 GPIO interrupt 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 "gpio-imx31.h" | ||
24 | |||
25 | extern int mc13783_event(void); | ||
26 | |||
27 | static const struct gpio_event gpio1_events = | ||
28 | { | ||
29 | .line = MC13783_GPIO_LINE, | ||
30 | .sense = GPIO_SENSE_RISING, | ||
31 | .callback = mc13783_event, | ||
32 | }; | ||
33 | |||
34 | const struct gpio_event_list gpio1_event_list = | ||
35 | { | ||
36 | .priority = 7, | ||
37 | .count = 1, | ||
38 | .events = &gpio1_events, | ||
39 | }; | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c new file mode 100644 index 0000000000..a7427f16c0 --- /dev/null +++ b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (c) 2008 by Michael Sevakis | ||
11 | * | ||
12 | * IMX31 GPIO event manager | ||
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 "avic-imx31.h" | ||
24 | #include "gpio-imx31.h" | ||
25 | |||
26 | /* UIE vector found in avic-imx31.c */ | ||
27 | extern void UIE_VECTOR(void); | ||
28 | |||
29 | /* Event lists are allocated for the specific target */ | ||
30 | #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) | ||
31 | static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void); | ||
32 | extern const struct gpio_event_list gpio1_event_list; | ||
33 | #endif | ||
34 | |||
35 | #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) | ||
36 | static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void); | ||
37 | extern const struct gpio_event_list gpio2_event_list; | ||
38 | #endif | ||
39 | |||
40 | #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) | ||
41 | static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void); | ||
42 | extern const struct gpio_event_list gpio3_event_list; | ||
43 | #endif | ||
44 | |||
45 | static struct gpio_module_descriptor | ||
46 | { | ||
47 | volatile unsigned long *base; /* Module base address */ | ||
48 | enum IMX31_INT_LIST ints; /* AVIC int number */ | ||
49 | void (*handler)(void); /* Interrupt function */ | ||
50 | const struct gpio_event_list *list; /* Event handler list */ | ||
51 | } gpio_descs[GPIO_NUM_GPIO] = | ||
52 | { | ||
53 | #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) | ||
54 | { | ||
55 | .base = (unsigned long *)GPIO1_BASE_ADDR, | ||
56 | .ints = GPIO1, | ||
57 | .handler = GPIO1_HANDLER, | ||
58 | }, | ||
59 | #endif | ||
60 | #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) | ||
61 | { | ||
62 | .base = (unsigned long *)GPIO2_BASE_ADDR, | ||
63 | .ints = GPIO2, | ||
64 | .handler = GPIO2_HANDLER, | ||
65 | }, | ||
66 | #endif | ||
67 | #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) | ||
68 | { | ||
69 | .base = (unsigned long *)GPIO3_BASE_ADDR, | ||
70 | .ints = GPIO3, | ||
71 | .handler = GPIO3_HANDLER, | ||
72 | }, | ||
73 | #endif | ||
74 | }; | ||
75 | |||
76 | static void gpio_call_events(enum gpio_module_number gpio) | ||
77 | { | ||
78 | const struct gpio_module_descriptor * const desc = &gpio_descs[gpio]; | ||
79 | const struct gpio_event_list * const list = desc->list; | ||
80 | volatile unsigned long * const base = desc->base; | ||
81 | unsigned i; | ||
82 | |||
83 | /* Intersect pending and unmasked bits */ | ||
84 | unsigned long pending = base[GPIO_ISR_I] & base[GPIO_IMR_I]; | ||
85 | |||
86 | /* Call each event handler in order */ | ||
87 | for (i = 0; i < list->count; i++) | ||
88 | { | ||
89 | const struct gpio_event * const event = &list->events[i]; | ||
90 | unsigned long bit = 1ul << event->line; | ||
91 | |||
92 | if ((pending & bit) && event->callback()) | ||
93 | pending &= ~bit; | ||
94 | } | ||
95 | |||
96 | if (pending != 0) | ||
97 | { | ||
98 | /* Wasn't handled */ | ||
99 | UIE_VECTOR(); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) | ||
104 | static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void) | ||
105 | { | ||
106 | gpio_call_events(GPIO1_NUM); | ||
107 | } | ||
108 | #endif | ||
109 | |||
110 | #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) | ||
111 | static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void) | ||
112 | { | ||
113 | gpio_call_events(GPIO2_NUM); | ||
114 | } | ||
115 | #endif | ||
116 | |||
117 | #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) | ||
118 | static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void) | ||
119 | { | ||
120 | gpio_call_events(GPIO3_NUM); | ||
121 | } | ||
122 | #endif | ||
123 | |||
124 | void gpio_init(void) | ||
125 | { | ||
126 | /* Mask-out GPIO interrupts - enable what's wanted later */ | ||
127 | GPIO1_IMR = 0; | ||
128 | GPIO2_IMR = 0; | ||
129 | GPIO3_IMR = 0; | ||
130 | |||
131 | /* Init the externally-defined event lists for each port */ | ||
132 | #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) | ||
133 | gpio_descs[GPIO1_NUM].list = &gpio1_event_list; | ||
134 | #endif | ||
135 | #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) | ||
136 | gpio_descs[GPIO2_NUM].list = &gpio2_event_list; | ||
137 | #endif | ||
138 | #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) | ||
139 | gpio_descs[GPIO3_NUM].list = &gpio3_event_list; | ||
140 | #endif | ||
141 | } | ||
142 | |||
143 | bool gpio_enable_event(enum gpio_module_number gpio, unsigned id) | ||
144 | { | ||
145 | const struct gpio_module_descriptor * const desc = &gpio_descs[gpio]; | ||
146 | const struct gpio_event * const event = &desc->list->events[id]; | ||
147 | volatile unsigned long * const base = desc->base; | ||
148 | volatile unsigned long * icr; | ||
149 | unsigned long mask; | ||
150 | unsigned long imr; | ||
151 | int shift; | ||
152 | |||
153 | if (id >= desc->list->count) | ||
154 | return false; | ||
155 | |||
156 | int oldlevel = disable_irq_save(); | ||
157 | |||
158 | imr = base[GPIO_IMR_I]; | ||
159 | |||
160 | if (imr == 0) | ||
161 | { | ||
162 | /* First enabled interrupt for this GPIO */ | ||
163 | avic_enable_int(desc->ints, IRQ, desc->list->priority, | ||
164 | desc->handler); | ||
165 | } | ||
166 | |||
167 | /* Set the line sense */ | ||
168 | icr = &base[GPIO_ICR1_I] + event->line / 16; | ||
169 | shift = 2*(event->line % 16); | ||
170 | mask = GPIO_SENSE_CONFIG_MASK << shift; | ||
171 | |||
172 | *icr = (*icr & ~mask) | ((event->sense << shift) & mask); | ||
173 | |||
174 | /* Unmask the line */ | ||
175 | base[GPIO_IMR_I] = imr | (1ul << event->line); | ||
176 | |||
177 | restore_irq(oldlevel); | ||
178 | |||
179 | return true; | ||
180 | } | ||
181 | |||
182 | void gpio_disable_event(enum gpio_module_number gpio, unsigned id) | ||
183 | { | ||
184 | const struct gpio_module_descriptor * const desc = &gpio_descs[gpio]; | ||
185 | const struct gpio_event * const event = &desc->list->events[id]; | ||
186 | volatile unsigned long * const base = desc->base; | ||
187 | unsigned long imr; | ||
188 | |||
189 | if (id >= desc->list->count) | ||
190 | return; | ||
191 | |||
192 | int oldlevel = disable_irq_save(); | ||
193 | |||
194 | /* Remove bit from mask */ | ||
195 | imr = base[GPIO_IMR_I] & ~(1ul << event->line); | ||
196 | |||
197 | /* Mask the line */ | ||
198 | base[GPIO_IMR_I] = imr; | ||
199 | |||
200 | if (imr == 0) | ||
201 | { | ||
202 | /* No events remain enabled */ | ||
203 | avic_disable_int(desc->ints); | ||
204 | } | ||
205 | |||
206 | restore_irq(oldlevel); | ||
207 | } | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h new file mode 100644 index 0000000000..a197558ad4 --- /dev/null +++ b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h | |||
@@ -0,0 +1,77 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (c) 2008 by Michael Sevakis | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef _GPIO_IMX31_H_ | ||
20 | #define _GPIO_IMX31_H_ | ||
21 | |||
22 | #include "gpio-target.h" | ||
23 | |||
24 | #define USE_GPIO1_EVENTS (1 << 0) | ||
25 | #define USE_GPIO2_EVENTS (1 << 1) | ||
26 | #define USE_GPIO3_EVENTS (1 << 2) | ||
27 | |||
28 | enum gpio_module_number | ||
29 | { | ||
30 | __GPIO_NUM_START = -1, | ||
31 | #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) | ||
32 | GPIO1_NUM, | ||
33 | #endif | ||
34 | #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) | ||
35 | GPIO2_NUM, | ||
36 | #endif | ||
37 | #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) | ||
38 | GPIO3_NUM, | ||
39 | #endif | ||
40 | GPIO_NUM_GPIO, | ||
41 | }; | ||
42 | |||
43 | /* Possible values for gpio interrupt line config */ | ||
44 | enum gpio_int_sense_enum | ||
45 | { | ||
46 | GPIO_SENSE_LOW_LEVEL = 0, /* High-level sensitive */ | ||
47 | GPIO_SENSE_HIGH_LEVEL, /* Low-level sensitive */ | ||
48 | GPIO_SENSE_RISING, /* Rising-edge sensitive */ | ||
49 | GPIO_SENSE_FALLING, /* Falling-edge sensitive */ | ||
50 | }; | ||
51 | |||
52 | #define GPIO_SENSE_CONFIG_MASK 0x3 | ||
53 | |||
54 | /* Pending events will be called in array order */ | ||
55 | |||
56 | /* Describes a single event for a pin */ | ||
57 | struct gpio_event | ||
58 | { | ||
59 | int line; /* Line number (0-31) */ | ||
60 | enum gpio_int_sense_enum sense; /* Type of sense */ | ||
61 | int (*callback)(void); /* Callback function (return nonzero | ||
62 | * to indicate this event was handled) */ | ||
63 | }; | ||
64 | |||
65 | /* Describes the events attached to a port */ | ||
66 | struct gpio_event_list | ||
67 | { | ||
68 | int priority; /* Interrupt priority for this GPIO */ | ||
69 | unsigned count; /* Count of events */ | ||
70 | const struct gpio_event *events; /* List of events */ | ||
71 | }; | ||
72 | |||
73 | void gpio_init(void); | ||
74 | bool gpio_enable_event(enum gpio_module_number gpio, unsigned id); | ||
75 | void gpio_disable_event(enum gpio_module_number gpio, unsigned id); | ||
76 | |||
77 | #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 new file mode 100644 index 0000000000..46e43af28d --- /dev/null +++ b/firmware/target/arm/imx31/gigabeat-s/gpio-target.h | |||
@@ -0,0 +1,31 @@ | |||
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 GPIO interrupt event descriptions header | ||
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 GPIO_TARGET_H | ||
22 | #define GPIO_TARGET_H | ||
23 | |||
24 | #define GPIO_EVENT_MASK (USE_GPIO1_EVENTS) | ||
25 | |||
26 | #define MC13783_GPIO_NUM GPIO1_NUM | ||
27 | #define MC13783_GPIO_ISR GPIO1_ISR | ||
28 | #define MC13783_GPIO_LINE 31 | ||
29 | #define MC13783_EVENT_ID 0 | ||
30 | |||
31 | #endif /* GPIO_TARGET_H */ | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c index 3af8f35f69..a04cd7f893 100644 --- a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c | |||
@@ -19,10 +19,13 @@ | |||
19 | #include "system.h" | 19 | #include "system.h" |
20 | #include "cpu.h" | 20 | #include "cpu.h" |
21 | #include "spi-imx31.h" | 21 | #include "spi-imx31.h" |
22 | #include "gpio-imx31.h" | ||
22 | #include "mc13783.h" | 23 | #include "mc13783.h" |
23 | #include "debug.h" | 24 | #include "debug.h" |
24 | #include "kernel.h" | 25 | #include "kernel.h" |
25 | 26 | ||
27 | #include "button-target.h" | ||
28 | |||
26 | /* This is all based on communicating with the MC13783 PMU which is on | 29 | /* This is all based on communicating with the MC13783 PMU which is on |
27 | * CSPI2 with the chip select at 0. The LCD controller resides on | 30 | * CSPI2 with the chip select at 0. The LCD controller resides on |
28 | * CSPI3 cs1, but we have no idea how to communicate to it */ | 31 | * CSPI3 cs1, but we have no idea how to communicate to it */ |
@@ -43,17 +46,68 @@ static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; | |||
43 | static const char *mc13783_thread_name = "pmic"; | 46 | static const char *mc13783_thread_name = "pmic"; |
44 | static struct wakeup mc13783_wake; | 47 | static struct wakeup mc13783_wake; |
45 | 48 | ||
49 | /* The next two functions are rather target-specific but they'll just be left | ||
50 | * here for the moment */ | ||
46 | static __attribute__((noreturn)) void mc13783_interrupt_thread(void) | 51 | static __attribute__((noreturn)) void mc13783_interrupt_thread(void) |
47 | { | 52 | { |
53 | const unsigned char status_regs[2] = | ||
54 | { | ||
55 | MC13783_INTERRUPT_STATUS0, | ||
56 | MC13783_INTERRUPT_STATUS1, | ||
57 | }; | ||
58 | uint32_t pending[2]; | ||
59 | uint32_t value; | ||
60 | |||
61 | mc13783_read_regset(status_regs, pending, 2); | ||
62 | mc13783_write_regset(status_regs, pending, 2); | ||
63 | |||
64 | gpio_enable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID); | ||
65 | |||
66 | /* Check initial states */ | ||
67 | value = mc13783_read(MC13783_INTERRUPT_SENSE1); | ||
68 | button_power_set_state((value & MC13783_ON1B) == 0); | ||
69 | set_headphones_inserted((value & MC13783_ON2B) == 0); | ||
70 | |||
71 | /* Enable desired PMIC interrupts */ | ||
72 | mc13783_clear(MC13783_INTERRUPT_MASK1, MC13783_ON1B | MC13783_ON2B); | ||
73 | |||
48 | while (1) | 74 | while (1) |
49 | { | 75 | { |
50 | wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK); | 76 | wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK); |
77 | |||
78 | mc13783_read_regset(status_regs, pending, 2); | ||
79 | mc13783_write_regset(status_regs, pending, 2); | ||
80 | |||
81 | #if 0 | ||
82 | if (pending[0]) | ||
83 | { | ||
84 | /* Handle ...PENDING0 */ | ||
85 | } | ||
86 | #endif | ||
87 | |||
88 | if (pending[1]) | ||
89 | { | ||
90 | /* Handle ...PENDING1 */ | ||
91 | if (pending[1] & (MC13783_ON1B | MC13783_ON2B)) | ||
92 | { | ||
93 | value = mc13783_read(MC13783_INTERRUPT_SENSE1); | ||
94 | |||
95 | if (pending[1] & MC13783_ON1B) | ||
96 | button_power_set_state((value & MC13783_ON1B) == 0); | ||
97 | |||
98 | if (pending[1] & MC13783_ON2B) | ||
99 | set_headphones_inserted((value & MC13783_ON2B) == 0); | ||
100 | } | ||
101 | } | ||
51 | } | 102 | } |
52 | } | 103 | } |
53 | 104 | ||
54 | static __attribute__((interrupt("IRQ"))) void mc13783_interrupt(void) | 105 | /* GPIO interrupt handler for mc13783 */ |
106 | int mc13783_event(void) | ||
55 | { | 107 | { |
108 | MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); | ||
56 | wakeup_signal(&mc13783_wake); | 109 | wakeup_signal(&mc13783_wake); |
110 | return 1; /* Yes, it's handled */ | ||
57 | } | 111 | } |
58 | 112 | ||
59 | void mc13783_init(void) | 113 | void mc13783_init(void) |
@@ -64,25 +118,44 @@ void mc13783_init(void) | |||
64 | /* Enable the PMIC SPI module */ | 118 | /* Enable the PMIC SPI module */ |
65 | spi_enable_module(&mc13783_spi); | 119 | spi_enable_module(&mc13783_spi); |
66 | 120 | ||
121 | /* Mask any PMIC interrupts for now - poll initial status in thread | ||
122 | * and enable them there */ | ||
123 | mc13783_write(MC13783_INTERRUPT_MASK0, 0xffffff); | ||
124 | mc13783_write(MC13783_INTERRUPT_MASK1, 0xffffff); | ||
125 | |||
126 | MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); | ||
127 | |||
67 | create_thread(mc13783_interrupt_thread, mc13783_thread_stack, | 128 | create_thread(mc13783_interrupt_thread, mc13783_thread_stack, |
68 | sizeof(mc13783_thread_stack), 0, mc13783_thread_name | 129 | sizeof(mc13783_thread_stack), 0, mc13783_thread_name |
69 | IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); | 130 | IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); |
70 | } | 131 | } |
71 | 132 | ||
72 | void mc13783_set(unsigned address, uint32_t bits) | 133 | uint32_t mc13783_set(unsigned address, uint32_t bits) |
73 | { | 134 | { |
74 | spi_lock(&mc13783_spi); | 135 | spi_lock(&mc13783_spi); |
136 | |||
75 | uint32_t data = mc13783_read(address); | 137 | uint32_t data = mc13783_read(address); |
76 | mc13783_write(address, data | bits); | 138 | |
139 | if (data != (uint32_t)-1) | ||
140 | mc13783_write(address, data | bits); | ||
141 | |||
77 | spi_unlock(&mc13783_spi); | 142 | spi_unlock(&mc13783_spi); |
143 | |||
144 | return data; | ||
78 | } | 145 | } |
79 | 146 | ||
80 | void mc13783_clear(unsigned address, uint32_t bits) | 147 | uint32_t mc13783_clear(unsigned address, uint32_t bits) |
81 | { | 148 | { |
82 | spi_lock(&mc13783_spi); | 149 | spi_lock(&mc13783_spi); |
150 | |||
83 | uint32_t data = mc13783_read(address); | 151 | uint32_t data = mc13783_read(address); |
84 | mc13783_write(address, data & ~bits); | 152 | |
153 | if (data != (uint32_t)-1) | ||
154 | mc13783_write(address, data & ~bits); | ||
155 | |||
85 | spi_unlock(&mc13783_spi); | 156 | spi_unlock(&mc13783_spi); |
157 | |||
158 | return data; | ||
86 | } | 159 | } |
87 | 160 | ||
88 | int mc13783_write(unsigned address, uint32_t data) | 161 | int mc13783_write(unsigned address, uint32_t data) |
@@ -108,7 +181,7 @@ int mc13783_write_multiple(unsigned start, const uint32_t *data, int count) | |||
108 | { | 181 | { |
109 | int i; | 182 | int i; |
110 | struct spi_transfer xfer; | 183 | struct spi_transfer xfer; |
111 | uint32_t packets[64]; | 184 | uint32_t packets[MC13783_NUM_REGS]; |
112 | 185 | ||
113 | if (start + count > MC13783_NUM_REGS) | 186 | if (start + count > MC13783_NUM_REGS) |
114 | return -1; | 187 | return -1; |
@@ -129,6 +202,36 @@ int mc13783_write_multiple(unsigned start, const uint32_t *data, int count) | |||
129 | return count - xfer.count; | 202 | return count - xfer.count; |
130 | } | 203 | } |
131 | 204 | ||
205 | int mc13783_write_regset(const unsigned char *regs, const uint32_t *data, | ||
206 | int count) | ||
207 | { | ||
208 | int i; | ||
209 | struct spi_transfer xfer; | ||
210 | uint32_t packets[MC13783_NUM_REGS]; | ||
211 | |||
212 | if (count > MC13783_NUM_REGS) | ||
213 | return -1; | ||
214 | |||
215 | for (i = 0; i < count; i++) | ||
216 | { | ||
217 | uint32_t reg = regs[i]; | ||
218 | |||
219 | if (reg >= MC13783_NUM_REGS) | ||
220 | return -1; | ||
221 | |||
222 | packets[i] = (1 << 31) | (reg << 25) | (data[i] & 0xffffff); | ||
223 | } | ||
224 | |||
225 | xfer.txbuf = packets; | ||
226 | xfer.rxbuf = packets; | ||
227 | xfer.count = count; | ||
228 | |||
229 | if (!spi_transfer(&mc13783_spi, &xfer)) | ||
230 | return -1; | ||
231 | |||
232 | return count - xfer.count; | ||
233 | } | ||
234 | |||
132 | uint32_t mc13783_read(unsigned address) | 235 | uint32_t mc13783_read(unsigned address) |
133 | { | 236 | { |
134 | uint32_t packet; | 237 | uint32_t packet; |
@@ -146,25 +249,53 @@ uint32_t mc13783_read(unsigned address) | |||
146 | if (!spi_transfer(&mc13783_spi, &xfer)) | 249 | if (!spi_transfer(&mc13783_spi, &xfer)) |
147 | return (uint32_t)-1; | 250 | return (uint32_t)-1; |
148 | 251 | ||
149 | return packet & 0xffffff; | 252 | return packet; |
150 | } | 253 | } |
151 | 254 | ||
152 | int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count) | 255 | int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count) |
153 | { | 256 | { |
154 | int i; | 257 | int i; |
155 | uint32_t packets[64]; | ||
156 | struct spi_transfer xfer; | 258 | struct spi_transfer xfer; |
157 | 259 | ||
158 | if (start + count > MC13783_NUM_REGS) | 260 | if (start + count > MC13783_NUM_REGS) |
159 | return -1; | 261 | return -1; |
160 | 262 | ||
161 | xfer.txbuf = packets; | 263 | xfer.txbuf = buffer; |
162 | xfer.rxbuf = buffer; | 264 | xfer.rxbuf = buffer; |
163 | xfer.count = count; | 265 | xfer.count = count; |
164 | 266 | ||
165 | /* Prepare TX payload */ | 267 | /* Prepare TX payload */ |
166 | for (i = 0; i < count; i++, start++) | 268 | for (i = 0; i < count; i++, start++) |
167 | packets[i] = start << 25; | 269 | buffer[i] = start << 25; |
270 | |||
271 | if (!spi_transfer(&mc13783_spi, &xfer)) | ||
272 | return -1; | ||
273 | |||
274 | return count - xfer.count; | ||
275 | } | ||
276 | |||
277 | int mc13783_read_regset(const unsigned char *regs, uint32_t *buffer, | ||
278 | int count) | ||
279 | { | ||
280 | int i; | ||
281 | struct spi_transfer xfer; | ||
282 | |||
283 | if (count > MC13783_NUM_REGS) | ||
284 | return -1; | ||
285 | |||
286 | for (i = 0; i < count; i++) | ||
287 | { | ||
288 | unsigned reg = regs[i]; | ||
289 | |||
290 | if (reg >= MC13783_NUM_REGS) | ||
291 | return -1; | ||
292 | |||
293 | buffer[i] = reg << 25; | ||
294 | } | ||
295 | |||
296 | xfer.txbuf = buffer; | ||
297 | xfer.rxbuf = buffer; | ||
298 | xfer.count = count; | ||
168 | 299 | ||
169 | if (!spi_transfer(&mc13783_spi, &xfer)) | 300 | if (!spi_transfer(&mc13783_spi, &xfer)) |
170 | return -1; | 301 | return -1; |
diff --git a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c index c739a19cba..f57c55a70b 100644 --- a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c | |||
@@ -17,14 +17,12 @@ | |||
17 | * | 17 | * |
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include "config.h" | 19 | #include "config.h" |
20 | #include "cpu.h" | ||
21 | #include <stdbool.h> | ||
22 | #include "kernel.h" | ||
23 | #include "system.h" | 20 | #include "system.h" |
24 | #include "power.h" | 21 | #include "power.h" |
25 | #include "pcf50606.h" | ||
26 | #include "backlight.h" | 22 | #include "backlight.h" |
27 | #include "backlight-target.h" | 23 | #include "backlight-target.h" |
24 | #include "avic-imx31.h" | ||
25 | #include "mc13783.h" | ||
28 | 26 | ||
29 | #ifndef SIMULATOR | 27 | #ifndef SIMULATOR |
30 | 28 | ||
@@ -54,6 +52,10 @@ bool ide_powered(void) | |||
54 | 52 | ||
55 | void power_off(void) | 53 | void power_off(void) |
56 | { | 54 | { |
55 | mc13783_set(MC13783_POWER_CONTROL0, MC13783_USEROFFSPI); | ||
56 | |||
57 | disable_interrupt(IRQ_FIQ_STATUS); | ||
58 | while (1); | ||
57 | } | 59 | } |
58 | 60 | ||
59 | #else /* SIMULATOR */ | 61 | #else /* SIMULATOR */ |
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c index bd7999558b..da5026a292 100644 --- a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include "system.h" | 2 | #include "system.h" |
3 | #include "panic.h" | 3 | #include "panic.h" |
4 | #include "avic-imx31.h" | 4 | #include "avic-imx31.h" |
5 | #include "gpio-imx31.h" | ||
5 | #include "mmu-imx31.h" | 6 | #include "mmu-imx31.h" |
6 | #include "system-target.h" | 7 | #include "system-target.h" |
7 | #include "lcd.h" | 8 | #include "lcd.h" |
@@ -23,6 +24,7 @@ void system_init(void) | |||
23 | /* MCR WFI enables wait mode */ | 24 | /* MCR WFI enables wait mode */ |
24 | CLKCTL_CCMR &= ~(3 << 14); | 25 | CLKCTL_CCMR &= ~(3 << 14); |
25 | avic_init(); | 26 | avic_init(); |
27 | gpio_init(); | ||
26 | } | 28 | } |
27 | 29 | ||
28 | #ifdef BOOTLOADER | 30 | #ifdef BOOTLOADER |