linux-sh.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] i2c: emev2: add slave support
@ 2015-11-30  0:15 Niklas Söderlund
  2015-11-30  0:15 ` Niklas Söderlund
  2015-12-02 10:02 ` Wolfram Sang
  0 siblings, 2 replies; 4+ messages in thread
From: Niklas Söderlund @ 2015-11-30  0:15 UTC (permalink / raw)
  To: wsa, linux-i2c
  Cc: ian.molton, laurent.pinchart, magnus.damm, linux-sh,
	Niklas Söderlund

Add i2c slave support to EMEV2.

Tested using a EMEV2, BeagleBone Black and a 24c02 eeprom. While the
EMEV2 provided a emulated eeprom on iic0 using slave-24c02 iic0 the Bone
could talk to both the physical and the emulated eeprom. The EMEV2 could
talk to the physical eeprom while still provide the emulated eeprom.

Niklas Söderlund (1):
  i2c: emev2: add slave support

 drivers/i2c/busses/i2c-emev2.c | 110 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)

--
2.6.2


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] i2c: emev2: add slave support
  2015-11-30  0:15 [PATCH] i2c: emev2: add slave support Niklas Söderlund
@ 2015-11-30  0:15 ` Niklas Söderlund
  2015-12-03 21:03   ` Wolfram Sang
  2015-12-02 10:02 ` Wolfram Sang
  1 sibling, 1 reply; 4+ messages in thread
From: Niklas Söderlund @ 2015-11-30  0:15 UTC (permalink / raw)
  To: wsa, linux-i2c
  Cc: ian.molton, laurent.pinchart, magnus.damm, linux-sh,
	Niklas Söderlund

Add I2C slave provider using the generic slave interface.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 drivers/i2c/busses/i2c-emev2.c | 110 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c
index 192ef6b..ad87b5a 100644
--- a/drivers/i2c/busses/i2c-emev2.c
+++ b/drivers/i2c/busses/i2c-emev2.c
@@ -71,6 +71,7 @@ struct em_i2c_device {
 	struct i2c_adapter adap;
 	struct completion msg_done;
 	struct clk *sclk;
+	struct i2c_client *slave;
 };
 
 static inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg)
@@ -226,22 +227,129 @@ static int em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 	return num;
 }
 
+static bool em_i2c_slave_irq(struct em_i2c_device *priv)
+{
+	u8 status, value;
+
+	if (!priv->slave)
+		return false;
+
+	status = readb(priv->base + I2C_OFS_IICSE0);
+
+	/* Extension code, do not participate */
+	if (status & I2C_BIT_EXC0) {
+		em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
+		return true;
+	}
+
+	/* Stop detected, we don't know if it's for slave or master */
+	if (status & I2C_BIT_SPD0) {
+		/* Notify slave device */
+		i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value);
+		/* Pretend we did not handle the interrupt */
+		return false;
+	}
+
+	/* Only handle interrupts addressed to us */
+	if (!(status & I2C_BIT_COI0))
+		return false;
+
+	/* Enable stop interrupts */
+	em_clear_set_bit(priv, 0, I2C_BIT_SPIE0, I2C_OFS_IICC0);
+
+	/* Transmission or Reception */
+	if (status & I2C_BIT_TRC0) {
+		if (status & I2C_BIT_ACKD0) {
+			/* 9 bit interrupt mode */
+			em_clear_set_bit(priv, 0, I2C_BIT_WTIM0, I2C_OFS_IICC0);
+
+			/* Send data */
+			enum i2c_slave_event event = status & I2C_BIT_STD0 ?
+				I2C_SLAVE_READ_REQUESTED :
+				I2C_SLAVE_READ_PROCESSED;
+			i2c_slave_event(priv->slave, event, &value);
+			writeb(value, priv->base + I2C_OFS_IIC0);
+		} else {
+			/* NACK, stop transmitting */
+			em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
+		}
+	} else {
+		/* 8 bit interrupt mode */
+		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0,
+				I2C_OFS_IICC0);
+		em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0,
+				I2C_OFS_IICC0);
+
+		if (status & I2C_BIT_STD0) {
+			i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED,
+					&value);
+		} else {
+			/* Recv data */
+			value = readb(priv->base + I2C_OFS_IIC0);
+			int ret = i2c_slave_event(priv->slave,
+					I2C_SLAVE_WRITE_RECEIVED, &value);
+			if (ret < 0)
+				em_clear_set_bit(priv, I2C_BIT_ACKE0, 0,
+						I2C_OFS_IICC0);
+		}
+	}
+
+	return true;
+}
+
 static irqreturn_t em_i2c_irq_handler(int this_irq, void *dev_id)
 {
 	struct em_i2c_device *priv = dev_id;
 
+	if (em_i2c_slave_irq(priv))
+		return IRQ_HANDLED;
+
 	complete(&priv->msg_done);
+
 	return IRQ_HANDLED;
 }
 
 static u32 em_i2c_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE;
+}
+
+static int em_i2c_reg_slave(struct i2c_client *slave)
+{
+	struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
+
+	if (priv->slave)
+		return -EBUSY;
+
+	if (slave->flags & I2C_CLIENT_TEN)
+		return -EAFNOSUPPORT;
+
+	priv->slave = slave;
+
+	/* Set slave address */
+	writeb(slave->addr << 1, priv->base + I2C_OFS_SVA0);
+
+	return 0;
+}
+
+static int em_i2c_unreg_slave(struct i2c_client *slave)
+{
+	struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
+
+	WARN_ON(!priv->slave);
+
+	writeb(0, priv->base + I2C_OFS_SVA0);
+
+	priv->slave = NULL;
+
+	return 0;
 }
 
 static struct i2c_algorithm em_i2c_algo = {
 	.master_xfer = em_i2c_xfer,
 	.functionality = em_i2c_func,
+	.reg_slave      = em_i2c_reg_slave,
+	.unreg_slave    = em_i2c_unreg_slave,
 };
 
 static int em_i2c_probe(struct platform_device *pdev)
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] i2c: emev2: add slave support
  2015-11-30  0:15 [PATCH] i2c: emev2: add slave support Niklas Söderlund
  2015-11-30  0:15 ` Niklas Söderlund
