* Re: [PATCH v3 1/8] i2c: iproc: I2C read up to 255 bytes support [not found] ` <1547791464-3540-2-git-send-email-rayagonda.kokatanur@broadcom.com> @ 2019-01-20 21:41 ` Ray Jui 0 siblings, 0 replies; 6+ messages in thread From: Ray Jui @ 2019-01-20 21:41 UTC (permalink / raw) To: Rayagonda Kokatanur, rjui Cc: bcm-kernel-feedback-list, shreesha.rajashekar, sbranden, wsa, linux-i2c, devicetree, linux-arm-kernel, linux-kernel, ccheng, heikki.krogerus, geert, arnd, manivannan.sadhasivam, ajayg, ard.biesheuvel, eajames, kramasub, vigneshr, mika.westerberg, pierre-yves.mordret, f.fainelli, aaron.wu, jdelvare, andriy.shevchenko, jarkko.nikula, robh+dt, mark.rutland, rayagonoda.kokatanur, Shreesha Rajashekar On 1/17/2019 10:04 PM, Rayagonda Kokatanur wrote: > From: Shreesha Rajashekar <shreesha@broadcom.com> > > Add support to allow I2C RX transfer up to 255 bytes. > > Signed-off-by: Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com> > Signed-off-by: Shreesha Rajashekar <shreesha@broadcom.com> > --- > drivers/i2c/busses/i2c-bcm-iproc.c | 98 +++++++++++++++++++++++++++++--------- > 1 file changed, 76 insertions(+), 22 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c > index 4c8c3bc4669c..eb7339a0280e 100644 > --- a/drivers/i2c/busses/i2c-bcm-iproc.c > +++ b/drivers/i2c/busses/i2c-bcm-iproc.c > @@ -80,6 +80,10 @@ > > #define I2C_TIMEOUT_MSEC 50000 > #define M_TX_RX_FIFO_SIZE 64 > +#define M_RX_FIFO_MAX_THLD_VALUE (M_TX_RX_FIFO_SIZE - 1) > + > +#define M_RX_MAX_READ_LEN 255 > +#define M_RX_FIFO_THLD_VALUE 50 > > enum bus_speed_index { > I2C_SPD_100K = 0, > @@ -102,17 +106,41 @@ struct bcm_iproc_i2c_dev { > > /* bytes that have been transferred */ > unsigned int tx_bytes; > + /* bytes that have been read */ > + unsigned int rx_bytes; > + unsigned int thld_bytes; > }; > > /* > * Can be expanded in the future if more interrupt status bits are utilized > */ > -#define ISR_MASK (BIT(IS_M_START_BUSY_SHIFT) | BIT(IS_M_TX_UNDERRUN_SHIFT)) > +#define ISR_MASK (BIT(IS_M_START_BUSY_SHIFT) | BIT(IS_M_TX_UNDERRUN_SHIFT)\ > + | BIT(IS_M_RX_THLD_SHIFT)) > + > +static void bcm_iproc_i2c_read_valid_bytes(struct bcm_iproc_i2c_dev *iproc_i2c) > +{ > + struct i2c_msg *msg = iproc_i2c->msg; > + > + /* Read valid data from RX FIFO */ > + while (iproc_i2c->rx_bytes < msg->len) { > + if (!((readl(iproc_i2c->base + > + M_FIFO_CTRL_OFFSET) >> > + M_FIFO_RX_CNT_SHIFT) & > + M_FIFO_RX_CNT_MASK)) > + break; > + > + msg->buf[iproc_i2c->rx_bytes] = > + (readl(iproc_i2c->base + M_RX_OFFSET) >> > + M_RX_DATA_SHIFT) & M_RX_DATA_MASK; > + iproc_i2c->rx_bytes++; > + } > +} > > static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data) > { > struct bcm_iproc_i2c_dev *iproc_i2c = data; > u32 status = readl(iproc_i2c->base + IS_OFFSET); > + u32 tmp; > > status &= ISR_MASK; > > @@ -136,8 +164,6 @@ static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data) > > /* mark the last byte */ > if (idx == msg->len - 1) { > - u32 tmp; > - > val |= BIT(M_TX_WR_STATUS_SHIFT); > > /* > @@ -156,6 +182,32 @@ static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data) > iproc_i2c->tx_bytes += tx_bytes; > } > > + if (status & BIT(IS_M_RX_THLD_SHIFT)) { > + struct i2c_msg *msg = iproc_i2c->msg; > + u32 bytes_left; > + > + bcm_iproc_i2c_read_valid_bytes(iproc_i2c); > + bytes_left = msg->len - iproc_i2c->rx_bytes; > + if (bytes_left == 0) { > + /* finished reading all data, disable rx thld event */ > + tmp = readl(iproc_i2c->base + IE_OFFSET); > + tmp &= ~BIT(IS_M_RX_THLD_SHIFT); > + writel(tmp, iproc_i2c->base + IE_OFFSET); > + } else if (bytes_left < iproc_i2c->thld_bytes) { > + /* set bytes left as threshold */ > + tmp = readl(iproc_i2c->base + M_FIFO_CTRL_OFFSET); > + tmp &= ~(M_FIFO_RX_THLD_MASK << M_FIFO_RX_THLD_SHIFT); > + tmp |= (bytes_left << M_FIFO_RX_THLD_SHIFT); > + writel(tmp, iproc_i2c->base + M_FIFO_CTRL_OFFSET); > + iproc_i2c->thld_bytes = bytes_left; > + } > + /* > + * bytes_left >= iproc_i2c->thld_bytes, > + * hence no need to change the THRESHOLD SET. > + * It will remain as iproc_i2c->thld_bytes itself > + */ > + } > + > if (status & BIT(IS_M_START_BUSY_SHIFT)) { > iproc_i2c->xfer_is_done = 1; > complete(&iproc_i2c->done); > @@ -253,7 +305,7 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > { > int ret, i; > u8 addr; > - u32 val; > + u32 val, tmp, val_intr_en; > unsigned int tx_bytes; > unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT_MSEC); > > @@ -298,7 +350,7 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > * transaction is done, i.e., the internal start_busy bit, transitions > * from 1 to 0. > */ > - val = BIT(IE_M_START_BUSY_SHIFT); > + val_intr_en = BIT(IE_M_START_BUSY_SHIFT); > > /* > * If TX data size is larger than the TX FIFO, need to enable TX > @@ -307,9 +359,7 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > */ > if (!(msg->flags & I2C_M_RD) && > msg->len > iproc_i2c->tx_bytes) > - val |= BIT(IE_M_TX_UNDERRUN_SHIFT); > - > - writel(val, iproc_i2c->base + IE_OFFSET); > + val_intr_en |= BIT(IE_M_TX_UNDERRUN_SHIFT); > > /* > * Now we can activate the transfer. For a read operation, specify the > @@ -317,11 +367,27 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > */ > val = BIT(M_CMD_START_BUSY_SHIFT); > if (msg->flags & I2C_M_RD) { > + iproc_i2c->rx_bytes = 0; > + if (msg->len > M_RX_FIFO_MAX_THLD_VALUE) > + iproc_i2c->thld_bytes = M_RX_FIFO_THLD_VALUE; > + else > + iproc_i2c->thld_bytes = msg->len; > + > + /* set threshold value */ > + tmp = readl(iproc_i2c->base + M_FIFO_CTRL_OFFSET); > + tmp &= ~(M_FIFO_RX_THLD_MASK << M_FIFO_RX_THLD_SHIFT); > + tmp |= iproc_i2c->thld_bytes << M_FIFO_RX_THLD_SHIFT; > + writel(tmp, iproc_i2c->base + M_FIFO_CTRL_OFFSET); > + > + /* enable the RX threshold interrupt */ > + val_intr_en |= BIT(IE_M_RX_THLD_SHIFT); > + > val |= (M_CMD_PROTOCOL_BLK_RD << M_CMD_PROTOCOL_SHIFT) | > (msg->len << M_CMD_RD_CNT_SHIFT); > } else { > val |= (M_CMD_PROTOCOL_BLK_WR << M_CMD_PROTOCOL_SHIFT); > } > + writel(val_intr_en, iproc_i2c->base + IE_OFFSET); > writel(val, iproc_i2c->base + M_CMD_OFFSET); > > time_left = wait_for_completion_timeout(&iproc_i2c->done, time_left); > @@ -353,17 +419,6 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > return ret; > } > > - /* > - * For a read operation, we now need to load the data from FIFO > - * into the memory buffer > - */ > - if (msg->flags & I2C_M_RD) { > - for (i = 0; i < msg->len; i++) { > - msg->buf[i] = (readl(iproc_i2c->base + M_RX_OFFSET) >> > - M_RX_DATA_SHIFT) & M_RX_DATA_MASK; > - } > - } > - > return 0; > } > > @@ -395,9 +450,8 @@ static uint32_t bcm_iproc_i2c_functionality(struct i2c_adapter *adap) > .functionality = bcm_iproc_i2c_functionality, > }; > > -static const struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { > - /* need to reserve one byte in the FIFO for the slave address */ > - .max_read_len = M_TX_RX_FIFO_SIZE - 1, > +static struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { > + .max_read_len = M_RX_MAX_READ_LEN, > }; > > static int bcm_iproc_i2c_cfg_speed(struct bcm_iproc_i2c_dev *iproc_i2c) > Reviewed-by: Ray Jui <ray.jui@broadcom.com> ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <1547791464-3540-3-git-send-email-rayagonda.kokatanur@broadcom.com>]
* Re: [PATCH v3 2/8] i2c: iproc: Add Slave mode support [not found] ` <1547791464-3540-3-git-send-email-rayagonda.kokatanur@broadcom.com> @ 2019-01-20 21:45 ` Ray Jui 0 siblings, 0 replies; 6+ messages in thread From: Ray Jui @ 2019-01-20 21:45 UTC (permalink / raw) To: Rayagonda Kokatanur, rjui Cc: bcm-kernel-feedback-list, shreesha.rajashekar, sbranden, wsa, linux-i2c, devicetree, linux-arm-kernel, linux-kernel, ccheng, heikki.krogerus, geert, arnd, manivannan.sadhasivam, ajayg, ard.biesheuvel, eajames, kramasub, vigneshr, mika.westerberg, pierre-yves.mordret, f.fainelli, aaron.wu, jdelvare, andriy.shevchenko, jarkko.nikula, robh+dt, mark.rutland, rayagonoda.kokatanur On 1/17/2019 10:04 PM, Rayagonda Kokatanur wrote: > From: Shreesha Rajashekar <shreesha.rajashekar@broadcom.com> > > Add I2C slave mode support to the iProc I2C driver. > I2C slave mode is supported in the iProc I2C block > in all iProc based SoCs that include the I2C block. > > Signed-off-by: Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com> > Signed-off-by: Shreesha Rajashekar <shreesha.rajashekar@broadcom.com> > Signed-off-by: Michael Cheng <ccheng@broadcom.com> > --- > drivers/i2c/busses/Kconfig | 1 + > drivers/i2c/busses/i2c-bcm-iproc.c | 315 ++++++++++++++++++++++++++++++++++++- > 2 files changed, 310 insertions(+), 6 deletions(-) > > diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig > index f2c681971201..e0798b82b3bc 100644 > --- a/drivers/i2c/busses/Kconfig > +++ b/drivers/i2c/busses/Kconfig > @@ -424,6 +424,7 @@ config I2C_BCM_IPROC > tristate "Broadcom iProc I2C controller" > depends on ARCH_BCM_IPROC || COMPILE_TEST > default ARCH_BCM_IPROC > + select I2C_SLAVE > help > If you say yes to this option, support will be included for the > Broadcom iProc I2C controller. > diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c > index eb7339a0280e..4a4a052efcc9 100644 > --- a/drivers/i2c/busses/i2c-bcm-iproc.c > +++ b/drivers/i2c/busses/i2c-bcm-iproc.c > @@ -23,11 +23,30 @@ > #define CFG_OFFSET 0x00 > #define CFG_RESET_SHIFT 31 > #define CFG_EN_SHIFT 30 > +#define CFG_SLAVE_ADDR_0_SHIFT 28 > #define CFG_M_RETRY_CNT_SHIFT 16 > #define CFG_M_RETRY_CNT_MASK 0x0f > > #define TIM_CFG_OFFSET 0x04 > #define TIM_CFG_MODE_400_SHIFT 31 > +#define TIM_RAND_SLAVE_STRETCH_SHIFT 24 > +#define TIM_RAND_SLAVE_STRETCH_MASK 0x7f > +#define TIM_PERIODIC_SLAVE_STRETCH_SHIFT 16 > +#define TIM_PERIODIC_SLAVE_STRETCH_MASK 0x7f > + > +#define S_CFG_SMBUS_ADDR_OFFSET 0x08 > +#define S_CFG_EN_NIC_SMB_ADDR3_SHIFT 31 > +#define S_CFG_NIC_SMB_ADDR3_SHIFT 24 > +#define S_CFG_NIC_SMB_ADDR3_MASK 0x7f > +#define S_CFG_EN_NIC_SMB_ADDR2_SHIFT 23 > +#define S_CFG_NIC_SMB_ADDR2_SHIFT 16 > +#define S_CFG_NIC_SMB_ADDR2_MASK 0x7f > +#define S_CFG_EN_NIC_SMB_ADDR1_SHIFT 15 > +#define S_CFG_NIC_SMB_ADDR1_SHIFT 8 > +#define S_CFG_NIC_SMB_ADDR1_MASK 0x7f > +#define S_CFG_EN_NIC_SMB_ADDR0_SHIFT 7 > +#define S_CFG_NIC_SMB_ADDR0_SHIFT 0 > +#define S_CFG_NIC_SMB_ADDR0_MASK 0x7f > > #define M_FIFO_CTRL_OFFSET 0x0c > #define M_FIFO_RX_FLUSH_SHIFT 31 > @@ -37,6 +56,14 @@ > #define M_FIFO_RX_THLD_SHIFT 8 > #define M_FIFO_RX_THLD_MASK 0x3f > > +#define S_FIFO_CTRL_OFFSET 0x10 > +#define S_FIFO_RX_FLUSH_SHIFT 31 > +#define S_FIFO_TX_FLUSH_SHIFT 30 > +#define S_FIFO_RX_CNT_SHIFT 16 > +#define S_FIFO_RX_CNT_MASK 0x7f > +#define S_FIFO_RX_THLD_SHIFT 8 > +#define S_FIFO_RX_THLD_MASK 0x3f > + > #define M_CMD_OFFSET 0x30 > #define M_CMD_START_BUSY_SHIFT 31 > #define M_CMD_STATUS_SHIFT 25 > @@ -46,6 +73,8 @@ > #define M_CMD_STATUS_NACK_ADDR 0x2 > #define M_CMD_STATUS_NACK_DATA 0x3 > #define M_CMD_STATUS_TIMEOUT 0x4 > +#define M_CMD_STATUS_FIFO_UNDERRUN 0x5 > +#define M_CMD_STATUS_RX_FIFO_FULL 0x6 > #define M_CMD_PROTOCOL_SHIFT 9 > #define M_CMD_PROTOCOL_MASK 0xf > #define M_CMD_PROTOCOL_BLK_WR 0x7 > @@ -54,17 +83,36 @@ > #define M_CMD_RD_CNT_SHIFT 0 > #define M_CMD_RD_CNT_MASK 0xff > > +#define S_CMD_OFFSET 0x34 > +#define S_CMD_START_BUSY_SHIFT 31 > +#define S_CMD_STATUS_SHIFT 23 > +#define S_CMD_STATUS_MASK 0x07 > +#define S_CMD_STATUS_SUCCESS 0x0 > +#define S_CMD_STATUS_TIMEOUT 0x5 > + > #define IE_OFFSET 0x38 > #define IE_M_RX_FIFO_FULL_SHIFT 31 > #define IE_M_RX_THLD_SHIFT 30 > #define IE_M_START_BUSY_SHIFT 28 > #define IE_M_TX_UNDERRUN_SHIFT 27 > +#define IE_S_RX_FIFO_FULL_SHIFT 26 > +#define IE_S_RX_THLD_SHIFT 25 > +#define IE_S_RX_EVENT_SHIFT 24 > +#define IE_S_START_BUSY_SHIFT 23 > +#define IE_S_TX_UNDERRUN_SHIFT 22 > +#define IE_S_RD_EVENT_SHIFT 21 > > #define IS_OFFSET 0x3c > #define IS_M_RX_FIFO_FULL_SHIFT 31 > #define IS_M_RX_THLD_SHIFT 30 > #define IS_M_START_BUSY_SHIFT 28 > #define IS_M_TX_UNDERRUN_SHIFT 27 > +#define IS_S_RX_FIFO_FULL_SHIFT 26 > +#define IS_S_RX_THLD_SHIFT 25 > +#define IS_S_RX_EVENT_SHIFT 24 > +#define IS_S_START_BUSY_SHIFT 23 > +#define IS_S_TX_UNDERRUN_SHIFT 22 > +#define IS_S_RD_EVENT_SHIFT 21 > > #define M_TX_OFFSET 0x40 > #define M_TX_WR_STATUS_SHIFT 31 > @@ -78,6 +126,18 @@ > #define M_RX_DATA_SHIFT 0 > #define M_RX_DATA_MASK 0xff > > +#define S_TX_OFFSET 0x48 > +#define S_TX_WR_STATUS_SHIFT 31 > +#define S_TX_DATA_SHIFT 0 > +#define S_TX_DATA_MASK 0xff > + > +#define S_RX_OFFSET 0x4c > +#define S_RX_STATUS_SHIFT 30 > +#define S_RX_STATUS_MASK 0x03 > +#define S_RX_PEC_ERR_SHIFT 29 > +#define S_RX_DATA_SHIFT 0 > +#define S_RX_DATA_MASK 0xff > + > #define I2C_TIMEOUT_MSEC 50000 > #define M_TX_RX_FIFO_SIZE 64 > #define M_RX_FIFO_MAX_THLD_VALUE (M_TX_RX_FIFO_SIZE - 1) > @@ -85,6 +145,30 @@ > #define M_RX_MAX_READ_LEN 255 > #define M_RX_FIFO_THLD_VALUE 50 > > +#define IE_M_ALL_INTERRUPT_SHIFT 27 > +#define IE_M_ALL_INTERRUPT_MASK 0x1e > + > +#define SLAVE_READ_WRITE_BIT_MASK 0x1 > +#define SLAVE_READ_WRITE_BIT_SHIFT 0x1 > +#define SLAVE_MAX_SIZE_TRANSACTION 64 > +#define SLAVE_CLOCK_STRETCH_TIME 25 > + > +#define IE_S_ALL_INTERRUPT_SHIFT 21 > +#define IE_S_ALL_INTERRUPT_MASK 0x3f > + > +enum i2c_slave_read_status { > + I2C_SLAVE_RX_FIFO_EMPTY = 0, > + I2C_SLAVE_RX_START, > + I2C_SLAVE_RX_DATA, > + I2C_SLAVE_RX_END, > +}; > + > +enum i2c_slave_xfer_dir { > + I2C_SLAVE_DIR_READ = 0, > + I2C_SLAVE_DIR_WRITE, > + I2C_SLAVE_DIR_NONE, > +}; > + > enum bus_speed_index { > I2C_SPD_100K = 0, > I2C_SPD_400K, > @@ -104,6 +188,9 @@ struct bcm_iproc_i2c_dev { > > struct i2c_msg *msg; > > + struct i2c_client *slave; > + enum i2c_slave_xfer_dir xfer_dir; > + > /* bytes that have been transferred */ > unsigned int tx_bytes; > /* bytes that have been read */ > @@ -117,6 +204,157 @@ struct bcm_iproc_i2c_dev { > #define ISR_MASK (BIT(IS_M_START_BUSY_SHIFT) | BIT(IS_M_TX_UNDERRUN_SHIFT)\ > | BIT(IS_M_RX_THLD_SHIFT)) > > +#define ISR_MASK_SLAVE (BIT(IS_S_START_BUSY_SHIFT)\ > + | BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EVENT_SHIFT)) > + > +static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave); > +static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave); > +static void bcm_iproc_i2c_enable_disable(struct bcm_iproc_i2c_dev *iproc_i2c, > + bool enable); > + > +static void bcm_iproc_i2c_slave_init( > + struct bcm_iproc_i2c_dev *iproc_i2c, bool need_reset) > +{ > + u32 val; > + > + if (need_reset) { > + /* put controller in reset */ > + val = readl(iproc_i2c->base + CFG_OFFSET); > + val |= BIT(CFG_RESET_SHIFT); > + val &= ~(BIT(CFG_RESET_SHIFT)); > + writel(val, iproc_i2c->base + CFG_OFFSET); > + > + /* wait 100 usec per spec */ > + udelay(100); > + > + /* bring controller out of reset */ > + val &= ~(BIT(CFG_RESET_SHIFT)); > + writel(val, iproc_i2c->base + CFG_OFFSET); > + } > + > + /* flush TX/RX FIFOs */ > + val = (BIT(S_FIFO_RX_FLUSH_SHIFT) | BIT(S_FIFO_TX_FLUSH_SHIFT)); > + writel(val, iproc_i2c->base + S_FIFO_CTRL_OFFSET); > + > + /* RANDOM SLAVE STRETCH time - 20ms*/ > + val = readl(iproc_i2c->base + TIM_CFG_OFFSET); > + val &= ~(TIM_RAND_SLAVE_STRETCH_MASK << TIM_RAND_SLAVE_STRETCH_SHIFT); > + val |= (SLAVE_CLOCK_STRETCH_TIME << TIM_RAND_SLAVE_STRETCH_SHIFT); > + writel(val, iproc_i2c->base + TIM_CFG_OFFSET); > + > + /* Configure the slave address */ > + val = readl(iproc_i2c->base + S_CFG_SMBUS_ADDR_OFFSET); > + val |= BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT); > + val &= ~(S_CFG_NIC_SMB_ADDR3_MASK << S_CFG_NIC_SMB_ADDR3_SHIFT); > + val |= (iproc_i2c->slave->addr << S_CFG_NIC_SMB_ADDR3_SHIFT); > + writel(val, iproc_i2c->base + S_CFG_SMBUS_ADDR_OFFSET); > + > + /* clear all pending slave interrupts */ > + writel(ISR_MASK_SLAVE, iproc_i2c->base + IS_OFFSET); > + > + /* Enable interrupt register for any READ event */ > + val = BIT(IE_S_RD_EVENT_SHIFT); > + /* Enable interrupt register to indicate a valid byte in receive fifo */ > + val |= BIT(IE_S_RX_EVENT_SHIFT); > + /* Enable interrupt register for the Slave BUSY command */ > + val |= BIT(IE_S_START_BUSY_SHIFT); > + writel(val, iproc_i2c->base + IE_OFFSET); > + > + iproc_i2c->xfer_dir = I2C_SLAVE_DIR_NONE; > +} > + > +static void bcm_iproc_i2c_check_slave_status( > + struct bcm_iproc_i2c_dev *iproc_i2c) > +{ > + u32 val; > + > + val = readl(iproc_i2c->base + S_CMD_OFFSET); > + val = (val >> S_CMD_STATUS_SHIFT) & S_CMD_STATUS_MASK; > + > + if (val == S_CMD_STATUS_TIMEOUT) { > + dev_err(iproc_i2c->device, "slave random stretch time timeout\n"); > + > + /* re-initialize i2c for recovery */ > + bcm_iproc_i2c_enable_disable(iproc_i2c, false); > + bcm_iproc_i2c_slave_init(iproc_i2c, true); > + bcm_iproc_i2c_enable_disable(iproc_i2c, true); > + } > +} > + > +static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c, > + u32 status) > +{ > + u8 value; > + u32 val; > + u32 rd_status; > + u32 tmp; > + > + /* Start of transaction. check address and populate the direction */ > + if (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_NONE) { > + tmp = readl(iproc_i2c->base + S_RX_OFFSET); > + rd_status = (tmp >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; > + /* This condition checks whether the request is a new request */ > + if (((rd_status == I2C_SLAVE_RX_START) && > + (status & BIT(IS_S_RX_EVENT_SHIFT))) || > + ((rd_status == I2C_SLAVE_RX_END) && > + (status & BIT(IS_S_RD_EVENT_SHIFT)))) { > + > + /* Last bit is W/R bit. > + * If 1 then its a read request(by master). > + */ > + iproc_i2c->xfer_dir = tmp & SLAVE_READ_WRITE_BIT_MASK; > + if (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_WRITE) > + i2c_slave_event(iproc_i2c->slave, > + I2C_SLAVE_READ_REQUESTED, &value); > + else > + i2c_slave_event(iproc_i2c->slave, > + I2C_SLAVE_WRITE_REQUESTED, &value); > + } > + } > + > + /* read request from master */ > + if ((status & BIT(IS_S_RD_EVENT_SHIFT)) && > + (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_WRITE)) { > + i2c_slave_event(iproc_i2c->slave, > + I2C_SLAVE_READ_PROCESSED, &value); > + writel(value, iproc_i2c->base + S_TX_OFFSET); > + > + val = BIT(S_CMD_START_BUSY_SHIFT); > + writel(val, iproc_i2c->base + S_CMD_OFFSET); > + } > + > + /* write request from master */ > + if ((status & BIT(IS_S_RX_EVENT_SHIFT)) && > + (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_READ)) { > + val = readl(iproc_i2c->base + S_RX_OFFSET); > + /* Its a write request by Master to Slave. > + * We read data present in receive FIFO > + */ > + value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); > + i2c_slave_event(iproc_i2c->slave, > + I2C_SLAVE_WRITE_RECEIVED, &value); > + > + /* check the status for the last byte of the transaction */ > + rd_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; > + if (rd_status == I2C_SLAVE_RX_END) > + iproc_i2c->xfer_dir = I2C_SLAVE_DIR_NONE; > + > + dev_dbg(iproc_i2c->device, "\nread value = 0x%x\n", value); > + } > + > + /* Stop */ > + if (status & BIT(IS_S_START_BUSY_SHIFT)) { > + i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value); > + iproc_i2c->xfer_dir = I2C_SLAVE_DIR_NONE; > + } > + > + /* clear interrupt status */ > + writel(status, iproc_i2c->base + IS_OFFSET); > + > + bcm_iproc_i2c_check_slave_status(iproc_i2c); > + return true; > +} > + > static void bcm_iproc_i2c_read_valid_bytes(struct bcm_iproc_i2c_dev *iproc_i2c) > { > struct i2c_msg *msg = iproc_i2c->msg; > @@ -142,6 +380,18 @@ static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data) > u32 status = readl(iproc_i2c->base + IS_OFFSET); > u32 tmp; > > + > + bool ret; > + u32 sl_status = status & ISR_MASK_SLAVE; > + > + if (sl_status) { > + ret = bcm_iproc_i2c_slave_isr(iproc_i2c, sl_status); > + if (ret) > + return IRQ_HANDLED; > + else > + return IRQ_NONE; > + } > + > status &= ISR_MASK; > > if (!status) > @@ -224,22 +474,25 @@ static int bcm_iproc_i2c_init(struct bcm_iproc_i2c_dev *iproc_i2c) > > /* put controller in reset */ > val = readl(iproc_i2c->base + CFG_OFFSET); > - val |= 1 << CFG_RESET_SHIFT; > - val &= ~(1 << CFG_EN_SHIFT); > + val |= BIT(CFG_RESET_SHIFT); > + val &= ~(BIT(CFG_RESET_SHIFT)); > writel(val, iproc_i2c->base + CFG_OFFSET); > > /* wait 100 usec per spec */ > udelay(100); > > /* bring controller out of reset */ > - val &= ~(1 << CFG_RESET_SHIFT); > + val &= ~(BIT(CFG_RESET_SHIFT)); > writel(val, iproc_i2c->base + CFG_OFFSET); > > /* flush TX/RX FIFOs and set RX FIFO threshold to zero */ > - val = (1 << M_FIFO_RX_FLUSH_SHIFT) | (1 << M_FIFO_TX_FLUSH_SHIFT); > + val = (BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT)); > writel(val, iproc_i2c->base + M_FIFO_CTRL_OFFSET); > /* disable all interrupts */ > - writel(0, iproc_i2c->base + IE_OFFSET); > + val = readl(iproc_i2c->base + IE_OFFSET); > + val &= ~(IE_M_ALL_INTERRUPT_MASK << > + IE_M_ALL_INTERRUPT_SHIFT); > + writel(val, iproc_i2c->base + IE_OFFSET); > > /* clear all pending interrupts */ > writel(0xffffffff, iproc_i2c->base + IS_OFFSET); > @@ -288,6 +541,14 @@ static int bcm_iproc_i2c_check_status(struct bcm_iproc_i2c_dev *iproc_i2c, > dev_dbg(iproc_i2c->device, "bus timeout\n"); > return -ETIMEDOUT; > > + case M_CMD_STATUS_FIFO_UNDERRUN: > + dev_dbg(iproc_i2c->device, "FIFO under-run\n"); > + return -ENXIO; > + > + case M_CMD_STATUS_RX_FIFO_FULL: > + dev_dbg(iproc_i2c->device, "Master Rx FIFO full > 10ms\n"); > + return -ETIMEDOUT; > + > default: > dev_dbg(iproc_i2c->device, "unknown error code=%d\n", val); > > @@ -442,12 +703,14 @@ static int bcm_iproc_i2c_xfer(struct i2c_adapter *adapter, > > static uint32_t bcm_iproc_i2c_functionality(struct i2c_adapter *adap) > { > - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; > + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE; > } > > static const struct i2c_algorithm bcm_iproc_algo = { > .master_xfer = bcm_iproc_i2c_xfer, > .functionality = bcm_iproc_i2c_functionality, > + .reg_slave = bcm_iproc_i2c_reg_slave, > + .unreg_slave = bcm_iproc_i2c_unreg_slave, > }; > > static struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { > @@ -612,6 +875,46 @@ static int bcm_iproc_i2c_resume(struct device *dev) > #define BCM_IPROC_I2C_PM_OPS NULL > #endif /* CONFIG_PM_SLEEP */ > > + > +static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave) > +{ > + struct bcm_iproc_i2c_dev *iproc_i2c = i2c_get_adapdata(slave->adapter); > + > + if (iproc_i2c->slave) > + return -EBUSY; > + > + if (slave->flags & I2C_CLIENT_TEN) > + return -EAFNOSUPPORT; > + > + iproc_i2c->slave = slave; > + bcm_iproc_i2c_slave_init(iproc_i2c, false); > + return 0; > +} > + > +static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave) > +{ > + u32 tmp; > + struct bcm_iproc_i2c_dev *iproc_i2c = i2c_get_adapdata(slave->adapter); > + > + if (!iproc_i2c->slave) > + return -EINVAL; > + > + iproc_i2c->slave = NULL; > + > + /* disable all slave interrupts */ > + tmp = readl(iproc_i2c->base + IE_OFFSET); > + tmp &= ~(IE_S_ALL_INTERRUPT_MASK << > + IE_S_ALL_INTERRUPT_SHIFT); > + writel(tmp, iproc_i2c->base + IE_OFFSET); > + > + /* Erase the slave address programmed */ > + tmp = readl(iproc_i2c->base + S_CFG_SMBUS_ADDR_OFFSET); > + tmp &= ~BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT); > + writel(tmp, iproc_i2c->base + S_CFG_SMBUS_ADDR_OFFSET); > + > + return 0; > +} > + > static const struct of_device_id bcm_iproc_i2c_of_match[] = { > { .compatible = "brcm,iproc-i2c" }, > { /* sentinel */ } > Reviewed-by: Ray Jui <ray.jui@broadcom.com> Thanks! ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 0/8] Add IPROC I2C slave mode and NIC I2C support [not found] <1547791464-3540-1-git-send-email-rayagonda.kokatanur@broadcom.com> [not found] ` <1547791464-3540-2-git-send-email-rayagonda.kokatanur@broadcom.com> [not found] ` <1547791464-3540-3-git-send-email-rayagonda.kokatanur@broadcom.com> @ 2019-01-20 21:49 ` Ray Jui 2019-01-28 19:31 ` Ray Jui 2 siblings, 1 reply; 6+ messages in thread From: Ray Jui @ 2019-01-20 21:49 UTC (permalink / raw) To: Rayagonda Kokatanur, rjui Cc: bcm-kernel-feedback-list, shreesha.rajashekar, sbranden, wsa, linux-i2c, devicetree, linux-arm-kernel, linux-kernel, ccheng, heikki.krogerus, geert, arnd, manivannan.sadhasivam, ajayg, ard.biesheuvel, eajames, kramasub, vigneshr, mika.westerberg, pierre-yves.mordret, f.fainelli, aaron.wu, jdelvare, andriy.shevchenko, jarkko.nikula, robh+dt, mark.rutland, rayagonoda.kokatanur Hi Rayagonda/Wolfram, I reviewed the entire patch series and added my Reviewed-by tag on 1/8 and 2/8. The rest of the patches in this series already had my Signed-off-by tag. Thanks, Ray On 1/17/2019 10:04 PM, Rayagonda Kokatanur wrote: > Hi, > This patchset contains support for IPROC I2C slave and NIC I2C support. > Following are the brief changes done inorder to support both IPROC I2C > slave mode and NIC I2C, > > a. Add support to allow I2C rx transfer upto 255 bytes > b. Add polling mode support to the iProc I2C driver. Polling mode is used > in certain SoCs where interrupt is not connected from the I2C block. > c. Add warpper read/write access for register to support indirect register > access. This is required in certain SoCs with this iProc I2C > block registered. > d. Remove the set RESET bit to LOW right after setting it to HIGH so that > wait duration can be met. > > This patch series is based on kernel v5.0.0-rc2. > > Changes from v2: > - Address Ray's review comments. > > Changes from v1: > - Rebased to Linux v5.0.0-rc2 > > Ray Jui (1): > dt-bindings: i2c: iproc: make 'interrupts' optional > > Rayagonda Kokatanur (5): > i2c: iproc: add polling support > i2c: iproc: use wrapper for read/write access > dt-bindings: i2c: iproc: add "brcm,iproc-nic-i2c" compatible string > i2c: iproc: add NIC I2C support > arm64: dts: Stingray: Add NIC i2c device node > > Shreesha Rajashekar (2): > i2c: iproc: I2C read up to 255 bytes support > i2c: iproc: Add Slave mode support > > .../devicetree/bindings/i2c/brcm,iproc-i2c.txt | 14 +- > .../arm64/boot/dts/broadcom/stingray/stingray.dtsi | 18 + > drivers/i2c/busses/Kconfig | 1 + > drivers/i2c/busses/i2c-bcm-iproc.c | 757 +++++++++++++++++---- > 4 files changed, 659 insertions(+), 131 deletions(-) > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 0/8] Add IPROC I2C slave mode and NIC I2C support 2019-01-20 21:49 ` [PATCH v3 0/8] Add IPROC I2C slave mode and NIC I2C support Ray Jui @ 2019-01-28 19:31 ` Ray Jui 2019-02-04 11:12 ` Wolfram Sang 0 siblings, 1 reply; 6+ messages in thread From: Ray Jui @ 2019-01-28 19:31 UTC (permalink / raw) To: Rayagonda Kokatanur, rjui, Wolfram Sang Cc: bcm-kernel-feedback-list, shreesha.rajashekar, sbranden, wsa, linux-i2c, devicetree, linux-arm-kernel, linux-kernel, ccheng, heikki.krogerus, geert, arnd, manivannan.sadhasivam, ajayg, ard.biesheuvel, eajames, kramasub, vigneshr, mika.westerberg, pierre-yves.mordret, f.fainelli, aaron.wu, jdelvare, andriy.shevchenko, jarkko.nikula, robh+dt, mark.rutland, rayagonoda.kokatanur Hi Wolfram, Just want to check if you had a chance to review the following patch series? Thanks, Ray On 1/20/2019 1:49 PM, Ray Jui wrote: > Hi Rayagonda/Wolfram, > > I reviewed the entire patch series and added my Reviewed-by tag on 1/8 > and 2/8. The rest of the patches in this series already had my > Signed-off-by tag. > > Thanks, > > Ray > > On 1/17/2019 10:04 PM, Rayagonda Kokatanur wrote: >> Hi, >> This patchset contains support for IPROC I2C slave and NIC I2C support. >> Following are the brief changes done inorder to support both IPROC I2C >> slave mode and NIC I2C, >> >> a. Add support to allow I2C rx transfer upto 255 bytes >> b. Add polling mode support to the iProc I2C driver. Polling mode is used >> in certain SoCs where interrupt is not connected from the I2C block. >> c. Add warpper read/write access for register to support indirect register >> access. This is required in certain SoCs with this iProc I2C >> block registered. >> d. Remove the set RESET bit to LOW right after setting it to HIGH so that >> wait duration can be met. >> >> This patch series is based on kernel v5.0.0-rc2. >> >> Changes from v2: >> - Address Ray's review comments. >> >> Changes from v1: >> - Rebased to Linux v5.0.0-rc2 >> >> Ray Jui (1): >> dt-bindings: i2c: iproc: make 'interrupts' optional >> >> Rayagonda Kokatanur (5): >> i2c: iproc: add polling support >> i2c: iproc: use wrapper for read/write access >> dt-bindings: i2c: iproc: add "brcm,iproc-nic-i2c" compatible string >> i2c: iproc: add NIC I2C support >> arm64: dts: Stingray: Add NIC i2c device node >> >> Shreesha Rajashekar (2): >> i2c: iproc: I2C read up to 255 bytes support >> i2c: iproc: Add Slave mode support >> >> .../devicetree/bindings/i2c/brcm,iproc-i2c.txt | 14 +- >> .../arm64/boot/dts/broadcom/stingray/stingray.dtsi | 18 + >> drivers/i2c/busses/Kconfig | 1 + >> drivers/i2c/busses/i2c-bcm-iproc.c | 757 +++++++++++++++++---- >> 4 files changed, 659 insertions(+), 131 deletions(-) >> ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 0/8] Add IPROC I2C slave mode and NIC I2C support 2019-01-28 19:31 ` Ray Jui @ 2019-02-04 11:12 ` Wolfram Sang 2019-02-04 23:09 ` Ray Jui 0 siblings, 1 reply; 6+ messages in thread From: Wolfram Sang @ 2019-02-04 11:12 UTC (permalink / raw) To: Ray Jui Cc: Rayagonda Kokatanur, rjui, bcm-kernel-feedback-list, shreesha.rajashekar, sbranden, linux-i2c, devicetree, linux-arm-kernel, linux-kernel, ccheng, heikki.krogerus, geert, arnd, manivannan.sadhasivam, ajayg, ard.biesheuvel, eajames, kramasub, vigneshr, mika.westerberg, pierre-yves.mordret, f.fainelli, aaron.wu, jdelvare, andriy.shevchenko, jarkko.nikula, robh+dt, mark.rutland, rayagonoda.kokatanur [-- Attachment #1: Type: text/plain, Size: 301 bytes --] Hi, > Just want to check if you had a chance to review the following patch series? I am sorry, but for some reason they are not listed in my patchwork instance, so they fell through the cracks :( Can you please resend them? I will double check they show up in patchwork then. Thanks, Wolfram [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 0/8] Add IPROC I2C slave mode and NIC I2C support 2019-02-04 11:12 ` Wolfram Sang @ 2019-02-04 23:09 ` Ray Jui 0 siblings, 0 replies; 6+ messages in thread From: Ray Jui @ 2019-02-04 23:09 UTC (permalink / raw) To: Wolfram Sang Cc: Rayagonda Kokatanur, rjui, bcm-kernel-feedback-list, shreesha.rajashekar, sbranden, linux-i2c, devicetree, linux-arm-kernel, linux-kernel, ccheng, heikki.krogerus, geert, arnd, manivannan.sadhasivam, ajayg, ard.biesheuvel, eajames, kramasub, vigneshr, mika.westerberg, pierre-yves.mordret, f.fainelli, aaron.wu, jdelvare, andriy.shevchenko, jarkko.nikula, robh+dt, mark.rutland, rayagonoda.kokatanur Hi Wolfram, On 2/4/2019 3:12 AM, Wolfram Sang wrote: > Hi, > >> Just want to check if you had a chance to review the following patch series? > > I am sorry, but for some reason they are not listed in my patchwork > instance, so they fell through the cracks :( Can you please resend them? > > I will double check they show up in patchwork then. Thanks. I think the issue might have something to do with Rayagonda's email client configuration. I will be helping to send out v4 of the patch series. Regards, Ray > > Thanks, > > Wolfram > ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2019-02-04 23:09 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <1547791464-3540-1-git-send-email-rayagonda.kokatanur@broadcom.com> [not found] ` <1547791464-3540-2-git-send-email-rayagonda.kokatanur@broadcom.com> 2019-01-20 21:41 ` [PATCH v3 1/8] i2c: iproc: I2C read up to 255 bytes support Ray Jui [not found] ` <1547791464-3540-3-git-send-email-rayagonda.kokatanur@broadcom.com> 2019-01-20 21:45 ` [PATCH v3 2/8] i2c: iproc: Add Slave mode support Ray Jui 2019-01-20 21:49 ` [PATCH v3 0/8] Add IPROC I2C slave mode and NIC I2C support Ray Jui 2019-01-28 19:31 ` Ray Jui 2019-02-04 11:12 ` Wolfram Sang 2019-02-04 23:09 ` Ray Jui
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).