17e4d5620SIcenowy Zheng /* 27e4d5620SIcenowy Zheng * Copyright (C) 2018 Marvell International Ltd. 37e4d5620SIcenowy Zheng * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io> 47e4d5620SIcenowy Zheng * 57e4d5620SIcenowy Zheng * SPDX-License-Identifier: BSD-3-Clause 67e4d5620SIcenowy Zheng * https://spdx.org/licenses 77e4d5620SIcenowy Zheng */ 87e4d5620SIcenowy Zheng 97e4d5620SIcenowy Zheng /* 107e4d5620SIcenowy Zheng * This driver is for Mentor Graphics Inventra MI2CV IP core, which is used 117e4d5620SIcenowy Zheng * for Marvell and Allwinner SoCs in ATF. 127e4d5620SIcenowy Zheng */ 137e4d5620SIcenowy Zheng 147e4d5620SIcenowy Zheng #include <errno.h> 1509d40e0eSAntonio Nino Diaz 1609d40e0eSAntonio Nino Diaz #include <common/debug.h> 1709d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h> 1809d40e0eSAntonio Nino Diaz #include <drivers/mentor/mi2cv.h> 1909d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 2009d40e0eSAntonio Nino Diaz 21dfc0fb27SAndre Przywara #include <mentor_i2c_plat.h> 227e4d5620SIcenowy Zheng 237e4d5620SIcenowy Zheng #if LOG_LEVEL >= LOG_LEVEL_VERBOSE 247e4d5620SIcenowy Zheng #define DEBUG_I2C 257e4d5620SIcenowy Zheng #endif 267e4d5620SIcenowy Zheng 277e4d5620SIcenowy Zheng #define I2C_TIMEOUT_VALUE 0x500 287e4d5620SIcenowy Zheng #define I2C_MAX_RETRY_CNT 1000 297e4d5620SIcenowy Zheng #define I2C_CMD_WRITE 0x0 307e4d5620SIcenowy Zheng #define I2C_CMD_READ 0x1 317e4d5620SIcenowy Zheng 327e4d5620SIcenowy Zheng #define I2C_DATA_ADDR_7BIT_OFFS 0x1 337e4d5620SIcenowy Zheng #define I2C_DATA_ADDR_7BIT_MASK (0xFF << I2C_DATA_ADDR_7BIT_OFFS) 347e4d5620SIcenowy Zheng 357e4d5620SIcenowy Zheng #define I2C_CONTROL_ACK 0x00000004 367e4d5620SIcenowy Zheng #define I2C_CONTROL_IFLG 0x00000008 377e4d5620SIcenowy Zheng #define I2C_CONTROL_STOP 0x00000010 387e4d5620SIcenowy Zheng #define I2C_CONTROL_START 0x00000020 397e4d5620SIcenowy Zheng #define I2C_CONTROL_TWSIEN 0x00000040 407e4d5620SIcenowy Zheng #define I2C_CONTROL_INTEN 0x00000080 417e4d5620SIcenowy Zheng 427e4d5620SIcenowy Zheng #define I2C_STATUS_START 0x08 437e4d5620SIcenowy Zheng #define I2C_STATUS_REPEATED_START 0x10 447e4d5620SIcenowy Zheng #define I2C_STATUS_ADDR_W_ACK 0x18 457e4d5620SIcenowy Zheng #define I2C_STATUS_DATA_W_ACK 0x28 467e4d5620SIcenowy Zheng #define I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER 0x38 477e4d5620SIcenowy Zheng #define I2C_STATUS_ADDR_R_ACK 0x40 487e4d5620SIcenowy Zheng #define I2C_STATUS_DATA_R_ACK 0x50 497e4d5620SIcenowy Zheng #define I2C_STATUS_DATA_R_NAK 0x58 507e4d5620SIcenowy Zheng #define I2C_STATUS_LOST_ARB_GENERAL_CALL 0x78 517e4d5620SIcenowy Zheng #define I2C_STATUS_IDLE 0xF8 527e4d5620SIcenowy Zheng 537e4d5620SIcenowy Zheng #define I2C_UNSTUCK_TRIGGER 0x1 547e4d5620SIcenowy Zheng #define I2C_UNSTUCK_ONGOING 0x2 557e4d5620SIcenowy Zheng #define I2C_UNSTUCK_ERROR 0x4 567e4d5620SIcenowy Zheng 577e4d5620SIcenowy Zheng static struct mentor_i2c_regs *base; 587e4d5620SIcenowy Zheng 597e4d5620SIcenowy Zheng static int mentor_i2c_lost_arbitration(uint32_t *status) 607e4d5620SIcenowy Zheng { 617e4d5620SIcenowy Zheng *status = mmio_read_32((uintptr_t)&base->status); 627e4d5620SIcenowy Zheng if ((*status == I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER) || 637e4d5620SIcenowy Zheng (*status == I2C_STATUS_LOST_ARB_GENERAL_CALL)) 647e4d5620SIcenowy Zheng return -EAGAIN; 657e4d5620SIcenowy Zheng 667e4d5620SIcenowy Zheng return 0; 677e4d5620SIcenowy Zheng } 687e4d5620SIcenowy Zheng 697e4d5620SIcenowy Zheng static void mentor_i2c_interrupt_clear(void) 707e4d5620SIcenowy Zheng { 717e4d5620SIcenowy Zheng uint32_t reg; 727e4d5620SIcenowy Zheng 737e4d5620SIcenowy Zheng reg = mmio_read_32((uintptr_t)&base->control); 7420719914SIcenowy Zheng #ifndef I2C_INTERRUPT_CLEAR_INVERTED 757e4d5620SIcenowy Zheng reg &= ~(I2C_CONTROL_IFLG); 7620719914SIcenowy Zheng #else 7720719914SIcenowy Zheng reg |= I2C_CONTROL_IFLG; 7820719914SIcenowy Zheng #endif 797e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->control, reg); 807e4d5620SIcenowy Zheng /* Wait for 1 us for the clear to take effect */ 817e4d5620SIcenowy Zheng udelay(1); 827e4d5620SIcenowy Zheng } 837e4d5620SIcenowy Zheng 84*d7b4cd41SJustin Chadwell static bool mentor_i2c_interrupt_get(void) 857e4d5620SIcenowy Zheng { 867e4d5620SIcenowy Zheng uint32_t reg; 877e4d5620SIcenowy Zheng 887e4d5620SIcenowy Zheng /* get the interrupt flag bit */ 897e4d5620SIcenowy Zheng reg = mmio_read_32((uintptr_t)&base->control); 907e4d5620SIcenowy Zheng reg &= I2C_CONTROL_IFLG; 91*d7b4cd41SJustin Chadwell return (reg != 0U); 927e4d5620SIcenowy Zheng } 937e4d5620SIcenowy Zheng 947e4d5620SIcenowy Zheng static int mentor_i2c_wait_interrupt(void) 957e4d5620SIcenowy Zheng { 967e4d5620SIcenowy Zheng uint32_t timeout = 0; 977e4d5620SIcenowy Zheng 987e4d5620SIcenowy Zheng while (!mentor_i2c_interrupt_get() && (timeout++ < I2C_TIMEOUT_VALUE)) 997e4d5620SIcenowy Zheng ; 1007e4d5620SIcenowy Zheng if (timeout >= I2C_TIMEOUT_VALUE) 1017e4d5620SIcenowy Zheng return -ETIMEDOUT; 1027e4d5620SIcenowy Zheng 1037e4d5620SIcenowy Zheng return 0; 1047e4d5620SIcenowy Zheng } 1057e4d5620SIcenowy Zheng 1067e4d5620SIcenowy Zheng static int mentor_i2c_start_bit_set(void) 1077e4d5620SIcenowy Zheng { 1087e4d5620SIcenowy Zheng int is_int_flag = 0; 1097e4d5620SIcenowy Zheng uint32_t status; 1107e4d5620SIcenowy Zheng 1117e4d5620SIcenowy Zheng if (mentor_i2c_interrupt_get()) 1127e4d5620SIcenowy Zheng is_int_flag = 1; 1137e4d5620SIcenowy Zheng 1147e4d5620SIcenowy Zheng /* set start bit */ 1157e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->control, 1167e4d5620SIcenowy Zheng mmio_read_32((uintptr_t)&base->control) | 1177e4d5620SIcenowy Zheng I2C_CONTROL_START); 1187e4d5620SIcenowy Zheng 1197e4d5620SIcenowy Zheng /* in case that the int flag was set before i.e. repeated start bit */ 1207e4d5620SIcenowy Zheng if (is_int_flag) { 1217e4d5620SIcenowy Zheng VERBOSE("%s: repeated start Bit\n", __func__); 1227e4d5620SIcenowy Zheng mentor_i2c_interrupt_clear(); 1237e4d5620SIcenowy Zheng } 1247e4d5620SIcenowy Zheng 1257e4d5620SIcenowy Zheng if (mentor_i2c_wait_interrupt()) { 1267e4d5620SIcenowy Zheng ERROR("Start clear bit timeout\n"); 1277e4d5620SIcenowy Zheng return -ETIMEDOUT; 1287e4d5620SIcenowy Zheng } 1297e4d5620SIcenowy Zheng 1307e4d5620SIcenowy Zheng /* check that start bit went down */ 1317e4d5620SIcenowy Zheng if ((mmio_read_32((uintptr_t)&base->control) & 1327e4d5620SIcenowy Zheng I2C_CONTROL_START) != 0) { 1337e4d5620SIcenowy Zheng ERROR("Start bit didn't went down\n"); 1347e4d5620SIcenowy Zheng return -EPERM; 1357e4d5620SIcenowy Zheng } 1367e4d5620SIcenowy Zheng 1377e4d5620SIcenowy Zheng /* check the status */ 1387e4d5620SIcenowy Zheng if (mentor_i2c_lost_arbitration(&status)) { 1397e4d5620SIcenowy Zheng ERROR("%s - %d: Lost arbitration, got status %x\n", 1407e4d5620SIcenowy Zheng __func__, __LINE__, status); 1417e4d5620SIcenowy Zheng return -EAGAIN; 1427e4d5620SIcenowy Zheng } 1437e4d5620SIcenowy Zheng if ((status != I2C_STATUS_START) && 1447e4d5620SIcenowy Zheng (status != I2C_STATUS_REPEATED_START)) { 1457e4d5620SIcenowy Zheng ERROR("Got status %x after enable start bit.\n", status); 1467e4d5620SIcenowy Zheng return -EPERM; 1477e4d5620SIcenowy Zheng } 1487e4d5620SIcenowy Zheng 1497e4d5620SIcenowy Zheng return 0; 1507e4d5620SIcenowy Zheng } 1517e4d5620SIcenowy Zheng 1527e4d5620SIcenowy Zheng static int mentor_i2c_stop_bit_set(void) 1537e4d5620SIcenowy Zheng { 1547e4d5620SIcenowy Zheng int timeout; 1557e4d5620SIcenowy Zheng uint32_t status; 1567e4d5620SIcenowy Zheng 1577e4d5620SIcenowy Zheng /* Generate stop bit */ 1587e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->control, 1597e4d5620SIcenowy Zheng mmio_read_32((uintptr_t)&base->control) | 1607e4d5620SIcenowy Zheng I2C_CONTROL_STOP); 1617e4d5620SIcenowy Zheng mentor_i2c_interrupt_clear(); 1627e4d5620SIcenowy Zheng 1637e4d5620SIcenowy Zheng timeout = 0; 1647e4d5620SIcenowy Zheng /* Read control register, check the control stop bit */ 1657e4d5620SIcenowy Zheng while ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) && 1667e4d5620SIcenowy Zheng (timeout++ < I2C_TIMEOUT_VALUE)) 1677e4d5620SIcenowy Zheng ; 1687e4d5620SIcenowy Zheng if (timeout >= I2C_TIMEOUT_VALUE) { 1697e4d5620SIcenowy Zheng ERROR("Stop bit didn't went down\n"); 1707e4d5620SIcenowy Zheng return -ETIMEDOUT; 1717e4d5620SIcenowy Zheng } 1727e4d5620SIcenowy Zheng 1737e4d5620SIcenowy Zheng /* check that stop bit went down */ 1747e4d5620SIcenowy Zheng if ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) != 0) { 1757e4d5620SIcenowy Zheng ERROR("Stop bit didn't went down\n"); 1767e4d5620SIcenowy Zheng return -EPERM; 1777e4d5620SIcenowy Zheng } 1787e4d5620SIcenowy Zheng 1797e4d5620SIcenowy Zheng /* check the status */ 1807e4d5620SIcenowy Zheng if (mentor_i2c_lost_arbitration(&status)) { 1817e4d5620SIcenowy Zheng ERROR("%s - %d: Lost arbitration, got status %x\n", 1827e4d5620SIcenowy Zheng __func__, __LINE__, status); 1837e4d5620SIcenowy Zheng return -EAGAIN; 1847e4d5620SIcenowy Zheng } 1857e4d5620SIcenowy Zheng if (status != I2C_STATUS_IDLE) { 1867e4d5620SIcenowy Zheng ERROR("Got status %x after enable stop bit.\n", status); 1877e4d5620SIcenowy Zheng return -EPERM; 1887e4d5620SIcenowy Zheng } 1897e4d5620SIcenowy Zheng 1907e4d5620SIcenowy Zheng return 0; 1917e4d5620SIcenowy Zheng } 1927e4d5620SIcenowy Zheng 1937e4d5620SIcenowy Zheng static int mentor_i2c_address_set(uint8_t chain, int command) 1947e4d5620SIcenowy Zheng { 1957e4d5620SIcenowy Zheng uint32_t reg, status; 1967e4d5620SIcenowy Zheng 1977e4d5620SIcenowy Zheng reg = (chain << I2C_DATA_ADDR_7BIT_OFFS) & I2C_DATA_ADDR_7BIT_MASK; 1987e4d5620SIcenowy Zheng reg |= command; 1997e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->data, reg); 2007e4d5620SIcenowy Zheng udelay(1); 2017e4d5620SIcenowy Zheng 2027e4d5620SIcenowy Zheng mentor_i2c_interrupt_clear(); 2037e4d5620SIcenowy Zheng 2047e4d5620SIcenowy Zheng if (mentor_i2c_wait_interrupt()) { 2057e4d5620SIcenowy Zheng ERROR("Start clear bit timeout\n"); 2067e4d5620SIcenowy Zheng return -ETIMEDOUT; 2077e4d5620SIcenowy Zheng } 2087e4d5620SIcenowy Zheng 2097e4d5620SIcenowy Zheng /* check the status */ 2107e4d5620SIcenowy Zheng if (mentor_i2c_lost_arbitration(&status)) { 2117e4d5620SIcenowy Zheng ERROR("%s - %d: Lost arbitration, got status %x\n", 2127e4d5620SIcenowy Zheng __func__, __LINE__, status); 2137e4d5620SIcenowy Zheng return -EAGAIN; 2147e4d5620SIcenowy Zheng } 2157e4d5620SIcenowy Zheng if (((status != I2C_STATUS_ADDR_R_ACK) && (command == I2C_CMD_READ)) || 2167e4d5620SIcenowy Zheng ((status != I2C_STATUS_ADDR_W_ACK) && (command == I2C_CMD_WRITE))) { 2177e4d5620SIcenowy Zheng /* only in debug, since in boot we try to read the SPD 2187e4d5620SIcenowy Zheng * of both DRAM, and we don't want error messages in cas 2197e4d5620SIcenowy Zheng * DIMM doesn't exist. 2207e4d5620SIcenowy Zheng */ 2217e4d5620SIcenowy Zheng INFO("%s: ERROR - status %x addr in %s mode.\n", __func__, 2227e4d5620SIcenowy Zheng status, (command == I2C_CMD_WRITE) ? "Write" : "Read"); 2237e4d5620SIcenowy Zheng return -EPERM; 2247e4d5620SIcenowy Zheng } 2257e4d5620SIcenowy Zheng 2267e4d5620SIcenowy Zheng return 0; 2277e4d5620SIcenowy Zheng } 2287e4d5620SIcenowy Zheng 2297e4d5620SIcenowy Zheng /* 2307e4d5620SIcenowy Zheng * The I2C module contains a clock divider to generate the SCL clock. 2317e4d5620SIcenowy Zheng * This function calculates and sets the <N> and <M> fields in the I2C Baud 2327e4d5620SIcenowy Zheng * Rate Register (t=01) to obtain given 'requested_speed'. 2337e4d5620SIcenowy Zheng * The requested_speed will be equal to: 2347e4d5620SIcenowy Zheng * CONFIG_SYS_TCLK / (10 * (M + 1) * (2 << N)) 2357e4d5620SIcenowy Zheng * Where M is the value represented by bits[6:3] and N is the value represented 2367e4d5620SIcenowy Zheng * by bits[2:0] of "I2C Baud Rate Register". 2377e4d5620SIcenowy Zheng * Therefore max M which can be set is 16 (2^4) and max N is 8 (2^3). So the 2387e4d5620SIcenowy Zheng * lowest possible baudrate is: 2397e4d5620SIcenowy Zheng * CONFIG_SYS_TCLK/(10 * (16 +1) * (2 << 8), which equals to: 2407e4d5620SIcenowy Zheng * CONFIG_SYS_TCLK/87040. Assuming that CONFIG_SYS_TCLK=250MHz, the lowest 2417e4d5620SIcenowy Zheng * possible frequency is ~2,872KHz. 2427e4d5620SIcenowy Zheng */ 2437e4d5620SIcenowy Zheng static unsigned int mentor_i2c_bus_speed_set(unsigned int requested_speed) 2447e4d5620SIcenowy Zheng { 2457e4d5620SIcenowy Zheng unsigned int n, m, freq, margin, min_margin = 0xffffffff; 2467e4d5620SIcenowy Zheng unsigned int actual_n = 0, actual_m = 0; 2477e4d5620SIcenowy Zheng int val; 2487e4d5620SIcenowy Zheng 2497e4d5620SIcenowy Zheng /* Calculate N and M for the TWSI clock baud rate */ 2507e4d5620SIcenowy Zheng for (n = 0; n < 8; n++) { 2517e4d5620SIcenowy Zheng for (m = 0; m < 16; m++) { 2527e4d5620SIcenowy Zheng freq = CONFIG_SYS_TCLK / (10 * (m + 1) * (2 << n)); 2537e4d5620SIcenowy Zheng val = requested_speed - freq; 2547e4d5620SIcenowy Zheng margin = (val > 0) ? val : -val; 2557e4d5620SIcenowy Zheng 2567e4d5620SIcenowy Zheng if ((freq <= requested_speed) && 2577e4d5620SIcenowy Zheng (margin < min_margin)) { 2587e4d5620SIcenowy Zheng min_margin = margin; 2597e4d5620SIcenowy Zheng actual_n = n; 2607e4d5620SIcenowy Zheng actual_m = m; 2617e4d5620SIcenowy Zheng } 2627e4d5620SIcenowy Zheng } 2637e4d5620SIcenowy Zheng } 2647e4d5620SIcenowy Zheng VERBOSE("%s: actual_n = %u, actual_m = %u\n", 2657e4d5620SIcenowy Zheng __func__, actual_n, actual_m); 2667e4d5620SIcenowy Zheng /* Set the baud rate */ 2677e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->baudrate, (actual_m << 3) | actual_n); 2687e4d5620SIcenowy Zheng 2697e4d5620SIcenowy Zheng return 0; 2707e4d5620SIcenowy Zheng } 2717e4d5620SIcenowy Zheng 2727e4d5620SIcenowy Zheng #ifdef DEBUG_I2C 2737e4d5620SIcenowy Zheng static int mentor_i2c_probe(uint8_t chip) 2747e4d5620SIcenowy Zheng { 2757e4d5620SIcenowy Zheng int ret = 0; 2767e4d5620SIcenowy Zheng 2777e4d5620SIcenowy Zheng ret = mentor_i2c_start_bit_set(); 2787e4d5620SIcenowy Zheng if (ret != 0) { 2797e4d5620SIcenowy Zheng mentor_i2c_stop_bit_set(); 2807e4d5620SIcenowy Zheng ERROR("%s - %d: %s", __func__, __LINE__, 2817e4d5620SIcenowy Zheng "mentor_i2c_start_bit_set failed\n"); 2827e4d5620SIcenowy Zheng return -EPERM; 2837e4d5620SIcenowy Zheng } 2847e4d5620SIcenowy Zheng 2857e4d5620SIcenowy Zheng ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE); 2867e4d5620SIcenowy Zheng if (ret != 0) { 2877e4d5620SIcenowy Zheng mentor_i2c_stop_bit_set(); 2887e4d5620SIcenowy Zheng ERROR("%s - %d: %s", __func__, __LINE__, 2897e4d5620SIcenowy Zheng "mentor_i2c_address_set failed\n"); 2907e4d5620SIcenowy Zheng return -EPERM; 2917e4d5620SIcenowy Zheng } 2927e4d5620SIcenowy Zheng 2937e4d5620SIcenowy Zheng mentor_i2c_stop_bit_set(); 2947e4d5620SIcenowy Zheng 2957e4d5620SIcenowy Zheng VERBOSE("%s: successful I2C probe\n", __func__); 2967e4d5620SIcenowy Zheng 2977e4d5620SIcenowy Zheng return ret; 2987e4d5620SIcenowy Zheng } 2997e4d5620SIcenowy Zheng #endif 3007e4d5620SIcenowy Zheng 3017e4d5620SIcenowy Zheng /* regular i2c transaction */ 3027e4d5620SIcenowy Zheng static int mentor_i2c_data_receive(uint8_t *p_block, uint32_t block_size) 3037e4d5620SIcenowy Zheng { 3047e4d5620SIcenowy Zheng uint32_t reg, status, block_size_read = block_size; 3057e4d5620SIcenowy Zheng 3067e4d5620SIcenowy Zheng /* Wait for cause interrupt */ 3077e4d5620SIcenowy Zheng if (mentor_i2c_wait_interrupt()) { 3087e4d5620SIcenowy Zheng ERROR("Start clear bit timeout\n"); 3097e4d5620SIcenowy Zheng return -ETIMEDOUT; 3107e4d5620SIcenowy Zheng } 3117e4d5620SIcenowy Zheng while (block_size_read) { 3127e4d5620SIcenowy Zheng if (block_size_read == 1) { 3137e4d5620SIcenowy Zheng reg = mmio_read_32((uintptr_t)&base->control); 3147e4d5620SIcenowy Zheng reg &= ~(I2C_CONTROL_ACK); 3157e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->control, reg); 3167e4d5620SIcenowy Zheng } 3177e4d5620SIcenowy Zheng mentor_i2c_interrupt_clear(); 3187e4d5620SIcenowy Zheng 3197e4d5620SIcenowy Zheng if (mentor_i2c_wait_interrupt()) { 3207e4d5620SIcenowy Zheng ERROR("Start clear bit timeout\n"); 3217e4d5620SIcenowy Zheng return -ETIMEDOUT; 3227e4d5620SIcenowy Zheng } 3237e4d5620SIcenowy Zheng /* check the status */ 3247e4d5620SIcenowy Zheng if (mentor_i2c_lost_arbitration(&status)) { 3257e4d5620SIcenowy Zheng ERROR("%s - %d: Lost arbitration, got status %x\n", 3267e4d5620SIcenowy Zheng __func__, __LINE__, status); 3277e4d5620SIcenowy Zheng return -EAGAIN; 3287e4d5620SIcenowy Zheng } 3297e4d5620SIcenowy Zheng if ((status != I2C_STATUS_DATA_R_ACK) && 3307e4d5620SIcenowy Zheng (block_size_read != 1)) { 3317e4d5620SIcenowy Zheng ERROR("Status %x in read transaction\n", status); 3327e4d5620SIcenowy Zheng return -EPERM; 3337e4d5620SIcenowy Zheng } 3347e4d5620SIcenowy Zheng if ((status != I2C_STATUS_DATA_R_NAK) && 3357e4d5620SIcenowy Zheng (block_size_read == 1)) { 3367e4d5620SIcenowy Zheng ERROR("Status %x in Rd Terminate\n", status); 3377e4d5620SIcenowy Zheng return -EPERM; 3387e4d5620SIcenowy Zheng } 3397e4d5620SIcenowy Zheng 3407e4d5620SIcenowy Zheng /* read the data */ 3417e4d5620SIcenowy Zheng *p_block = (uint8_t) mmio_read_32((uintptr_t)&base->data); 3427e4d5620SIcenowy Zheng VERBOSE("%s: place %d read %x\n", __func__, 3437e4d5620SIcenowy Zheng block_size - block_size_read, *p_block); 3447e4d5620SIcenowy Zheng p_block++; 3457e4d5620SIcenowy Zheng block_size_read--; 3467e4d5620SIcenowy Zheng } 3477e4d5620SIcenowy Zheng 3487e4d5620SIcenowy Zheng return 0; 3497e4d5620SIcenowy Zheng } 3507e4d5620SIcenowy Zheng 3517e4d5620SIcenowy Zheng static int mentor_i2c_data_transmit(uint8_t *p_block, uint32_t block_size) 3527e4d5620SIcenowy Zheng { 3537e4d5620SIcenowy Zheng uint32_t status, block_size_write = block_size; 3547e4d5620SIcenowy Zheng 3557e4d5620SIcenowy Zheng if (mentor_i2c_wait_interrupt()) { 3567e4d5620SIcenowy Zheng ERROR("Start clear bit timeout\n"); 3577e4d5620SIcenowy Zheng return -ETIMEDOUT; 3587e4d5620SIcenowy Zheng } 3597e4d5620SIcenowy Zheng 3607e4d5620SIcenowy Zheng while (block_size_write) { 3617e4d5620SIcenowy Zheng /* write the data */ 3627e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->data, (uint32_t) *p_block); 3637e4d5620SIcenowy Zheng VERBOSE("%s: index = %d, data = %x\n", __func__, 3647e4d5620SIcenowy Zheng block_size - block_size_write, *p_block); 3657e4d5620SIcenowy Zheng p_block++; 3667e4d5620SIcenowy Zheng block_size_write--; 3677e4d5620SIcenowy Zheng 3687e4d5620SIcenowy Zheng mentor_i2c_interrupt_clear(); 3697e4d5620SIcenowy Zheng 3707e4d5620SIcenowy Zheng if (mentor_i2c_wait_interrupt()) { 3717e4d5620SIcenowy Zheng ERROR("Start clear bit timeout\n"); 3727e4d5620SIcenowy Zheng return -ETIMEDOUT; 3737e4d5620SIcenowy Zheng } 3747e4d5620SIcenowy Zheng 3757e4d5620SIcenowy Zheng /* check the status */ 3767e4d5620SIcenowy Zheng if (mentor_i2c_lost_arbitration(&status)) { 3777e4d5620SIcenowy Zheng ERROR("%s - %d: Lost arbitration, got status %x\n", 3787e4d5620SIcenowy Zheng __func__, __LINE__, status); 3797e4d5620SIcenowy Zheng return -EAGAIN; 3807e4d5620SIcenowy Zheng } 3817e4d5620SIcenowy Zheng if (status != I2C_STATUS_DATA_W_ACK) { 3827e4d5620SIcenowy Zheng ERROR("Status %x in write transaction\n", status); 3837e4d5620SIcenowy Zheng return -EPERM; 3847e4d5620SIcenowy Zheng } 3857e4d5620SIcenowy Zheng } 3867e4d5620SIcenowy Zheng 3877e4d5620SIcenowy Zheng return 0; 3887e4d5620SIcenowy Zheng } 3897e4d5620SIcenowy Zheng 3907e4d5620SIcenowy Zheng static int mentor_i2c_target_offset_set(uint8_t chip, uint32_t addr, int alen) 3917e4d5620SIcenowy Zheng { 3927e4d5620SIcenowy Zheng uint8_t off_block[2]; 3937e4d5620SIcenowy Zheng uint32_t off_size; 3947e4d5620SIcenowy Zheng 3957e4d5620SIcenowy Zheng if (alen == 2) { /* 2-byte addresses support */ 3967e4d5620SIcenowy Zheng off_block[0] = (addr >> 8) & 0xff; 3977e4d5620SIcenowy Zheng off_block[1] = addr & 0xff; 3987e4d5620SIcenowy Zheng off_size = 2; 3997e4d5620SIcenowy Zheng } else { /* 1-byte addresses support */ 4007e4d5620SIcenowy Zheng off_block[0] = addr & 0xff; 4017e4d5620SIcenowy Zheng off_size = 1; 4027e4d5620SIcenowy Zheng } 4037e4d5620SIcenowy Zheng VERBOSE("%s: off_size = %x addr1 = %x addr2 = %x\n", __func__, 4047e4d5620SIcenowy Zheng off_size, off_block[0], off_block[1]); 4057e4d5620SIcenowy Zheng return mentor_i2c_data_transmit(off_block, off_size); 4067e4d5620SIcenowy Zheng } 4077e4d5620SIcenowy Zheng 4087e4d5620SIcenowy Zheng #ifdef I2C_CAN_UNSTUCK 4097e4d5620SIcenowy Zheng static int mentor_i2c_unstuck(int ret) 4107e4d5620SIcenowy Zheng { 4117e4d5620SIcenowy Zheng uint32_t v; 4127e4d5620SIcenowy Zheng 4137e4d5620SIcenowy Zheng if (ret != -ETIMEDOUT) 4147e4d5620SIcenowy Zheng return ret; 4157e4d5620SIcenowy Zheng VERBOSE("Trying to \"unstuck i2c\"... "); 4167e4d5620SIcenowy Zheng i2c_init(base); 4177e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->unstuck, I2C_UNSTUCK_TRIGGER); 4187e4d5620SIcenowy Zheng do { 4197e4d5620SIcenowy Zheng v = mmio_read_32((uintptr_t)&base->unstuck); 4207e4d5620SIcenowy Zheng } while (v & I2C_UNSTUCK_ONGOING); 4217e4d5620SIcenowy Zheng 4227e4d5620SIcenowy Zheng if (v & I2C_UNSTUCK_ERROR) { 4237e4d5620SIcenowy Zheng VERBOSE("failed - soft reset i2c\n"); 4247e4d5620SIcenowy Zheng ret = -EPERM; 4257e4d5620SIcenowy Zheng } else { 4267e4d5620SIcenowy Zheng VERBOSE("ok\n"); 4277e4d5620SIcenowy Zheng i2c_init(base); 4287e4d5620SIcenowy Zheng ret = -EAGAIN; 4297e4d5620SIcenowy Zheng } 4307e4d5620SIcenowy Zheng return ret; 4317e4d5620SIcenowy Zheng } 4327e4d5620SIcenowy Zheng #else 4337e4d5620SIcenowy Zheng static int mentor_i2c_unstuck(int ret) 4347e4d5620SIcenowy Zheng { 4357e4d5620SIcenowy Zheng VERBOSE("Cannot \"unstuck i2c\" - soft reset i2c\n"); 4367e4d5620SIcenowy Zheng return -EPERM; 4377e4d5620SIcenowy Zheng } 4387e4d5620SIcenowy Zheng #endif 4397e4d5620SIcenowy Zheng 4407e4d5620SIcenowy Zheng /* 4417e4d5620SIcenowy Zheng * API Functions 4427e4d5620SIcenowy Zheng */ 4437e4d5620SIcenowy Zheng void i2c_init(void *i2c_base) 4447e4d5620SIcenowy Zheng { 4457e4d5620SIcenowy Zheng /* For I2C speed and slave address, now we do not set them since 4467e4d5620SIcenowy Zheng * we just provide the working speed and slave address otherwhere 4477e4d5620SIcenowy Zheng * for i2c_init 4487e4d5620SIcenowy Zheng */ 4497e4d5620SIcenowy Zheng base = (struct mentor_i2c_regs *)i2c_base; 4507e4d5620SIcenowy Zheng 4517e4d5620SIcenowy Zheng /* Reset the I2C logic */ 4527e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->soft_reset, 0); 4537e4d5620SIcenowy Zheng 4547e4d5620SIcenowy Zheng udelay(200); 4557e4d5620SIcenowy Zheng 4567e4d5620SIcenowy Zheng mentor_i2c_bus_speed_set(CONFIG_SYS_I2C_SPEED); 4577e4d5620SIcenowy Zheng 4587e4d5620SIcenowy Zheng /* Enable the I2C and slave */ 4597e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->control, 4607e4d5620SIcenowy Zheng I2C_CONTROL_TWSIEN | I2C_CONTROL_ACK); 4617e4d5620SIcenowy Zheng 4627e4d5620SIcenowy Zheng /* set the I2C slave address */ 4637e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->xtnd_slave_addr, 0); 4647e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->slave_address, CONFIG_SYS_I2C_SLAVE); 4657e4d5620SIcenowy Zheng 4667e4d5620SIcenowy Zheng /* unmask I2C interrupt */ 4677e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->control, 4687e4d5620SIcenowy Zheng mmio_read_32((uintptr_t)&base->control) | 4697e4d5620SIcenowy Zheng I2C_CONTROL_INTEN); 4707e4d5620SIcenowy Zheng 4717e4d5620SIcenowy Zheng udelay(10); 4727e4d5620SIcenowy Zheng } 4737e4d5620SIcenowy Zheng 4747e4d5620SIcenowy Zheng /* 4757e4d5620SIcenowy Zheng * i2c_read: - Read multiple bytes from an i2c device 4767e4d5620SIcenowy Zheng * 4777e4d5620SIcenowy Zheng * The higher level routines take into account that this function is only 4787e4d5620SIcenowy Zheng * called with len < page length of the device (see configuration file) 4797e4d5620SIcenowy Zheng * 4807e4d5620SIcenowy Zheng * @chip: address of the chip which is to be read 4817e4d5620SIcenowy Zheng * @addr: i2c data address within the chip 4827e4d5620SIcenowy Zheng * @alen: length of the i2c data address (1..2 bytes) 4837e4d5620SIcenowy Zheng * @buffer: where to write the data 4847e4d5620SIcenowy Zheng * @len: how much byte do we want to read 4857e4d5620SIcenowy Zheng * @return: 0 in case of success 4867e4d5620SIcenowy Zheng */ 4877e4d5620SIcenowy Zheng int i2c_read(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len) 4887e4d5620SIcenowy Zheng { 4897e4d5620SIcenowy Zheng int ret = 0; 4907e4d5620SIcenowy Zheng uint32_t counter = 0; 4917e4d5620SIcenowy Zheng 4927e4d5620SIcenowy Zheng #ifdef DEBUG_I2C 4937e4d5620SIcenowy Zheng mentor_i2c_probe(chip); 4947e4d5620SIcenowy Zheng #endif 4957e4d5620SIcenowy Zheng 4967e4d5620SIcenowy Zheng do { 4977e4d5620SIcenowy Zheng if (ret != -EAGAIN && ret) { 4987e4d5620SIcenowy Zheng ERROR("i2c transaction failed, after %d retries\n", 4997e4d5620SIcenowy Zheng counter); 5007e4d5620SIcenowy Zheng mentor_i2c_stop_bit_set(); 5017e4d5620SIcenowy Zheng return ret; 5027e4d5620SIcenowy Zheng } 5037e4d5620SIcenowy Zheng 5047e4d5620SIcenowy Zheng /* wait for 1 us for the interrupt clear to take effect */ 5057e4d5620SIcenowy Zheng if (counter > 0) 5067e4d5620SIcenowy Zheng udelay(1); 5077e4d5620SIcenowy Zheng counter++; 5087e4d5620SIcenowy Zheng 5097e4d5620SIcenowy Zheng ret = mentor_i2c_start_bit_set(); 5107e4d5620SIcenowy Zheng if (ret) { 5117e4d5620SIcenowy Zheng ret = mentor_i2c_unstuck(ret); 5127e4d5620SIcenowy Zheng continue; 5137e4d5620SIcenowy Zheng } 5147e4d5620SIcenowy Zheng 5157e4d5620SIcenowy Zheng /* if EEPROM device */ 5167e4d5620SIcenowy Zheng if (alen != 0) { 5177e4d5620SIcenowy Zheng ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE); 5187e4d5620SIcenowy Zheng if (ret) 5197e4d5620SIcenowy Zheng continue; 5207e4d5620SIcenowy Zheng 5217e4d5620SIcenowy Zheng ret = mentor_i2c_target_offset_set(chip, addr, alen); 5227e4d5620SIcenowy Zheng if (ret) 5237e4d5620SIcenowy Zheng continue; 5247e4d5620SIcenowy Zheng ret = mentor_i2c_start_bit_set(); 5257e4d5620SIcenowy Zheng if (ret) 5267e4d5620SIcenowy Zheng continue; 5277e4d5620SIcenowy Zheng } 5287e4d5620SIcenowy Zheng 5297e4d5620SIcenowy Zheng ret = mentor_i2c_address_set(chip, I2C_CMD_READ); 5307e4d5620SIcenowy Zheng if (ret) 5317e4d5620SIcenowy Zheng continue; 5327e4d5620SIcenowy Zheng 5337e4d5620SIcenowy Zheng ret = mentor_i2c_data_receive(buffer, len); 5347e4d5620SIcenowy Zheng if (ret) 5357e4d5620SIcenowy Zheng continue; 5367e4d5620SIcenowy Zheng 5377e4d5620SIcenowy Zheng ret = mentor_i2c_stop_bit_set(); 5387e4d5620SIcenowy Zheng } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT)); 5397e4d5620SIcenowy Zheng 5407e4d5620SIcenowy Zheng if (counter == I2C_MAX_RETRY_CNT) { 5417e4d5620SIcenowy Zheng ERROR("I2C transactions failed, got EAGAIN %d times\n", 5427e4d5620SIcenowy Zheng I2C_MAX_RETRY_CNT); 5437e4d5620SIcenowy Zheng ret = -EPERM; 5447e4d5620SIcenowy Zheng } 5457e4d5620SIcenowy Zheng mmio_write_32((uintptr_t)&base->control, 5467e4d5620SIcenowy Zheng mmio_read_32((uintptr_t)&base->control) | 5477e4d5620SIcenowy Zheng I2C_CONTROL_ACK); 5487e4d5620SIcenowy Zheng 5497e4d5620SIcenowy Zheng udelay(1); 5507e4d5620SIcenowy Zheng return ret; 5517e4d5620SIcenowy Zheng } 5527e4d5620SIcenowy Zheng 5537e4d5620SIcenowy Zheng /* 5547e4d5620SIcenowy Zheng * i2c_write: - Write multiple bytes to an i2c device 5557e4d5620SIcenowy Zheng * 5567e4d5620SIcenowy Zheng * The higher level routines take into account that this function is only 5577e4d5620SIcenowy Zheng * called with len < page length of the device (see configuration file) 5587e4d5620SIcenowy Zheng * 5597e4d5620SIcenowy Zheng * @chip: address of the chip which is to be written 5607e4d5620SIcenowy Zheng * @addr: i2c data address within the chip 5617e4d5620SIcenowy Zheng * @alen: length of the i2c data address (1..2 bytes) 5627e4d5620SIcenowy Zheng * @buffer: where to find the data to be written 5637e4d5620SIcenowy Zheng * @len: how much byte do we want to read 5647e4d5620SIcenowy Zheng * @return: 0 in case of success 5657e4d5620SIcenowy Zheng */ 5667e4d5620SIcenowy Zheng int i2c_write(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len) 5677e4d5620SIcenowy Zheng { 5687e4d5620SIcenowy Zheng int ret = 0; 5697e4d5620SIcenowy Zheng uint32_t counter = 0; 5707e4d5620SIcenowy Zheng 5717e4d5620SIcenowy Zheng do { 5727e4d5620SIcenowy Zheng if (ret != -EAGAIN && ret) { 5737e4d5620SIcenowy Zheng ERROR("i2c transaction failed\n"); 5747e4d5620SIcenowy Zheng mentor_i2c_stop_bit_set(); 5757e4d5620SIcenowy Zheng return ret; 5767e4d5620SIcenowy Zheng } 5777e4d5620SIcenowy Zheng /* wait for 1 us for the interrupt clear to take effect */ 5787e4d5620SIcenowy Zheng if (counter > 0) 5797e4d5620SIcenowy Zheng udelay(1); 5807e4d5620SIcenowy Zheng counter++; 5817e4d5620SIcenowy Zheng 5827e4d5620SIcenowy Zheng ret = mentor_i2c_start_bit_set(); 5837e4d5620SIcenowy Zheng if (ret) { 5847e4d5620SIcenowy Zheng ret = mentor_i2c_unstuck(ret); 5857e4d5620SIcenowy Zheng continue; 5867e4d5620SIcenowy Zheng } 5877e4d5620SIcenowy Zheng 5887e4d5620SIcenowy Zheng ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE); 5897e4d5620SIcenowy Zheng if (ret) 5907e4d5620SIcenowy Zheng continue; 5917e4d5620SIcenowy Zheng 5927e4d5620SIcenowy Zheng /* if EEPROM device */ 5937e4d5620SIcenowy Zheng if (alen != 0) { 5947e4d5620SIcenowy Zheng ret = mentor_i2c_target_offset_set(chip, addr, alen); 5957e4d5620SIcenowy Zheng if (ret) 5967e4d5620SIcenowy Zheng continue; 5977e4d5620SIcenowy Zheng } 5987e4d5620SIcenowy Zheng 5997e4d5620SIcenowy Zheng ret = mentor_i2c_data_transmit(buffer, len); 6007e4d5620SIcenowy Zheng if (ret) 6017e4d5620SIcenowy Zheng continue; 6027e4d5620SIcenowy Zheng 6037e4d5620SIcenowy Zheng ret = mentor_i2c_stop_bit_set(); 6047e4d5620SIcenowy Zheng } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT)); 6057e4d5620SIcenowy Zheng 6067e4d5620SIcenowy Zheng if (counter == I2C_MAX_RETRY_CNT) { 6077e4d5620SIcenowy Zheng ERROR("I2C transactions failed, got EAGAIN %d times\n", 6087e4d5620SIcenowy Zheng I2C_MAX_RETRY_CNT); 6097e4d5620SIcenowy Zheng ret = -EPERM; 6107e4d5620SIcenowy Zheng } 6117e4d5620SIcenowy Zheng 6127e4d5620SIcenowy Zheng udelay(1); 6137e4d5620SIcenowy Zheng return ret; 6147e4d5620SIcenowy Zheng } 615