1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c
index adc9b7f..96b4b2a 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;
 static struct ascodec_request *req_head = NULL;
 static struct ascodec_request *req_tail = NULL;

-#if CONFIG_CPU == AS3525
 static struct wakeup adc_wkup;
 static struct ascodec_request as_audio_req;

@@ -112,13 +111,11 @@ static int int_adc = 0;
 #endif /* DEBUG */

 static void ascodec_read_cb(unsigned const char *data, unsigned int len);
-#endif /* CONFIG_CPU == AS3525 */

 static void ascodec_start_req(struct ascodec_request *req);
 static int  ascodec_continue_req(struct ascodec_request *req, int irq_status);
 static void ascodec_finish_req(struct ascodec_request *req);

-#if CONFIG_CPU == AS3525
 void INT_AUDIO(void)
 {
     VIC_INT_EN_CLEAR = INTERRUPT_AUDIO;
@@ -126,7 +123,6 @@ void INT_AUDIO(void)

     ascodec_async_read(AS3514_IRQ_ENRD0, 3, &as_audio_req, ascodec_read_cb);
 }
-#endif /* CONFIG_CPU == AS3525 */

 void INT_I2C_AUDIO(void)
 {
@@ -166,9 +162,7 @@ void ascodec_init(void)
     int prescaler;

     mutex_init(&as_mtx);
-#if CONFIG_CPU == AS3525
     wakeup_init(&adc_wkup);
-#endif

     /* enable clock */
     CGU_PERI |= CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
@@ -186,9 +180,7 @@ void ascodec_init(void)
     I2C2_IMR = 0x00;          /* disable interrupts */
     I2C2_INT_CLR |= I2C2_RIS; /* clear interrupt status */
     VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO;
-#if CONFIG_CPU == AS3525 /* interrupts do not work correctly on as3525v2 */
     VIC_INT_ENABLE = INTERRUPT_AUDIO;
-#endif

     /* detect if USB was connected at startup since there is no transition */
     if(ascodec_read(AS3514_IRQ_ENRD0) & USB_STATUS)
@@ -203,9 +195,16 @@ void ascodec_init(void)
 #endif
         IRQ_USBSTAT);

+#if CONFIG_CPU == AS3525v2
+    /* XIRQ = IRQ, active low reset signal, 6mA open-drain output */
+    ascodec_write_pmu(0x1a, 3, 0x03);
+    /* Generate irq on (rtc,) adc change */
+    ascodec_write(AS3514_IRQ_ENRD2, /*IRQ_RTC |*/ IRQ_ADC);
+#else
     /* Generate irq for push-pull, active high, irq on rtc+adc change */
     ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE |
                                     /*IRQ_RTC |*/ IRQ_ADC);
+#endif
 }

 /* returns != 0 when busy */
@@ -432,28 +431,17 @@ int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data)
     return i;
 }

-/*
- * Reading AS3514_IRQ_ENRD0 clears all interrupt bits, so we cache the results
- * and clear individual bits when a specific interrupt is checked:
- * - we clear the ENDOFCH (end of charge) interrupt when it's read
- * - we set the usb and charger presence when the status change is detected
- *
- * on AS3525(v1) ENRD0 is only read in an interrupt handler
- * on AS3525v2 the interrupt handler doesn't work (yet), so we read the register
- * synchronously.
- *  - To avoid race conditions all the reads to this register must be atomic.
- *    We don't need to disable interrupts when reading it because all the reads
- *    (in powermgmt-ascodec.c and power-as3525.c) are performed by the same
- *    thread (the power thread).
- */
-static void cache_enrd0(int enrd0)
+static void ascodec_read_cb(unsigned const char *data, unsigned int len)
 {
-    if (enrd0 & CHG_ENDOFCH) { /* chg finished */
+    if (len != 3) /* some error happened? */
+        return;
+
+    if (data[0] & CHG_ENDOFCH) { /* chg finished */
         ascodec_enrd0_shadow |= CHG_ENDOFCH;
         IFDEBUG(int_chg_finished++);
     }
-    if (enrd0 & CHG_CHANGED) { /* chg status changed */
-        if (enrd0 & CHG_STATUS) {
+    if (data[0] & CHG_CHANGED) { /* chg status changed */
+        if (data[0] & CHG_STATUS) {
             ascodec_enrd0_shadow |= CHG_STATUS;
             IFDEBUG(int_chg_insert++);
         } else {
@@ -461,8 +449,8 @@ static void cache_enrd0(int enrd0)
             IFDEBUG(int_chg_remove++);
         }
     }
-    if (enrd0 & USB_CHANGED) { /* usb status changed */
-        if (enrd0 & USB_STATUS) {
+    if (data[0] & USB_CHANGED) { /* usb status changed */
+        if (data[0] & USB_STATUS) {
             IFDEBUG(int_usb_insert++);
             usb_insert_int();
         } else {
@@ -470,16 +458,6 @@ static void cache_enrd0(int enrd0)
             usb_remove_int();
         }
     }
-}
-
-#if CONFIG_CPU == AS3525
-static void ascodec_read_cb(unsigned const char *data, unsigned int len)
-{
-    if (len != 3) /* some error happened? */
-        return;
-
-    cache_enrd0(data[0]);
-
     if (data[2] & IRQ_RTC) { /* rtc irq */
         /*
          * 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)
     VIC_INT_ENABLE = INTERRUPT_AUDIO;
 }

-#endif /* CONFIG_CPU == AS3525 */
-
 void ascodec_wait_adc_finished(void)
 {
-#if CONFIG_CPU == AS3525
     wakeup_wait(&adc_wkup, TIMEOUT_BLOCK);
-#else
-    /* no interrupts, busy wait
-     * XXX: make sure this is the only reader of IRQ_ENRD2
-     */
-    while(!(ascodec_read(AS3514_IRQ_ENRD2) & IRQ_ADC))
-        yield();
-#endif
 }

 #ifdef CONFIG_CHARGING
 bool ascodec_endofch(void)
 {
-#if CONFIG_CPU != AS3525
-    cache_enrd0(ascodec_read(AS3514_IRQ_ENRD0));
-#endif
     bool ret = ascodec_enrd0_shadow & CHG_ENDOFCH;
     ascodec_enrd0_shadow &= ~CHG_ENDOFCH; // clear interrupt
     return ret;
@@ -522,9 +487,6 @@ bool ascodec_endofch(void)

 bool ascodec_chg_status(void)
 {
-#if CONFIG_CPU != AS3525
-    cache_enrd0(ascodec_read(AS3514_IRQ_ENRD0));
-#endif
     return ascodec_enrd0_shadow & CHG_STATUS;
 }
 #endif /* CONFIG_CHARGING */