diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-04-12 16:56:45 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-04-12 16:56:45 +0000 |
commit | a7af9e4a7f25f5a32306c74e95a677e6c85f399e (patch) | |
tree | 5df60e8382b69cf943840852269ea9387d42ea46 /firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c | |
parent | ddfd787c54d78104dac4ed144ff6cb6df8617a0e (diff) | |
download | rockbox-a7af9e4a7f25f5a32306c74e95a677e6c85f399e.tar.gz rockbox-a7af9e4a7f25f5a32306c74e95a677e6c85f399e.zip |
Add GPIO manager. Get the PMIC interrupt handling working (along with power button and HP detect). Add some reg field defined instead of using raw numbers. Add PMIC info to debug ports screen. Refine PMIC driver ops a little bit.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17086 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 | 151 |
1 files changed, 141 insertions, 10 deletions
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; |