Re: [oc] I2c-ocore linux driver debug

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

> Discussions about the Linux i2c drivers belongs on the
> linux-i2c@xxxxxxxxxxxxxxx list, let's move discussion there.
>

Ok, I wrote on opencore list because I made a little modification in
VHDL design (wrapper).

>
> It could be that we have a problem with zero length transfers (don't
> have access to any smbus devices) - Could you please send a proper
> patch in diff -urpN format?
>

Done

--
Bye, FabM
--- ../../../../../../buildroot/project_build_armv4t/apf9328/linux-2.6.27.2/drivers/i2c/busses/i2c-ocores.c	2008-10-10 00:13:53.000000000 +0200
+++ i2c-ocores.c	2009-01-14 17:11:03.000000000 +0100
@@ -36,26 +36,30 @@ struct ocores_i2c {
 #define OCI2C_PRELOW		0
 #define OCI2C_PREHIGH		1
 #define OCI2C_CONTROL		2
-#define OCI2C_DATA		3
-#define OCI2C_CMD		4 /* write only */
-#define OCI2C_STATUS		4 /* read only, same address as OCI2C_CMD */
-
-#define OCI2C_CTRL_IEN		0x40
-#define OCI2C_CTRL_EN		0x80
-
-#define OCI2C_CMD_START		0x91
-#define OCI2C_CMD_STOP		0x41
-#define OCI2C_CMD_READ		0x21
-#define OCI2C_CMD_WRITE		0x11
-#define OCI2C_CMD_READ_ACK	0x21
-#define OCI2C_CMD_READ_NACK	0x29
-#define OCI2C_CMD_IACK		0x01
-
-#define OCI2C_STAT_IF		0x01
-#define OCI2C_STAT_TIP		0x02
-#define OCI2C_STAT_ARBLOST	0x20
-#define OCI2C_STAT_BUSY		0x40
-#define OCI2C_STAT_NACK		0x80
+#define OCI2C_CMD			4 /* write only */
+#define OCI2C_DATA_TXR		5
+#define OCI2C_STATUS		6 /* read only, same address as OCI2C_CMD */
+#define OCI2C_DATA_RXR		7
+
+
+#define OCI2C_CTRL_IEN		(0x40) 
+#define OCI2C_CTRL_EN		(0x80)
+
+#define OCI2C_CMD_START		(0x91)
+#define OCI2C_CMD_STOP		(0x41)
+#define OCI2C_CMD_READ		(0x21)
+#define OCI2C_CMD_WRITE		(0x11)
+#define OCI2C_CMD_READ_ACK	(0x21)
+#define OCI2C_CMD_READ_NACK	(0x29)
+#define OCI2C_CMD_IACK		(0x01)
+#define OCI2C_CMD_NACK		(0x08)
+#define OCI2C_CMD_ACK		(0x00)
+
+#define OCI2C_STAT_IF		(0x01)
+#define OCI2C_STAT_TIP		(0x02)
+#define OCI2C_STAT_ARBLOST	(0x20)
+#define OCI2C_STAT_BUSY		(0x40)
+#define OCI2C_STAT_NACK		(0x80)
 
 #define STATE_DONE		0
 #define STATE_START		1
@@ -65,12 +69,12 @@ struct ocores_i2c {
 
 static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
 {
-	iowrite8(value, i2c->base + reg * i2c->regstep);
+	iowrite16((u16)value, i2c->base + reg * i2c->regstep);
 }
 
 static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
 {
-	return ioread8(i2c->base + reg * i2c->regstep);
+	return (u8)ioread16(i2c->base + reg * i2c->regstep);
 }
 
 static void ocores_process(struct ocores_i2c *i2c)
@@ -78,6 +82,15 @@ static void ocores_process(struct ocores
 	struct i2c_msg *msg = i2c->msg;
 	u8 stat = oc_getreg(i2c, OCI2C_STATUS);
 
+	/* manage SMBus quick command */
+	if ((i2c->state == STATE_START)&&(i2c->msg->len==0)){
+		if(stat&OCI2C_STAT_NACK){
+			i2c->state = STATE_ERROR;
+		}else{
+			i2c->state = STATE_DONE;
+		}
+	}
+
 	if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
 		/* stop has been sent */
 		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
@@ -88,7 +101,7 @@ static void ocores_process(struct ocores
 	/* error? */
 	if (stat & OCI2C_STAT_ARBLOST) {
 		i2c->state = STATE_ERROR;
-		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP|OCI2C_CMD_READ);
 		return;
 	}
 
@@ -98,11 +111,11 @@ static void ocores_process(struct ocores
 
 		if (stat & OCI2C_STAT_NACK) {
 			i2c->state = STATE_ERROR;
-			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP|OCI2C_CMD_READ);
 			return;
 		}
 	} else
-		msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA);
+		msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA_RXR);
 
 	/* end of msg? */
 	if (i2c->pos == msg->len) {
@@ -121,7 +134,7 @@ static void ocores_process(struct ocores
 
 				i2c->state = STATE_START;
 
-				oc_setreg(i2c, OCI2C_DATA, addr);
+				oc_setreg(i2c, OCI2C_DATA_TXR, addr);
 				oc_setreg(i2c, OCI2C_CMD,  OCI2C_CMD_START);
 				return;
 			} else
@@ -129,17 +142,21 @@ static void ocores_process(struct ocores
 					? STATE_READ : STATE_WRITE;
 		} else {
 			i2c->state = STATE_DONE;
-			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
+			wake_up(&i2c->wait);
 			return;
 		}
 	}
 
 	if (i2c->state == STATE_READ) {
-		oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ?
-			  OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK);
-	} else {
-		oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]);
-		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE);
+		oc_setreg(i2c, OCI2C_CMD, ((i2c->pos == (msg->len-1)) ?
+			  (OCI2C_CMD_READ_NACK|OCI2C_CMD_STOP) : OCI2C_CMD_READ_ACK));
+		return;
+	} else {/* STATE_WRITE */
+		oc_setreg(i2c, OCI2C_DATA_TXR, msg->buf[i2c->pos++]);
+		oc_setreg(i2c, OCI2C_CMD, ((i2c->pos == msg->len) ?
+			(OCI2C_CMD_WRITE|OCI2C_CMD_STOP):OCI2C_CMD_WRITE));
+		return;
 	}
 }
 
@@ -161,11 +178,15 @@ static int ocores_xfer(struct i2c_adapte
 	i2c->nmsgs = num;
 	i2c->state = STATE_START;
 
-	oc_setreg(i2c, OCI2C_DATA,
+	oc_setreg(i2c, OCI2C_DATA_TXR,
 			(i2c->msg->addr << 1) |
 			((i2c->msg->flags & I2C_M_RD) ? 1:0));
 
-	oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
+	if(i2c->msg->len == 0)
+		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START|OCI2C_CMD_STOP);
+	else
+		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
+
 
 	if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
 			       (i2c->state == STATE_DONE), HZ))
@@ -215,7 +236,7 @@ static int __devinit ocores_i2c_probe(st
 	struct ocores_i2c *i2c;
 	struct ocores_i2c_platform_data *pdata;
 	struct resource *res, *res2;
-	int ret;
+	int ret=0;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)

[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux