diff mbox

i2c: cadence: Handling Slave monitor mode

Message ID BL2FFO11FD05378650E02EA6549B4DF50E8030@BL2FFO11FD053.protection.gbl
State Rejected
Headers show

Commit Message

Nava kishore Manne March 17, 2015, 4:18 p.m. UTC
In slave monitor mode, the I2C interface is set up as a master and
continues to attempt a transfer to a particular slave until the
slave device responds with an ACK.

Added this feature for zero length transfers enable the controller
for slave monitor interrupt and get the status. Disable the slave
monitor mode feature upon successful handling.

Signed-off-by: Nava kishore Manne <navam@xilinx.com>
Acked-by: Harini Katakam <harinik@xilinx.com>
---
 drivers/i2c/busses/i2c-cadence.c | 69 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 62 insertions(+), 7 deletions(-)

Comments

Wolfram Sang March 27, 2015, 3:37 p.m. UTC | #1
On Tue, Mar 17, 2015 at 09:48:15PM +0530, Nava kishore Manne wrote:
> In slave monitor mode, the I2C interface is set up as a master and
> continues to attempt a transfer to a particular slave until the
> slave device responds with an ACK.
> 
> Added this feature for zero length transfers enable the controller
> for slave monitor interrupt and get the status. Disable the slave
> monitor mode feature upon successful handling.
> 
> Signed-off-by: Nava kishore Manne <navam@xilinx.com>
> Acked-by: Harini Katakam <harinik@xilinx.com>

I am not sure this is going to work.

How often is this access tried when there is no device? It should be
tried only once.

Those 0byte messages can be read or write, so transferring one bit, one
could say. I assume this one can only read? (which is not a show-stopper
but the cases should be handled)
Harini Katakam April 2, 2015, 8:09 p.m. UTC | #2
Hi Wolfram,

On Fri, Mar 27, 2015 at 9:07 PM, Wolfram Sang <wsa@the-dreams.de> wrote:
> On Tue, Mar 17, 2015 at 09:48:15PM +0530, Nava kishore Manne wrote:
>> In slave monitor mode, the I2C interface is set up as a master and
>> continues to attempt a transfer to a particular slave until the
>> slave device responds with an ACK.
>>
>> Added this feature for zero length transfers enable the controller
>> for slave monitor interrupt and get the status. Disable the slave
>> monitor mode feature upon successful handling.
>>
>> Signed-off-by: Nava kishore Manne <navam@xilinx.com>
>> Acked-by: Harini Katakam <harinik@xilinx.com>
>
> I am not sure this is going to work.
>
> How often is this access tried when there is no device? It should be
> tried only once.

Once slave monitor is enabled in the host controller, it retries till there's an
ACK or slave monitor is disabled. The SW wont be involved and need not
be interrupted in this gap. The way this feature works in the controller though,
I'm afraid there's no way to distinguish between no slave/ busy slave.
The out is the software timeout in that case.
Please suggest how to use this feature better.

>
> Those 0byte messages can be read or write, so transferring one bit, one
> could say. I assume this one can only read? (which is not a show-stopper
> but the cases should be handled)
>

Yes, only read is used.

Thanks for the review.

Regards,
Harini
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wolfram Sang April 2, 2015, 8:29 p.m. UTC | #3
> >> In slave monitor mode, the I2C interface is set up as a master and
> >> continues to attempt a transfer to a particular slave until the
> >> slave device responds with an ACK.
> >>
> >> Added this feature for zero length transfers enable the controller
> >> for slave monitor interrupt and get the status. Disable the slave
> >> monitor mode feature upon successful handling.
> >>
> >> Signed-off-by: Nava kishore Manne <navam@xilinx.com>
> >> Acked-by: Harini Katakam <harinik@xilinx.com>
> >
> > I am not sure this is going to work.
> >
> > How often is this access tried when there is no device? It should be
> > tried only once.
> 
> Once slave monitor is enabled in the host controller, it retries till there's an
> ACK or slave monitor is disabled. The SW wont be involved and need not

So, it is kind of flooding the bus until the timeout? That is not a
single zero byte message.

> be interrupted in this gap. The way this feature works in the controller though,
> I'm afraid there's no way to distinguish between no slave/ busy slave.
> The out is the software timeout in that case.
> Please suggest how to use this feature better.

