Ejemplo n.º 1
0
unsigned char i2c_transmit(com_state_t type) {
    switch (type) {
        case START:
            status_reg = ADDR_MATCH;
            i2c_interrupt();
        break;
        case DATA:
        case DATA_NACK:
            if (!dir_cpy) {
                if (gc) {
                    status_reg = DATA_RXGC;
                    i2c_interrupt();
                } else {
                    status_reg = DATA_RX;
                    i2c_interrupt();
                }
            } else {
                status_reg = DATA_TX;
                i2c_interrupt();
            }
        break;
        case STOP:
            status_reg = STOP_CATCHED;
            i2c_interrupt();
            return 0;
    }
    // TODO(NR) Timeout
    return (0);
}
Ejemplo n.º 2
0
void intc_cpu_int_group_6(void)
{
	/* Determine interrupt number. */
	int intc_group_6 = intc_get_ec_int();

	switch (intc_group_6) {
#ifdef CONFIG_I2C
	case IT83XX_IRQ_SMB_A:
		i2c_interrupt(IT83XX_I2C_CH_A);
		break;

	case IT83XX_IRQ_SMB_B:
		i2c_interrupt(IT83XX_I2C_CH_B);
		break;

	case IT83XX_IRQ_SMB_C:
		i2c_interrupt(IT83XX_I2C_CH_C);
		break;

	case IT83XX_IRQ_SMB_D:
		i2c_interrupt(IT83XX_I2C_CH_D);
		break;

	case IT83XX_IRQ_SMB_E:
		i2c_interrupt(IT83XX_I2C_CH_E);
		break;

	case IT83XX_IRQ_SMB_F:
		i2c_interrupt(IT83XX_I2C_CH_F);
		break;
#endif
	default:
		break;
	}
}
Ejemplo n.º 3
0
void intc_cpu_int_group_6(void)
{
	/* Determine interrupt number. */
	int intc_group_6 = intc_get_ec_int();

	switch (intc_group_6) {

	case IT83XX_IRQ_SMB_A:
		i2c_interrupt(0);
		break;

	case IT83XX_IRQ_SMB_B:
		i2c_interrupt(1);
		break;

	case IT83XX_IRQ_SMB_C:
		i2c_interrupt(2);
		break;

	default:
		break;
	}
}
void interrupt_func(void)
{
  // I2C interrupt handler
  i2c_interrupt();

  if (INTCONbits.TMR0IF == 1) {
    TMR0 = T0CNT;
    INTCONbits.TMR0IF = 0;
    gcounter++;
    if (gcounter > 8000) {
      gcounter = 0;
    }
  }

  if (INTCONbits.RABIF == 1) {
    unsigned short now = TMR3;
    //TMR3 = 0;
    //PIR2bits.TMR3IF = 0;
    INTCONbits.RABIF = 0;
    debug_counter++;
  }
}
Ejemplo n.º 5
0
int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size,
		  uint8_t *in, int in_size, int flags)
{
	int ctrl = i2c_port_to_controller(port);
	volatile struct i2c_status *p_status = i2c_stsobjs + ctrl;

	if (out_size == 0 && in_size == 0)
		return EC_SUCCESS;

	interrupt_disable();
	/* make sure bus is not occupied by the other task */
	if (p_status->task_waiting != TASK_ID_INVALID) {
		interrupt_enable();
		return EC_ERROR_BUSY;
	}

	/* Assign current task ID */
	p_status->task_waiting = task_get_current();
	interrupt_enable();

	/* Select port for multi-ports i2c controller */
	i2c_select_port(port);

	/* Copy data to controller struct */
	p_status->flags       = flags;
	p_status->tx_buf      = out;
	p_status->sz_txbuf    = out_size;
	p_status->rx_buf      = in;
	p_status->sz_rxbuf    = in_size;
#if I2C_7BITS_ADDR
	/* Set slave address from 7-bits to 8-bits */
	p_status->slave_addr  = (slave_addr<<1);
#else
	/* Set slave address (8-bits) */
	p_status->slave_addr  = slave_addr;
#endif
	/* Reset index & error */
	p_status->idx_buf     = 0;
	p_status->err_code    = SMB_OK;

	/* Make sure we're in a good state to start */
	if ((flags & I2C_XFER_START) && (i2c_bus_busy(ctrl)
			|| (i2c_get_line_levels(port) != I2C_LINE_IDLE))) {

		/* Attempt to unwedge the controller. */
		i2c_unwedge(ctrl);
		/* recovery i2c controller */
		i2c_recovery(ctrl);
		/* Select port again for recovery */
		i2c_select_port(port);
	}

	CPUTS("\n");

	/* Start master transaction */
	i2c_master_transaction(ctrl);

	/* Reset task ID */
	p_status->task_waiting = TASK_ID_INVALID;

	/* Disable SMB interrupt and New Address Match interrupt source */
	i2c_interrupt(ctrl, 0);

	CPRINTS("-Err:0x%02x\n", p_status->err_code);

	return (p_status->err_code == SMB_OK) ? EC_SUCCESS : EC_ERROR_UNKNOWN;
}
Ejemplo n.º 6
0
inline void i2c_handle_sda_irq(int controller)
{
	volatile struct i2c_status *p_status = i2c_stsobjs + controller;
	/* 1 Issue Start is successful ie. write address byte */
	if (p_status->oper_state == SMB_MASTER_START
			|| p_status->oper_state == SMB_REPEAT_START) {
		uint8_t addr = p_status->slave_addr;
		/* Prepare address byte */
		if (p_status->sz_txbuf == 0) {/* Receive mode */
			p_status->oper_state = SMB_READ_OPER;
			/*
			 * Receiving one byte only - set nack just
			 * before writing address byte
			 */
			if (p_status->sz_rxbuf == 1)
				I2C_NACK(controller);

			/* Write the address to the bus R bit*/
			I2C_WRITE_BYTE(controller, (addr | 0x1));
			CPRINTS("-ARR-0x%02x", addr);
		} else {/* Transmit mode */
			p_status->oper_state = SMB_WRITE_OPER;
			/* Write the address to the bus W bit*/
			I2C_WRITE_BYTE(controller, addr);
			CPRINTS("-ARW-0x%02x", addr);
		}
		/* Completed handling START condition */
		return;
	}
	/* 2 Handle master write operation  */
	else if (p_status->oper_state == SMB_WRITE_OPER) {
		/* all bytes have been written, in a pure write operation */
		if (p_status->idx_buf == p_status->sz_txbuf) {
			/*  no more message */
			if (p_status->sz_rxbuf == 0) {
				/* need to STOP or not */
				if (p_status->flags & I2C_XFER_STOP) {
					/* Issue a STOP condition on the bus */
					I2C_STOP(controller);
					CPUTS("-SP");
					/* Clear SDAST by writing dummy byte */
					I2C_WRITE_BYTE(controller, 0xFF);
				}

				/* Set error code */
				p_status->err_code = SMB_OK;
				/* Set SMB status if we need stall bus */
				p_status->oper_state
				= (p_status->flags & I2C_XFER_STOP)
					? SMB_IDLE : SMB_WRITE_SUSPEND;
				/*
				 * Disable interrupt for i2c master stall SCL
				 * and forbid SDAST generate interrupt
				 * until common layer start other transactions
				 */
				if (p_status->oper_state == SMB_WRITE_SUSPEND)
					i2c_interrupt(controller, 0);
				/* Notify upper layer */
				task_set_event(p_status->task_waiting,
						TASK_EVENT_I2C_IDLE, 0);
				CPUTS("-END");
			}
			/* need to restart & send slave address immediately */
			else {
				uint8_t addr_byte = p_status->slave_addr;
				/*
				 * Prepare address byte
				 * and start to receive bytes
				 */
				p_status->oper_state = SMB_READ_OPER;
				/* Reset index of buffer */
				p_status->idx_buf = 0;

				/*
				 * Generate (Repeated) Start
				 * upon next write to SDA
				 */
				I2C_START(controller);
				CPUTS("-RST");
				/*
				 * Receiving one byte only - set nack just
				 * before writing address byte
				 */
				if (p_status->sz_rxbuf == 1) {
					I2C_NACK(controller);
					CPUTS("-GNA");
				}
				/* Write the address to the bus R bit*/
				I2C_WRITE_BYTE(controller, (addr_byte | 0x1));
				CPUTS("-ARR");
			}
		}
		/* write next byte (not last byte and not slave address */
		else {
			I2C_WRITE_BYTE(controller,
					p_status->tx_buf[p_status->idx_buf++]);
			CPRINTS("-W(%02x)",
					p_status->tx_buf[p_status->idx_buf-1]);
		}
	}
	/* 3 Handle master read operation (read or after a write operation) */
	else if (p_status->oper_state == SMB_READ_OPER) {
		uint8_t data;
		/* last byte is about to be read - end of transaction */
		if (p_status->idx_buf == (p_status->sz_rxbuf - 1)) {
			/* need to STOP or not */
			if (p_status->flags & I2C_XFER_STOP) {
				/* Stop should set before reading last byte */
				I2C_STOP(controller);
				CPUTS("-SP");
			}
		}
		/* Check if byte-before-last is about to be read */
		else if (p_status->idx_buf == (p_status->sz_rxbuf - 2)) {
			/*
			 * Set nack before reading byte-before-last,
			 * so that nack will be generated after receive
			 * of last byte
			 */
			if (p_status->flags & I2C_XFER_STOP) {
				I2C_NACK(controller);
				CPUTS("-GNA");
			}
		}

		/* Read last byte but flag don't include I2C_XFER_STOP */
		if (p_status->idx_buf == p_status->sz_rxbuf-1) {
			/*
			 * Disable interrupt before i2c master read SDA reg
			 * (stall SCL) and forbid SDAST generate interrupt
			 * until common layer start other transactions
			 */
			if (!(p_status->flags & I2C_XFER_STOP))
				i2c_interrupt(controller, 0);
		}

		/* Read data for SMBSDA */
		I2C_READ_BYTE(controller, data);
		CPRINTS("-R(%02x)", data);

		/* Read to buffer */
		p_status->rx_buf[p_status->idx_buf++] = data;

		/* last byte is read - end of transaction */
		if (p_status->idx_buf == p_status->sz_rxbuf) {
			/* Set current status */
			p_status->oper_state = (p_status->flags & I2C_XFER_STOP)
					? SMB_IDLE : SMB_READ_SUSPEND;
			/* Set error code */
			p_status->err_code = SMB_OK;
			/* Notify upper layer of missing data */
			task_set_event(p_status->task_waiting,
					TASK_EVENT_I2C_IDLE, 0);
			CPUTS("-END");
		}
	}
}
Ejemplo n.º 7
0
enum smb_error i2c_master_transaction(int controller)
{
	/* Set i2c mode to object */
	int events = 0;
	volatile struct i2c_status *p_status = i2c_stsobjs + controller;

