示例#1
0
/**
 * i2c_pnx_master_xmit - transmit data to slave
 * @adap:		pointer to I2C adapter structure
 *
 * Sends one byte of data to the slave
 */
static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
{
	u32 val;

	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	if (alg_data->mif.len > 0) {
		/* We still have something to talk about... */
		val = *alg_data->mif.buf++;

		alg_data->mif.len--;
		iowrite32(val, I2C_REG_TX(alg_data));

		dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n",
			__func__, val, alg_data->mif.len + 1);

		if (alg_data->mif.len == 0) {
			if (alg_data->last) {
				/* Wait until the STOP is seen. */
				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
					dev_err(&alg_data->adapter.dev,
						"The bus is still active after timeout\n");
			}
			/* Disable master interrupts */
			iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
				~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
				  I2C_REG_CTL(alg_data));

			del_timer_sync(&alg_data->mif.timer);

			dev_dbg(&alg_data->adapter.dev,
				"%s(): Waking up xfer routine.\n",
				__func__);

			complete(&alg_data->mif.complete);
		}
	} else if (alg_data->mif.len == 0) {
		/* zero-sized transfer */
		i2c_pnx_stop(alg_data);

		/* Disable master interrupts. */
		iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
			~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
			  I2C_REG_CTL(alg_data));

		/* Stop timer. */
		del_timer_sync(&alg_data->mif.timer);
		dev_dbg(&alg_data->adapter.dev,
			"%s(): Waking up xfer routine after zero-xfer.\n",
			__func__);

		complete(&alg_data->mif.complete);
	}

	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	return 0;
}
示例#2
0
文件: i2c-pnx.c 项目: c444b774/linux
/**
 * i2c_pnx_start - start a device
 * @slave_addr:		slave address
 * @adap:		pointer to adapter structure
 *
 * Generate a START signal in the desired mode.
 */
static int i2c_pnx_start(unsigned char slave_addr,
	struct i2c_pnx_algo_data *alg_data)
{
	dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,
		slave_addr, alg_data->mif.mode);

	/* Check for 7 bit slave addresses only */
	if (slave_addr & ~0x7f) {
		dev_err(&alg_data->adapter.dev,
			"%s: Invalid slave address %x. Only 7-bit addresses are supported\n",
			alg_data->adapter.name, slave_addr);
		return -EINVAL;
	}

	/* First, make sure bus is idle */
	if (wait_timeout(alg_data)) {
		/* Somebody else is monopolizing the bus */
		dev_err(&alg_data->adapter.dev,
			"%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
			alg_data->adapter.name, slave_addr,
			ioread32(I2C_REG_CTL(alg_data)),
			ioread32(I2C_REG_STS(alg_data)));
		return -EBUSY;
	} else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
		/* Sorry, we lost the bus */
		dev_err(&alg_data->adapter.dev,
		        "%s: Arbitration failure. Slave addr = %02x\n",
			alg_data->adapter.name, slave_addr);
		return -EIO;
	}

	/*
	 * OK, I2C is enabled and we have the bus.
	 * Clear the current TDI and AFI status flags.
	 */
	iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
		  I2C_REG_STS(alg_data));

	dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,
		(slave_addr << 1) | start_bit | alg_data->mif.mode);

	/* Write the slave address, START bit and R/W bit */
	iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
		  I2C_REG_TX(alg_data));

	dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);

	return 0;
}
示例#3
0
static int i2c_pnx_start(unsigned char slave_addr,
	struct i2c_pnx_algo_data *alg_data)
{
	dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,
		slave_addr, alg_data->mif.mode);

	/*                                      */
	if (slave_addr & ~0x7f) {
		dev_err(&alg_data->adapter.dev,
			"%s: Invalid slave address %x. Only 7-bit addresses are supported\n",
			alg_data->adapter.name, slave_addr);
		return -EINVAL;
	}

	/*                              */
	if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
		/*                                       */
		dev_err(&alg_data->adapter.dev,
			"%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
			alg_data->adapter.name, slave_addr,
			ioread32(I2C_REG_CTL(alg_data)),
			ioread32(I2C_REG_STS(alg_data)));
		return -EBUSY;
	} else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
		/*                        */
		dev_err(&alg_data->adapter.dev,
		        "%s: Arbitration failure. Slave addr = %02x\n",
			alg_data->adapter.name, slave_addr);
		return -EIO;
	}

	/*
                                           
                                               
  */
	iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
		  I2C_REG_STS(alg_data));

	dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,
		(slave_addr << 1) | start_bit | alg_data->mif.mode);

	/*                                                */
	iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
		  I2C_REG_TX(alg_data));

	dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);

	return 0;
}
示例#4
0
文件: i2c-pnx.c 项目: c444b774/linux
/**
 * i2c_pnx_stop - stop a device
 * @adap:		pointer to I2C adapter structure
 *
 * Generate a STOP signal to terminate the master transaction.
 */
