diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-05-21 08:42:11 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-05-21 08:42:11 +0000 |
commit | a9c20f5789c13b486d217024a020f9d6163e2d51 (patch) | |
tree | 5da52ca9cc7a28ba21ced042cb739e6160d5f87b /firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c | |
parent | 5f796087b009fee1ae60904b0355cc7febe3330f (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c | 161 |
1 files changed, 79 insertions, 82 deletions
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 | ||
52 | static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; | 52 | extern const struct mc13783_event_list mc13783_event_list; |
53 | |||
54 | static int mc13783_thread_stack[3*DEFAULT_STACK_SIZE/sizeof(int)]; | ||
53 | static const char *mc13783_thread_name = "pmic"; | 55 | static const char *mc13783_thread_name = "pmic"; |
54 | static struct wakeup mc13783_wake; | 56 | static struct wakeup mc13783_wake; |
57 | |||
58 | /* Tracking for which interrupts are enabled */ | ||
59 | static uint32_t pmic_int_enabled[2] = | ||
60 | { 0x00000000, 0x00000000 }; | ||
61 | |||
62 | static const unsigned char pmic_intm_regs[2] = | ||
63 | { MC13783_INTERRUPT_MASK0, MC13783_INTERRUPT_MASK1 }; | ||
64 | |||
65 | static 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 |
56 | static bool pmic_close = false; | 69 | static bool pmic_close = false; |
57 | static struct thread_entry *mc13783_thread_p = NULL; | 70 | static 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 */ | ||
62 | static void mc13783_interrupt_thread(void) | 73 | static 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 */ |
162 | int mc13783_event(void) | 128 | void 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 | ||
169 | void mc13783_init(void) | 134 | void 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 | |||
173 | bool 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 | |||
190 | void 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 | ||
208 | uint32_t mc13783_set(unsigned address, uint32_t bits) | 205 | uint32_t mc13783_set(unsigned address, uint32_t bits) |
209 | { | 206 | { |