summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
diff options
context:
space:
mode:
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;