text: /*
   * Copyright (c) 2016 Intel Corporation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  /**
   * @file I2C/TWI Controller driver for Atmel SAM3 family processor
   *
   * Notes on this driver:
   * 1. The controller does not have a documented way to
   *    issue RESTART when changing transfer direction as master.
   *
   *    Datasheet said about using the internal address register
   *    (IADR) to write 3 bytes before reading. This limits
   *    the number of bytes to write before a read. Also,
   *    this was documented under 7-bit addressing, and nothing
   *    about this with 10-bit addressing.
   *
   *    Experiments show that STOP has to be issued or the controller
   *    hangs forever. This was tested with reading and writing
   *    the Fujitsu I2C-based FRAM MB85RC256V.
   */
  
  #include <errno.h>
  
  #include <nanokernel.h>
  
  #include <board.h>
  #include <i2c.h>
  #include <sys_clock.h>
  
  #include <misc/util.h>
  
  #include "i2c_atmel_sam3.h"
  
  
  #ifndef CONFIG_I2C_DEBUG
  #define DBG(...) { ; }
  #else
  #if defined(CONFIG_STDOUT_CONSOLE)
  #include <stdio.h>
  #define DBG printf
  #else
  #define DBG printk
  #endif /* CONFIG_STDOUT_CONSOLE */
  #endif /* CONFIG_I2C_DEBUG */
  
  
  /* for use with dev_data->state */
  #define STATE_READY		0
  #define STATE_BUSY		(1 << 0)
  #define STATE_TX		(1 << 1)
  #define STATE_RX		(1 << 2)
  
  /* return values for internal functions */
  #define RET_OK			0
  #define RET_ERR			1
  #define RET_NACK		2
  
  
  typedef void (*config_func_t)(struct device *port);
  
  
  struct i2c_sam3_dev_config {
  	volatile struct __twi	*port;
  
  	config_func_t		config_func;
  };
  
  struct i2c_sam3_dev_data {
  	device_sync_call_t	sync;
  	union dev_config	dev_config;
  
  	volatile uint32_t	state;
  
  	uint8_t			*xfr_buf;
  	uint32_t		xfr_len;
  	uint32_t		xfr_flags;
  };
  
  
  /**
   * Calculate clock dividers for TWI controllers.
   *
   * @param dev Device struct
   * @return Value used for TWI_CWGR register.
   */
  static uint32_t clk_div_calc(struct device *dev)
  {
  #if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 84000000)
  
  	/* Use pre-calculated clock dividers when the SoC is running at
  	 * 84 MHz. This saves execution time and ROM space.
  	 */
  	struct i2c_sam3_dev_data * const dev_data = dev->driver_data;
  
  	switch ((dev_data->dev_config.bits.speed)) {
  	case I2C_SPEED_STANDARD:
  		/* CKDIV = 1
  		 * CHDIV = CLDIV = 208 = 0xD0
  		 */
  		return 0x0001D0D0;
  	case I2C_SPEED_FAST:
  		/* CKDIV = 0
  		 * CHDIV = 101 = 0x65
  		 * CLDIV = 106 = 0x6A
  		 */
  		return 0x0000656A;
  	default:
  		/* Return 0 as error */
  		return 0;
  	}
  
  #else /* !(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 84000000) */
  
  	/* Need to calcualte the clock dividers if the SoC is running at
  	 * other frequencies.
  	 */
  
  	struct i2c_sam3_dev_data * const dev_data = dev->driver_data;
  	uint32_t i2c_clk;
  	uint32_t cldiv, chdiv, ckdiv;
  	uint32_t i2c_h_min_time, i2c_l_min_time;
  	uint32_t cldiv_min, chdiv_min;
  	uint32_t mck;
  
  	/* The T(low) and T(high) are used to calculate CLDIV and CHDIV.
  	 * Since we treat both clock low and clock high to have same period,
  	 * the I2C clock frequency used for calculation has to be doubled.
  	 *
  	 * The I2C spec has the following minimum timing requirement:
  	 * Standard Speed: High 4000ns, Low 4700ns
  	 * Fast Speed: High 600ns, Low 1300ns
  	 *
  	 * So use these to calculate chdiv_min and cldiv_min.
  	 */
  	switch ((dev_data->dev_config.bits.speed)) {
  	case I2C_SPEED_STANDARD:
  		i2c_clk = 100000 * 2;
  		i2c_h_min_time = 4000;
  		i2c_l_min_time = 4700;
  		break;
  	case I2C_SPEED_FAST:
  		i2c_clk = 400000 * 2;
  		i2c_h_min_time = 600;
  		i2c_l_min_time = 1300;
  		break;
  	default:
  		/* Return 0 as error */
  		return 0;
  	}
  
  	/* Calculate CLDIV (which will be used for CHDIV also) */
  	cldiv = (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) / i2c_clk - 4;
  
  	/* Calculate minimum CHDIV and CLDIV */
  
  	/* Make 1/mck be in micro second */
  	mck = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC
  	      / MSEC_PER_SEC / USEC_PER_MSEC;
  
  	/* The +1 is to make sure we don't go under the minimum
  	 * after the division. In other words, force rounding up.
  	 */
  	cldiv_min = (i2c_l_min_time * mck / 1000) - 4 + 1;
  	chdiv_min = (i2c_h_min_time * mck / 1000) - 4 + 1;
  
  	ckdiv = 0;
  	while (cldiv > 255) {
  		ckdiv++;
  
  		/* Math is there to round up.
  		 * Rounding up makes the SCL periods longer,
  		 * which makes clock slower.
  		 * This is fine as faster clock may cause
  		 * issues.
  		 */
  		cldiv = (cldiv >> 1) + (cldiv & 0x01);
  
  		cldiv_min = (cldiv_min >> 1) + (cldiv_min & 0x01);
  		chdiv_min = (chdiv_min >> 1) + (chdiv_min & 0x01);
  	}
  
  	chdiv = cldiv;
  
  	/* Make sure we are above minimum requirements */
  	cldiv = max(cldiv, cldiv_min);
  	chdiv = max(chdiv, chdiv_min);
  
  	return ((ckdiv << TWI_CWGR_CKDIV_POS) + (chdiv << TWI_CWGR_CHDIV_POS)
  		+ (cldiv << TWI_CWGR_CLDIV_POS));
  
  #endif /* CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 84000000 */
  }
  
  static int i2c_sam3_runtime_configure(struct device *dev, uint32_t config)
  {
  	struct i2c_sam3_dev_config * const cfg = dev->config->config_info;
  	struct i2c_sam3_dev_data * const dev_data = dev->driver_data;
  	uint32_t reg;
  	uint32_t clk;
  
  	dev_data->dev_config.raw = config;
  	reg = 0;
  
  	/* Currently support master mode only */
  	if (dev_data->dev_config.bits.is_slave_read) {
  		return -EINVAL;
  	}
  
  	/* Calculate clock dividers */
  	clk = clk_div_calc(dev);
  	if (!clk) {
  		return -EINVAL;
  	}
  
  	/* Disable controller first before changing anything */
  	cfg->port->cr = TWI_CR_MSDIS | TWI_CR_SVDIS;
  
  	/* Setup clock wavefore generator */
  	cfg->port->cwgr = clk;
  
  	return 0;
  }
  
  static void i2c_sam3_isr(void *arg)
  {
  	struct device * const dev = (struct device *)arg;
  	struct i2c_sam3_dev_config *const cfg = dev->config->config_info;
  	struct i2c_sam3_dev_data * const dev_data = dev->driver_data;
  
  	/* Disable all interrupts so they can be processed
  	 * before ISR is called again.
  	 */
  	cfg->port->idr = TWI_IRQ_DISABLE;
  
  	device_sync_call_complete(&dev_data->sync);
  }
  
  /* This should be used ONLY IF <bits> are the only bits of concern.
   * This is because reading from status register will clear certain
   * bits, and thus status might be ignored afterwards.
   */
  static inline void sr_bits_set_wait(struct device *dev, uint32_t bits)
  {
  	struct i2c_sam3_dev_config *const cfg = dev->config->config_info;
  
  	while (!(cfg->port->sr & bits)) {
  		/* loop till <bits> are set */
  	};
  }
  
  /* Clear the status registers from previous transfers */
  static inline void status_reg_clear(struct device *dev)
  {
  	struct i2c_sam3_dev_config *const cfg = dev->config->config_info;
  	uint32_t stat_reg;
  
  	do {
  		stat_reg = cfg->port->sr;
  
  		/* ignore these */
  		stat_reg &= ~(TWI_IRQ_PDC | TWI_IRQ_TXRDY | TWI_IRQ_TXCOMP
  				| TWI_IRQ_SVREAD);
  
  		if (stat_reg & TWI_IRQ_OVRE) {
  			continue;
  		}
  
  		if (stat_reg & TWI_IRQ_NACK) {
  			continue;
  		}
  
  		if (stat_reg & TWI_IRQ_RXRDY) {
  			stat_reg = cfg->port->rhr;
  		}
  	} while (stat_reg);
  }
  
  static inline void transfer_setup(struct device *dev, uint16_t slave_address)
  {
  	struct i2c_sam3_dev_config *const cfg = dev->config->config_info;
  	struct i2c_sam3_dev_data * const dev_data = dev->driver_data;
  	uint32_t mmr;
  	uint32_t iadr;
  
  	/* Set slave address */
  	if (dev_data->dev_config.bits.use_10_bit_addr) {
  		/* 10-bit slave addressing:
  		 * first two bits goes to MMR/DADR, other 8 to IADR.
  		 *
  		 * 0x78 is the 0b11110xx bit prefix.
  		 */
  		mmr = 0x78 | ((slave_address >> 8) & 0x03);
  		mmr <<= TWI_MMR_DADR_POS;
  		mmr |= TWI_MMR_IADRSZ_1_BYTE;
  
  		iadr = slave_address & 0xFF;
  	} else {
  		/* 7-bit slave addressing */
  		mmr = (slave_address << TWI_MMR_DADR_POS) & TWI_MMR_DADR_MASK;
  
  		iadr = 0;
  	}
  
  	cfg->port->mmr = mmr;
  	cfg->port->iadr = iadr;
  }
  
  static inline int msg_write(struct device *dev)
  {
  	struct i2c_sam3_dev_config *const cfg = dev->config->config_info;
  	struct i2c_sam3_dev_data * const dev_data = dev->driver_data;
  
  	/* To write to slave */
  	cfg->port->mmr &= ~TWI_MMR_MREAD;
  
  	/* Setup PDC to do DMA transfer */
  	cfg->port->pdc.ptcr = PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS;
  	cfg->port->pdc.tpr = (uint32_t)dev_data->xfr_buf;
  	cfg->port->pdc.tcr = dev_data->xfr_len;
  
  	/* Enable TX related interrupts.
  	 * TXRDY is used by PDC so we don't want to interfere.
  	 */
  	cfg->port->ier = TWI_IRQ_ENDTX | TWI_IRQ_NACK;
  
  	/* Start DMA transfer for TX */
  	cfg->port->pdc.ptcr = PDC_PTCR_TXTEN;
  
  	/* Wait till transfer is done or error occurs */
  	device_sync_call_wait(&dev_data->sync);
  
  	/* Check for error */
  	if (cfg->port->sr & TWI_IRQ_NACK) {
  		return RET_NACK;
  	}
  
  	/* STOP if needed */
  	if (dev_data->xfr_flags & I2C_MSG_STOP) {
  		cfg->port->cr = TWI_CR_STOP;
  
  		/* Wait for TXCOMP if sending STOP.
  		 * The transfer is done and the controller just needs to
  		 * 'send' the STOP bit. So wait should be very short.
  		 */
  		sr_bits_set_wait(dev, TWI_IRQ_TXCOMP);
  	} else {
  		/* If no STOP, just wait for TX buffer to clear.
  		 * At this point, this should take no time.
  		 */
  		sr_bits_set_wait(dev, TWI_IRQ_TXRDY);
  	}
  
  	/* Disable PDC */
  	cfg->port->pdc.ptcr = PDC_PTCR_TXTDIS;
  
  	return RET_OK;
  }
  
  static inline int msg_read(struct device *dev)
  {
  	struct i2c_sam3_dev_config *const cfg = dev->config->config_info;
  	struct i2c_sam3_dev_data * const dev_data = dev->driver_data;
  	uint32_t stat_reg;
  	uint32_t ctrl_reg;
  	uint32_t last_len;
  
  	/* To read from slave */
  	cfg->port->mmr |= TWI_MMR_MREAD;
  
  	/* START bit in control register needs to be set to start
  	 * reading from slave. If the previous message is also read,
  	 * there is no need to set the START bit again.
  	 */
  	ctrl_reg = 0;
  	if (dev_data->xfr_flags & I2C_MSG_RESTART) {
  		ctrl_reg = TWI_CR_START;
  	}
  	/* If there is only one byte to read, need to send STOP also. */
  	if ((dev_data->xfr_len == 1)
  	    && (dev_data->xfr_flags & I2C_MSG_STOP)) {
  		ctrl_reg |= TWI_CR_STOP;
  		dev_data->xfr_flags &= ~I2C_MSG_STOP;
  	}
  	cfg->port->cr = ctrl_reg;
  
  	/* Note that this is entirely possible to do the last byte without
  	 * going through DMA. But that requires another block of code to
  	 * setup the transfer and test for RXRDY bit (and other). So do it
  	 * this way to save a few bytes of code space.
  	 */
  	while (dev_data->xfr_len > 0) {
  		/* Setup PDC to do DMA transfer. */
  		cfg->port->pdc.ptcr = PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS;
  		cfg->port->pdc.rpr = (uint32_t)dev_data->xfr_buf;
  
  		/* Note that we need to set the STOP bit before reading
  		 * last byte from RHR. So we need to process the last byte
  		 * differently.
  		 */
  		if (dev_data->xfr_len > 1) {
  			last_len = dev_data->xfr_len - 1;
  		} else {
  			last_len = 1;
  
  			/* Set STOP bit for last byte.
  			 * The extra check here is to prevent setting
  			 * TWI_CR_STOP twice, when the message length
  			 * is 1, as it is already set above.
  			 */
  			if (dev_data->xfr_flags & I2C_MSG_STOP) {
  				cfg->port->cr = TWI_CR_STOP;
  			}
  		}
  		cfg->port->pdc.rcr = last_len;
  
  		/* Start DMA transfer for RX */
  		cfg->port->pdc.ptcr = PDC_PTCR_RXTEN;
  
  		/* Enable RX related interrupts
  		 * RXRDY is used by PDC so we don't want to interfere.
  		 */
  		cfg->port->ier = TWI_IRQ_ENDRX | TWI_IRQ_NACK | TWI_IRQ_OVRE;
  
  		/* Wait till transfer is done or error occurs */
  		device_sync_call_wait(&dev_data->sync);
  
  		/* Check for errors */
  		stat_reg = cfg->port->sr;
  		if (stat_reg & TWI_IRQ_NACK) {
  			return RET_NACK;
  		}
  
  		if (stat_reg & TWI_IRQ_OVRE) {
  			return RET_ERR;
  		}
  
  		/* no more bytes to send */
  		if (dev_data->xfr_len == 0) {
  			break;
  		}
  
  		dev_data->xfr_buf += last_len;
  		dev_data->xfr_len -= last_len;
  	}
  
  	/* Disable PDC */
  	cfg->port->pdc.ptcr = PDC_PTCR_RXTDIS;
  
  	/* TXCOMP is kind of misleading here. This bit is set when THR/RHR
  	 * and all shift registers are empty, and STOP (or NACK) is detected.
  	 * So we wait here.
  	 */
  	sr_bits_set_wait(dev, TWI_IRQ_TXCOMP);
  
  	return RET_OK;
  }
  
  static int i2c_sam3_transfer(struct device *dev,
  			     struct i2c_msg *msgs, uint8_t num_msgs,
  			     uint16_t slave_address)
  {
  	struct i2c_sam3_dev_config *const cfg = dev->config->config_info;
  	struct i2c_sam3_dev_data * const dev_data = dev->driver_data;
  	struct i2c_msg *cur_msg = msgs;
  	uint8_t msg_left = num_msgs;
  	uint32_t pflags = 0;
  	int ret = 0;
  	int xfr_ret;
  
  	/* Why bother processing no messages */
  	if (!msgs || !num_msgs) {
  		return -ENOTSUP;
  	}
  
  	/* Device is busy servicing another transfer */
  	if (dev_data->state & STATE_BUSY) {
  		return -EIO;
  	}
  
  	dev_data->state = STATE_BUSY;
  
  	/* Need to clear status from previous transfers */
  	status_reg_clear(dev);
  
  	/* Enable master */
  	cfg->port->cr = TWI_CR_MSEN | TWI_CR_SVDIS;
  
  	transfer_setup(dev, slave_address);
  
  	/* Process all messages one-by-one */
  	while (msg_left > 0) {
  		dev_data->xfr_buf = cur_msg->buf;
  		dev_data->xfr_len = cur_msg->len;
  		dev_data->xfr_flags = cur_msg->flags;
  
  		/* Send STOP if this is the last message */
  		if (msg_left == 1) {
  			dev_data->xfr_flags |= I2C_MSG_STOP;
  		}
  
  		/* The controller does not have a documented way to
  		 * issue RESTART when changing transfer direction as master.
  		 *
  		 * Datasheet said about using the internal address register
  		 * (IADR) to write 3 bytes before reading. This limits
  		 * the number of bytes to write before a read. Also,
  		 * this was documented under 7-bit addressing, and nothing
  		 * about this with 10-bit addressing.
  		 *
  		 * Experiments show that STOP has to be issued or
  		 * the controller hangs forever.
  		 */
  		if (msg_left > 1) {
  			if ((dev_data->xfr_flags & I2C_MSG_RW_MASK) !=
  			    (cur_msg[1].flags & I2C_MSG_RW_MASK)) {
  				dev_data->xfr_flags |= I2C_MSG_STOP;
  			}
  		}
  
  		/* The RESTART flag is used to indicate whether to set
  		 * the START bit in control register. This is used only
  		 * when changing from write to read, as the START needs
  		 * to be set to start receiving. This is also to avoid
  		 * setting the START bit multiple time if we are doing
  		 * multiple read messages in a roll.
  		 */
  		if ((dev_data->xfr_flags & I2C_MSG_RW_MASK) !=
  		    (pflags & I2C_MSG_RW_MASK)) {
  			dev_data->xfr_flags |= I2C_MSG_RESTART;
  		}
  
  		dev_data->state &= ~(STATE_TX | STATE_RX);
  
  		if ((dev_data->xfr_flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
  			dev_data->state |= STATE_TX;
  			xfr_ret = msg_write(dev);
  		} else {
  			dev_data->state |= STATE_RX;
  			xfr_ret = msg_read(dev);
  		}
  
  		if (xfr_ret == RET_NACK) {
  			/* Disable PDC if NACK is received. */
  			cfg->port->pdc.ptcr = PDC_PTCR_TXTDIS
  					      | PDC_PTCR_RXTDIS;
  
  			ret = -EIO;
  			goto done;
  		}
  
  		if (xfr_ret == RET_ERR) {
  			/* Error encountered:
  			 * Reset the controller and configure it again.
  			 */
  			cfg->port->pdc.ptcr = PDC_PTCR_TXTDIS
  					      | PDC_PTCR_RXTDIS;
  			cfg->port->cr = TWI_CR_SWRST | TWI_CR_MSDIS
  					| TWI_CR_SVDIS;
  
  			i2c_sam3_runtime_configure(dev,
  						   dev_data->dev_config.raw);
  
  			ret = -EIO;
  			goto done;
  		}
  
  		cur_msg++;
  		msg_left--;
  		pflags = cur_msg->flags;
  	}
  
  done:
  	dev_data->state = STATE_READY;
  
  	/* Disable master and slave after transfer is done */
  	cfg->port->cr = TWI_CR_MSDIS | TWI_CR_SVDIS;
  
  	return ret;
  }
  
  static int i2c_sam3_suspend(struct device *dev)
  {
  	/* TODO - add this code */
  	return 0;
  }
  
  static int i2c_sam3_resume(struct device *dev)
  {
  	/* TODO - add this code */
  	return 0;
  }
  
  static struct i2c_driver_api api_funcs = {
  	.configure = i2c_sam3_runtime_configure,
  	.transfer = i2c_sam3_transfer,
  	.suspend = i2c_sam3_suspend,
  	.resume = i2c_sam3_resume,
  };
  
  static int i2c_sam3_init(struct device *dev)
  {
  	struct i2c_sam3_dev_config * const cfg = dev->config->config_info;
  	struct i2c_sam3_dev_data * const dev_data = dev->driver_data;
  
  	dev->driver_api = &api_funcs;
  
  	device_sync_call_init(&dev_data->sync);
  
  	/* Disable all interrupts */
  	cfg->port->idr = TWI_IRQ_DISABLE;
  
  	cfg->config_func(dev);
  
  	if (i2c_sam3_runtime_configure(dev, dev_data->dev_config.raw)
  	    != 0) {
  		DBG("I2C: Cannot set default configuration 0x%x\n",
  		    dev_data->dev_config.raw);
  		return -EINVAL;
  	}
  
  	return 0;
  }
  
  #ifdef CONFIG_I2C_ATMEL_SAM3_0
  
  static void config_func_0(struct device *port);
  
  static struct i2c_sam3_dev_config dev_config_0 = {
  	.port = __TWI0,
  	.config_func = config_func_0,
  };
  
  static struct i2c_sam3_dev_data dev_data_0 = {
  	.dev_config.raw = CONFIG_I2C_ATMEL_SAM3_0_DEFAULT_CFG,
  };
  
  DEVICE_INIT(i2c_sam3_0, CONFIG_I2C_ATMEL_SAM3_0_NAME, &i2c_sam3_init,
  	    &dev_data_0, &dev_config_0,
  	    SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
  
  static void config_func_0(struct device *dev)
  {
  	/* Enable clock for TWI0 controller */
  	__PMC->pcer0 = (1 << PID_TWI0);
  
  	IRQ_CONNECT(IRQ_TWI0, CONFIG_I2C_ATMEL_SAM3_0_IRQ_PRI,
  		    i2c_sam3_isr, DEVICE_GET(i2c_sam3_0), 0);
  	irq_enable(IRQ_TWI0);
  }
  
  #endif /* CONFIG_I2C_ATMEL_SAM3_0 */
  
  #ifdef CONFIG_I2C_ATMEL_SAM3_1
  
  static void config_func_1(struct device *port);
  
  static struct i2c_sam3_dev_config dev_config_1 = {
  	.port = __TWI1,
  	.config_func = config_func_1,
  };
  
  static struct i2c_sam3_dev_data dev_data_1 = {
  	.dev_config.raw = CONFIG_I2C_ATMEL_SAM3_1_DEFAULT_CFG,
  };
  
  DEVICE_INIT(i2c_sam3_1, CONFIG_I2C_ATMEL_SAM3_1_NAME, &i2c_sam3_init,
  	    &dev_data_1, &dev_config_1,
  	    SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
  
  static void config_func_1(struct device *dev)
  {
  	/* Enable clock for TWI0 controller */
  	__PMC->pcer0 = (1 << PID_TWI1);
  
  	IRQ_CONNECT(IRQ_TWI1, CONFIG_I2C_ATMEL_SAM3_1_IRQ_PRI,
  		    i2c_sam3_isr, DEVICE_GET(i2c_sam3_1), 0);
  	irq_enable(IRQ_TWI1);
  }
  
  #endif /* CONFIG_I2C_ATMEL_SAM3_1 */
  