I suggest to not use the feature and accept that this device cannot do
zero byte length messages.

Thanks,

   Wolfram
Nava kishore Manne April 4, 2015, 1:14 p.m. UTC | #4
Hi Wolfram,


> -----Original Message-----
> From: Wolfram Sang [mailto:wsa@the-dreams.de]
> Sent: Friday, April 03, 2015 1:59 AM
> To: Harini Katakam
> Cc: Nava kishore Manne; Michal Simek; Soren Brinkmann; linux-arm-
> kernel@lists.infradead.org; linux-i2c@vger.kernel.org; linux-
> kernel@vger.kernel.org; Anirudha Sarangi; Srikanth Vemula; Nava kishore
> Manne
> Subject: Re: [PATCH] i2c: cadence: Handling Slave monitor mode
>
>
> > >> In slave monitor mode, the I2C interface is set up as a master and
> > >> continues to attempt a transfer to a particular slave until the
> > >> slave device responds with an ACK.
> > >>
> > >> Added this feature for zero length transfers enable the controller
> > >> for slave monitor interrupt and get the status. Disable the slave
> > >> monitor mode feature upon successful handling.
> > >>
> > >> Signed-off-by: Nava kishore Manne <navam@xilinx.com>
> > >> Acked-by: Harini Katakam <harinik@xilinx.com>
> > >
> > > I am not sure this is going to work.
> > >
> > > How often is this access tried when there is no device? It should be
> > > tried only once.
> >
> > Once slave monitor is enabled in the host controller, it retries till
> > there's an ACK or slave monitor is disabled. The SW wont be involved
> > and need not
>
> So, it is kind of flooding the bus until the timeout? That is not a single zero
> byte message.
>
It will not flooding the bus until the timeout. Once it fails to access the bus it will be ideal for 15 clock cycles. Master again retrying to access the
Slave immediately after the 15 clock cycles (There is a register in the controller to set the retry value min: 0 cycles, max: 16 cycles).This process will repeat until
The software timeout will happen (1000msec).

Regards,
Navakishore.
> > be interrupted in this gap. The way this feature works in the
> > controller though, I'm afraid there's no way to distinguish between no
> slave/ busy slave.
> > The out is the software timeout in that case.
> > Please suggest how to use this feature better.
>
> I suggest to not use the feature and accept that this device cannot do zero
> byte length messages.
>
> Thanks,
>
>    Wolfram



This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wolfram Sang April 4, 2015, 3:34 p.m. UTC | #5
> > So, it is kind of flooding the bus until the timeout? That is not a single zero
> > byte message.
> >
> It will not flooding the bus until the timeout. Once it fails to access the bus it will be ideal for 15 clock cycles. Master again retrying to access the
> Slave immediately after the 15 clock cycles (There is a register in the controller to set the retry value min: 0 cycles, max: 16 cycles).This process will repeat until
> The software timeout will happen (1000msec).

Compared to do one access only this is "kind of flooding", no?
diff mbox

Patch

diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index 7d7a14c..6bac2cb 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -25,11 +25,13 @@ 
 #define CDNS_I2C_DATA_OFFSET		0x0C /* I2C Data Register, RW */
 #define CDNS_I2C_ISR_OFFSET		0x10 /* IRQ Status Register, RW */
 #define CDNS_I2C_XFER_SIZE_OFFSET	0x14 /* Transfer Size Register, RW */
+#define CDNS_I2C_SLV_PAUSE_OFFSET	0x18 /* Transfer Size Register, RW */
 #define CDNS_I2C_TIME_OUT_OFFSET	0x1C /* Time Out Register, RW */
 #define CDNS_I2C_IER_OFFSET		0x24 /* IRQ Enable Register, WO */
 #define CDNS_I2C_IDR_OFFSET		0x28 /* IRQ Disable Register, WO */
 
 /* Control Register Bit mask definitions */
+#define CDNS_I2C_CR_SLVMON		BIT(5) /* Slave monitor mode bit */
 #define CDNS_I2C_CR_HOLD		BIT(4) /* Hold Bus bit */
 #define CDNS_I2C_CR_ACK_EN		BIT(3)
 #define CDNS_I2C_CR_NEA			BIT(2)
@@ -310,6 +312,23 @@  static irqreturn_t cdns_i2c_isr(int irq, void *ptr)
 		status = IRQ_HANDLED;
 	}
 
