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