/* Internal divider settings for standard mode, fast mode and fast mode plus */ struct bus_speed_cfg {
uint8_t time_m; /* Number of cycles for setup time */
uint8_t time_n; /* Number of cycles for hold time */
uint8_t prescale; /* Prescale divider */
uint8_t time_p; /* Timing coefficient */
uint8_t no_div; /* Disable clock divider */
uint8_t time_div; /* Post-prescale divider */
};
/* Internal divider settings for high-speed mode */ struct hs_bus_speed_cfg {
uint8_t hs_hold; /* Number of clock cycles SCL stays low until
the end of bit period */
uint8_t hs_high_phase; /* Number of clock cycles SCL stays high
before it falls */
uint8_t hs_setup; /* Number of clock cycles SCL stays low
before it rises */
uint8_t prescale; /* Prescale divider */
uint8_t time_p; /* Timing coefficient */
uint8_t no_div; /* Disable clock divider */
uint8_t time_div; /* Post-prescale divider */
};
if ((status & ~ISR_RESERVED_MASK) == 0) return IRQ_NONE;
/* Must flush the TX FIFO when NAK detected */ if (status & ISR_NOACK_MASK)
writel(TXFCR_FIFO_FLUSH_MASK | TXFCR_FIFO_EN_MASK,
dev->base + TXFCR_OFFSET);
/* Wait for ISR_CMDBUSY_MASK to go low before writing to CS, DAT, or RCD */ staticint bcm_kona_i2c_wait_if_busy(struct bcm_kona_i2c_dev *dev)
{ unsignedlong timeout = jiffies + msecs_to_jiffies(I2C_TIMEOUT);
while (readl(dev->base + ISR_OFFSET) & ISR_CMDBUSY_MASK) if (time_after(jiffies, timeout)) {
dev_err(dev->device, "CMDBUSY timeout\n"); return -ETIMEDOUT;
}
return 0;
}
/* Send command to I2C bus */ staticint bcm_kona_send_i2c_cmd(struct bcm_kona_i2c_dev *dev, enum bcm_kona_cmd_t cmd)
{ int rc; unsignedlong time_left = msecs_to_jiffies(I2C_TIMEOUT);
/* Make sure the hardware is ready */
rc = bcm_kona_i2c_wait_if_busy(dev); if (rc < 0) return rc;
/* Read a single RX FIFO worth of data from the i2c bus */ staticint bcm_kona_i2c_read_fifo_single(struct bcm_kona_i2c_dev *dev,
uint8_t *buf, unsignedint len, unsignedint last_byte_nak)
{ unsignedlong time_left = msecs_to_jiffies(I2C_TIMEOUT);
/* Mark as incomplete before starting the RX FIFO */
reinit_completion(&dev->done);
/* Wait for FIFO read to complete */
time_left = wait_for_completion_timeout(&dev->done, time_left);
/* Mask all interrupts */
writel(0, dev->base + IER_OFFSET);
if (!time_left) {
dev_err(dev->device, "RX FIFO time out\n"); return -EREMOTEIO;
}
/* Read data from FIFO */ for (; len > 0; len--, buf++)
*buf = readl(dev->base + RXFIFORDOUT_OFFSET);
return 0;
}
/* Read any amount of data using the RX FIFO from the i2c bus */ staticint bcm_kona_i2c_read_fifo(struct bcm_kona_i2c_dev *dev, struct i2c_msg *msg)
{ unsignedint bytes_to_read = MAX_RX_FIFO_SIZE; unsignedint last_byte_nak = 0; unsignedint bytes_read = 0; int rc;
uint8_t *tmp_buf = msg->buf;
while (bytes_read < msg->len) { if (msg->len - bytes_read <= MAX_RX_FIFO_SIZE) {
last_byte_nak = 1; /* NAK last byte of transfer */
bytes_to_read = msg->len - bytes_read;
}
/* Write a single byte of data to the i2c bus */ staticint bcm_kona_i2c_write_byte(struct bcm_kona_i2c_dev *dev, uint8_t data, unsignedint nak_expected)
{ int rc; unsignedlong time_left = msecs_to_jiffies(I2C_TIMEOUT); unsignedint nak_received;
/* Make sure the hardware is ready */
rc = bcm_kona_i2c_wait_if_busy(dev); if (rc < 0) return rc;
/* Write a single TX FIFO worth of data to the i2c bus */ staticint bcm_kona_i2c_write_fifo_single(struct bcm_kona_i2c_dev *dev,
uint8_t *buf, unsignedint len)
{ int k; unsignedlong time_left = msecs_to_jiffies(I2C_TIMEOUT); unsignedint fifo_status;
/* Mark as incomplete before sending data to the TX FIFO */
reinit_completion(&dev->done);
/* Unmask the fifo empty and nak interrupt */
writel(IER_FIFO_INT_EN_MASK | IER_NOACK_EN_MASK,
dev->base + IER_OFFSET);
/* Disable IRQ to load a FIFO worth of data without interruption */
disable_irq(dev->irq);
/* Write data into FIFO */ for (k = 0; k < len; k++)
writel(buf[k], (dev->base + DAT_OFFSET));
/* Enable IRQ now that data has been loaded */
enable_irq(dev->irq);
/* Wait for FIFO to empty */ do {
time_left = wait_for_completion_timeout(&dev->done, time_left);
fifo_status = readl(dev->base + FIFO_STATUS_OFFSET);
} while (time_left && !(fifo_status & FIFO_STATUS_TXFIFO_EMPTY_MASK));
/* Mask all interrupts */
writel(0, dev->base + IER_OFFSET);
/* Check if there was a NAK */ if (readl(dev->base + CS_OFFSET) & CS_ACK_MASK) {
dev_err(dev->device, "unexpected NAK\n"); return -EREMOTEIO;
}
/* Check if a timeout occured */ if (!time_left) {
dev_err(dev->device, "completion timed out\n"); return -EREMOTEIO;
}
return 0;
}
/* Write any amount of data using TX FIFO to the i2c bus */ staticint bcm_kona_i2c_write_fifo(struct bcm_kona_i2c_dev *dev, struct i2c_msg *msg)
{ unsignedint bytes_to_write = MAX_TX_FIFO_SIZE; unsignedint bytes_written = 0; int rc;
uint8_t *tmp_buf = msg->buf;
while (bytes_written < msg->len) { if (msg->len - bytes_written <= MAX_TX_FIFO_SIZE)
bytes_to_write = msg->len - bytes_written;
if (msg->flags & I2C_M_TEN) { /* First byte is 11110XX0 where XX is upper 2 bits */
addr = i2c_10bit_addr_hi_from_msg(msg) & ~I2C_M_RD; if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) return -EREMOTEIO;
/* Second byte is the remaining 8 bits */
addr = i2c_10bit_addr_lo_from_msg(msg); if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) return -EREMOTEIO;
if (msg->flags & I2C_M_RD) { /* For read, send restart command */ if (bcm_kona_send_i2c_cmd(dev, BCM_CMD_RESTART) < 0) return -EREMOTEIO;
/* Then re-send the first byte with the read bit set */
addr = i2c_10bit_addr_hi_from_msg(msg); if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) return -EREMOTEIO;
}
} else {
addr = i2c_8bit_addr_from_msg(msg);
if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) return -EREMOTEIO;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.