	/* Assign current SMB status of controller */
	if (p_status->oper_state == SMB_IDLE) {
		/* New transaction */
		p_status->oper_state = SMB_MASTER_START;
	} else if (p_status->oper_state == SMB_WRITE_SUSPEND) {
		if (p_status->sz_txbuf == 0) {
			/* Read bytes from next transaction */
			p_status->oper_state = SMB_REPEAT_START;
			CPUTS("R");
		} else {
			/* Continue to write the other bytes */
			p_status->oper_state = SMB_WRITE_OPER;
			I2C_WRITE_BYTE(controller,
					p_status->tx_buf[p_status->idx_buf++]);
			CPRINTS("-W(%02x)",
					p_status->tx_buf[p_status->idx_buf-1]);
		}
	} else if (p_status->oper_state == SMB_READ_SUSPEND) {
		/* Need to read the other bytes from next transaction */
		uint8_t data;
		uint8_t timeout = 10; /* unit: us */
		p_status->oper_state = SMB_READ_OPER;

		/* wait for SDAST issue */
		while (timeout > 0) {
			if (IS_BIT_SET(NPCX_SMBST(controller),
					NPCX_SMBST_SDAST))
				break;
			if (--timeout > 0)
				usleep(10);
		}
		if (timeout == 0)
			return EC_ERROR_TIMEOUT;

		/*
		 * Read first byte from SMBSDA in case SDAST interrupt occurs
		 * immediately before task_wait_event_mask() func
		 */
		I2C_READ_BYTE(controller, data);
		CPRINTS("-R(%02x)", data);
		/* Read to buffer */
		p_status->rx_buf[p_status->idx_buf++] = data;
	}

