/** * i2c_dw_init_slave() - Initialize the DesignWare i2c slave hardware * @dev: device private data * * This function configures and enables the I2C in slave mode. * This function is called during I2C init function, and in case of timeout at * run time. * * Return: 0 on success, or negative errno otherwise.
*/ staticint i2c_dw_init_slave(struct dw_i2c_dev *dev)
{ int ret;
ret = i2c_dw_acquire_lock(dev); if (ret) return ret;
/* Disable the adapter. */
__i2c_dw_disable(dev);
/* Write SDA hold time if supported */ if (dev->sda_hold_time)
regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time);
if (dev->slave) return -EBUSY; if (slave->flags & I2C_CLIENT_TEN) return -EAFNOSUPPORT;
pm_runtime_get_sync(dev->dev);
/* * Set slave address in the IC_SAR register, * the address to which the DW_apb_i2c responds.
*/
__i2c_dw_disable_nowait(dev);
regmap_write(dev->map, DW_IC_SAR, slave->addr);
dev->slave = slave;
/* * The IC_INTR_STAT register just indicates "enabled" interrupts. * The unmasked raw version of interrupt status bits is available * in the IC_RAW_INTR_STAT register. * * That is, * stat = readl(IC_INTR_STAT); * equals to, * stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK); * * The raw version might be useful for debugging purposes.
*/
regmap_read(dev->map, DW_IC_INTR_STAT, &stat);
/* * Do not use the IC_CLR_INTR register to clear interrupts, or * you'll miss some interrupts, triggered during the period from * readl(IC_INTR_STAT) to readl(IC_CLR_INTR). * * Instead, use the separately-prepared IC_CLR_* registers.
*/ if (stat & DW_IC_INTR_TX_ABRT)
regmap_read(dev->map, DW_IC_CLR_TX_ABRT, &dummy); if (stat & DW_IC_INTR_RX_UNDER)
regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &dummy); if (stat & DW_IC_INTR_RX_OVER)
regmap_read(dev->map, DW_IC_CLR_RX_OVER, &dummy); if (stat & DW_IC_INTR_TX_OVER)
regmap_read(dev->map, DW_IC_CLR_TX_OVER, &dummy); if (stat & DW_IC_INTR_RX_DONE)
regmap_read(dev->map, DW_IC_CLR_RX_DONE, &dummy); if (stat & DW_IC_INTR_ACTIVITY)
regmap_read(dev->map, DW_IC_CLR_ACTIVITY, &dummy); if (stat & DW_IC_INTR_STOP_DET)
regmap_read(dev->map, DW_IC_CLR_STOP_DET, &dummy); if (stat & DW_IC_INTR_START_DET)
regmap_read(dev->map, DW_IC_CLR_START_DET, &dummy); if (stat & DW_IC_INTR_GEN_CALL)
regmap_read(dev->map, DW_IC_CLR_GEN_CALL, &dummy);
return stat;
}
/* * Interrupt service routine. This gets called whenever an I2C slave interrupt * occurs.
*/ static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
{ struct dw_i2c_dev *dev = dev_id; unsignedint raw_stat, stat, enabled, tmp;
u8 val = 0, slave_activity;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.