text: // SPDX-License-Identifier: BSD-2-Clause
  /*
   * Copyright 2021 NXP
   *
   * I2C driver for I2C Controller
   *
   */
  #include <assert.h>
  #include <drivers/ls_i2c.h>
  #include <io.h>
  #include <kernel/boot.h>
  #include <kernel/dt.h>
  #include <kernel/delay.h>
  #include <libfdt.h>
  #include <mm/core_memprot.h>
  #include <string.h>
  
  static const char * const i2c_controller_map[] = {
  	"/soc/i2c@2000000", "/soc/i2c@2010000", "/soc/i2c@2020000",
  	"/soc/i2c@2030000", "/soc/i2c@2040000", "/soc/i2c@2050000",
  	"/soc/i2c@2060000", "/soc/i2c@2070000"
  };
  
  /*
   * I2C divisor and ibfd register values when glitch filter is enabled
   * In case of duplicate SCL divisor value, the ibfd value with high MUL value
   * has been selected. A higher MUL value results in a lower sampling rate of
   * the I2C signals. This gives the I2C module greater immunity against glitches
   * in the I2C signals.
   */
  static const struct i2c_clock_divisor_pair clk_div_glitch_enabled[] = {
  	{ 34, 0x0 },	 { 36, 0x1 },	  { 38, 0x2 },	  { 40, 0x3 },
  	{ 42, 0x4 },	 { 44, 0x8 },	  { 48, 0x9 },	  { 52, 0xA },
  	{ 54, 0x7 },	 { 56, 0xB },	  { 60, 0xC },	  { 64, 0x10 },
  	{ 68, 0x40 },	 { 72, 0x41 },	  { 76, 0x42 },	  { 80, 0x43 },
  	{ 84, 0x44 },	 { 88, 0x48 },	  { 96, 0x49 },	  { 104, 0x4A },
  	{ 108, 0x47 },	 { 112, 0x4B },	  { 120, 0x4C },  { 128, 0x50 },
  	{ 136, 0x80 },	 { 144, 0x81 },	  { 152, 0x82 },  { 160, 0x83 },
  	{ 168, 0x84 },	 { 176, 0x88 },	  { 192, 0x89 },  { 208, 0x8A },
  	{ 216, 0x87 },	 { 224, 0x8B },	  { 240, 0x8C },  { 256, 0x90 },
  	{ 288, 0x91 },	 { 320, 0x92 },	  { 336, 0x8F },  { 352, 0x93 },
  	{ 384, 0x98 },	 { 416, 0x95 },	  { 448, 0x99 },  { 480, 0x96 },
  	{ 512, 0x9A },	 { 576, 0x9B },	  { 640, 0xA0 },  { 704, 0x9D },
  	{ 768, 0xA1 },	 { 832, 0x9E },	  { 896, 0xA2 },  { 960, 0x67 },
  	{ 1024, 0xA3 },	 { 1152, 0xA4 },  { 1280, 0xA8 }, { 1536, 0xA9 },
  	{ 1792, 0xAA },	 { 1920, 0xA7 },  { 2048, 0xAB }, { 2304, 0xAC },
  	{ 2560, 0xB0 },	 { 3072, 0xB1 },  { 3584, 0xB2 }, { 3840, 0xAF },
  	{ 4096, 0xB3 },	 { 4608, 0xB4 },  { 5120, 0xB8 }, { 6144, 0xB9 },
  	{ 7168, 0xBA },	 { 7680, 0xB7 },  { 8192, 0xBB }, { 9216, 0xBC },
  	{ 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF }
  };
  
  /*
   * I2C divisor and ibfd register values when glitch filter is disabled.
   * In case of duplicate SCL divisor value, the ibfd value with high MUL value
   * has been selected. A higher MUL value results in a lower sampling rate of
   * the I2C signals. This gives the I2C module greater immunity against glitches
   * in the I2C signals.
   */
  static const struct i2c_clock_divisor_pair clk_div_glitch_disabled[] = {
  	{ 20, 0x0 },	 { 22, 0x1 },	  { 24, 0x2 },	  { 26, 0x3 },
  	{ 28, 0x8 },	 { 30, 0x5 },	  { 32, 0x9 },	  { 34, 0x6 },
  	{ 36, 0x0A },	 { 40, 0x40 },	  { 44, 0x41 },	  { 48, 0x42 },
  	{ 52, 0x43 },	 { 56, 0x48 },	  { 60, 0x45 },	  { 64, 0x49 },
  	{ 68, 0x46 },	 { 72, 0x4A },	  { 80, 0x80 },	  { 88, 0x81 },
  	{ 96, 0x82 },	 { 104, 0x83 },	  { 112, 0x88 },  { 120, 0x85 },
  	{ 128, 0x89 },	 { 136, 0x86 },	  { 144, 0x8A },  { 160, 0x8B },
  	{ 176, 0x8C },	 { 192, 0x90 },	  { 208, 0x56 },  { 224, 0x91 },
  	{ 240, 0x1F },	 { 256, 0x92 },	  { 272, 0x8F },  { 288, 0x93 },
  	{ 320, 0x98 },	 { 352, 0x95 },	  { 384, 0x99 },  { 416, 0x96 },
  	{ 448, 0x9A },	 { 480, 0x5F },	  { 512, 0x9B },  { 576, 0x9C },
  	{ 640, 0xA0 },	 { 768, 0xA1 },	  { 896, 0xA2 },  { 960, 0x9F },
  	{ 1024, 0xA3 },	 { 1152, 0xA4 },  { 1280, 0xA8 }, { 1536, 0xA9 },
  	{ 1792, 0xAA },	 { 1920, 0xA7 },  { 2048, 0xAB }, { 2304, 0xAC },
  	{ 2560, 0xAD },	 { 3072, 0xB1 },  { 3584, 0xB2 }, { 3840, 0xAF },
  	{ 4096, 0xB3 },	 { 4608, 0xB4 },  { 5120, 0xB8 }, { 6144, 0xB9 },
  	{ 7168, 0xBA },	 { 7680, 0xB7 },  { 8192, 0xBB }, { 9216, 0xBC },
  	{ 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF }
  };
  
  void i2c_reset(vaddr_t base)
  {
  	struct i2c_regs *regs = (struct i2c_regs *)base;
  
  	io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_MDIS);
  	io_setbits8((vaddr_t)&regs->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF);
  	io_clrbits8((vaddr_t)&regs->ibcr, I2C_IBCR_IBIE | I2C_IBCR_DMAEN);
  	io_clrbits8((vaddr_t)&regs->ibic, I2C_IBIC_BIIE);
  }
  
  /*
   * Get I2c Bus Frequency Divider Register value based on clock_divisor
   * and if the glitch is enabled or not in I2c controller.
   * base			Base address of I2C controller
   * clock_divisor	Clock Divisor
   */
  static uint8_t i2c_get_ibfd(vaddr_t base, uint16_t clock_divisor)
  {
  	struct i2c_regs *regs = (struct i2c_regs *)base;
  	const struct i2c_clock_divisor_pair *dpair = NULL;
  	size_t dpair_sz = 0;
  	unsigned int n = 0;
  
  	if (io_read8((vaddr_t)&regs->ibdbg) & I2C_IBDBG_GLFLT_EN) {
  		dpair = clk_div_glitch_enabled;
  		dpair_sz = ARRAY_SIZE(clk_div_glitch_enabled);
  	} else {
  		dpair = clk_div_glitch_disabled;
  		dpair_sz = ARRAY_SIZE(clk_div_glitch_disabled);
  	}
  
  	for (n = 0; n < dpair_sz - 1; n++)
  		if (clock_divisor < dpair[n].divisor)
  			break;
  
  	return dpair[n].ibfd;
  }
  
  TEE_Result i2c_init(struct ls_i2c_data *i2c_data)
  {
  	struct i2c_regs *regs = NULL;
  	uint16_t clock_divisor = 0;
  	uint8_t ibfd = 0; /* I2c Bus Frequency Divider Register */
  	size_t size = 0;
  	int node = 0;
  	vaddr_t ctrl_base = 0;
  	void *fdt = NULL;
  
  	/*
  	 * First get the I2C Controller base address from the DTB
  	 * if DTB present and if the I2C Controller defined in it.
  	 */
  	fdt = get_embedded_dt();
  	if (!fdt) {
  		EMSG("Unable to get the Embedded DTB, I2C init failed\n");
  		return TEE_ERROR_GENERIC;
  	}
  
  	node = fdt_path_offset(fdt,
  			       i2c_controller_map[i2c_data->i2c_controller]);
  	if (node > 0) {
  		if (dt_map_dev(fdt, node, &ctrl_base, &size) < 0) {
  			EMSG("Unable to get virtual address");
  			return TEE_ERROR_GENERIC;
  		}
  	} else {
  		EMSG("Unable to get I2C offset node");
  		return TEE_ERROR_ITEM_NOT_FOUND;
  	}
  
  	i2c_data->base = ctrl_base;
  
  	regs = (struct i2c_regs *)ctrl_base;
  
  	clock_divisor = (i2c_data->i2c_bus_clock + i2c_data->speed - 1) /
  			i2c_data->speed;
  	ibfd = i2c_get_ibfd(ctrl_base, clock_divisor);
  
  	io_write8((vaddr_t)&regs->ibfd, ibfd);
  
  	i2c_reset(ctrl_base);
  
  	return TEE_SUCCESS;
  }
  
  /*
   * Check if I2C bus is busy with previous transaction or not.
   * regs         pointer to I2c controller registers
   * test_busy	this flag tells if we need to check the busy bit in IBSR reg
   */
  static TEE_Result i2c_bus_test_bus_busy(struct i2c_regs *regs, bool test_busy)
  {
  	unsigned int n = 0;
  	uint8_t reg = 0;
  
  	for (n = 0; n < I2C_NUM_RETRIES; n++) {
  		reg = io_read8((vaddr_t)&regs->ibsr);
  
  		if (reg & I2C_IBSR_IBAL) {
  			io_write8((vaddr_t)&regs->ibsr, reg);
  			return TEE_ERROR_BUSY;
  		}
  
  		if (test_busy && (reg & I2C_IBSR_IBB))
  			break;
  
  		if (!test_busy && !(reg & I2C_IBSR_IBB))
  			break;
  
  		mdelay(1);
  	}
  
  	if (n == I2C_NUM_RETRIES)
  		return TEE_ERROR_BUSY;
  
  	return TEE_SUCCESS;
  }
  
  /*
   * Check if data transfer to/from i2c controller is complete.
   * regs		pointer to I2c controller registers
   * test_rx_ack	this flag tells if we need to check RXAK bit in IBSR reg
   */
  static TEE_Result i2c_transfer_complete(struct i2c_regs *regs, bool test_rx_ack)
  {
  	unsigned int n = 0;
  	uint8_t reg = 0;
  
  	for (n = 0; n < I2C_NUM_RETRIES; n++) {
  		reg = io_read8((vaddr_t)&regs->ibsr);
  
  		if (reg & I2C_IBSR_IBIF) {
  			/* Write 1 to clear the IBIF field */
  			io_write8((vaddr_t)&regs->ibsr, reg);
  			break;
  		}
  		mdelay(1);
  	}
  
  	if (n == I2C_NUM_RETRIES)
  		return TEE_ERROR_BUSY;
  
  	if (test_rx_ack && (reg & I2C_IBSR_RXAK))
  		return TEE_ERROR_NO_DATA;
  
  	if (reg & I2C_IBSR_TCF)
  		return TEE_SUCCESS;
  
  	return TEE_ERROR_GENERIC;
  }
  
  /*
   * Read data from I2c controller.
   * regs			pointer to I2c controller registers
   * slave_address	slave address from which to read
   * operation		pointer to i2c_operation struct
   * is_last_operation	if current operation is last operation
   */
  static TEE_Result i2c_read(struct i2c_regs *regs, unsigned int slave_address,
  			   struct i2c_operation *operation,
  			   bool is_last_operation)
  {
  	TEE_Result res = TEE_ERROR_GENERIC;
  	unsigned int n = 0;
  
  	/* Write Slave Address */
  	io_write8((vaddr_t)&regs->ibdr, (slave_address << 0x1) | BIT(0));
  	res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK);
  	if (res)
  		return res;
  
  	/* select Receive mode. */
  	io_clrbits8((vaddr_t)&regs->ibcr, I2C_IBCR_TXRX);
  	if (operation->length_in_bytes > 1) {
  		/* Set No ACK = 0 */
  		io_clrbits8((vaddr_t)&regs->ibcr, I2C_IBCR_NOACK);
  	}
  
  	/* Perform a dummy read to initiate the receive operation. */
  	io_read8((vaddr_t)&regs->ibdr);
  
  	for (n = 0; n < operation->length_in_bytes; n++) {
  		res = i2c_transfer_complete(regs, I2C_BUS_NO_TEST_RX_ACK);
  		if (res)
  			return res;
  		if (n == (operation->length_in_bytes - 2)) {
  			/* Set No ACK = 1 */
  			io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_NOACK);
  		} else if (n == (operation->length_in_bytes - 1)) {
  			if (!is_last_operation) {
  				/* select Transmit mode (for repeat start) */
  				io_setbits8((vaddr_t)&regs->ibcr,
  					    I2C_IBCR_TXRX);
  			} else {
  				/* Generate Stop Signal */
  				io_clrbits8((vaddr_t)&regs->ibcr,
  					    (I2C_IBCR_MSSL | I2C_IBCR_TXRX));
  				res = i2c_bus_test_bus_busy(regs,
  							    I2C_BUS_TEST_IDLE);
  				if (res)
  					return res;
  			}
  		}
  		operation->buffer[n] = io_read8((vaddr_t)&regs->ibdr);
  	}
  
  	return TEE_SUCCESS;
  }
  
  /*
   * Write data to I2c controller
   * regs			pointer to I2c controller registers
   * slave_address	slave address from which to read
   * operation		pointer to i2c_operation struct
   */
  static TEE_Result i2c_write(struct i2c_regs *regs, unsigned int slave_address,
  			    struct i2c_operation *operation)
  {
  	TEE_Result res = TEE_ERROR_GENERIC;
  	unsigned int n = 0;
  
  	/* Write Slave Address */
  	io_write8((vaddr_t)&regs->ibdr,
  		  (slave_address << 0x1) & ~(BIT(0)));
  	res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK);
  	if (res)
  		return res;
  
  	/* Write Data */
  	for (n = 0; n < operation->length_in_bytes; n++) {
  		io_write8((vaddr_t)&regs->ibdr, operation->buffer[n]);
  		res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK);
  		if (res)
  			return res;
  	}
  
  	return TEE_SUCCESS;
  }
  
  /*
   * Generate Stop Signal and disable I2C controller.
   * regs		pointer to I2c controller registers
   */
  static TEE_Result i2c_stop(struct i2c_regs *regs)
  {
  	TEE_Result res = TEE_SUCCESS;
  	uint8_t reg = 0;
  
  	reg = io_read8((vaddr_t)&regs->ibsr);
  	if (reg & I2C_IBSR_IBB) {
  		/* Generate Stop Signal */
  		io_clrbits8((vaddr_t)&regs->ibcr,
  			    I2C_IBCR_MSSL | I2C_IBCR_TXRX);
  		res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE);
  		if (res)
  			return res;
  	}
  
  	/* Disable I2c Controller */
  	io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_MDIS);
  
  	return TEE_SUCCESS;
  }
  
  /*
   * Generate Start Signal and set I2C controller in transmit mode.
   * regs		pointer to I2c controller registers
   */
  static TEE_Result i2c_start(struct i2c_regs *regs)
  {
  	TEE_Result res = TEE_ERROR_GENERIC;
  
  	io_setbits8((vaddr_t)&regs->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF);
  	io_clrbits8((vaddr_t)&regs->ibcr, I2C_IBCR_MDIS);
  
  	/* Wait controller to be stable */
  	mdelay(1);
  
  	/* Generate Start Signal */
  	io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_MSSL);
  	res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY);
  	if (res)
  		return res;
  
  	/* Select Transmit Mode. set No ACK = 1 */
  	io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_TXRX | I2C_IBCR_NOACK);
  
  	return TEE_SUCCESS;
  }
  
  TEE_Result i2c_bus_xfer(vaddr_t base, unsigned int slave_address,
  			struct i2c_operation *i2c_operation,
  			unsigned int operation_count)
  {
  	unsigned int n = 0;
  	struct i2c_regs *regs = (struct i2c_regs *)base;
  	struct i2c_operation *operation = NULL;
  	TEE_Result res = TEE_ERROR_GENERIC;
  	bool is_last_operation = false;
  
  	res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE);
  	if (res)
  		goto out;
  
  	res = i2c_start(regs);
  	if (res)
  		goto out;
  
  	for (n = 0, operation = i2c_operation;
  	     n < operation_count; n++, operation++) {
  		if (n == (operation_count - 1))
  			is_last_operation = true;
  
  		/* Send repeat start after first transmit/receive */
  		if (n) {
  			io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_RSTA);
  			res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY);
  			if (res)
  				goto out;
  		}
  
  		/* Read/write data */
  		if (operation->flags & I2C_FLAG_READ)
  			res = i2c_read(regs, slave_address, operation,
  				       is_last_operation);
  		else
  			res = i2c_write(regs, slave_address, operation);
  		if (res)
  			goto out;
  	}
  
  out:
  	i2c_stop(regs);
  
  	return res;
  }
  