@ 2015-12-02 10:02 ` Wolfram Sang
  1 sibling, 0 replies; 4+ messages in thread
From: Wolfram Sang @ 2015-12-02 10:02 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: linux-i2c, ian.molton, laurent.pinchart, magnus.damm, linux-sh

[-- Attachment #1: Type: text/plain, Size: 593 bytes --]

On Mon, Nov 30, 2015 at 01:15:57AM +0100, Niklas Söderlund wrote:
> Add i2c slave support to EMEV2.
> 
> Tested using a EMEV2, BeagleBone Black and a 24c02 eeprom. While the
> EMEV2 provided a emulated eeprom on iic0 using slave-24c02 iic0 the Bone
> could talk to both the physical and the emulated eeprom. The EMEV2 could
> talk to the physical eeprom while still provide the emulated eeprom.

Yay, good testing here.

Which board did you use? KZM9D? Do you have pin descriptions for the
connectors, if so? I am looking for these for quite some time.

Thanks,

   Wolfram


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] i2c: emev2: add slave support
  2015-11-30  0:15 ` Niklas Söderlund
@ 2015-12-03 21:03   ` Wolfram Sang
  0 siblings, 0 replies; 4+ messages in thread
From: Wolfram Sang @ 2015-12-03 21:03 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: linux-i2c, ian.molton, laurent.pinchart, magnus.damm, linux-sh

[-- Attachment #1: Type: text/plain, Size: 423 bytes --]

On Mon, Nov 30, 2015 at 01:15:58AM +0100, Niklas Söderlund wrote:
> Add I2C slave provider using the generic slave interface.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>

Looks mostly fine. Sparse says:

    SPARSE
drivers/i2c/busses/i2c-emev2.c:267:25: warning: mixing declarations and code
drivers/i2c/busses/i2c-emev2.c:289:25: warning: mixing declarations and code

Please fix.


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-12-03 21:03 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-30  0:15 [PATCH] i2c: emev2: add slave support Niklas Söderlund
2015-11-30  0:15 ` Niklas Söderlund
2015-12-03 21:03   ` Wolfram Sang
2015-12-02 10:02 ` Wolfram Sang

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).