1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Synopsys DesignWare I2C adapter driver (slave only). 4 * 5 * Based on the Synopsys DesignWare I2C adapter driver (master). 6 * 7 * Copyright (C) 2016 Synopsys Inc. 8 */ 9 10 #define DEFAULT_SYMBOL_NAMESPACE "I2C_DW" 11 12 #include <linux/delay.h> 13 #include <linux/err.h> 14 #include <linux/errno.h> 15 #include <linux/i2c.h> 16 #include <linux/interrupt.h> 17 #include <linux/io.h> 18 #include <linux/module.h> 19 #include <linux/pm_runtime.h> 20 #include <linux/regmap.h> 21 22 #include "i2c-designware-core.h" 23 24 int i2c_dw_reg_slave(struct i2c_client *slave) 25 { 26 struct dw_i2c_dev *dev = i2c_get_adapdata(slave->adapter); 27 int ret; 28 29 if (!i2c_check_functionality(slave->adapter, I2C_FUNC_SLAVE)) 30 return -EOPNOTSUPP; 31 if (dev->slave) 32 return -EBUSY; 33 if (slave->flags & I2C_CLIENT_TEN) 34 return -EAFNOSUPPORT; 35 36 ret = i2c_dw_acquire_lock(dev); 37 if (ret) 38 return ret; 39 40 pm_runtime_get_sync(dev->dev); 41 __i2c_dw_disable_nowait(dev); 42 dev->slave = slave; 43 i2c_dw_set_mode(dev, DW_IC_SLAVE); 44 45 i2c_dw_release_lock(dev); 46 47 return 0; 48 } 49 50 int i2c_dw_unreg_slave(struct i2c_client *slave) 51 { 52 struct dw_i2c_dev *dev = i2c_get_adapdata(slave->adapter); 53 54 regmap_write(dev->map, DW_IC_INTR_MASK, 0); 55 i2c_dw_disable(dev); 56 synchronize_irq(dev->irq); 57 dev->slave = NULL; 58 i2c_dw_set_mode(dev, DW_IC_MASTER); 59 pm_runtime_put_sync_suspend(dev->dev); 60 61 return 0; 62 } 63 64 static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev) 65 { 66 unsigned int stat, dummy; 67 68 /* 69 * The IC_INTR_STAT register just indicates "enabled" interrupts. 70 * The unmasked raw version of interrupt status bits is available 71 * in the IC_RAW_INTR_STAT register. 72 * 73 * That is, 74 * stat = readl(IC_INTR_STAT); 75 * equals to, 76 * stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK); 77 * 78 * The raw version might be useful for debugging purposes. 79 */ 80 regmap_read(dev->map, DW_IC_INTR_STAT, &stat); 81 82 /* 83 * Do not use the IC_CLR_INTR register to clear interrupts, or 84 * you'll miss some interrupts, triggered during the period from 85 * readl(IC_INTR_STAT) to readl(IC_CLR_INTR). 86 * 87 * Instead, use the separately-prepared IC_CLR_* registers. 88 */ 89 if (stat & DW_IC_INTR_TX_ABRT) 90 regmap_read(dev->map, DW_IC_CLR_TX_ABRT, &dummy); 91 if (stat & DW_IC_INTR_RX_UNDER) 92 regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &dummy); 93 if (stat & DW_IC_INTR_RX_OVER) 94 regmap_read(dev->map, DW_IC_CLR_RX_OVER, &dummy); 95 if (stat & DW_IC_INTR_TX_OVER) 96 regmap_read(dev->map, DW_IC_CLR_TX_OVER, &dummy); 97 if (stat & DW_IC_INTR_RX_DONE) 98 regmap_read(dev->map, DW_IC_CLR_RX_DONE, &dummy); 99 if (stat & DW_IC_INTR_ACTIVITY) 100 regmap_read(dev->map, DW_IC_CLR_ACTIVITY, &dummy); 101 if (stat & DW_IC_INTR_STOP_DET) 102 regmap_read(dev->map, DW_IC_CLR_STOP_DET, &dummy); 103 if (stat & DW_IC_INTR_START_DET) 104 regmap_read(dev->map, DW_IC_CLR_START_DET, &dummy); 105 if (stat & DW_IC_INTR_GEN_CALL) 106 regmap_read(dev->map, DW_IC_CLR_GEN_CALL, &dummy); 107 108 return stat; 109 } 110 111 /* 112 * Interrupt service routine. This gets called whenever an I2C slave interrupt 113 * occurs. 114 */ 115 irqreturn_t i2c_dw_isr_slave(struct dw_i2c_dev *dev) 116 { 117 unsigned int raw_stat, stat, enabled, tmp; 118 u8 val = 0, slave_activity; 119 120 regmap_read(dev->map, DW_IC_ENABLE, &enabled); 121 regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_stat); 122 regmap_read(dev->map, DW_IC_STATUS, &tmp); 123 slave_activity = ((tmp & DW_IC_STATUS_SLAVE_ACTIVITY) >> 6); 124 125 if (!enabled || !(raw_stat & ~DW_IC_INTR_ACTIVITY) || !dev->slave) 126 return IRQ_NONE; 127 128 stat = i2c_dw_read_clear_intrbits_slave(dev); 129 dev_dbg(dev->dev, 130 "%#x STATUS SLAVE_ACTIVITY=%#x : RAW_INTR_STAT=%#x : INTR_STAT=%#x\n", 131 enabled, slave_activity, raw_stat, stat); 132 133 if (stat & DW_IC_INTR_RX_FULL) { 134 if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { 135 dev->status |= STATUS_WRITE_IN_PROGRESS; 136 dev->status &= ~STATUS_READ_IN_PROGRESS; 137 i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, 138 &val); 139 } 140 141 do { 142 regmap_read(dev->map, DW_IC_DATA_CMD, &tmp); 143 if (tmp & DW_IC_DATA_CMD_FIRST_DATA_BYTE) 144 i2c_slave_event(dev->slave, 145 I2C_SLAVE_WRITE_REQUESTED, 146 &val); 147 val = tmp; 148 i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED, 149 &val); 150 regmap_read(dev->map, DW_IC_STATUS, &tmp); 151 } while (tmp & DW_IC_STATUS_RFNE); 152 } 153 154 if (stat & DW_IC_INTR_RD_REQ) { 155 if (slave_activity) { 156 regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp); 157 158 if (!(dev->status & STATUS_READ_IN_PROGRESS)) { 159 i2c_slave_event(dev->slave, 160 I2C_SLAVE_READ_REQUESTED, 161 &val); 162 dev->status |= STATUS_READ_IN_PROGRESS; 163 dev->status &= ~STATUS_WRITE_IN_PROGRESS; 164 } else { 165 i2c_slave_event(dev->slave, 166 I2C_SLAVE_READ_PROCESSED, 167 &val); 168 } 169 regmap_write(dev->map, DW_IC_DATA_CMD, val); 170 } 171 } 172 173 if (stat & DW_IC_INTR_STOP_DET) 174 i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val); 175 176 return IRQ_HANDLED; 177 } 178 179 void i2c_dw_configure_slave(struct dw_i2c_dev *dev) 180 { 181 if (dev->flags & ACCESS_POLLING) 182 return; 183 184 dev->functionality |= I2C_FUNC_SLAVE; 185 186 dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL | 187 DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED; 188 } 189 EXPORT_SYMBOL_GPL(i2c_dw_configure_slave); 190 191 MODULE_AUTHOR("Luis Oliveira <lolivei@synopsys.com>"); 192 MODULE_DESCRIPTION("Synopsys DesignWare I2C bus slave adapter"); 193 MODULE_LICENSE("GPL v2"); 194 MODULE_IMPORT_NS("I2C_DW_COMMON"); 195