1*819d0141SSahil Malhotra // SPDX-License-Identifier: BSD-2-Clause 2*819d0141SSahil Malhotra /* 3*819d0141SSahil Malhotra * Copyright 2021 NXP 4*819d0141SSahil Malhotra * 5*819d0141SSahil Malhotra * I2C driver for I2C Controller 6*819d0141SSahil Malhotra * 7*819d0141SSahil Malhotra */ 8*819d0141SSahil Malhotra #include <assert.h> 9*819d0141SSahil Malhotra #include <drivers/ls_i2c.h> 10*819d0141SSahil Malhotra #include <io.h> 11*819d0141SSahil Malhotra #include <kernel/boot.h> 12*819d0141SSahil Malhotra #include <kernel/dt.h> 13*819d0141SSahil Malhotra #include <kernel/delay.h> 14*819d0141SSahil Malhotra #include <libfdt.h> 15*819d0141SSahil Malhotra #include <mm/core_memprot.h> 16*819d0141SSahil Malhotra #include <string.h> 17*819d0141SSahil Malhotra 18*819d0141SSahil Malhotra static const char * const i2c_controller_map[] = { 19*819d0141SSahil Malhotra "/soc/i2c@2000000", "/soc/i2c@2010000", "/soc/i2c@2020000", 20*819d0141SSahil Malhotra "/soc/i2c@2030000", "/soc/i2c@2040000", "/soc/i2c@2050000", 21*819d0141SSahil Malhotra "/soc/i2c@2060000", "/soc/i2c@2070000" 22*819d0141SSahil Malhotra }; 23*819d0141SSahil Malhotra 24*819d0141SSahil Malhotra /* 25*819d0141SSahil Malhotra * I2C divisor and ibfd register values when glitch filter is enabled 26*819d0141SSahil Malhotra * In case of duplicate SCL divisor value, the ibfd value with high MUL value 27*819d0141SSahil Malhotra * has been selected. A higher MUL value results in a lower sampling rate of 28*819d0141SSahil Malhotra * the I2C signals. This gives the I2C module greater immunity against glitches 29*819d0141SSahil Malhotra * in the I2C signals. 30*819d0141SSahil Malhotra */ 31*819d0141SSahil Malhotra static const struct i2c_clock_divisor_pair clk_div_glitch_enabled[] = { 32*819d0141SSahil Malhotra { 34, 0x0 }, { 36, 0x1 }, { 38, 0x2 }, { 40, 0x3 }, 33*819d0141SSahil Malhotra { 42, 0x4 }, { 44, 0x8 }, { 48, 0x9 }, { 52, 0xA }, 34*819d0141SSahil Malhotra { 54, 0x7 }, { 56, 0xB }, { 60, 0xC }, { 64, 0x10 }, 35*819d0141SSahil Malhotra { 68, 0x40 }, { 72, 0x41 }, { 76, 0x42 }, { 80, 0x43 }, 36*819d0141SSahil Malhotra { 84, 0x44 }, { 88, 0x48 }, { 96, 0x49 }, { 104, 0x4A }, 37*819d0141SSahil Malhotra { 108, 0x47 }, { 112, 0x4B }, { 120, 0x4C }, { 128, 0x50 }, 38*819d0141SSahil Malhotra { 136, 0x80 }, { 144, 0x81 }, { 152, 0x82 }, { 160, 0x83 }, 39*819d0141SSahil Malhotra { 168, 0x84 }, { 176, 0x88 }, { 192, 0x89 }, { 208, 0x8A }, 40*819d0141SSahil Malhotra { 216, 0x87 }, { 224, 0x8B }, { 240, 0x8C }, { 256, 0x90 }, 41*819d0141SSahil Malhotra { 288, 0x91 }, { 320, 0x92 }, { 336, 0x8F }, { 352, 0x93 }, 42*819d0141SSahil Malhotra { 384, 0x98 }, { 416, 0x95 }, { 448, 0x99 }, { 480, 0x96 }, 43*819d0141SSahil Malhotra { 512, 0x9A }, { 576, 0x9B }, { 640, 0xA0 }, { 704, 0x9D }, 44*819d0141SSahil Malhotra { 768, 0xA1 }, { 832, 0x9E }, { 896, 0xA2 }, { 960, 0x67 }, 45*819d0141SSahil Malhotra { 1024, 0xA3 }, { 1152, 0xA4 }, { 1280, 0xA8 }, { 1536, 0xA9 }, 46*819d0141SSahil Malhotra { 1792, 0xAA }, { 1920, 0xA7 }, { 2048, 0xAB }, { 2304, 0xAC }, 47*819d0141SSahil Malhotra { 2560, 0xB0 }, { 3072, 0xB1 }, { 3584, 0xB2 }, { 3840, 0xAF }, 48*819d0141SSahil Malhotra { 4096, 0xB3 }, { 4608, 0xB4 }, { 5120, 0xB8 }, { 6144, 0xB9 }, 49*819d0141SSahil Malhotra { 7168, 0xBA }, { 7680, 0xB7 }, { 8192, 0xBB }, { 9216, 0xBC }, 50*819d0141SSahil Malhotra { 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF } 51*819d0141SSahil Malhotra }; 52*819d0141SSahil Malhotra 53*819d0141SSahil Malhotra /* 54*819d0141SSahil Malhotra * I2C divisor and ibfd register values when glitch filter is disabled. 55*819d0141SSahil Malhotra * In case of duplicate SCL divisor value, the ibfd value with high MUL value 56*819d0141SSahil Malhotra * has been selected. A higher MUL value results in a lower sampling rate of 57*819d0141SSahil Malhotra * the I2C signals. This gives the I2C module greater immunity against glitches 58*819d0141SSahil Malhotra * in the I2C signals. 59*819d0141SSahil Malhotra */ 60*819d0141SSahil Malhotra static const struct i2c_clock_divisor_pair clk_div_glitch_disabled[] = { 61*819d0141SSahil Malhotra { 20, 0x0 }, { 22, 0x1 }, { 24, 0x2 }, { 26, 0x3 }, 62*819d0141SSahil Malhotra { 28, 0x8 }, { 30, 0x5 }, { 32, 0x9 }, { 34, 0x6 }, 63*819d0141SSahil Malhotra { 36, 0x0A }, { 40, 0x40 }, { 44, 0x41 }, { 48, 0x42 }, 64*819d0141SSahil Malhotra { 52, 0x43 }, { 56, 0x48 }, { 60, 0x45 }, { 64, 0x49 }, 65*819d0141SSahil Malhotra { 68, 0x46 }, { 72, 0x4A }, { 80, 0x80 }, { 88, 0x81 }, 66*819d0141SSahil Malhotra { 96, 0x82 }, { 104, 0x83 }, { 112, 0x88 }, { 120, 0x85 }, 67*819d0141SSahil Malhotra { 128, 0x89 }, { 136, 0x86 }, { 144, 0x8A }, { 160, 0x8B }, 68*819d0141SSahil Malhotra { 176, 0x8C }, { 192, 0x90 }, { 208, 0x56 }, { 224, 0x91 }, 69*819d0141SSahil Malhotra { 240, 0x1F }, { 256, 0x92 }, { 272, 0x8F }, { 288, 0x93 }, 70*819d0141SSahil Malhotra { 320, 0x98 }, { 352, 0x95 }, { 384, 0x99 }, { 416, 0x96 }, 71*819d0141SSahil Malhotra { 448, 0x9A }, { 480, 0x5F }, { 512, 0x9B }, { 576, 0x9C }, 72*819d0141SSahil Malhotra { 640, 0xA0 }, { 768, 0xA1 }, { 896, 0xA2 }, { 960, 0x9F }, 73*819d0141SSahil Malhotra { 1024, 0xA3 }, { 1152, 0xA4 }, { 1280, 0xA8 }, { 1536, 0xA9 }, 74*819d0141SSahil Malhotra { 1792, 0xAA }, { 1920, 0xA7 }, { 2048, 0xAB }, { 2304, 0xAC }, 75*819d0141SSahil Malhotra { 2560, 0xAD }, { 3072, 0xB1 }, { 3584, 0xB2 }, { 3840, 0xAF }, 76*819d0141SSahil Malhotra { 4096, 0xB3 }, { 4608, 0xB4 }, { 5120, 0xB8 }, { 6144, 0xB9 }, 77*819d0141SSahil Malhotra { 7168, 0xBA }, { 7680, 0xB7 }, { 8192, 0xBB }, { 9216, 0xBC }, 78*819d0141SSahil Malhotra { 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF } 79*819d0141SSahil Malhotra }; 80*819d0141SSahil Malhotra 81*819d0141SSahil Malhotra void i2c_reset(vaddr_t base) 82*819d0141SSahil Malhotra { 83*819d0141SSahil Malhotra struct i2c_regs *regs = (struct i2c_regs *)base; 84*819d0141SSahil Malhotra 85*819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); 86*819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF); 87*819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_IBIE | I2C_IBCR_DMAEN); 88*819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibic, I2C_IBIC_BIIE); 89*819d0141SSahil Malhotra } 90*819d0141SSahil Malhotra 91*819d0141SSahil Malhotra /* 92*819d0141SSahil Malhotra * Get I2c Bus Frequency Divider Register value based on clock_divisor 93*819d0141SSahil Malhotra * and if the glitch is enabled or not in I2c controller. 94*819d0141SSahil Malhotra * base Base address of I2C controller 95*819d0141SSahil Malhotra * clock_divisor Clock Divisor 96*819d0141SSahil Malhotra */ 97*819d0141SSahil Malhotra static uint8_t i2c_get_ibfd(vaddr_t base, uint16_t clock_divisor) 98*819d0141SSahil Malhotra { 99*819d0141SSahil Malhotra struct i2c_regs *regs = (struct i2c_regs *)base; 100*819d0141SSahil Malhotra const struct i2c_clock_divisor_pair *dpair = NULL; 101*819d0141SSahil Malhotra size_t dpair_sz = 0; 102*819d0141SSahil Malhotra unsigned int n = 0; 103*819d0141SSahil Malhotra 104*819d0141SSahil Malhotra if (io_read8((vaddr_t)®s->ibdbg) & I2C_IBDBG_GLFLT_EN) { 105*819d0141SSahil Malhotra dpair = clk_div_glitch_enabled; 106*819d0141SSahil Malhotra dpair_sz = ARRAY_SIZE(clk_div_glitch_enabled); 107*819d0141SSahil Malhotra } else { 108*819d0141SSahil Malhotra dpair = clk_div_glitch_disabled; 109*819d0141SSahil Malhotra dpair_sz = ARRAY_SIZE(clk_div_glitch_disabled); 110*819d0141SSahil Malhotra } 111*819d0141SSahil Malhotra 112*819d0141SSahil Malhotra for (n = 0; n < dpair_sz - 1; n++) 113*819d0141SSahil Malhotra if (clock_divisor < dpair[n].divisor) 114*819d0141SSahil Malhotra break; 115*819d0141SSahil Malhotra 116*819d0141SSahil Malhotra return dpair[n].ibfd; 117*819d0141SSahil Malhotra } 118*819d0141SSahil Malhotra 119*819d0141SSahil Malhotra TEE_Result i2c_init(struct ls_i2c_data *i2c_data) 120*819d0141SSahil Malhotra { 121*819d0141SSahil Malhotra struct i2c_regs *regs = NULL; 122*819d0141SSahil Malhotra uint16_t clock_divisor = 0; 123*819d0141SSahil Malhotra uint8_t ibfd = 0; /* I2c Bus Frequency Divider Register */ 124*819d0141SSahil Malhotra size_t size = 0; 125*819d0141SSahil Malhotra int node = 0; 126*819d0141SSahil Malhotra vaddr_t ctrl_base = 0; 127*819d0141SSahil Malhotra void *fdt = NULL; 128*819d0141SSahil Malhotra 129*819d0141SSahil Malhotra /* 130*819d0141SSahil Malhotra * First get the I2C Controller base address from the DTB 131*819d0141SSahil Malhotra * if DTB present and if the I2C Controller defined in it. 132*819d0141SSahil Malhotra */ 133*819d0141SSahil Malhotra fdt = get_embedded_dt(); 134*819d0141SSahil Malhotra if (!fdt) { 135*819d0141SSahil Malhotra EMSG("Unable to get the Embedded DTB, I2C init failed\n"); 136*819d0141SSahil Malhotra return TEE_ERROR_GENERIC; 137*819d0141SSahil Malhotra } 138*819d0141SSahil Malhotra 139*819d0141SSahil Malhotra node = fdt_path_offset(fdt, 140*819d0141SSahil Malhotra i2c_controller_map[i2c_data->i2c_controller]); 141*819d0141SSahil Malhotra if (node > 0) { 142*819d0141SSahil Malhotra if (dt_map_dev(fdt, node, &ctrl_base, &size) < 0) { 143*819d0141SSahil Malhotra EMSG("Unable to get virtual address"); 144*819d0141SSahil Malhotra return TEE_ERROR_GENERIC; 145*819d0141SSahil Malhotra } 146*819d0141SSahil Malhotra } else { 147*819d0141SSahil Malhotra EMSG("Unable to get I2C offset node"); 148*819d0141SSahil Malhotra return TEE_ERROR_ITEM_NOT_FOUND; 149*819d0141SSahil Malhotra } 150*819d0141SSahil Malhotra 151*819d0141SSahil Malhotra i2c_data->base = ctrl_base; 152*819d0141SSahil Malhotra 153*819d0141SSahil Malhotra regs = (struct i2c_regs *)ctrl_base; 154*819d0141SSahil Malhotra 155*819d0141SSahil Malhotra clock_divisor = (i2c_data->i2c_bus_clock + i2c_data->speed - 1) / 156*819d0141SSahil Malhotra i2c_data->speed; 157*819d0141SSahil Malhotra ibfd = i2c_get_ibfd(ctrl_base, clock_divisor); 158*819d0141SSahil Malhotra 159*819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibfd, ibfd); 160*819d0141SSahil Malhotra 161*819d0141SSahil Malhotra i2c_reset(ctrl_base); 162*819d0141SSahil Malhotra 163*819d0141SSahil Malhotra return TEE_SUCCESS; 164*819d0141SSahil Malhotra } 165*819d0141SSahil Malhotra 166*819d0141SSahil Malhotra /* 167*819d0141SSahil Malhotra * Check if I2C bus is busy with previous transaction or not. 168*819d0141SSahil Malhotra * regs pointer to I2c controller registers 169*819d0141SSahil Malhotra * test_busy this flag tells if we need to check the busy bit in IBSR reg 170*819d0141SSahil Malhotra */ 171*819d0141SSahil Malhotra static TEE_Result i2c_bus_test_bus_busy(struct i2c_regs *regs, bool test_busy) 172*819d0141SSahil Malhotra { 173*819d0141SSahil Malhotra unsigned int n = 0; 174*819d0141SSahil Malhotra uint8_t reg = 0; 175*819d0141SSahil Malhotra 176*819d0141SSahil Malhotra for (n = 0; n < I2C_NUM_RETRIES; n++) { 177*819d0141SSahil Malhotra reg = io_read8((vaddr_t)®s->ibsr); 178*819d0141SSahil Malhotra 179*819d0141SSahil Malhotra if (reg & I2C_IBSR_IBAL) { 180*819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibsr, reg); 181*819d0141SSahil Malhotra return TEE_ERROR_BUSY; 182*819d0141SSahil Malhotra } 183*819d0141SSahil Malhotra 184*819d0141SSahil Malhotra if (test_busy && (reg & I2C_IBSR_IBB)) 185*819d0141SSahil Malhotra break; 186*819d0141SSahil Malhotra 187*819d0141SSahil Malhotra if (!test_busy && !(reg & I2C_IBSR_IBB)) 188*819d0141SSahil Malhotra break; 189*819d0141SSahil Malhotra 190*819d0141SSahil Malhotra mdelay(1); 191*819d0141SSahil Malhotra } 192*819d0141SSahil Malhotra 193*819d0141SSahil Malhotra if (n == I2C_NUM_RETRIES) 194*819d0141SSahil Malhotra return TEE_ERROR_BUSY; 195*819d0141SSahil Malhotra 196*819d0141SSahil Malhotra return TEE_SUCCESS; 197*819d0141SSahil Malhotra } 198*819d0141SSahil Malhotra 199*819d0141SSahil Malhotra /* 200*819d0141SSahil Malhotra * Check if data transfer to/from i2c controller is complete. 201*819d0141SSahil Malhotra * regs pointer to I2c controller registers 202*819d0141SSahil Malhotra * test_rx_ack this flag tells if we need to check RXAK bit in IBSR reg 203*819d0141SSahil Malhotra */ 204*819d0141SSahil Malhotra static TEE_Result i2c_transfer_complete(struct i2c_regs *regs, bool test_rx_ack) 205*819d0141SSahil Malhotra { 206*819d0141SSahil Malhotra unsigned int n = 0; 207*819d0141SSahil Malhotra uint8_t reg = 0; 208*819d0141SSahil Malhotra 209*819d0141SSahil Malhotra for (n = 0; n < I2C_NUM_RETRIES; n++) { 210*819d0141SSahil Malhotra reg = io_read8((vaddr_t)®s->ibsr); 211*819d0141SSahil Malhotra 212*819d0141SSahil Malhotra if (reg & I2C_IBSR_IBIF) { 213*819d0141SSahil Malhotra /* Write 1 to clear the IBIF field */ 214*819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibsr, reg); 215*819d0141SSahil Malhotra break; 216*819d0141SSahil Malhotra } 217*819d0141SSahil Malhotra mdelay(1); 218*819d0141SSahil Malhotra } 219*819d0141SSahil Malhotra 220*819d0141SSahil Malhotra if (n == I2C_NUM_RETRIES) 221*819d0141SSahil Malhotra return TEE_ERROR_BUSY; 222*819d0141SSahil Malhotra 223*819d0141SSahil Malhotra if (test_rx_ack && (reg & I2C_IBSR_RXAK)) 224*819d0141SSahil Malhotra return TEE_ERROR_NO_DATA; 225*819d0141SSahil Malhotra 226*819d0141SSahil Malhotra if (reg & I2C_IBSR_TCF) 227*819d0141SSahil Malhotra return TEE_SUCCESS; 228*819d0141SSahil Malhotra 229*819d0141SSahil Malhotra return TEE_ERROR_GENERIC; 230*819d0141SSahil Malhotra } 231*819d0141SSahil Malhotra 232*819d0141SSahil Malhotra /* 233*819d0141SSahil Malhotra * Read data from I2c controller. 234*819d0141SSahil Malhotra * regs pointer to I2c controller registers 235*819d0141SSahil Malhotra * slave_address slave address from which to read 236*819d0141SSahil Malhotra * operation pointer to i2c_operation struct 237*819d0141SSahil Malhotra * is_last_operation if current operation is last operation 238*819d0141SSahil Malhotra */ 239*819d0141SSahil Malhotra static TEE_Result i2c_read(struct i2c_regs *regs, unsigned int slave_address, 240*819d0141SSahil Malhotra struct i2c_operation *operation, 241*819d0141SSahil Malhotra bool is_last_operation) 242*819d0141SSahil Malhotra { 243*819d0141SSahil Malhotra TEE_Result res = TEE_ERROR_GENERIC; 244*819d0141SSahil Malhotra unsigned int n = 0; 245*819d0141SSahil Malhotra 246*819d0141SSahil Malhotra /* Write Slave Address */ 247*819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibdr, (slave_address << 0x1) | BIT(0)); 248*819d0141SSahil Malhotra res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); 249*819d0141SSahil Malhotra if (res) 250*819d0141SSahil Malhotra return res; 251*819d0141SSahil Malhotra 252*819d0141SSahil Malhotra /* select Receive mode. */ 253*819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_TXRX); 254*819d0141SSahil Malhotra if (operation->length_in_bytes > 1) { 255*819d0141SSahil Malhotra /* Set No ACK = 0 */ 256*819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_NOACK); 257*819d0141SSahil Malhotra } 258*819d0141SSahil Malhotra 259*819d0141SSahil Malhotra /* Perform a dummy read to initiate the receive operation. */ 260*819d0141SSahil Malhotra io_read8((vaddr_t)®s->ibdr); 261*819d0141SSahil Malhotra 262*819d0141SSahil Malhotra for (n = 0; n < operation->length_in_bytes; n++) { 263*819d0141SSahil Malhotra res = i2c_transfer_complete(regs, I2C_BUS_NO_TEST_RX_ACK); 264*819d0141SSahil Malhotra if (res) 265*819d0141SSahil Malhotra return res; 266*819d0141SSahil Malhotra if (n == (operation->length_in_bytes - 2)) { 267*819d0141SSahil Malhotra /* Set No ACK = 1 */ 268*819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_NOACK); 269*819d0141SSahil Malhotra } else if (n == (operation->length_in_bytes - 1)) { 270*819d0141SSahil Malhotra if (!is_last_operation) { 271*819d0141SSahil Malhotra /* select Transmit mode (for repeat start) */ 272*819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, 273*819d0141SSahil Malhotra I2C_IBCR_TXRX); 274*819d0141SSahil Malhotra } else { 275*819d0141SSahil Malhotra /* Generate Stop Signal */ 276*819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, 277*819d0141SSahil Malhotra (I2C_IBCR_MSSL | I2C_IBCR_TXRX)); 278*819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, 279*819d0141SSahil Malhotra I2C_BUS_TEST_IDLE); 280*819d0141SSahil Malhotra if (res) 281*819d0141SSahil Malhotra return res; 282*819d0141SSahil Malhotra } 283*819d0141SSahil Malhotra } 284*819d0141SSahil Malhotra operation->buffer[n] = io_read8((vaddr_t)®s->ibdr); 285*819d0141SSahil Malhotra } 286*819d0141SSahil Malhotra 287*819d0141SSahil Malhotra return TEE_SUCCESS; 288*819d0141SSahil Malhotra } 289*819d0141SSahil Malhotra 290*819d0141SSahil Malhotra /* 291*819d0141SSahil Malhotra * Write data to I2c controller 292*819d0141SSahil Malhotra * regs pointer to I2c controller registers 293*819d0141SSahil Malhotra * slave_address slave address from which to read 294*819d0141SSahil Malhotra * operation pointer to i2c_operation struct 295*819d0141SSahil Malhotra */ 296*819d0141SSahil Malhotra static TEE_Result i2c_write(struct i2c_regs *regs, unsigned int slave_address, 297*819d0141SSahil Malhotra struct i2c_operation *operation) 298*819d0141SSahil Malhotra { 299*819d0141SSahil Malhotra TEE_Result res = TEE_ERROR_GENERIC; 300*819d0141SSahil Malhotra unsigned int n = 0; 301*819d0141SSahil Malhotra 302*819d0141SSahil Malhotra /* Write Slave Address */ 303*819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibdr, 304*819d0141SSahil Malhotra (slave_address << 0x1) & ~(BIT(0))); 305*819d0141SSahil Malhotra res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); 306*819d0141SSahil Malhotra if (res) 307*819d0141SSahil Malhotra return res; 308*819d0141SSahil Malhotra 309*819d0141SSahil Malhotra /* Write Data */ 310*819d0141SSahil Malhotra for (n = 0; n < operation->length_in_bytes; n++) { 311*819d0141SSahil Malhotra io_write8((vaddr_t)®s->ibdr, operation->buffer[n]); 312*819d0141SSahil Malhotra res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); 313*819d0141SSahil Malhotra if (res) 314*819d0141SSahil Malhotra return res; 315*819d0141SSahil Malhotra } 316*819d0141SSahil Malhotra 317*819d0141SSahil Malhotra return TEE_SUCCESS; 318*819d0141SSahil Malhotra } 319*819d0141SSahil Malhotra 320*819d0141SSahil Malhotra /* 321*819d0141SSahil Malhotra * Generate Stop Signal and disable I2C controller. 322*819d0141SSahil Malhotra * regs pointer to I2c controller registers 323*819d0141SSahil Malhotra */ 324*819d0141SSahil Malhotra static TEE_Result i2c_stop(struct i2c_regs *regs) 325*819d0141SSahil Malhotra { 326*819d0141SSahil Malhotra TEE_Result res = TEE_SUCCESS; 327*819d0141SSahil Malhotra uint8_t reg = 0; 328*819d0141SSahil Malhotra 329*819d0141SSahil Malhotra reg = io_read8((vaddr_t)®s->ibsr); 330*819d0141SSahil Malhotra if (reg & I2C_IBSR_IBB) { 331*819d0141SSahil Malhotra /* Generate Stop Signal */ 332*819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, 333*819d0141SSahil Malhotra I2C_IBCR_MSSL | I2C_IBCR_TXRX); 334*819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE); 335*819d0141SSahil Malhotra if (res) 336*819d0141SSahil Malhotra return res; 337*819d0141SSahil Malhotra } 338*819d0141SSahil Malhotra 339*819d0141SSahil Malhotra /* Disable I2c Controller */ 340*819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); 341*819d0141SSahil Malhotra 342*819d0141SSahil Malhotra return TEE_SUCCESS; 343*819d0141SSahil Malhotra } 344*819d0141SSahil Malhotra 345*819d0141SSahil Malhotra /* 346*819d0141SSahil Malhotra * Generate Start Signal and set I2C controller in transmit mode. 347*819d0141SSahil Malhotra * regs pointer to I2c controller registers 348*819d0141SSahil Malhotra */ 349*819d0141SSahil Malhotra static TEE_Result i2c_start(struct i2c_regs *regs) 350*819d0141SSahil Malhotra { 351*819d0141SSahil Malhotra TEE_Result res = TEE_ERROR_GENERIC; 352*819d0141SSahil Malhotra 353*819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF); 354*819d0141SSahil Malhotra io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); 355*819d0141SSahil Malhotra 356*819d0141SSahil Malhotra /* Wait controller to be stable */ 357*819d0141SSahil Malhotra mdelay(1); 358*819d0141SSahil Malhotra 359*819d0141SSahil Malhotra /* Generate Start Signal */ 360*819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MSSL); 361*819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY); 362*819d0141SSahil Malhotra if (res) 363*819d0141SSahil Malhotra return res; 364*819d0141SSahil Malhotra 365*819d0141SSahil Malhotra /* Select Transmit Mode. set No ACK = 1 */ 366*819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_TXRX | I2C_IBCR_NOACK); 367*819d0141SSahil Malhotra 368*819d0141SSahil Malhotra return TEE_SUCCESS; 369*819d0141SSahil Malhotra } 370*819d0141SSahil Malhotra 371*819d0141SSahil Malhotra TEE_Result i2c_bus_xfer(vaddr_t base, unsigned int slave_address, 372*819d0141SSahil Malhotra struct i2c_operation *i2c_operation, 373*819d0141SSahil Malhotra unsigned int operation_count) 374*819d0141SSahil Malhotra { 375*819d0141SSahil Malhotra unsigned int n = 0; 376*819d0141SSahil Malhotra struct i2c_regs *regs = (struct i2c_regs *)base; 377*819d0141SSahil Malhotra struct i2c_operation *operation = NULL; 378*819d0141SSahil Malhotra TEE_Result res = TEE_ERROR_GENERIC; 379*819d0141SSahil Malhotra bool is_last_operation = false; 380*819d0141SSahil Malhotra 381*819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE); 382*819d0141SSahil Malhotra if (res) 383*819d0141SSahil Malhotra goto out; 384*819d0141SSahil Malhotra 385*819d0141SSahil Malhotra res = i2c_start(regs); 386*819d0141SSahil Malhotra if (res) 387*819d0141SSahil Malhotra goto out; 388*819d0141SSahil Malhotra 389*819d0141SSahil Malhotra for (n = 0, operation = i2c_operation; 390*819d0141SSahil Malhotra n < operation_count; n++, operation++) { 391*819d0141SSahil Malhotra if (n == (operation_count - 1)) 392*819d0141SSahil Malhotra is_last_operation = true; 393*819d0141SSahil Malhotra 394*819d0141SSahil Malhotra /* Send repeat start after first transmit/receive */ 395*819d0141SSahil Malhotra if (n) { 396*819d0141SSahil Malhotra io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_RSTA); 397*819d0141SSahil Malhotra res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY); 398*819d0141SSahil Malhotra if (res) 399*819d0141SSahil Malhotra goto out; 400*819d0141SSahil Malhotra } 401*819d0141SSahil Malhotra 402*819d0141SSahil Malhotra /* Read/write data */ 403*819d0141SSahil Malhotra if (operation->flags & I2C_FLAG_READ) 404*819d0141SSahil Malhotra res = i2c_read(regs, slave_address, operation, 405*819d0141SSahil Malhotra is_last_operation); 406*819d0141SSahil Malhotra else 407*819d0141SSahil Malhotra res = i2c_write(regs, slave_address, operation); 408*819d0141SSahil Malhotra if (res) 409*819d0141SSahil Malhotra goto out; 410*819d0141SSahil Malhotra } 411*819d0141SSahil Malhotra 412*819d0141SSahil Malhotra out: 413*819d0141SSahil Malhotra i2c_stop(regs); 414*819d0141SSahil Malhotra 415*819d0141SSahil Malhotra return res; 416*819d0141SSahil Malhotra } 417