summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/mc13783-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/mc13783-imx31.c')
-rw-r--r--firmware/target/arm/imx31/mc13783-imx31.c241
1 files changed, 173 insertions, 68 deletions
diff --git a/firmware/target/arm/imx31/mc13783-imx31.c b/firmware/target/arm/imx31/mc13783-imx31.c
index a083614488..5146122327 100644
--- a/firmware/target/arm/imx31/mc13783-imx31.c
+++ b/firmware/target/arm/imx31/mc13783-imx31.c
@@ -20,7 +20,6 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "system.h" 21#include "system.h"
22#include "cpu.h" 22#include "cpu.h"
23#include "spi-imx31.h"
24#include "gpio-imx31.h" 23#include "gpio-imx31.h"
25#include "mc13783.h" 24#include "mc13783.h"
26#include "debug.h" 25#include "debug.h"
@@ -29,9 +28,14 @@
29extern const struct mc13783_event_list mc13783_event_list; 28extern const struct mc13783_event_list mc13783_event_list;
30extern struct spi_node mc13783_spi; 29extern struct spi_node mc13783_spi;
31 30
31/* PMIC event service data */
32static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; 32static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)];
33static const char *mc13783_thread_name = "pmic"; 33static const char *mc13783_thread_name = "pmic";
34static struct wakeup mc13783_wake; 34static struct wakeup mc13783_svc_wake;
35
36/* Synchronous thread communication objects */
37static struct mutex mc13783_spi_mutex;
38static struct wakeup mc13783_spi_wake;
35 39
36/* Tracking for which interrupts are enabled */ 40/* Tracking for which interrupts are enabled */
37static uint32_t pmic_int_enabled[2] = 41static uint32_t pmic_int_enabled[2] =
@@ -45,6 +49,34 @@ static const unsigned char pmic_ints_regs[2] =
45 49
46static volatile unsigned int mc13783_thread_id = 0; 50static volatile unsigned int mc13783_thread_id = 0;
47 51
52static void mc13783_xfer_complete_cb(struct spi_transfer_desc *trans);
53
54/* Transfer descriptor for synchronous reads and writes */
55static struct spi_transfer_desc mc13783_transfer =
56{
57 .node = &mc13783_spi,
58 .txbuf = NULL,
59 .rxbuf = NULL,
60 .count = 0,
61 .callback = mc13783_xfer_complete_cb,
62 .next = NULL,
63};
64
65/* Called when a transfer is finished and data is ready/written */
66static void mc13783_xfer_complete_cb(struct spi_transfer_desc *xfer)
67{
68 if (xfer->count != 0)
69 return;
70
71 wakeup_signal(&mc13783_spi_wake);
72}
73
74static inline bool wait_for_transfer_complete(void)
75{
76 return wakeup_wait(&mc13783_spi_wake, HZ*2) == OBJ_WAIT_SUCCEEDED &&
77 mc13783_transfer.count == 0;
78}
79
48static void mc13783_interrupt_thread(void) 80static void mc13783_interrupt_thread(void)
49{ 81{
50 uint32_t pending[2]; 82 uint32_t pending[2];
@@ -56,18 +88,18 @@ static void mc13783_interrupt_thread(void)
56 { 88 {
57 const struct mc13783_event *event, *event_last; 89 const struct mc13783_event *event, *event_last;
58 90
59 wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK); 91 wakeup_wait(&mc13783_svc_wake, TIMEOUT_BLOCK);
60 92
61 if (mc13783_thread_id == 0) 93 if (mc13783_thread_id == 0)
62 break; 94 break;
63 95
64 mc13783_read_regset(pmic_ints_regs, pending, 2); 96 mc13783_read_regs(pmic_ints_regs, pending, 2);
65 97
66 /* Only clear interrupts being dispatched */ 98 /* Only clear interrupts being dispatched */
67 pending[0] &= pmic_int_enabled[0]; 99 pending[0] &= pmic_int_enabled[0];
68 pending[1] &= pmic_int_enabled[1]; 100 pending[1] &= pmic_int_enabled[1];
69 101
70 mc13783_write_regset(pmic_ints_regs, pending, 2); 102 mc13783_write_regs(pmic_ints_regs, pending, 2);
71 103
72 /* Whatever is going to be serviced in this loop has been 104 /* Whatever is going to be serviced in this loop has been
73 * acknowledged. Reenable interrupt and if anything was still 105 * acknowledged. Reenable interrupt and if anything was still
@@ -93,7 +125,7 @@ static void mc13783_interrupt_thread(void)
93 } 125 }
94 126
95 if ((pending[0] | pending[1]) == 0) 127 if ((pending[0] | pending[1]) == 0)
96 break; /* Teminate early if nothing more to service */ 128 break; /* Terminate early if nothing more to service */
97 } 129 }
98 while (++event < event_last); 130 while (++event < event_last);
99 } 131 }
@@ -107,13 +139,16 @@ void mc13783_event(void)
107 /* Mask the interrupt (unmasked when PMIC thread services it). */ 139 /* Mask the interrupt (unmasked when PMIC thread services it). */
108 imx31_regclr32(&MC13783_GPIO_IMR, 1ul << MC13783_GPIO_LINE); 140 imx31_regclr32(&MC13783_GPIO_IMR, 1ul << MC13783_GPIO_LINE);
109 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); 141 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE);
110 wakeup_signal(&mc13783_wake); 142 wakeup_signal(&mc13783_svc_wake);
111} 143}
112 144
113void mc13783_init(void) 145void mc13783_init(void)
114{ 146{
115 /* Serial interface must have been initialized first! */ 147 /* Serial interface must have been initialized first! */
116 wakeup_init(&mc13783_wake); 148 wakeup_init(&mc13783_svc_wake);
149 mutex_init(&mc13783_spi_mutex);
150
151 wakeup_init(&mc13783_spi_wake);
117 152
118 /* Enable the PMIC SPI module */ 153 /* Enable the PMIC SPI module */
119 spi_enable_module(&mc13783_spi); 154 spi_enable_module(&mc13783_spi);
@@ -139,8 +174,9 @@ void mc13783_close(void)
139 return; 174 return;
140 175
141 mc13783_thread_id = 0; 176 mc13783_thread_id = 0;
142 wakeup_signal(&mc13783_wake); 177 wakeup_signal(&mc13783_svc_wake);
143 thread_wait(thread_id); 178 thread_wait(thread_id);
179 spi_disable_module(&mc13783_spi);
144} 180}
145 181
146bool mc13783_enable_event(enum mc13783_event_ids id) 182bool mc13783_enable_event(enum mc13783_event_ids id)
@@ -150,12 +186,12 @@ bool mc13783_enable_event(enum mc13783_event_ids id)
150 int set = event->set; 186 int set = event->set;
151 uint32_t mask = event->mask; 187 uint32_t mask = event->mask;
152 188
153 spi_lock(&mc13783_spi); 189 mutex_lock(&mc13783_spi_mutex);
154 190
155 pmic_int_enabled[set] |= mask; 191 pmic_int_enabled[set] |= mask;
156 mc13783_clear(pmic_intm_regs[set], mask); 192 mc13783_clear(pmic_intm_regs[set], mask);
157 193
158 spi_unlock(&mc13783_spi); 194 mutex_unlock(&mc13783_spi_mutex);
159 195
160 return true; 196 return true;
161} 197}
@@ -167,66 +203,77 @@ void mc13783_disable_event(enum mc13783_event_ids id)
167 int set = event->set; 203 int set = event->set;
168 uint32_t mask = event->mask; 204 uint32_t mask = event->mask;
169 205
170 spi_lock(&mc13783_spi); 206 mutex_lock(&mc13783_spi_mutex);
171 207
172 pmic_int_enabled[set] &= ~mask; 208 pmic_int_enabled[set] &= ~mask;
173 mc13783_set(pmic_intm_regs[set], mask); 209 mc13783_set(pmic_intm_regs[set], mask);
174 210
175 spi_unlock(&mc13783_spi); 211 mutex_unlock(&mc13783_spi_mutex);
176} 212}
177 213
178uint32_t mc13783_set(unsigned address, uint32_t bits) 214uint32_t mc13783_set(unsigned address, uint32_t bits)
179{ 215{
180 spi_lock(&mc13783_spi); 216 uint32_t data;
217
218 mutex_lock(&mc13783_spi_mutex);
181 219
182 uint32_t data = mc13783_read(address); 220 data = mc13783_read(address);
183 221
184 if (data != MC13783_DATA_ERROR) 222 if (data != MC13783_DATA_ERROR)
185 mc13783_write(address, data | bits); 223 mc13783_write(address, data | bits);
186 224
187 spi_unlock(&mc13783_spi); 225 mutex_unlock(&mc13783_spi_mutex);
188 226
189 return data; 227 return data;
190} 228}
191 229
192uint32_t mc13783_clear(unsigned address, uint32_t bits) 230uint32_t mc13783_clear(unsigned address, uint32_t bits)
193{ 231{
194 spi_lock(&mc13783_spi); 232 uint32_t data;
195 233
196 uint32_t data = mc13783_read(address); 234 mutex_lock(&mc13783_spi_mutex);
235
236 data = mc13783_read(address);
197 237
198 if (data != MC13783_DATA_ERROR) 238 if (data != MC13783_DATA_ERROR)
199 mc13783_write(address, data & ~bits); 239 mc13783_write(address, data & ~bits);
200 240
201 spi_unlock(&mc13783_spi); 241 mutex_unlock(&mc13783_spi_mutex);
202 242
203 return data; 243 return data;
204} 244}
205 245
206int mc13783_write(unsigned address, uint32_t data) 246int mc13783_write(unsigned address, uint32_t data)
207{ 247{
208 struct spi_transfer xfer;
209 uint32_t packet; 248 uint32_t packet;
249 int i;
210 250
211 if (address >= MC13783_NUM_REGS) 251 if (address >= MC13783_NUM_REGS)
212 return -1; 252 return -1;
213 253
214 packet = (1 << 31) | (address << 25) | (data & 0xffffff); 254 packet = (1 << 31) | (address << 25) | (data & 0xffffff);
215 xfer.txbuf = &packet;
216 xfer.rxbuf = &packet;
217 xfer.count = 1;
218 255
219 if (!spi_transfer(&mc13783_spi, &xfer)) 256 mutex_lock(&mc13783_spi_mutex);
220 return -1; 257
258 mc13783_transfer.txbuf = &packet;
259 mc13783_transfer.rxbuf = NULL;
260 mc13783_transfer.count = 1;
261
262 i = -1;
263
264 if (spi_transfer(&mc13783_transfer) && wait_for_transfer_complete())
265 i = 1 - mc13783_transfer.count;
266
267 mutex_unlock(&mc13783_spi_mutex);
221 268
222 return 1 - xfer.count; 269 return i;
223} 270}
224 271
225uint32_t mc13783_write_masked(unsigned address, uint32_t data, uint32_t mask) 272uint32_t mc13783_write_masked(unsigned address, uint32_t data, uint32_t mask)
226{ 273{
227 uint32_t old; 274 uint32_t old;
228 275
229 spi_lock(&mc13783_spi); 276 mutex_lock(&mc13783_spi_mutex);
230 277
231 old = mc13783_read(address); 278 old = mc13783_read(address);
232 279
@@ -238,86 +285,144 @@ uint32_t mc13783_write_masked(unsigned address, uint32_t data, uint32_t mask)
238 old = MC13783_DATA_ERROR; 285 old = MC13783_DATA_ERROR;
239 } 286 }
240 287
241 spi_unlock(&mc13783_spi); 288 mutex_unlock(&mc13783_spi_mutex);
242 289
243 return old; 290 return old;
244} 291}
245 292
246int mc13783_write_regset(const unsigned char *regs, const uint32_t *data, 293uint32_t mc13783_read(unsigned address)
247 int count)
248{ 294{
249 int i; 295 uint32_t packet;
250 struct spi_transfer xfer;
251 uint32_t packets[MC13783_NUM_REGS];
252 296
253 if ((unsigned)count > MC13783_NUM_REGS) 297 if (address >= MC13783_NUM_REGS)
254 return -1; 298 return MC13783_DATA_ERROR;
299
300 packet = address << 25;
301
302 mutex_lock(&mc13783_spi_mutex);
303
304 mc13783_transfer.txbuf = &packet;
305 mc13783_transfer.rxbuf = &packet;
306 mc13783_transfer.count = 1;
307
308 if (!spi_transfer(&mc13783_transfer) || !wait_for_transfer_complete())
309 packet = MC13783_DATA_ERROR;
310
311 mutex_unlock(&mc13783_spi_mutex);
312
313 return packet;
314}
315
316int mc13783_read_regs(const unsigned char *regs, uint32_t *buffer,
317 int count)
318{
319 int i;
255 320
256 for (i = 0; i < count; i++) 321 for (i = 0; i < count; i++)
257 { 322 {
258 uint32_t reg = regs[i]; 323 unsigned reg = regs[i];
259 324
260 if (reg >= MC13783_NUM_REGS) 325 if (reg >= MC13783_NUM_REGS)
261 return -1; 326 return -1;
262 327
263 packets[i] = (1 << 31) | (reg << 25) | (data[i] & 0xffffff); 328 buffer[i] = reg << 25;
264 } 329 }
265 330
266 xfer.txbuf = packets; 331 mutex_lock(&mc13783_spi_mutex);
267 xfer.rxbuf = packets;
268 xfer.count = count;
269 332
270 if (!spi_transfer(&mc13783_spi, &xfer)) 333 mc13783_transfer.txbuf = buffer;
271 return -1; 334 mc13783_transfer.rxbuf = buffer;
335 mc13783_transfer.count = count;
336
337 i = -1;
338
339 if (spi_transfer(&mc13783_transfer) && wait_for_transfer_complete())
340 i = count - mc13783_transfer.count;
272 341
273 return count - xfer.count; 342 mutex_unlock(&mc13783_spi_mutex);
343
344 return i;
274} 345}
275 346
276uint32_t mc13783_read(unsigned address) 347int mc13783_write_regs(const unsigned char *regs, uint32_t *buffer,
348 int count)
277{ 349{
278 uint32_t packet; 350 int i;
279 struct spi_transfer xfer;
280 351
281 if (address >= MC13783_NUM_REGS) 352 for (i = 0; i < count; i++)
282 return MC13783_DATA_ERROR; 353 {
354 unsigned reg = regs[i];
283 355
284 packet = address << 25; 356 if (reg >= MC13783_NUM_REGS)
357 return -1;
285 358
286 xfer.txbuf = &packet; 359 buffer[i] = (1 << 31) | (reg << 25) | (buffer[i] & 0xffffff);
287 xfer.rxbuf = &packet; 360 }
288 xfer.count = 1;
289 361
290 if (!spi_transfer(&mc13783_spi, &xfer)) 362 mutex_lock(&mc13783_spi_mutex);
291 return MC13783_DATA_ERROR;
292 363
293 return packet; 364 mc13783_transfer.txbuf = buffer;
365 mc13783_transfer.rxbuf = NULL;
366 mc13783_transfer.count = count;
367
368 i = -1;
369
370 if (spi_transfer(&mc13783_transfer) && wait_for_transfer_complete())
371 i = count - mc13783_transfer.count;
372
373 mutex_unlock(&mc13783_spi_mutex);
374
375 return i;
294} 376}
295 377
296int mc13783_read_regset(const unsigned char *regs, uint32_t *buffer, 378#if 0 /* Not needed right now */
297 int count) 379bool mc13783_read_async(struct spi_transfer_desc *xfer,
380 const unsigned char *regs, uint32_t *buffer,
381 int count, spi_transfer_cb_fn_type callback)
298{ 382{
299 int i; 383 int i;
300 struct spi_transfer xfer;
301
302 if ((unsigned)count > MC13783_NUM_REGS)
303 return -1;
304 384
305 for (i = 0; i < count; i++) 385 for (i = 0; i < count; i++)
306 { 386 {
307 unsigned reg = regs[i]; 387 unsigned reg = regs[i];
308 388
309 if (reg >= MC13783_NUM_REGS) 389 if (reg >= MC13783_NUM_REGS)
310 return -1; 390 return false;
311 391
312 buffer[i] = reg << 25; 392 buffer[i] = reg << 25;
313 } 393 }
314 394
315 xfer.txbuf = buffer; 395 xfer->node = &mc13783_spi;
316 xfer.rxbuf = buffer; 396 xfer->txbuf = buffer;
317 xfer.count = count; 397 xfer->rxbuf = buffer;
398 xfer->count = count;
399 xfer->callback = callback;
318 400
319 if (!spi_transfer(&mc13783_spi, &xfer)) 401 return spi_transfer(xfer);
320 return -1; 402}
403#endif
404
405bool mc13783_write_async(struct spi_transfer_desc *xfer,
406 const unsigned char *regs, uint32_t *buffer,
407 int count, spi_transfer_cb_fn_type callback)
408{
409 int i;
410
411 for (i = 0; i < count; i++)
412 {
413 unsigned reg = regs[i];
414
415 if (reg >= MC13783_NUM_REGS)
416 return false;
417
418 buffer[i] = (1 << 31) | (reg << 25) | (buffer[i] & 0xffffff);
419 }
420
421 xfer->node = &mc13783_spi;
422 xfer->txbuf = buffer;
423 xfer->rxbuf = NULL;
424 xfer->count = count;
425 xfer->callback = callback;
321 426
322 return count - xfer.count; 427 return spi_transfer(xfer);
323} 428}