+	/* Handling Slave monitor mode interrupt */
+	if (isr_status & CDNS_I2C_IXR_SLV_RDY) {
+		unsigned int ctrl_reg;
+		/* Read control register */
+		ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
+
+		/* Disable slave monitor mode */
+		ctrl_reg &= ~CDNS_I2C_CR_SLVMON;
+		cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
+
+		/* Clear interrupt flag for slvmon mode */
+		cdns_i2c_writereg(CDNS_I2C_IXR_SLV_RDY, CDNS_I2C_IDR_OFFSET);
+
+		done_flag = 1;
+		status = IRQ_HANDLED;
+	}
+
 	/* Update the status for errors */
 	id->err_status = isr_status & CDNS_I2C_IXR_ERR_INTR_MASK;
 	if (id->err_status)
@@ -444,6 +463,40 @@  static void cdns_i2c_msend(struct cdns_i2c *id)
 }
 
 /**
+ * cdns_i2c_slvmon - Handling Slav monitor mode feature
+ * @id:		pointer to the i2c device
+ */
+static void cdns_i2c_slvmon(struct cdns_i2c *id)
+{
+	unsigned int ctrl_reg;
+	unsigned int isr_status;
+
+	id->p_recv_buf = NULL;
+	id->p_send_buf = id->p_msg->buf;
+	id->send_count = id->p_msg->len;
+
+	/* Clear the interrupts in interrupt status register. */
+	isr_status = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET);
+	cdns_i2c_writereg(isr_status, CDNS_I2C_ISR_OFFSET);
+
+	/* Enable slvmon control reg */
+	ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
+	ctrl_reg |=  CDNS_I2C_CR_MS | CDNS_I2C_CR_NEA | CDNS_I2C_CR_SLVMON
+			| CDNS_I2C_CR_CLR_FIFO;
+	ctrl_reg &= ~(CDNS_I2C_CR_RW);
+	cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
+
+	/* Initialize slvmon reg */
+	cdns_i2c_writereg(0xF, CDNS_I2C_SLV_PAUSE_OFFSET);
+
+	/* Set the slave address to start the slave address transmission */
+	cdns_i2c_writereg(id->p_msg->addr, CDNS_I2C_ADDR_OFFSET);
+
+	/* Setup slvmon interrupt flag */
+	cdns_i2c_writereg(CDNS_I2C_IXR_SLV_RDY, CDNS_I2C_IER_OFFSET);
+}
+
+/**
  * cdns_i2c_master_reset - Reset the interface
  * @adap:	pointer to the i2c adapter driver instance
  *
@@ -459,7 +512,7 @@  static void cdns_i2c_master_reset(struct i2c_adapter *adap)
 	cdns_i2c_writereg(CDNS_I2C_IXR_ALL_INTR_MASK, CDNS_I2C_IDR_OFFSET);
 	/* Clear the hold bit and fifos */
 	regval = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
-	regval &= ~CDNS_I2C_CR_HOLD;
+	regval &= ~(CDNS_I2C_CR_HOLD | CDNS_I2C_CR_SLVMON);
 	regval |= CDNS_I2C_CR_CLR_FIFO;
 	cdns_i2c_writereg(regval, CDNS_I2C_CR_OFFSET);
 	/* Update the transfercount register to zero */
@@ -493,9 +546,11 @@  static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg,
 			cdns_i2c_writereg(reg | CDNS_I2C_CR_NEA,
 					CDNS_I2C_CR_OFFSET);
 	}
-
-	/* Check for the R/W flag on each msg */
-	if (msg->flags & I2C_M_RD)
+	/* Check for zero lenght - Slave monitor mode */
+	if (msg->len == 0)
+		cdns_i2c_slvmon(id);
+	 /* Check for the R/W flag on each msg */
+	else if (msg->flags & I2C_M_RD)
 		cdns_i2c_mrecv(id);
 	else
 		cdns_i2c_msend(id);
@@ -535,10 +590,10 @@  static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 	int ret, count;
 	u32 reg;
 	struct cdns_i2c *id = adap->algo_data;
-
 	/* Check if the bus is free */
-	if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA)
-		return -EAGAIN;
+	if (msgs->len)
+		if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA)
+			return -EAGAIN;
 
 	/*
 	 * Set the flag to one when multiple messages are to be