Пример #1
0
static irqreturn_t
i2c_pnx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned long stat;
	i2c_pnx_algo_data_t *alg_data = (i2c_pnx_algo_data_t *)dev_id;

	if (alg_data->mode == slave) {
#ifdef CONFIG_I2C_PNX_SLAVE_SUPPORT
		/* process slave-related events */
		pr_debug ("%s(): sstat = %x sctrl = %x\n", __FUNCTION__,
			alg_data->slave->sts, alg_data->slave->ctl);
		stat = alg_data->slave->sts;

		/* Now let's see what kind of event this is */
		if (stat & sstatus_afi) {
			/* We lost arbitration in the midst of a transfer */
			pr_debug ("%s(): Arbitration failed!\n", __FUNCTION__);
			alg_data->slave->sts |= sstatus_afi; /* clear AFI flag */
		}

		if (stat & sstatus_nai) {
			/* Master did not acknowledge our transfer */
			pr_debug ("%s(): Master did not acknowledge!\n", __FUNCTION__);
		}

		if ((!(stat & sstatus_tffs)) && (!(stat & sstatus_tfes))) {
			/* We can push some more data into slave TX FIFO */
			pr_debug ("%s(): filling up slave FIFO.\n", __FUNCTION__);
			if (!alg_data->buf_index)
				/* no more need in this interrupt */
				alg_data->slave->ctl &= ~scntrl_tffsie;

			alg_data->slave->txs = 0x000000FF
				& alg_data->buffer [alg_data->buf_index--];
		}

		if (!(stat & sstatus_rfe)) {
			/* RX FIFO contains data to process */
			pr_debug ("%s(): S <<- M\n", __FUNCTION__);
			if (alg_data->slave_recv_cb)
				alg_data->slave_recv_cb (alg_data);
			else
				pr_debug ("%s(): no slave receive callback installed!\n", __FUNCTION__);
		} else if (stat & sstatus_drsi) {
			/* I2C master requests data */
			/* request data from higher level code and send it */
			if (alg_data->slave_send_cb)
				alg_data->slave_send_cb (alg_data);
			else
				pr_debug ("%s(): no slave send callback installed!\n", __FUNCTION__);
		}
#endif
	} else {
		/* process master-related events */
#if I2C_PNX010X_DEBUG
		pr_debug ("%s(): mstat = %x mctrl = %x, mmode = %s\n", __FUNCTION__,
			alg_data->master->sts, alg_data->master->ctl,
			i2c_pnx_modestr[alg_data->mif.mode]);
#endif
		stat = alg_data->master->sts;

		/* Now let's see what kind of event this is */
		if (stat & mstatus_afi) {
			/* We lost arbitration in the midst of a transfer */
			alg_data->mif.ret = -EIO;

			/* Disable master interrupts. */
			alg_data->master->ctl &= ~(mcntrl_afie | mcntrl_naie |
				mcntrl_drmie | mcntrl_rffie);

			/* Stop timer, to prevent timeout. */
			del_timer_sync(&alg_data->mif.timer);
			complete(&alg_data->mif.complete);
		} else if (stat & mstatus_nai) {
			/* Slave did not acknowledge, generate a STOP */
			pr_debug ("%s(): Slave did not acknowledge, generating a STOP.\n", __FUNCTION__);
			i2c_pnx_stop(alg_data);

			/* Disable master interrupts. */
			alg_data->master->ctl &= ~(mcntrl_afie | mcntrl_naie |
				mcntrl_drmie | mcntrl_rffie);

			/* Our return value. */
			alg_data->mif.ret = -EFAULT;

			/* Stop timer, to prevent timeout. */
			del_timer_sync(&alg_data->mif.timer);
			complete(&alg_data->mif.complete);
		} else
			/* Two options:
			 * - Master Tx needs data.
			 * - There is data in the Rx-fifo
			 * The latter is only the case if we have requested for data,
			 * via a dummy write. (See 'i2c_pnx_master_rcv'.)
			 * We therefore check, as a sanity check, whether that interrupt
			 * has been enabled.
			 */
			if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
				if (alg_data->mif.mode == xmit) {
					i2c_pnx_master_xmit(alg_data);
				} else if (alg_data->mif.mode == rcv) {
					i2c_pnx_master_rcv(alg_data);
				}
			}

			/* Clear TDI and AFI bits by writing 1's in the respective position. */
			alg_data->master->sts |= mstatus_tdi | mstatus_afi;
	}

	pr_debug ("%s(): Exit, stat = %x ctrl = %x.\n",
		__FUNCTION__, alg_data->master->sts, alg_data->master->ctl);

	return IRQ_HANDLED;
}
Пример #2
0
static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
{
	struct i2c_pnx_algo_data *alg_data = dev_id;
	u32 stat, ctl;

	dev_dbg(&alg_data->adapter.dev,
		"%s(): mstat = %x mctrl = %x, mode = %d\n",
		__func__,
		ioread32(I2C_REG_STS(alg_data)),
		ioread32(I2C_REG_CTL(alg_data)),
		alg_data->mif.mode);
	stat = ioread32(I2C_REG_STS(alg_data));

	/* let's see what kind of event this is */
	if (stat & mstatus_afi) {
		/* We lost arbitration in the midst of a transfer */
		alg_data->mif.ret = -EIO;

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

		/* Stop timer, to prevent timeout. */
		del_timer_sync(&alg_data->mif.timer);
		complete(&alg_data->mif.complete);
	} else if (stat & mstatus_nai) {
		/* Slave did not acknowledge, generate a STOP */
		dev_dbg(&alg_data->adapter.dev,
			"%s(): Slave did not acknowledge, generating a STOP.\n",
			__func__);
		i2c_pnx_stop(alg_data);

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

		/* Our return value. */
		alg_data->mif.ret = -EIO;

		/* Stop timer, to prevent timeout. */
		del_timer_sync(&alg_data->mif.timer);
		complete(&alg_data->mif.complete);
	} else {
		/*
		 * Two options:
		 * - Master Tx needs data.
		 * - There is data in the Rx-fifo
		 * The latter is only the case if we have requested for data,
		 * via a dummy write. (See 'i2c_pnx_master_rcv'.)
		 * We therefore check, as a sanity check, whether that interrupt
		 * has been enabled.
		 */
		if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
			if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
				i2c_pnx_master_xmit(alg_data);
			} else if (alg_data->mif.mode == I2C_SMBUS_READ) {
				i2c_pnx_master_rcv(alg_data);
			}
		}
	}

	/* Clear TDI and AFI bits */
	stat = ioread32(I2C_REG_STS(alg_data));
	iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));

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

	return IRQ_HANDLED;
}
Пример #3
0
static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
{
	struct i2c_pnx_algo_data *alg_data = dev_id;
	u32 stat, ctl;

	dev_dbg(&alg_data->adapter.dev,
		"%s(): mstat = %x mctrl = %x, mode = %d\n",
		__func__,
		ioread32(I2C_REG_STS(alg_data)),
		ioread32(I2C_REG_CTL(alg_data)),
		alg_data->mif.mode);
	stat = ioread32(I2C_REG_STS(alg_data));

	/*                                      */
	if (stat & mstatus_afi) {
		/*                                                */
		alg_data->mif.ret = -EIO;

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

		/*                                 */
		del_timer_sync(&alg_data->mif.timer);
		complete(&alg_data->mif.complete);
	} else if (stat & mstatus_nai) {
		/*                                            */
		dev_dbg(&alg_data->adapter.dev,
			"%s(): Slave did not acknowledge, generating a STOP.\n",
			__func__);
		i2c_pnx_stop(alg_data);

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

		/*                   */
		alg_data->mif.ret = -EIO;

		/*                                 */
		del_timer_sync(&alg_data->mif.timer);
		complete(&alg_data->mif.complete);
	} else {
		/*
                 
                            
                                   
                                                               
                                                   
                                                                  
                      
   */
		if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
			if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
				i2c_pnx_master_xmit(alg_data);
			} else if (alg_data->mif.mode == I2C_SMBUS_READ) {
				i2c_pnx_master_rcv(alg_data);
			}
		}
	}

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

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

	return IRQ_HANDLED;
}