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; }
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; }
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; }