static void i2c_event_handler(int port) { /* save and clear status */ i2c_sr1[port] = STM32_I2C_SR1(port); STM32_I2C_SR1(port) = 0; /* Confirm that you are not in master mode */ if (STM32_I2C_SR2(port) & (1 << 0)) { CPRINTS("slave ISR triggered in master mode, ignoring"); return; } /* transfer matched our slave address */ if (i2c_sr1[port] & (1 << 1)) { /* If it's a receiver slave */ if (!(STM32_I2C_SR2(port) & (1 << 2))) { dma_start_rx(dma_rx_option + port, sizeof(host_buffer), host_buffer); STM32_I2C_CR2(port) |= (1 << 11); rx_pending = 1; } /* cleared by reading SR1 followed by reading SR2 */ STM32_I2C_SR1(port); STM32_I2C_SR2(port); } else if (i2c_sr1[port] & (1 << 4)) { /* If it's a receiver slave */ if (!(STM32_I2C_SR2(port) & (1 << 2))) { /* Disable, and clear the DMA transfer complete flag */ dma_disable(DMAC_SLAVE_RX); dma_clear_isr(DMAC_SLAVE_RX); /* Turn off i2c's DMA flag */ STM32_I2C_CR2(port) &= ~(1 << 11); } /* clear STOPF bit by reading SR1 and then writing CR1 */ STM32_I2C_SR1(port); STM32_I2C_CR1(port) = STM32_I2C_CR1(port); } /* TxE event */ if (i2c_sr1[port] & (1 << 7)) { if (port == I2C2) { /* AP is waiting for EC response */ if (rx_pending) { i2c_process_command(); /* reset host buffer after end of transfer */ rx_pending = 0; } else { /* spurious read : return dummy value */ STM32_I2C_DR(port) = 0xec; } } } }
static void i2c_event_handler(int port) { int i2c_isr; static int rx_pending, buf_idx; #ifdef TCPCI_I2C_SLAVE int addr; #endif i2c_isr = STM32_I2C_ISR(port); /* * Check for error conditions. Note, arbitration loss and bus error * are the only two errors we can get as a slave allowing clock * stretching and in non-SMBus mode. */ if (i2c_isr & (STM32_I2C_ISR_ARLO | STM32_I2C_ISR_BERR)) { rx_pending = 0; tx_pending = 0; /* Make sure TXIS interrupt is disabled */ STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; /* Clear error status bits */ STM32_I2C_ICR(port) |= STM32_I2C_ICR_BERRCF | STM32_I2C_ICR_ARLOCF; } /* Transfer matched our slave address */ if (i2c_isr & STM32_I2C_ISR_ADDR) { if (i2c_isr & STM32_I2C_ISR_DIR) { /* Transmitter slave */ /* Clear transmit buffer */ STM32_I2C_ISR(port) |= STM32_I2C_ISR_TXE; /* Enable txis interrupt to start response */ STM32_I2C_CR1(port) |= STM32_I2C_CR1_TXIE; } else { /* Receiver slave */ buf_idx = 0; rx_pending = 1; } /* Clear ADDR bit by writing to ADDRCF bit */ STM32_I2C_ICR(port) |= STM32_I2C_ICR_ADDRCF; /* Inhibit stop mode when addressed until STOPF flag is set */ disable_sleep(SLEEP_MASK_I2C_SLAVE); } /* Stop condition on bus */ if (i2c_isr & STM32_I2C_ISR_STOP) { #ifdef TCPCI_I2C_SLAVE /* * if tcpc is being addressed, and we received a stop * while rx is pending, then this is a write only to * the tcpc. */ addr = STM32_I2C_ISR_ADDCODE(STM32_I2C_ISR(port)); if (rx_pending && ADDR_IS_TCPC(addr)) i2c_process_tcpc_command(0, addr, buf_idx); #endif rx_pending = 0; tx_pending = 0; /* Make sure TXIS interrupt is disabled */ STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; /* Clear STOPF bit by writing to STOPCF bit */ STM32_I2C_ICR(port) |= STM32_I2C_ICR_STOPCF; /* No longer inhibit deep sleep after stop condition */ enable_sleep(SLEEP_MASK_I2C_SLAVE); } /* Receiver full event */ if (i2c_isr & STM32_I2C_ISR_RXNE) host_buffer[buf_idx++] = STM32_I2C_RXDR(port); /* Master requested STOP or RESTART */ if (i2c_isr & STM32_I2C_ISR_NACK) { /* Make sure TXIS interrupt is disabled */ STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; /* Clear NACK */ STM32_I2C_ICR(port) |= STM32_I2C_ICR_NACKCF; /* Resend last byte on RESTART */ if (port == I2C_PORT_EC && tx_index) tx_index--; } /* Transmitter empty event */ if (i2c_isr & STM32_I2C_ISR_TXIS) { if (port == I2C_PORT_EC) { /* host is waiting for PD response */ if (tx_pending) { if (tx_index < tx_end) { STM32_I2C_TXDR(port) = host_buffer[tx_index++]; } else { STM32_I2C_TXDR(port) = 0xec; /* * Set tx_index = 0 to prevent NACK * handler resending last buffer byte. */ tx_index = 0; tx_end = 0; /* No pending data */ tx_pending = 0; } } else if (rx_pending) { host_i2c_resp_port = port; /* * Disable TXIS interrupt, transmission will * be prepared by host command task. */ STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; #ifdef TCPCI_I2C_SLAVE addr = STM32_I2C_ISR_ADDCODE( STM32_I2C_ISR(port)); if (ADDR_IS_TCPC(addr)) i2c_process_tcpc_command(1, addr, buf_idx); else #endif i2c_process_command(); /* Reset host buffer after end of transfer */ rx_pending = 0; tx_pending = 1; } else { STM32_I2C_TXDR(port) = 0xec; } } } }