2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 struct ao_i2c_stm_info {
23 struct stm_i2c *stm_i2c;
26 #define I2C_TIMEOUT 100
32 static uint8_t ao_i2c_state[STM_NUM_I2C];
33 static uint16_t ao_i2c_addr[STM_NUM_I2C];
34 uint8_t ao_i2c_mutex[STM_NUM_I2C];
36 #define AO_STM_I2C_CR1 ((0 << STM_I2C_CR1_SWRST) | \
37 (0 << STM_I2C_CR1_ALERT) | \
38 (0 << STM_I2C_CR1_PEC) | \
39 (0 << STM_I2C_CR1_POS) | \
40 (0 << STM_I2C_CR1_ACK) | \
41 (0 << STM_I2C_CR1_STOP) | \
42 (0 << STM_I2C_CR1_START) | \
43 (0 << STM_I2C_CR1_NOSTRETCH) | \
44 (0 << STM_I2C_CR1_ENGC) | \
45 (0 << STM_I2C_CR1_ENPEC) | \
46 (0 << STM_I2C_CR1_ENARP) | \
47 (0 << STM_I2C_CR1_SMBTYPE) | \
48 (0 << STM_I2C_CR1_SMBUS) | \
49 (1 << STM_I2C_CR1_PE))
51 #define AO_STM_I2C_CR2 ((0 << STM_I2C_CR2_LAST) | \
52 (0 << STM_I2C_CR2_DMAEN) | \
53 (0 << STM_I2C_CR2_ITBUFEN) | \
54 (0 << STM_I2C_CR2_ITEVTEN) | \
55 (0 << STM_I2C_CR2_ITERREN) | \
56 (STM_I2C_CR2_FREQ_16_MHZ << STM_I2C_CR2_FREQ))
58 static const struct ao_i2c_stm_info ao_i2c_stm_info[STM_NUM_I2C] = {
60 .tx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C1_TX),
61 .rx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C1_RX),
65 .tx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C2_TX),
66 .rx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C2_RX),
71 static uint8_t *ao_i2c_recv_data[STM_NUM_I2C];
72 static uint16_t ao_i2c_recv_len[STM_NUM_I2C];
73 static uint16_t ev_count;
76 ao_i2c_ev_isr(uint8_t index)
78 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
83 if (sr1 & (1 << STM_I2C_SR1_SB))
84 stm_i2c->dr = ao_i2c_addr[index];
85 if (sr1 & (1 << STM_I2C_SR1_ADDR)) {
86 stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN);
87 ao_i2c_state[index] = I2C_RUNNING;
88 ao_wakeup(&ao_i2c_state[index]);
90 if (sr1 & (1 << STM_I2C_SR1_BTF)) {
91 stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN);
92 ao_wakeup(&ao_i2c_state[index]);
95 if (sr1 & (1 << STM_I2C_SR1_RXNE)) {
96 if (ao_i2c_recv_len[index]) {
97 switch (--ao_i2c_recv_len[index]) {
99 ao_wakeup(&ao_i2c_recv_len[index]);
102 stm_i2c->cr1 &= ~(1 << STM_I2C_CR1_ACK);
105 *(ao_i2c_recv_data[index]++) = stm_i2c->dr;
111 void stm_i2c1_ev_isr(void) { ao_i2c_ev_isr(0); }
112 void stm_i2c2_ev_isr(void) { ao_i2c_ev_isr(1); }
115 ao_i2c_er_isr(uint8_t index)
117 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
121 if (sr1 & (1 << STM_I2C_SR1_AF)) {
122 ao_i2c_state[index] = I2C_ERROR;
123 stm_i2c->sr1 = sr1 & ~(1 << STM_I2C_SR1_AF);
124 ao_wakeup(&ao_i2c_state[index]);
128 void stm_i2c1_er_isr(void) { ao_i2c_er_isr(0); }
129 void stm_i2c2_er_isr(void) { ao_i2c_er_isr(1); }
132 ao_i2c_get(uint8_t index)
134 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
135 ao_mutex_get(&ao_i2c_mutex[index]);
142 ao_i2c_put(uint8_t index)
144 ao_mutex_put(&ao_i2c_mutex[index]);
147 static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) {
148 uint32_t sr1 = stm_i2c->sr1;
149 printf("%s: sr1: %x\n", where, sr1); flush();
153 static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) {
154 uint32_t sr2 = stm_i2c->sr2;
155 printf("%s: sr2: %x\n", where, sr2); flush();
159 static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) {
160 printf("%s: cr1: %x\n", where, cr1); flush();
164 static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) {
165 uint32_t cr1 = stm_i2c->cr1;
166 printf("%s: cr1: %x\n", where, cr1); flush();
170 static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) {
171 printf("%s: cr2: %x\n", where, cr2); flush();
175 static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) {
176 uint32_t dr = stm_i2c->dr;
177 printf("%s: dr: %x\n", where, dr); flush();
181 static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) {
182 printf("%s: dr: %x\n", where, dr); flush();
187 ao_i2c_check_status(char *where, uint8_t index, uint32_t sr1_want, uint32_t sr2_want)
189 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
190 uint32_t sr1_got, sr2_got;
193 sr1_got = in_sr1(where, stm_i2c);
194 if ((sr1_got & sr1_want) != sr1_want) {
195 printf ("%s: sr1 wanted %x got %x\n", where, sr1_want, sr1_got);
200 sr2_got = in_sr2(where, stm_i2c);
201 if ((sr2_got & sr2_want) != sr2_want) {
202 printf ("%s: sr1 wanted %x got %x\n",
203 where, sr2_want, sr2_got);
207 printf ("%s: got sr1 %x and sr2 %x\n", where, sr1_want, sr2_want);
212 ao_i2c_check_idle(uint8_t index)
214 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
218 for (t = 0; t < I2C_TIMEOUT; t++) {
219 if (!ao_i2c_check_status("check idle", index,
221 (1 << STM_I2C_SR2_BUSY)))
227 if (t == I2C_TIMEOUT)
233 ao_i2c_start(uint8_t index, uint16_t addr)
235 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
240 if (!ao_i2c_check_idle(index)) {
241 printf ("i2c busy\n");
246 ao_i2c_state[index] = I2C_IDLE;
247 ao_i2c_addr[index] = addr;
249 out_cr2("start", stm_i2c, AO_STM_I2C_CR2);
250 out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START));
251 for (t = 0; t < I2C_TIMEOUT; t++) {
252 if (ao_i2c_check_status("waiting for start",
254 (1 << STM_I2C_SR1_SB),
255 (1 << STM_I2C_SR2_BUSY) |
256 (1 << STM_I2C_SR2_MSL)))
260 if (t == I2C_TIMEOUT) {
261 printf ("No start mode\n");
264 out_dr("address", stm_i2c, addr);
266 sr1 = (1 << STM_I2C_SR1_ADDR);
267 sr2 = (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL);
269 sr1 = (1 << STM_I2C_SR1_TXE) | (1 << STM_I2C_SR1_ADDR);
270 sr2 = (1 << STM_I2C_SR2_TRA) | (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL);
273 for (t = 0; t < I2C_TIMEOUT; t++) {
274 if (ao_i2c_check_status("waiting for addr",
280 if (t == I2C_TIMEOUT) {
281 printf ("Set addr failed\n");
284 ao_i2c_state[index] = I2C_RUNNING;
286 out_cr2("start", stm_i2c, AO_STM_I2C_CR2);
287 out_cr1("start", stm_i2c,
288 AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START));
289 out_cr2("start", stm_i2c,
290 AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN));
293 while (ao_i2c_state[index] == I2C_IDLE)
294 if (ao_sleep(&ao_i2c_state[index]))
299 return ao_i2c_state[index] == I2C_RUNNING;
303 ao_i2c_stop(uint8_t index)
305 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
307 ao_i2c_state[index] = I2C_IDLE;
308 out_cr2("enable isr", stm_i2c,
309 AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN));
311 out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP));
313 /* XXX check to see if there is an interrupt here */
314 while (in_cr1("stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))
316 printf ("ev_count in stop: %d\n", ev_count);
320 ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)
322 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
329 for (t = 0; t < I2C_TIMEOUT; t++) {
330 if (ao_i2c_check_status("send", index,
331 (1 << STM_I2C_SR1_TXE),
336 if (t == I2C_TIMEOUT)
338 out_dr("send", stm_i2c, *b++);
341 uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index;
343 /* Clear any pending ADDR bit */
344 in_sr2("send clear addr", stm_i2c);
345 out_cr2("send", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN));
346 ao_dma_set_transfer(tx_dma_index,
350 (0 << STM_DMA_CCR_MEM2MEM) |
351 (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
352 (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
353 (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
354 (1 << STM_DMA_CCR_MINC) |
355 (0 << STM_DMA_CCR_PINC) |
356 (0 << STM_DMA_CCR_CIRC) |
357 (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
359 ao_dma_start(tx_dma_index);
362 while (!ao_dma_done[tx_dma_index])
363 if (ao_sleep(&ao_dma_done[tx_dma_index])) {
364 printf ("send timeout\n");
367 ao_dma_done_transfer(tx_dma_index);
368 out_cr2("send enable isr", stm_i2c,
369 AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN));
370 while ((in_sr1("send_btf", stm_i2c) & (1 << STM_I2C_SR1_BTF)) == 0)
371 if (ao_sleep(&ao_i2c_state[index]))
373 out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2);
382 ao_i2c_recv_dma_isr(int index)
385 struct stm_i2c *stm_i2c = NULL;
387 for (i = 0; i < STM_NUM_I2C; i++)
388 if (index == ao_i2c_stm_info[i].rx_dma_index) {
389 stm_i2c = ao_i2c_stm_info[i].stm_i2c;
394 stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST);
395 ao_dma_done[index] = 1;
396 ao_wakeup(&ao_dma_done[index]);
400 ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)
402 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
410 out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1);
411 /* Clear any pending ADDR bit */
412 in_sr2("clear addr", stm_i2c);
413 out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP));
416 /* Clear any pending ADDR bit */
417 out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_POS));
418 if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR))
419 in_sr2("clear addr", stm_i2c);
420 out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP));
423 // out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS));
424 out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK));
425 /* Clear any pending ADDR bit */
426 if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR))
427 in_sr2("clear addr", stm_i2c);
432 for (t = 0; t < I2C_TIMEOUT; t++) {
433 if (in_sr1("recv", stm_i2c) & (1 << STM_I2C_SR1_RXNE))
437 if (t == I2C_TIMEOUT)
439 *b++ = in_dr("recv", stm_i2c);
440 if (len == 2 && stop) {
441 out_cr1("clear ack", stm_i2c,
442 // AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP) | (1 << STM_I2C_CR1_POS));
443 AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP));
447 for (t = 0; t < I2C_TIMEOUT; t++) {
448 if (!(in_cr1("recv stop", stm_i2c) & (1 << STM_I2C_CR1_STOP)))
452 if (t == I2C_TIMEOUT)
457 uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index;
458 ao_dma_set_transfer(rx_dma_index,
462 (0 << STM_DMA_CCR_MEM2MEM) |
463 (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
464 (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
465 (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
466 (1 << STM_DMA_CCR_MINC) |
467 (0 << STM_DMA_CCR_PINC) |
468 (0 << STM_DMA_CCR_CIRC) |
469 (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
471 stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS);
472 stm_i2c->cr2 = AO_STM_I2C_CR2;
474 stm_i2c->cr1 = AO_STM_I2C_CR1;
475 stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST);
478 ao_dma_start(rx_dma_index);
480 while (!ao_dma_done[rx_dma_index])
481 ao_sleep(&ao_dma_done[rx_dma_index]);
483 ao_dma_done_transfer(rx_dma_index);
488 ao_i2c_channel_init(uint8_t index)
490 struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
492 /* Turn I2C off while configuring */
494 stm_i2c->cr2 = AO_STM_I2C_CR2;
503 stm_i2c->ccr = ((1 << STM_I2C_CCR_FS) |
504 (0 << STM_I2C_CCR_DUTY) |
505 (20 << STM_I2C_CCR_CCR));
508 stm_i2c->cr1 = AO_STM_I2C_CR1;
514 /* All of the I2C configurations are on port B */
515 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
518 stm_afr_set(&stm_gpiob, 6, STM_AFR_AF4);
519 stm_afr_set(&stm_gpiob, 7, STM_AFR_AF4);
522 stm_afr_set(&stm_gpiob, 8, STM_AFR_AF4);
523 stm_afr_set(&stm_gpiob, 9, STM_AFR_AF4);
525 # error "No I2C_1 port configuration specified"
529 stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_I2C1EN);
530 ao_i2c_channel_init(0);
532 stm_nvic_set_enable(STM_ISR_I2C1_EV_POS);
533 stm_nvic_set_priority(STM_ISR_I2C1_EV_POS, 3);
534 stm_nvic_set_enable(STM_ISR_I2C1_ER_POS);
535 stm_nvic_set_priority(STM_ISR_I2C1_ER_POS, 3);
540 stm_afr_set(&stm_gpiob, 10, STM_AFR_AF4);
541 stm_afr_set(&stm_gpiob, 11, STM_AFR_AF4);
543 # error "No I2C_2 port configuration specified"
545 stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_I2C2EN);
546 ao_i2c_channel_init(1);
548 stm_nvic_set_enable(STM_ISR_I2C2_EV_POS);
549 stm_nvic_set_priority(STM_ISR_I2C2_EV_POS, 3);
550 stm_nvic_set_enable(STM_ISR_I2C2_ER_POS);
551 stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, 3);