summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/as3525/ascodec-as3525.c70
1 files changed, 16 insertions, 54 deletions
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c
index adc9b7f9a8..708215deed 100644
--- a/firmware/target/arm/as3525/ascodec-as3525.c
+++ b/firmware/target/arm/as3525/ascodec-as3525.c
@@ -96,7 +96,6 @@ static unsigned char *req_data_ptr = NULL;
96static struct ascodec_request *req_head = NULL; 96static struct ascodec_request *req_head = NULL;
97static struct ascodec_request *req_tail = NULL; 97static struct ascodec_request *req_tail = NULL;
98 98
99#if CONFIG_CPU == AS3525
100static struct wakeup adc_wkup; 99static struct wakeup adc_wkup;
101static struct ascodec_request as_audio_req; 100static struct ascodec_request as_audio_req;
102 101
@@ -112,13 +111,11 @@ static int int_adc = 0;
112#endif /* DEBUG */ 111#endif /* DEBUG */
113 112
114static void ascodec_read_cb(unsigned const char *data, unsigned int len); 113static void ascodec_read_cb(unsigned const char *data, unsigned int len);
115#endif /* CONFIG_CPU == AS3525 */
116 114
117static void ascodec_start_req(struct ascodec_request *req); 115static void ascodec_start_req(struct ascodec_request *req);
118static int ascodec_continue_req(struct ascodec_request *req, int irq_status); 116static int ascodec_continue_req(struct ascodec_request *req, int irq_status);
119static void ascodec_finish_req(struct ascodec_request *req); 117static void ascodec_finish_req(struct ascodec_request *req);
120 118
121#if CONFIG_CPU == AS3525
122void INT_AUDIO(void) 119void INT_AUDIO(void)
123{ 120{
124 VIC_INT_EN_CLEAR = INTERRUPT_AUDIO; 121 VIC_INT_EN_CLEAR = INTERRUPT_AUDIO;
@@ -126,7 +123,6 @@ void INT_AUDIO(void)
126 123
127 ascodec_async_read(AS3514_IRQ_ENRD0, 3, &as_audio_req, ascodec_read_cb); 124 ascodec_async_read(AS3514_IRQ_ENRD0, 3, &as_audio_req, ascodec_read_cb);
128} 125}
129#endif /* CONFIG_CPU == AS3525 */
130 126
131void INT_I2C_AUDIO(void) 127void INT_I2C_AUDIO(void)
132{ 128{
@@ -166,9 +162,7 @@ void ascodec_init(void)
166 int prescaler; 162 int prescaler;
167 163
168 mutex_init(&as_mtx); 164 mutex_init(&as_mtx);
169#if CONFIG_CPU == AS3525
170 wakeup_init(&adc_wkup); 165 wakeup_init(&adc_wkup);
171#endif
172 166
173 /* enable clock */ 167 /* enable clock */
174 CGU_PERI |= CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE; 168 CGU_PERI |= CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
@@ -186,9 +180,7 @@ void ascodec_init(void)
186 I2C2_IMR = 0x00; /* disable interrupts */ 180 I2C2_IMR = 0x00; /* disable interrupts */
187 I2C2_INT_CLR |= I2C2_RIS; /* clear interrupt status */ 181 I2C2_INT_CLR |= I2C2_RIS; /* clear interrupt status */
188 VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO; 182 VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO;
189#if CONFIG_CPU == AS3525 /* interrupts do not work correctly on as3525v2 */
190 VIC_INT_ENABLE = INTERRUPT_AUDIO; 183 VIC_INT_ENABLE = INTERRUPT_AUDIO;
191#endif
192 184
193 /* detect if USB was connected at startup since there is no transition */ 185 /* detect if USB was connected at startup since there is no transition */
194 if(ascodec_read(AS3514_IRQ_ENRD0) & USB_STATUS) 186 if(ascodec_read(AS3514_IRQ_ENRD0) & USB_STATUS)
@@ -203,9 +195,16 @@ void ascodec_init(void)
203#endif 195#endif
204 IRQ_USBSTAT); 196 IRQ_USBSTAT);
205 197
198#if CONFIG_CPU == AS3525v2
199 /* XIRQ = IRQ, active low reset signal, 6mA push-pull output */
200 ascodec_write_pmu(0x1a, 3, (1<<2)|3); /* 1A-3 = Out_Cntr3 register */
201 /* Generate irq on (rtc,) adc change */
202 ascodec_write(AS3514_IRQ_ENRD2, /*IRQ_RTC |*/ IRQ_ADC);
203#else
206 /* Generate irq for push-pull, active high, irq on rtc+adc change */ 204 /* Generate irq for push-pull, active high, irq on rtc+adc change */
207 ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE | 205 ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE |
208 /*IRQ_RTC |*/ IRQ_ADC); 206 /*IRQ_RTC |*/ IRQ_ADC);
207#endif
209} 208}
210 209
211/* returns != 0 when busy */ 210/* returns != 0 when busy */
@@ -432,28 +431,17 @@ int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data)
432 return i; 431 return i;
433} 432}
434 433
435/* 434static void ascodec_read_cb(unsigned const char *data, unsigned int len)
436 * Reading AS3514_IRQ_ENRD0 clears all interrupt bits, so we cache the results
437 * and clear individual bits when a specific interrupt is checked:
438 * - we clear the ENDOFCH (end of charge) interrupt when it's read
439 * - we set the usb and charger presence when the status change is detected
440 *
441 * on AS3525(v1) ENRD0 is only read in an interrupt handler
442 * on AS3525v2 the interrupt handler doesn't work (yet), so we read the register
443 * synchronously.
444 * - To avoid race conditions all the reads to this register must be atomic.
445 * We don't need to disable interrupts when reading it because all the reads
446 * (in powermgmt-ascodec.c and power-as3525.c) are performed by the same
447 * thread (the power thread).
448 */
449static void cache_enrd0(int enrd0)
450{ 435{
451 if (enrd0 & CHG_ENDOFCH) { /* chg finished */ 436 if (len != 3) /* some error happened? */
437 return;
438
439 if (data[0] & CHG_ENDOFCH) { /* chg finished */
452 ascodec_enrd0_shadow |= CHG_ENDOFCH; 440 ascodec_enrd0_shadow |= CHG_ENDOFCH;
453 IFDEBUG(int_chg_finished++); 441 IFDEBUG(int_chg_finished++);
454 } 442 }
455 if (enrd0 & CHG_CHANGED) { /* chg status changed */ 443 if (data[0] & CHG_CHANGED) { /* chg status changed */
456 if (enrd0 & CHG_STATUS) { 444 if (data[0] & CHG_STATUS) {
457 ascodec_enrd0_shadow |= CHG_STATUS; 445 ascodec_enrd0_shadow |= CHG_STATUS;
458 IFDEBUG(int_chg_insert++); 446 IFDEBUG(int_chg_insert++);
459 } else { 447 } else {
@@ -461,8 +449,8 @@ static void cache_enrd0(int enrd0)
461 IFDEBUG(int_chg_remove++); 449 IFDEBUG(int_chg_remove++);
462 } 450 }
463 } 451 }
464 if (enrd0 & USB_CHANGED) { /* usb status changed */ 452 if (data[0] & USB_CHANGED) { /* usb status changed */
465 if (enrd0 & USB_STATUS) { 453 if (data[0] & USB_STATUS) {
466 IFDEBUG(int_usb_insert++); 454 IFDEBUG(int_usb_insert++);
467 usb_insert_int(); 455 usb_insert_int();
468 } else { 456 } else {
@@ -470,16 +458,6 @@ static void cache_enrd0(int enrd0)
470 usb_remove_int(); 458 usb_remove_int();
471 } 459 }
472 } 460 }
473}
474
475#if CONFIG_CPU == AS3525
476static void ascodec_read_cb(unsigned const char *data, unsigned int len)
477{
478 if (len != 3) /* some error happened? */
479 return;
480
481 cache_enrd0(data[0]);
482
483 if (data[2] & IRQ_RTC) { /* rtc irq */ 461 if (data[2] & IRQ_RTC) { /* rtc irq */
484 /* 462 /*
485 * Can be configured for once per second or once per minute, 463 * Can be configured for once per second or once per minute,
@@ -494,27 +472,14 @@ static void ascodec_read_cb(unsigned const char *data, unsigned int len)
494 VIC_INT_ENABLE = INTERRUPT_AUDIO; 472 VIC_INT_ENABLE = INTERRUPT_AUDIO;
495} 473}
496 474
497#endif /* CONFIG_CPU == AS3525 */
498
499void ascodec_wait_adc_finished(void) 475void ascodec_wait_adc_finished(void)
500{ 476{
501#if CONFIG_CPU == AS3525
502 wakeup_wait(&adc_wkup, TIMEOUT_BLOCK); 477 wakeup_wait(&adc_wkup, TIMEOUT_BLOCK);
503#else
504 /* no interrupts, busy wait
505 * XXX: make sure this is the only reader of IRQ_ENRD2
506 */
507 while(!(ascodec_read(AS3514_IRQ_ENRD2) & IRQ_ADC))
508 yield();
509#endif
510} 478}
511 479
512#ifdef CONFIG_CHARGING 480#ifdef CONFIG_CHARGING
513bool ascodec_endofch(void) 481bool ascodec_endofch(void)
514{ 482{
515#if CONFIG_CPU != AS3525
516 cache_enrd0(ascodec_read(AS3514_IRQ_ENRD0));
517#endif
518 bool ret = ascodec_enrd0_shadow & CHG_ENDOFCH; 483 bool ret = ascodec_enrd0_shadow & CHG_ENDOFCH;
519 ascodec_enrd0_shadow &= ~CHG_ENDOFCH; // clear interrupt 484 ascodec_enrd0_shadow &= ~CHG_ENDOFCH; // clear interrupt
520 return ret; 485 return ret;
@@ -522,9 +487,6 @@ bool ascodec_endofch(void)
522 487
523bool ascodec_chg_status(void) 488bool ascodec_chg_status(void)
524{ 489{
525#if CONFIG_CPU != AS3525
526 cache_enrd0(ascodec_read(AS3514_IRQ_ENRD0));
527#endif
528 return ascodec_enrd0_shadow & CHG_STATUS; 490 return ascodec_enrd0_shadow & CHG_STATUS;
529} 491}
530#endif /* CONFIG_CHARGING */ 492#endif /* CONFIG_CHARGING */