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