-unsigned int i2c_get_bus_num(void)
-{
- return g_current_bus;
-}
-#endif
-
-void i2c_init(int speed, int slaveadd)
-{
- struct s3c24x0_i2c *i2c;
-#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
- struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
-#endif
- ulong start_time = get_timer(0);
-
- /* By default i2c channel 0 is the current bus */
- g_current_bus = 0;
- i2c = get_base_i2c();
-
- /*
- * In case the previous transfer is still going, wait to give it a
- * chance to finish.
- */
- while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
- if (get_timer(start_time) > I2C_TIMEOUT_MS) {
- printf("%s: I2C bus busy for %p\n", __func__,
- &i2c->iicstat);
- return;
- }
- }
-
-#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
- int i;
-
- if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) {
-#ifdef CONFIG_S3C2410
- ulong old_gpecon = readl(&gpio->gpecon);
-#endif
-#ifdef CONFIG_S3C2400
- ulong old_gpecon = readl(&gpio->pgcon);
-#endif
- /* bus still busy probably by (most) previously interrupted
- transfer */
-
-#ifdef CONFIG_S3C2410
- /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */
- writel((readl(&gpio->gpecon) & ~0xF0000000) | 0x10000000,
- &gpio->gpecon);
-#endif
-#ifdef CONFIG_S3C2400
- /* set I2CSDA and I2CSCL (PG5, PG6) to GPIO */
- writel((readl(&gpio->pgcon) & ~0x00003c00) | 0x00001000,
- &gpio->pgcon);
-#endif
-
- /* toggle I2CSCL until bus idle */
- SetI2CSCL(0);
- udelay(1000);
- i = 10;
- while ((i > 0) && (GetI2CSDA() != 1)) {
- SetI2CSCL(1);
- udelay(1000);
- SetI2CSCL(0);
- udelay(1000);
- i--;
- }
- SetI2CSCL(1);
- udelay(1000);
-
- /* restore pin functions */
-#ifdef CONFIG_S3C2410
- writel(old_gpecon, &gpio->gpecon);
-#endif
-#ifdef CONFIG_S3C2400
- writel(old_gpecon, &gpio->pgcon);
-#endif
- }
-#endif /* #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) */
- i2c_ch_init(i2c, speed, slaveadd);
-}
-
-/*
- * Poll the appropriate bit of the fifo status register until the interface is
- * ready to process the next byte or timeout expires.
- *
- * In addition to the FIFO status register this function also polls the
- * interrupt status register to be able to detect unexpected transaction
- * completion.
- *
- * When FIFO is ready to process the next byte, this function returns I2C_OK.
- * If in course of polling the INT_I2C assertion is detected, the function
- * returns I2C_NOK. If timeout happens before any of the above conditions is
- * met - the function returns I2C_NOK_TOUT;
-
- * @param i2c: pointer to the appropriate i2c register bank.
- * @param rx_transfer: set to True if the receive transaction is in progress.
- * @return: as described above.
- */
-static unsigned hsi2c_poll_fifo(struct exynos5_hsi2c *i2c, bool rx_transfer)
-{
- u32 fifo_bit = rx_transfer ? HSI2C_RX_FIFO_EMPTY : HSI2C_TX_FIFO_FULL;
- int i = HSI2C_TIMEOUT_US;
-
- while (readl(&i2c->usi_fifo_stat) & fifo_bit) {
- if (readl(&i2c->usi_int_stat) & HSI2C_INT_I2C_EN) {
- /*
- * There is a chance that assertion of
- * HSI2C_INT_I2C_EN and deassertion of
- * HSI2C_RX_FIFO_EMPTY happen simultaneously. Let's
- * give FIFO status priority and check it one more
- * time before reporting interrupt. The interrupt will
- * be reported next time this function is called.
- */
- if (rx_transfer &&
- !(readl(&i2c->usi_fifo_stat) & fifo_bit))
- break;
- return I2C_NOK;
- }
- if (!i--) {
- debug("%s: FIFO polling timeout!\n", __func__);
- return I2C_NOK_TOUT;
- }
- udelay(1);
- }
- return I2C_OK;
-}
-
-/*
- * Preapre hsi2c transaction, either read or write.
- *
- * Set up transfer as described in section 27.5.1.2 'I2C Channel Auto Mode' of
- * the 5420 UM.
- *
- * @param i2c: pointer to the appropriate i2c register bank.
- * @param chip: slave address on the i2c bus (with read/write bit exlcuded)
- * @param len: number of bytes expected to be sent or received
- * @param rx_transfer: set to true for receive transactions
- * @param: issue_stop: set to true if i2c stop condition should be generated
- * after this transaction.
- * @return: I2C_NOK_TOUT in case the bus remained busy for HSI2C_TIMEOUT_US,
- * I2C_OK otherwise.
- */
-static int hsi2c_prepare_transaction(struct exynos5_hsi2c *i2c,
- u8 chip,
- u16 len,
- bool rx_transfer,
- bool issue_stop)
-{
- u32 conf;
-
- conf = len | HSI2C_MASTER_RUN;
-
- if (issue_stop)
- conf |= HSI2C_STOP_AFTER_TRANS;
-
- /* Clear to enable Timeout */
- writel(readl(&i2c->usi_timeout) & ~HSI2C_TIMEOUT_EN, &i2c->usi_timeout);
-
- /* Set slave address */
- writel(HSI2C_SLV_ADDR_MAS(chip), &i2c->i2c_addr);
-
- if (rx_transfer) {
- /* i2c master, read transaction */
- writel((HSI2C_RXCHON | HSI2C_FUNC_MODE_I2C | HSI2C_MASTER),
- &i2c->usi_ctl);
-
- /* read up to len bytes, stop after transaction is finished */
- writel(conf | HSI2C_READ_WRITE, &i2c->usi_auto_conf);
- } else {
- /* i2c master, write transaction */
- writel((HSI2C_TXCHON | HSI2C_FUNC_MODE_I2C | HSI2C_MASTER),
- &i2c->usi_ctl);
-
- /* write up to len bytes, stop after transaction is finished */
- writel(conf, &i2c->usi_auto_conf);
- }
-
- /* Reset all pending interrupt status bits we care about, if any */
- writel(HSI2C_INT_I2C_EN, &i2c->usi_int_stat);
-
- return I2C_OK;
-}
-
-/*
- * Wait while i2c bus is settling down (mostly stop gets completed).
- */
-static int hsi2c_wait_while_busy(struct exynos5_hsi2c *i2c)
-{
- int i = HSI2C_TIMEOUT_US;
-
- while (readl(&i2c->usi_trans_status) & HSI2C_MASTER_BUSY) {
- if (!i--) {
- debug("%s: bus busy\n", __func__);
- return I2C_NOK_TOUT;
- }
- udelay(1);
- }
- return I2C_OK;
-}
-
-static int hsi2c_write(struct exynos5_hsi2c *i2c,
- unsigned char chip,
- unsigned char addr[],
- unsigned char alen,
- unsigned char data[],
- unsigned short len,
- bool issue_stop)
-{
- int i, rv = 0;
-
- if (!(len + alen)) {
- /* Writes of zero length not supported in auto mode. */
- debug("%s: zero length writes not supported\n", __func__);
- return I2C_NOK;
- }
-
- rv = hsi2c_prepare_transaction
- (i2c, chip, len + alen, false, issue_stop);
- if (rv != I2C_OK)
- return rv;
-
- /* Move address, if any, and the data, if any, into the FIFO. */
- for (i = 0; i < alen; i++) {
- rv = hsi2c_poll_fifo(i2c, false);
- if (rv != I2C_OK) {
- debug("%s: address write failed\n", __func__);
- goto write_error;
- }
- writel(addr[i], &i2c->usi_txdata);
- }
-
- for (i = 0; i < len; i++) {
- rv = hsi2c_poll_fifo(i2c, false);
- if (rv != I2C_OK) {
- debug("%s: data write failed\n", __func__);
- goto write_error;
- }
- writel(data[i], &i2c->usi_txdata);
- }
-
- rv = hsi2c_wait_for_trx(i2c);
-
- write_error:
- if (issue_stop) {
- int tmp_ret = hsi2c_wait_while_busy(i2c);
- if (rv == I2C_OK)
- rv = tmp_ret;
- }
-
- writel(HSI2C_FUNC_MODE_I2C, &i2c->usi_ctl); /* done */
- return rv;
-}
-
-static int hsi2c_read(struct exynos5_hsi2c *i2c,
- unsigned char chip,
- unsigned char addr[],
- unsigned char alen,
- unsigned char data[],
- unsigned short len)
-{
- int i, rv, tmp_ret;
- bool drop_data = false;
-
- if (!len) {
- /* Reads of zero length not supported in auto mode. */
- debug("%s: zero length read adjusted\n", __func__);
- drop_data = true;
- len = 1;
- }
-
- if (alen) {
- /* Internal register adress needs to be written first. */
- rv = hsi2c_write(i2c, chip, addr, alen, NULL, 0, false);
- if (rv != I2C_OK)
- return rv;
- }
-
- rv = hsi2c_prepare_transaction(i2c, chip, len, true, true);
-
- if (rv != I2C_OK)
- return rv;
-
- for (i = 0; i < len; i++) {
- rv = hsi2c_poll_fifo(i2c, true);
- if (rv != I2C_OK)
- goto read_err;
- if (drop_data)
- continue;
- data[i] = readl(&i2c->usi_rxdata);
- }
-
- rv = hsi2c_wait_for_trx(i2c);
-
- read_err:
- tmp_ret = hsi2c_wait_while_busy(i2c);
- if (rv == I2C_OK)
- rv = tmp_ret;
-
- writel(HSI2C_FUNC_MODE_I2C, &i2c->usi_ctl); /* done */
- return rv;
-}
-