	/* Generate a START condition */
	if (p_status->oper_state == SMB_MASTER_START ||
			p_status->oper_state == SMB_REPEAT_START) {
		I2C_START(controller);
		CPUTS("ST");
	}

	/* Enable SMB interrupt and New Address Match interrupt source */
	i2c_interrupt(controller, 1);

	/* Wait for transfer complete or timeout */
	events = task_wait_event_mask(TASK_EVENT_I2C_IDLE,
			p_status->timeout_us);

	/* Handle bus timeout */
	if ((events & TASK_EVENT_I2C_IDLE) == 0) {
		/* Recovery I2C controller */
		i2c_recovery(controller);
		p_status->err_code = SMB_TIMEOUT_ERROR;
	}

	/*
	 * In slave write operation, NACK is OK, otherwise it is a problem
	 */
	else if (p_status->err_code == SMB_BUS_ERROR ||
			p_status->err_code == SMB_MASTER_NO_ADDRESS_MATCH){
		i2c_recovery(controller);
	}

	/* Wait till STOP condition is generated */
	if (p_status->err_code == SMB_OK && i2c_wait_stop_completed(controller,
			I2C_MIN_TIMEOUT) != EC_SUCCESS) {
		cprints(CC_I2C, "STOP fail! scl %02x is held by slave device!",
				controller);
		p_status->err_code = SMB_TIMEOUT_ERROR;
	}

	return p_status->err_code;
}