static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
{
	/* Only 1 msec max timeout due to interrupt context */
	long timeout = 1000;

	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	/* Write a STOP bit to TX FIFO */
	iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));

	/* Wait until the STOP is seen. */
	while (timeout > 0 &&
	       (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
		/* may be called from interrupt context */
		udelay(1);
		timeout--;
	}

	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));
}
示例#5
0
static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
{
	/*                                                  */
	long timeout = 1000;

	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	/*                             */
	iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));

	/*                              */
	while (timeout > 0 &&
	       (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
		/*                                      */
		udelay(1);
		timeout--;
	}

	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));
}
示例#6
0
文件: i2c-pnx.c 项目: c444b774/linux
/**
 * i2c_pnx_master_rcv - receive data from slave
 * @adap:		pointer to I2C adapter structure
 *
 * Reads one byte data from the slave
 */
static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
{
	unsigned int val = 0;
	u32 ctl = 0;

	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	/* Check, whether there is already data,
	 * or we didn't 'ask' for it yet.
	 */
	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
		/* 'Asking' is done asynchronously, e.g. dummy TX of several
		 * bytes is done before the first actual RX arrives in FIFO.
		 * Therefore, ordered bytes (via TX) are counted separately.
		 */
		if (alg_data->mif.order) {
			dev_dbg(&alg_data->adapter.dev,
				"%s(): Write dummy data to fill Rx-fifo...\n",
				__func__);

			if (alg_data->mif.order == 1) {
				/* Last byte, do not acknowledge next rcv. */
				val |= stop_bit;

				/*
				 * Enable interrupt RFDAIE (data in Rx fifo),
				 * and disable DRMIE (need data for Tx)
				 */
				ctl = ioread32(I2C_REG_CTL(alg_data));
				ctl |= mcntrl_rffie | mcntrl_daie;
				ctl &= ~mcntrl_drmie;
				iowrite32(ctl, I2C_REG_CTL(alg_data));
			}

			/*
			 * Now we'll 'ask' for data:
			 * For each byte we want to receive, we must
			 * write a (dummy) byte to the Tx-FIFO.
			 */
			iowrite32(val, I2C_REG_TX(alg_data));
			alg_data->mif.order--;
		}
		return 0;
	}

	/* Handle data. */
	if (alg_data->mif.len > 0) {
		val = ioread32(I2C_REG_RX(alg_data));
		*alg_data->mif.buf++ = (u8) (val & 0xff);
		dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n",
			__func__, val, alg_data->mif.len);

		alg_data->mif.len--;
		if (alg_data->mif.len == 0) {
			if (alg_data->last)
				/* Wait until the STOP is seen. */
				if (wait_timeout(alg_data))
					dev_err(&alg_data->adapter.dev,
						"The bus is still active after timeout\n");

			/* Disable master interrupts */
			ctl = ioread32(I2C_REG_CTL(alg_data));
			ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
				 mcntrl_drmie | mcntrl_daie);
			iowrite32(ctl, I2C_REG_CTL(alg_data));

			/* Kill timer. */
			del_timer_sync(&alg_data->mif.timer);
			complete(&alg_data->mif.complete);
		}
	}

	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	return 0;
}
示例#7
0
/**
 * i2c_pnx_master_rcv - receive data from slave
 * @adap:		pointer to I2C adapter structure
 *
 * Reads one byte data from the slave
 */
