static void xiic_start_xfer(struct xiic_i2c *i2c) { unsigned long flags; spin_lock_irqsave(&i2c->lock, flags); xiic_reinit(i2c); /* disable interrupts globally */ xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0); spin_unlock_irqrestore(&i2c->lock, flags); __xiic_start_xfer(i2c); xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); }
static irqreturn_t xiic_isr(int irq, void *dev_id) { struct xiic_i2c *i2c = dev_id; spin_lock(&i2c->lock); /* disable interrupts globally */ xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0); dev_dbg(i2c->adap.dev.parent, "%s entry\n", __func__); xiic_process(i2c); xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); spin_unlock(&i2c->lock); return IRQ_HANDLED; }
static void xiic_deinit(struct xiic_i2c *i2c) { u8 cr; xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); /* Disable IIC Device. */ cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK); }
static void xiic_reinit(struct xiic_i2c *i2c) { xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); /* Set receive Fifo depth to maximum (zero based). */ xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); /* Reset Tx Fifo. */ xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); /* make sure RX fifo is empty */ xiic_clear_rx_fifo(i2c); /* Enable interrupts */ xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); xiic_irq_clr_en(i2c, XIIC_INTR_ARB_LOST_MASK); }
static int xiic_i2c_probe(struct platform_device *pdev) { struct xiic_i2c *i2c; struct xiic_i2c_platform_data *pdata; struct resource *res; int ret, irq; u8 i; u32 sr; i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); i2c->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; pdata = dev_get_platdata(&pdev->dev); /* hook up driver to tree */ platform_set_drvdata(pdev, i2c); i2c->adap = xiic_adapter; i2c_set_adapdata(&i2c->adap, i2c); i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.of_node = pdev->dev.of_node; mutex_init(&i2c->lock); init_waitqueue_head(&i2c->wait); i2c->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2c->clk)) { dev_err(&pdev->dev, "input clock not found.\n"); return PTR_ERR(i2c->clk); } ret = clk_prepare_enable(i2c->clk); if (ret) { dev_err(&pdev->dev, "Unable to enable clock.\n"); return ret; } i2c->dev = &pdev->dev; pm_runtime_enable(i2c->dev); pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT); pm_runtime_use_autosuspend(i2c->dev); pm_runtime_set_active(i2c->dev); ret = devm_request_threaded_irq(&pdev->dev, irq, xiic_isr, xiic_process, IRQF_ONESHOT, pdev->name, i2c); if (ret < 0) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); goto err_clk_dis; } /* * Detect endianness * Try to reset the TX FIFO. Then check the EMPTY flag. If it is not * set, assume that the endianness was wrong and swap. */ i2c->endianness = LITTLE; xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); /* Reset is cleared in xiic_reinit */ sr = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET); if (!(sr & XIIC_SR_TX_FIFO_EMPTY_MASK)) i2c->endianness = BIG; xiic_reinit(i2c); /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); if (ret) { xiic_deinit(i2c); goto err_clk_dis; } if (pdata) { /* add in known devices to the bus */ for (i = 0; i < pdata->num_devices; i++) i2c_new_device(&i2c->adap, pdata->devices + i); } return 0; err_clk_dis: pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_disable_unprepare(i2c->clk); return ret; }
static irqreturn_t xiic_process(int irq, void *dev_id) { struct xiic_i2c *i2c = dev_id; u32 pend, isr, ier; u32 clr = 0; /* Get the interrupt Status from the IPIF. There is no clearing of * interrupts in the IPIF. Interrupts must be cleared at the source. * To find which interrupts are pending; AND interrupts pending with * interrupts masked. */ mutex_lock(&i2c->lock); isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); pend = isr & ier; dev_dbg(i2c->adap.dev.parent, "%s: IER: 0x%x, ISR: 0x%x, pend: 0x%x\n", __func__, ier, isr, pend); dev_dbg(i2c->adap.dev.parent, "%s: SR: 0x%x, msg: %p, nmsgs: %d\n", __func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), i2c->tx_msg, i2c->nmsgs); /* Service requesting interrupt */ if ((pend & XIIC_INTR_ARB_LOST_MASK) || ((pend & XIIC_INTR_TX_ERROR_MASK) && !(pend & XIIC_INTR_RX_FULL_MASK))) { /* bus arbritration lost, or... * Transmit error _OR_ RX completed * if this happens when RX_FULL is not set * this is probably a TX error */ dev_dbg(i2c->adap.dev.parent, "%s error\n", __func__); /* dynamic mode seem to suffer from problems if we just flushes * fifos and the next message is a TX with len 0 (only addr) * reset the IP instead of just flush fifos */ xiic_reinit(i2c); if (i2c->rx_msg) xiic_wakeup(i2c, STATE_ERROR); if (i2c->tx_msg) xiic_wakeup(i2c, STATE_ERROR); } if (pend & XIIC_INTR_RX_FULL_MASK) { /* Receive register/FIFO is full */ clr |= XIIC_INTR_RX_FULL_MASK; if (!i2c->rx_msg) { dev_dbg(i2c->adap.dev.parent, "%s unexpexted RX IRQ\n", __func__); xiic_clear_rx_fifo(i2c); goto out; } xiic_read_rx(i2c); if (xiic_rx_space(i2c) == 0) { /* this is the last part of the message */ i2c->rx_msg = NULL; /* also clear TX error if there (RX complete) */ clr |= (isr & XIIC_INTR_TX_ERROR_MASK); dev_dbg(i2c->adap.dev.parent, "%s end of message, nmsgs: %d\n", __func__, i2c->nmsgs); /* send next message if this wasn't the last, * otherwise the transfer will be finialise when * receiving the bus not busy interrupt */ if (i2c->nmsgs > 1) { i2c->nmsgs--; i2c->tx_msg++; dev_dbg(i2c->adap.dev.parent, "%s will start next...\n", __func__); __xiic_start_xfer(i2c); } } } if (pend & XIIC_INTR_BNB_MASK) { /* IIC bus has transitioned to not busy */ clr |= XIIC_INTR_BNB_MASK; /* The bus is not busy, disable BusNotBusy interrupt */ xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK); if (!i2c->tx_msg) goto out; if ((i2c->nmsgs == 1) && !i2c->rx_msg && xiic_tx_space(i2c) == 0) xiic_wakeup(i2c, STATE_DONE); else xiic_wakeup(i2c, STATE_ERROR); } if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) { /* Transmit register/FIFO is empty or ½ empty */ clr |= (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)); if (!i2c->tx_msg) { dev_dbg(i2c->adap.dev.parent, "%s unexpexted TX IRQ\n", __func__); goto out; } xiic_fill_tx_fifo(i2c); /* current message sent and there is space in the fifo */ if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >= 2) { dev_dbg(i2c->adap.dev.parent, "%s end of message sent, nmsgs: %d\n", __func__, i2c->nmsgs); if (i2c->nmsgs > 1) { i2c->nmsgs--; i2c->tx_msg++; __xiic_start_xfer(i2c); } else { xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); dev_dbg(i2c->adap.dev.parent, "%s Got TX IRQ but no more to do...\n", __func__); } } else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1)) /* current frame is sent and is last, * make sure to disable tx half */ xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); } out: dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); mutex_unlock(&i2c->lock); return IRQ_HANDLED; }
static inline void xiic_irq_clr(struct xiic_i2c *i2c, u32 mask) { u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask); }
static inline void xiic_irq_en(struct xiic_i2c *i2c, u32 mask) { u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier | mask); }
static int xiic_i2c_probe(struct platform_device *pdev) { struct xiic_i2c *i2c; struct xiic_i2c_platform_data *pdata; struct resource *res; int ret, irq; u8 i; u32 sr; i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); i2c->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; pdata = dev_get_platdata(&pdev->dev); /* hook up driver to tree */ platform_set_drvdata(pdev, i2c); i2c->adap = xiic_adapter; i2c_set_adapdata(&i2c->adap, i2c); i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.of_node = pdev->dev.of_node; spin_lock_init(&i2c->lock); init_waitqueue_head(&i2c->wait); ret = devm_request_irq(&pdev->dev, irq, xiic_isr, 0, pdev->name, i2c); if (ret < 0) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); return ret; } /* * Detect endianness * Try to reset the TX FIFO. Then check the EMPTY flag. If it is not * set, assume that the endianness was wrong and swap. */ i2c->endianness = LITTLE; xiic_setreg32(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); /* Reset is cleared in xiic_reinit */ sr = xiic_getreg32(i2c, XIIC_SR_REG_OFFSET); if (!(sr & XIIC_SR_TX_FIFO_EMPTY_MASK)) i2c->endianness = BIG; xiic_reinit(i2c); /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); if (ret) { dev_err(&pdev->dev, "Failed to add adapter\n"); xiic_deinit(i2c); return ret; } if (pdata) { /* add in known devices to the bus */ for (i = 0; i < pdata->num_devices; i++) i2c_new_device(&i2c->adap, pdata->devices + i); } return 0; }