summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-04-12 16:56:45 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-04-12 16:56:45 +0000
commita7af9e4a7f25f5a32306c74e95a677e6c85f399e (patch)
tree5df60e8382b69cf943840852269ea9387d42ea46 /firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
parentddfd787c54d78104dac4ed144ff6cb6df8617a0e (diff)
downloadrockbox-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.c151
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)];
43static const char *mc13783_thread_name = "pmic"; 46static const char *mc13783_thread_name = "pmic";
44static struct wakeup mc13783_wake; 47static 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 */
46static __attribute__((noreturn)) void mc13783_interrupt_thread(void) 51static __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
54static __attribute__((interrupt("IRQ"))) void mc13783_interrupt(void) 105/* GPIO interrupt handler for mc13783 */
106int 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
59void mc13783_init(void) 113void 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
72void mc13783_set(unsigned address, uint32_t bits) 133uint32_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
80void mc13783_clear(unsigned address, uint32_t bits) 147uint32_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
88int mc13783_write(unsigned address, uint32_t data) 161int 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
205int 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
132uint32_t mc13783_read(unsigned address) 235uint32_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
152int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count) 255int 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
277int 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;