static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
{
	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
	unsigned int val = 0;
	u32 ctl = 0;

	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	/* Check, whether there is already data,
	 * or we didn't 'ask' for it yet.
	 */
	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
		dev_dbg(&adap->dev, "%s(): Write dummy data to fill "
			"Rx-fifo...\n", __func__);

		if (alg_data->mif.len == 1) {
			/* Last byte, do not acknowledge next rcv. */
			val |= stop_bit;
			if (!alg_data->last)
				val |= start_bit;

			/*
			 * Enable interrupt RFDAIE (data in Rx fifo),
			 * and disable DRMIE (need data for Tx)
			 */
			ctl = ioread32(I2C_REG_CTL(alg_data));
			ctl |= mcntrl_rffie | mcntrl_daie;
			ctl &= ~mcntrl_drmie;
			iowrite32(ctl, I2C_REG_CTL(alg_data));
		}

		/*
		 * Now we'll 'ask' for data:
		 * For each byte we want to receive, we must
		 * write a (dummy) byte to the Tx-FIFO.
		 */
		iowrite32(val, I2C_REG_TX(alg_data));

		return 0;
	}

	/* Handle data. */
	if (alg_data->mif.len > 0) {
		val = ioread32(I2C_REG_RX(alg_data));
		*alg_data->mif.buf++ = (u8) (val & 0xff);
		dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __func__, val,
			alg_data->mif.len);

		alg_data->mif.len--;
		if (alg_data->mif.len == 0) {
			if (alg_data->last)
				/* Wait until the STOP is seen. */
				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
					dev_err(&adap->dev, "The bus is still "
						"active after timeout\n");

			/* Disable master interrupts */
			ctl = ioread32(I2C_REG_CTL(alg_data));
			ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
				 mcntrl_drmie | mcntrl_daie);
			iowrite32(ctl, I2C_REG_CTL(alg_data));

			/* Kill timer. */
			del_timer_sync(&alg_data->mif.timer);
			complete(&alg_data->mif.complete);
		}
	}

	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	return 0;
}
示例#8
0
static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
{
	unsigned int val = 0;
	u32 ctl = 0;

	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	/*                                      
                                  
  */
	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
		dev_dbg(&alg_data->adapter.dev,
			"%s(): Write dummy data to fill Rx-fifo...\n",
			__func__);

		if (alg_data->mif.len == 1) {
			/*                                         */
			val |= stop_bit;

			/*
                                                
                                          
    */
			ctl = ioread32(I2C_REG_CTL(alg_data));
			ctl |= mcntrl_rffie | mcntrl_daie;
			ctl &= ~mcntrl_drmie;
			iowrite32(ctl, I2C_REG_CTL(alg_data));
		}

		/*
                              
                                              
                                         
   */
		iowrite32(val, I2C_REG_TX(alg_data));

		return 0;
	}

	/*              */
	if (alg_data->mif.len > 0) {
		val = ioread32(I2C_REG_RX(alg_data));
		*alg_data->mif.buf++ = (u8) (val & 0xff);
		dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n",
			__func__, val, alg_data->mif.len);

		alg_data->mif.len--;
		if (alg_data->mif.len == 0) {
			if (alg_data->last)
				/*                              */
				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
					dev_err(&alg_data->adapter.dev,
						"The bus is still active after timeout\n");

			/*                           */
			ctl = ioread32(I2C_REG_CTL(alg_data));
			ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
				 mcntrl_drmie | mcntrl_daie);
			iowrite32(ctl, I2C_REG_CTL(alg_data));

			/*             */
			del_timer_sync(&alg_data->mif.timer);
			complete(&alg_data->mif.complete);
		}
	}

	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	return 0;
}
示例#9
0
static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
{
	u32 val;

	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	if (alg_data->mif.len > 0) {
		/*                                          */
		val = *alg_data->mif.buf++;

		if (alg_data->mif.len == 1)
			val |= stop_bit;

		alg_data->mif.len--;
		iowrite32(val, I2C_REG_TX(alg_data));

		dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n",
			__func__, val, alg_data->mif.len + 1);

		if (alg_data->mif.len == 0) {
			if (alg_data->last) {
				/*                              */
				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
					dev_err(&alg_data->adapter.dev,
						"The bus is still active after timeout\n");
			}
			/*                           */
			iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
				~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
				  I2C_REG_CTL(alg_data));

			del_timer_sync(&alg_data->mif.timer);

			dev_dbg(&alg_data->adapter.dev,
				"%s(): Waking up xfer routine.\n",
				__func__);

			complete(&alg_data->mif.complete);
		}
	} else if (alg_data->mif.len == 0) {
		/*                     */
		i2c_pnx_stop(alg_data);

		/*                            */
		iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
			~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
			  I2C_REG_CTL(alg_data));

		/*             */
		del_timer_sync(&alg_data->mif.timer);
		dev_dbg(&alg_data->adapter.dev,
			"%s(): Waking up xfer routine after zero-xfer.\n",
			__func__);

		complete(&alg_data->mif.complete);
	}

	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
		__func__, ioread32(I2C_REG_STS(alg_data)));

	return 0;
}