1819d0141SSahil Malhotra // SPDX-License-Identifier: BSD-2-Clause 2819d0141SSahil Malhotra /* 3819d0141SSahil Malhotra * Copyright 2021 NXP 4819d0141SSahil Malhotra * 5819d0141SSahil Malhotra * I2C driver for I2C Controller 6819d0141SSahil Malhotra * 7819d0141SSahil Malhotra */ 8819d0141SSahil Malhotra #include <assert.h> 9819d0141SSahil Malhotra #include <drivers/ls_i2c.h> 10819d0141SSahil Malhotra #include <io.h> 11819d0141SSahil Malhotra #include <kernel/boot.h> 12819d0141SSahil Malhotra #include <kernel/dt.h> 13819d0141SSahil Malhotra #include <kernel/delay.h> 14819d0141SSahil Malhotra #include <libfdt.h> 15819d0141SSahil Malhotra #include <mm/core_memprot.h> 16819d0141SSahil Malhotra #include <string.h> 17819d0141SSahil Malhotra 18819d0141SSahil Malhotra static const char * const i2c_controller_map[] = { 19819d0141SSahil Malhotra "/soc/i2c@2000000", "/soc/i2c@2010000", "/soc/i2c@2020000", 20819d0141SSahil Malhotra "/soc/i2c@2030000", "/soc/i2c@2040000", "/soc/i2c@2050000", 21819d0141SSahil Malhotra "/soc/i2c@2060000", "/soc/i2c@2070000" 22819d0141SSahil Malhotra }; 23819d0141SSahil Malhotra 24819d0141SSahil Malhotra /* 25819d0141SSahil Malhotra * I2C divisor and ibfd register values when glitch filter is enabled 26819d0141SSahil Malhotra * In case of duplicate SCL divisor value, the ibfd value with high MUL value 27819d0141SSahil Malhotra * has been selected. A higher MUL value results in a lower sampling rate of 28819d0141SSahil Malhotra * the I2C signals. This gives the I2C module greater immunity against glitches 29819d0141SSahil Malhotra * in the I2C signals. 30819d0141SSahil Malhotra */ 31819d0141SSahil Malhotra static const struct i2c_clock_divisor_pair clk_div_glitch_enabled[] = { 32819d0141SSahil Malhotra { 34, 0x0 }, { 36, 0x1 }, { 38, 0x2 }, { 40, 0x3 }, 33819d0141SSahil Malhotra { 42, 0x4 }, { 44, 0x8 }, { 48, 0x9 }, { 52, 0xA }, 34819d0141SSahil Malhotra { 54, 0x7 }, { 56, 0xB }, { 60, 0xC }, { 64, 0x10 }, 35819d0141SSahil Malhotra { 68, 0x40 }, { 72, 0x41 }, { 76, 0x42 }, { 80, 0x43 }, 36819d0141SSahil Malhotra { 84, 0x44 }, { 88, 0x48 }, { 96, 0x49 }, { 104, 0x4A }, 37819d0141SSahil Malhotra { 108, 0x47 }, { 112, 0x4B }, { 120, 0x4C }, { 128, 0x50 }, 38819d0141SSahil Malhotra { 136, 0x80 }, { 144, 0x81 }, { 152, 0x82 }, { 160, 0x83 }, 39819d0141SSahil Malhotra { 168, 0x84 }, { 176, 0x88 }, { 192, 0x89 }, { 208, 0x8A }, 40819d0141SSahil Malhotra { 216, 0x87 }, { 224, 0x8B }, { 240, 0x8C }, { 256, 0x90 }, 41819d0141SSahil Malhotra { 288, 0x91 }, { 320, 0x92 }, { 336, 0x8F }, { 352, 0x93 }, 42819d0141SSahil Malhotra { 384, 0x98 }, { 416, 0x95 }, { 448, 0x99 }, { 480, 0x96 }, 43819d0141SSahil Malhotra { 512, 0x9A }, { 576, 0x9B }, { 640, 0xA0 }, { 704, 0x9D }, 44819d0141SSahil Malhotra { 768, 0xA1 }, { 832, 0x9E }, { 896, 0xA2 }, { 960, 0x67 }, 45819d0141SSahil Malhotra { 1024, 0xA3 }, { 1152, 0xA4 }, { 1280, 0xA8 }, { 1536, 0xA9 }, 46819d0141SSahil Malhotra { 1792, 0xAA }, { 1920, 0xA7 }, { 2048, 0xAB }, { 2304, 0xAC }, 47819d0141SSahil Malhotra { 2560, 0xB0 }, { 3072, 0xB1 }, { 3584, 0xB2 }, { 3840, 0xAF }, 48819d0141SSahil Malhotra { 4096, 0xB3 }, { 4608, 0xB4 }, { 5120, 0xB8 }, { 6144, 0xB9 }, 49819d0141SSahil Malhotra { 7168, 0xBA }, { 7680, 0xB7 }, { 8192, 0xBB }, { 9216, 0xBC }, 50819d0141SSahil Malhotra { 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF } 51819d0141SSahil Malhotra }; 52819d0141SSahil Malhotra 53819d0141SSahil Malhotra /* 54819d0141SSahil Malhotra * I2C divisor and ibfd register values when glitch filter is disabled. 55819d0141SSahil Malhotra * In case of duplicate SCL divisor value, the ibfd value with high MUL value 56819d0141SSahil Malhotra * has been selected. A higher MUL value results in a lower sampling rate of 57819d0141SSahil Malhotra * the I2C signals. This gives the I2C module greater immunity against glitches 58819d0141SSahil Malhotra * in the I2C signals. 59819d0141SSahil Malhotra */ 60819d0141SSahil Malhotra static const struct i2c_clock_divisor_pair clk_div_glitch_disabled[] = { 61819d0141SSahil Malhotra { 20, 0x0 }, { 22, 0x1 }, { 24, 0x2 }, { 26, 0x3 }, 62819d0141SSahil Malhotra { 28, 0x8 }, { 30, 0x5 }, { 32, 0x9 }, { 34, 0x6 }, 63819d0141SSahil Malhotra { 36, 0x0A }, { 40, 0x40 }, { 44, 0x41 }, { 48, 0x42 }, 64819d0141SSahil Malhotra { 52, 0x43 }, { 56, 0x48 }, { 60, 0x45 }, { 64, 0x49 }, 65819d0141SSahil Malhotra { 68, 0x46 }, { 72, 0x4A }, { 80, 0x80 }, { 88, 0x81 }, 66819d0141SSahil Malhotra { 96, 0x82 }, { 104, 0x83 }, { 112, 0x88 }, { 120, 0x85 }, 67819d0141SSahil Malhotra { 128, 0x89 }, { 136, 0x86 }, { 144, 0x8A }, { 160, 0x8B }, 68819d0141SSahil Malhotra { 176, 0x8C }, { 192, 0x90 }, { 208, 0x56 }, { 224, 0x91 }, 69819d0141SSahil Malhotra { 240, 0x1F }, { 256, 0x92 }, { 272, 0x8F }, { 288, 0x93 }, 70819d0141SSahil Malhotra { 320, 0x98 }, { 352, 0x95 }, { 384, 0x99 }, { 416, 0x96 }, 71819d0141SSahil Malhotra { 448, 0x9A }, { 480, 0x5F }, { 512, 0x9B }, { 576, 0x9C }, 72819d0141SSahil Malhotra { 640, 0xA0 }, { 768, 0xA1 }, { 896, 0xA2 }, { 960, 0x9F }, 73819d0141SSahil Malhotra { 1024, 0xA3 }, { 1152, 0xA4 }, { 1280, 0xA8 }, { 1536, 0xA9 }, 74819d0141SSahil Malhotra { 1792, 0xAA }, { 1920, 0xA7 }, { 2048, 0xAB }, { 2304, 0xAC }, 75819d0141SSahil Malhotra { 2560, 0xAD }, { 3072, 0xB1 }, { 3584, 0xB2 }, { 3840, 0xAF }, 76819d0141SSahil Malhotra { 4096, 0xB3 }, { 4608, 0xB4 }, { 5120, 0xB8 }, { 6144, 0xB9 }, 77819d0141SSahil Malhotra { 7168, 0xBA }, { 7680, 0xB7 }, { 8192, 0xBB }, { 9216, 0xBC }, 78819d0141SSahil Malhotra { 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF } 79819d0141SSahil Malhotra }; 80819d0141SSahil Malhotra 81819d0141SSahil Malhotra void i2c_reset(vaddr_t base) 82819d0141SSahil Malhotra { 83819d0141SSahil Malhotra struct i2c_regs *regs = (struct i2c_regs *)base; 84819d0141SSahil Malhotra 85819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); 86819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF); 87819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_IBIE | I2C_IBCR_DMAEN); 88819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibic, I2C_IBIC_BIIE); 89819d0141SSahil Malhotra } 90819d0141SSahil Malhotra 91819d0141SSahil Malhotra /* 92819d0141SSahil Malhotra * Get I2c Bus Frequency Divider Register value based on clock_divisor 93819d0141SSahil Malhotra * and if the glitch is enabled or not in I2c controller. 94819d0141SSahil Malhotra * base Base address of I2C controller 95819d0141SSahil Malhotra * clock_divisor Clock Divisor 96819d0141SSahil Malhotra */ 97819d0141SSahil Malhotra static uint8_t i2c_get_ibfd(vaddr_t base, uint16_t clock_divisor) 98819d0141SSahil Malhotra { 99819d0141SSahil Malhotra struct i2c_regs *regs = (struct i2c_regs *)base; 100819d0141SSahil Malhotra const struct i2c_clock_divisor_pair *dpair = NULL; 101819d0141SSahil Malhotra size_t dpair_sz = 0; 102819d0141SSahil Malhotra unsigned int n = 0; 103819d0141SSahil Malhotra 104819d0141SSahil Malhotra if (io_read8((vaddr_t)®s->ibdbg) & I2C_IBDBG_GLFLT_EN) { 105819d0141SSahil Malhotra dpair = clk_div_glitch_enabled; 106819d0141SSahil Malhotra dpair_sz = ARRAY_SIZE(clk_div_glitch_enabled); 107819d0141SSahil Malhotra } else { 108819d0141SSahil Malhotra dpair = clk_div_glitch_disabled; 109819d0141SSahil Malhotra dpair_sz = ARRAY_SIZE(clk_div_glitch_disabled); 110819d0141SSahil Malhotra } 111819d0141SSahil Malhotra 112819d0141SSahil Malhotra for (n = 0; n < dpair_sz - 1; n++) 113819d0141SSahil Malhotra if (clock_divisor < dpair[n].divisor) 114819d0141SSahil Malhotra break; 115819d0141SSahil Malhotra 116819d0141SSahil Malhotra return dpair[n].ibfd; 117819d0141SSahil Malhotra } 118819d0141SSahil Malhotra 119819d0141SSahil Malhotra TEE_Result i2c_init(struct ls_i2c_data *i2c_data) 120819d0141SSahil Malhotra { 121819d0141SSahil Malhotra struct i2c_regs *regs = NULL; 122819d0141SSahil Malhotra uint16_t clock_divisor = 0; 123819d0141SSahil Malhotra uint8_t ibfd = 0; /* I2c Bus Frequency Divider Register */ 124819d0141SSahil Malhotra size_t size = 0; 125819d0141SSahil Malhotra int node = 0; 126819d0141SSahil Malhotra vaddr_t ctrl_base = 0; 127819d0141SSahil Malhotra void *fdt = NULL; 128819d0141SSahil Malhotra 129819d0141SSahil Malhotra /* 130819d0141SSahil Malhotra * First get the I2C Controller base address from the DTB 131819d0141SSahil Malhotra * if DTB present and if the I2C Controller defined in it. 132819d0141SSahil Malhotra */ 133819d0141SSahil Malhotra fdt = get_embedded_dt(); 134819d0141SSahil Malhotra if (!fdt) { 135819d0141SSahil Malhotra EMSG("Unable to get the Embedded DTB, I2C init failed\n"); 136819d0141SSahil Malhotra return TEE_ERROR_GENERIC; 137819d0141SSahil Malhotra } 138819d0141SSahil Malhotra 139819d0141SSahil Malhotra node = fdt_path_offset(fdt, 140819d0141SSahil Malhotra i2c_controller_map[i2c_data->i2c_controller]); 141819d0141SSahil Malhotra if (node > 0) { 142*a5d5bbc8SVesa Jääskeläinen if (dt_map_dev(fdt, node, &ctrl_base, &size, 143*a5d5bbc8SVesa Jääskeläinen DT_MAP_AUTO) < 0) { 144819d0141SSahil Malhotra EMSG("Unable to get virtual address"); 145819d0141SSahil Malhotra return TEE_ERROR_GENERIC; 146819d0141SSahil Malhotra } 147819d0141SSahil Malhotra } else { 148819d0141SSahil Malhotra EMSG("Unable to get I2C offset node"); 149819d0141SSahil Malhotra return TEE_ERROR_ITEM_NOT_FOUND; 150819d0141SSahil Malhotra } 151819d0141SSahil Malhotra 152819d0141SSahil Malhotra i2c_data->base = ctrl_base; 153819d0141SSahil Malhotra 154819d0141SSahil Malhotra regs = (struct i2c_regs *)ctrl_base; 155819d0141SSahil Malhotra 156819d0141SSahil Malhotra clock_divisor = (i2c_data->i2c_bus_clock + i2c_data->speed - 1) / 157819d0141SSahil Malhotra i2c_data->speed; 158819d0141SSahil Malhotra ibfd = i2c_get_ibfd(ctrl_base, clock_divisor); 159819d0141SSahil Malhotra 160819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibfd, ibfd); 161819d0141SSahil Malhotra 162819d0141SSahil Malhotra i2c_reset(ctrl_base); 163819d0141SSahil Malhotra 164819d0141SSahil Malhotra return TEE_SUCCESS; 165819d0141SSahil Malhotra } 166819d0141SSahil Malhotra 167819d0141SSahil Malhotra /* 168819d0141SSahil Malhotra * Check if I2C bus is busy with previous transaction or not. 169819d0141SSahil Malhotra * regs pointer to I2c controller registers 170819d0141SSahil Malhotra * test_busy this flag tells if we need to check the busy bit in IBSR reg 171819d0141SSahil Malhotra */ 172819d0141SSahil Malhotra static TEE_Result i2c_bus_test_bus_busy(struct i2c_regs *regs, bool test_busy) 173819d0141SSahil Malhotra { 174819d0141SSahil Malhotra unsigned int n = 0; 175819d0141SSahil Malhotra uint8_t reg = 0; 176819d0141SSahil Malhotra 177819d0141SSahil Malhotra for (n = 0; n < I2C_NUM_RETRIES; n++) { 178819d0141SSahil Malhotra reg = io_read8((vaddr_t)®s->ibsr); 179819d0141SSahil Malhotra 180819d0141SSahil Malhotra if (reg & I2C_IBSR_IBAL) { 181819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibsr, reg); 182819d0141SSahil Malhotra return TEE_ERROR_BUSY; 183819d0141SSahil Malhotra } 184819d0141SSahil Malhotra 185819d0141SSahil Malhotra if (test_busy && (reg & I2C_IBSR_IBB)) 186819d0141SSahil Malhotra break; 187819d0141SSahil Malhotra 188819d0141SSahil Malhotra if (!test_busy && !(reg & I2C_IBSR_IBB)) 189819d0141SSahil Malhotra break; 190819d0141SSahil Malhotra 191819d0141SSahil Malhotra mdelay(1); 192819d0141SSahil Malhotra } 193819d0141SSahil Malhotra 194819d0141SSahil Malhotra if (n == I2C_NUM_RETRIES) 195819d0141SSahil Malhotra return TEE_ERROR_BUSY; 196819d0141SSahil Malhotra 197819d0141SSahil Malhotra return TEE_SUCCESS; 198819d0141SSahil Malhotra } 199819d0141SSahil Malhotra 200819d0141SSahil Malhotra /* 201819d0141SSahil Malhotra * Check if data transfer to/from i2c controller is complete. 202819d0141SSahil Malhotra * regs pointer to I2c controller registers 203819d0141SSahil Malhotra * test_rx_ack this flag tells if we need to check RXAK bit in IBSR reg 204819d0141SSahil Malhotra */ 205819d0141SSahil Malhotra static TEE_Result i2c_transfer_complete(struct i2c_regs *regs, bool test_rx_ack) 206819d0141SSahil Malhotra { 207819d0141SSahil Malhotra unsigned int n = 0; 208819d0141SSahil Malhotra uint8_t reg = 0; 209819d0141SSahil Malhotra 210819d0141SSahil Malhotra for (n = 0; n < I2C_NUM_RETRIES; n++) { 211819d0141SSahil Malhotra reg = io_read8((vaddr_t)®s->ibsr); 212819d0141SSahil Malhotra 213819d0141SSahil Malhotra if (reg & I2C_IBSR_IBIF) { 214819d0141SSahil Malhotra /* Write 1 to clear the IBIF field */ 215819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibsr, reg); 216819d0141SSahil Malhotra break; 217819d0141SSahil Malhotra } 218819d0141SSahil Malhotra mdelay(1); 219819d0141SSahil Malhotra } 220819d0141SSahil Malhotra 221819d0141SSahil Malhotra if (n == I2C_NUM_RETRIES) 222819d0141SSahil Malhotra return TEE_ERROR_BUSY; 223819d0141SSahil Malhotra 224819d0141SSahil Malhotra if (test_rx_ack && (reg & I2C_IBSR_RXAK)) 225819d0141SSahil Malhotra return TEE_ERROR_NO_DATA; 226819d0141SSahil Malhotra 227819d0141SSahil Malhotra if (reg & I2C_IBSR_TCF) 228819d0141SSahil Malhotra return TEE_SUCCESS; 229819d0141SSahil Malhotra 230819d0141SSahil Malhotra return TEE_ERROR_GENERIC; 231819d0141SSahil Malhotra } 232819d0141SSahil Malhotra 233819d0141SSahil Malhotra /* 234819d0141SSahil Malhotra * Read data from I2c controller. 235819d0141SSahil Malhotra * regs pointer to I2c controller registers 236819d0141SSahil Malhotra * slave_address slave address from which to read 237819d0141SSahil Malhotra * operation pointer to i2c_operation struct 238819d0141SSahil Malhotra * is_last_operation if current operation is last operation 239819d0141SSahil Malhotra */ 240819d0141SSahil Malhotra static TEE_Result i2c_read(struct i2c_regs *regs, unsigned int slave_address, 241819d0141SSahil Malhotra struct i2c_operation *operation, 242819d0141SSahil Malhotra bool is_last_operation) 243819d0141SSahil Malhotra { 244819d0141SSahil Malhotra TEE_Result res = TEE_ERROR_GENERIC; 245819d0141SSahil Malhotra unsigned int n = 0; 246819d0141SSahil Malhotra 247819d0141SSahil Malhotra /* Write Slave Address */ 248819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibdr, (slave_address << 0x1) | BIT(0)); 249819d0141SSahil Malhotra res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); 250819d0141SSahil Malhotra if (res) 251819d0141SSahil Malhotra return res; 252819d0141SSahil Malhotra 253819d0141SSahil Malhotra /* select Receive mode. */ 254819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_TXRX); 255819d0141SSahil Malhotra if (operation->length_in_bytes > 1) { 256819d0141SSahil Malhotra /* Set No ACK = 0 */ 257819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_NOACK); 258819d0141SSahil Malhotra } 259819d0141SSahil Malhotra 260819d0141SSahil Malhotra /* Perform a dummy read to initiate the receive operation. */ 261819d0141SSahil Malhotra io_read8((vaddr_t)®s->ibdr); 262819d0141SSahil Malhotra 263819d0141SSahil Malhotra for (n = 0; n < operation->length_in_bytes; n++) { 264819d0141SSahil Malhotra res = i2c_transfer_complete(regs, I2C_BUS_NO_TEST_RX_ACK); 265819d0141SSahil Malhotra if (res) 266819d0141SSahil Malhotra return res; 267819d0141SSahil Malhotra if (n == (operation->length_in_bytes - 2)) { 268819d0141SSahil Malhotra /* Set No ACK = 1 */ 269819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_NOACK); 270819d0141SSahil Malhotra } else if (n == (operation->length_in_bytes - 1)) { 271819d0141SSahil Malhotra if (!is_last_operation) { 272819d0141SSahil Malhotra /* select Transmit mode (for repeat start) */ 273819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, 274819d0141SSahil Malhotra I2C_IBCR_TXRX); 275819d0141SSahil Malhotra } else { 276819d0141SSahil Malhotra /* Generate Stop Signal */ 277819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, 278819d0141SSahil Malhotra (I2C_IBCR_MSSL | I2C_IBCR_TXRX)); 279819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, 280819d0141SSahil Malhotra I2C_BUS_TEST_IDLE); 281819d0141SSahil Malhotra if (res) 282819d0141SSahil Malhotra return res; 283819d0141SSahil Malhotra } 284819d0141SSahil Malhotra } 285819d0141SSahil Malhotra operation->buffer[n] = io_read8((vaddr_t)®s->ibdr); 286819d0141SSahil Malhotra } 287819d0141SSahil Malhotra 288819d0141SSahil Malhotra return TEE_SUCCESS; 289819d0141SSahil Malhotra } 290819d0141SSahil Malhotra 291819d0141SSahil Malhotra /* 292819d0141SSahil Malhotra * Write data to I2c controller 293819d0141SSahil Malhotra * regs pointer to I2c controller registers 294819d0141SSahil Malhotra * slave_address slave address from which to read 295819d0141SSahil Malhotra * operation pointer to i2c_operation struct 296819d0141SSahil Malhotra */ 297819d0141SSahil Malhotra static TEE_Result i2c_write(struct i2c_regs *regs, unsigned int slave_address, 298819d0141SSahil Malhotra struct i2c_operation *operation) 299819d0141SSahil Malhotra { 300819d0141SSahil Malhotra TEE_Result res = TEE_ERROR_GENERIC; 301819d0141SSahil Malhotra unsigned int n = 0; 302819d0141SSahil Malhotra 303819d0141SSahil Malhotra /* Write Slave Address */ 304819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibdr, 305819d0141SSahil Malhotra (slave_address << 0x1) & ~(BIT(0))); 306819d0141SSahil Malhotra res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); 307819d0141SSahil Malhotra if (res) 308819d0141SSahil Malhotra return res; 309819d0141SSahil Malhotra 310819d0141SSahil Malhotra /* Write Data */ 311819d0141SSahil Malhotra for (n = 0; n < operation->length_in_bytes; n++) { 312819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibdr, operation->buffer[n]); 313819d0141SSahil Malhotra res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); 314819d0141SSahil Malhotra if (res) 315819d0141SSahil Malhotra return res; 316819d0141SSahil Malhotra } 317819d0141SSahil Malhotra 318819d0141SSahil Malhotra return TEE_SUCCESS; 319819d0141SSahil Malhotra } 320819d0141SSahil Malhotra 321819d0141SSahil Malhotra /* 322819d0141SSahil Malhotra * Generate Stop Signal and disable I2C controller. 323819d0141SSahil Malhotra * regs pointer to I2c controller registers 324819d0141SSahil Malhotra */ 325819d0141SSahil Malhotra static TEE_Result i2c_stop(struct i2c_regs *regs) 326819d0141SSahil Malhotra { 327819d0141SSahil Malhotra TEE_Result res = TEE_SUCCESS; 328819d0141SSahil Malhotra uint8_t reg = 0; 329819d0141SSahil Malhotra 330819d0141SSahil Malhotra reg = io_read8((vaddr_t)®s->ibsr); 331819d0141SSahil Malhotra if (reg & I2C_IBSR_IBB) { 332819d0141SSahil Malhotra /* Generate Stop Signal */ 333819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, 334819d0141SSahil Malhotra I2C_IBCR_MSSL | I2C_IBCR_TXRX); 335819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE); 336819d0141SSahil Malhotra if (res) 337819d0141SSahil Malhotra return res; 338819d0141SSahil Malhotra } 339819d0141SSahil Malhotra 340819d0141SSahil Malhotra /* Disable I2c Controller */ 341819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); 342819d0141SSahil Malhotra 343819d0141SSahil Malhotra return TEE_SUCCESS; 344819d0141SSahil Malhotra } 345819d0141SSahil Malhotra 346819d0141SSahil Malhotra /* 347819d0141SSahil Malhotra * Generate Start Signal and set I2C controller in transmit mode. 348819d0141SSahil Malhotra * regs pointer to I2c controller registers 349819d0141SSahil Malhotra */ 350819d0141SSahil Malhotra static TEE_Result i2c_start(struct i2c_regs *regs) 351819d0141SSahil Malhotra { 352819d0141SSahil Malhotra TEE_Result res = TEE_ERROR_GENERIC; 353819d0141SSahil Malhotra 354819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF); 355819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); 356819d0141SSahil Malhotra 357819d0141SSahil Malhotra /* Wait controller to be stable */ 358819d0141SSahil Malhotra mdelay(1); 359819d0141SSahil Malhotra 360819d0141SSahil Malhotra /* Generate Start Signal */ 361819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MSSL); 362819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY); 363819d0141SSahil Malhotra if (res) 364819d0141SSahil Malhotra return res; 365819d0141SSahil Malhotra 366819d0141SSahil Malhotra /* Select Transmit Mode. set No ACK = 1 */ 367819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_TXRX | I2C_IBCR_NOACK); 368819d0141SSahil Malhotra 369819d0141SSahil Malhotra return TEE_SUCCESS; 370819d0141SSahil Malhotra } 371819d0141SSahil Malhotra 372819d0141SSahil Malhotra TEE_Result i2c_bus_xfer(vaddr_t base, unsigned int slave_address, 373819d0141SSahil Malhotra struct i2c_operation *i2c_operation, 374819d0141SSahil Malhotra unsigned int operation_count) 375819d0141SSahil Malhotra { 376819d0141SSahil Malhotra unsigned int n = 0; 377819d0141SSahil Malhotra struct i2c_regs *regs = (struct i2c_regs *)base; 378819d0141SSahil Malhotra struct i2c_operation *operation = NULL; 379819d0141SSahil Malhotra TEE_Result res = TEE_ERROR_GENERIC; 380819d0141SSahil Malhotra bool is_last_operation = false; 381819d0141SSahil Malhotra 382819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE); 383819d0141SSahil Malhotra if (res) 384819d0141SSahil Malhotra goto out; 385819d0141SSahil Malhotra 386819d0141SSahil Malhotra res = i2c_start(regs); 387819d0141SSahil Malhotra if (res) 388819d0141SSahil Malhotra goto out; 389819d0141SSahil Malhotra 390819d0141SSahil Malhotra for (n = 0, operation = i2c_operation; 391819d0141SSahil Malhotra n < operation_count; n++, operation++) { 392819d0141SSahil Malhotra if (n == (operation_count - 1)) 393819d0141SSahil Malhotra is_last_operation = true; 394819d0141SSahil Malhotra 395819d0141SSahil Malhotra /* Send repeat start after first transmit/receive */ 396819d0141SSahil Malhotra if (n) { 397819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_RSTA); 398819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY); 399819d0141SSahil Malhotra if (res) 400819d0141SSahil Malhotra goto out; 401819d0141SSahil Malhotra } 402819d0141SSahil Malhotra 403819d0141SSahil Malhotra /* Read/write data */ 404819d0141SSahil Malhotra if (operation->flags & I2C_FLAG_READ) 405819d0141SSahil Malhotra res = i2c_read(regs, slave_address, operation, 406819d0141SSahil Malhotra is_last_operation); 407819d0141SSahil Malhotra else 408819d0141SSahil Malhotra res = i2c_write(regs, slave_address, operation); 409819d0141SSahil Malhotra if (res) 410819d0141SSahil Malhotra goto out; 411819d0141SSahil Malhotra } 412819d0141SSahil Malhotra 413819d0141SSahil Malhotra out: 414819d0141SSahil Malhotra i2c_stop(regs); 415819d0141SSahil Malhotra 416819d0141SSahil Malhotra return res; 417819d0141SSahil Malhotra } 418