Subject: Re: 2byte read/write on SMBus
To: None <tsutsui@ceres.dti.ne.jp>
From: KIYOHARA Takashi <kiyohara@kk.iij4u.or.jp>
List: port-evbmips
Date: 06/14/2006 01:40:54
----Next_Part(Wed_Jun_14_01:40:54_2006_852)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi! tsutsui-san,


Once again! ;-)

Thanks,
--
kiyohara


From: KIYOHARA Takashi <kiyohara@kk.iij4u.or.jp>
Date: Sat, 27 May 2006 11:39:11 +0900 (JST)

> From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
> Date: Tue, 23 May 2006 18:45:33 +0900
> 
> > kiyohara@kk.iij4u.or.jp wrote:
> > 
> > > Our OMSAL400 should read/write 2 bytes on SMBus.  It is possible by the
> > > addition of the following functions to a present mounting. 
> > 
> > - What device actually requires such 2 byte ops?
> > - Does it require 2 byte stream data? Or word (uint16_t) data?
> >   If the latter, your code doesn't work properly on big endian
> >   environment, I think. (I'm not sure how I2C APIs are defined though)
> 
> LM77 (lmtemp(4)) use 2 byte ops.
> But, the former is my mistake, and correctness is a latter word ops.  And,
> it seems to have to consider endian as you think. 


----Next_Part(Wed_Jun_14_01:40:54_2006_852)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="ausmbus_psc.diff"

Index: ausmbus_psc.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/alchemy/dev/ausmbus_psc.c,v
retrieving revision 1.4
diff -u -r1.4 ausmbus_psc.c
--- ausmbus_psc.c	27 Mar 2006 19:03:50 -0000	1.4
+++ ausmbus_psc.c	13 Jun 2006 16:26:01 -0000
@@ -87,8 +87,10 @@
 /* subroutine functions for i2c_controller */
 static int	ausmbus_receive_1(struct ausmbus_softc *, uint8_t *);
 static int	ausmbus_read_1(struct ausmbus_softc *, uint8_t, uint8_t *);
+static int	ausmbus_read_2(struct ausmbus_softc *, uint8_t, uint16_t *);
 static int	ausmbus_send_1(struct ausmbus_softc *, uint8_t);
 static int	ausmbus_write_1(struct ausmbus_softc *, uint8_t, uint8_t);
+static int	ausmbus_write_2(struct ausmbus_softc *, uint8_t, uint16_t);
 static int	ausmbus_wait_mastertx(struct ausmbus_softc *sc);
 static int	ausmbus_wait_masterrx(struct ausmbus_softc *sc);
 static int	ausmbus_initiate_xfer(void *, i2c_addr_t, int);
@@ -214,35 +216,42 @@
 {
 	struct ausmbus_softc *sc  = (struct ausmbus_softc *)cookie;
 	const uint8_t *cmd = vcmd;
-	uint8_t *buf = vbuf;
 
 	sc->sc_smbus_slave_addr  = addr;
 
 	/* Receive byte */
 	if ((I2C_OP_READ_P(op)) && (cmdlen == 0) && (buflen == 1)) {
-		return ausmbus_receive_1(sc, buf);
+		return ausmbus_receive_1(sc, (uint8_t *)vbuf);
 	}
 
 	/* Read byte */
 	if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 1)) {
-		return ausmbus_read_1(sc, *cmd, buf);
+		return ausmbus_read_1(sc, *cmd, (uint8_t *)vbuf);
+	}
+
+	/* Read word */
+	if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 2)) {
+		return ausmbus_read_2(sc, *cmd, (uint16_t *)vbuf);
 	}
 
 	/* Send byte */
 	if ((I2C_OP_WRITE_P(op)) && (cmdlen == 0) && (buflen == 1)) {
-		return ausmbus_send_1(sc, *buf);
+		return ausmbus_send_1(sc, *((uint8_t *)vbuf));
 	}
 
 	/* Write byte */
 	if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 1)) {
-		return ausmbus_write_1(sc, *cmd, *buf);
+		return ausmbus_write_1(sc, *cmd, *((uint8_t *)vbuf));
+	}
+
+	/* Write word */
+	if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 2)) {
+		return ausmbus_write_2(sc, *cmd, *((uint16_t *)vbuf));
 	}
 
 	/*
 	 * XXX: TODO Please Support other protocols defined in SMBus 2.0 
 	 * - Quick Command
-	 * - Write word
-	 * - Read word
 	 * - Process call
 	 * - Block write/read
 	 * - Clock write-block read process cal
@@ -298,6 +307,42 @@
 }
 
 static int
+ausmbus_read_2(struct ausmbus_softc *sc, uint8_t cmd, uint16_t *vp)
+{
+	int error;
+	uint8_t high, low;
+
+	error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_WRITE);
+	if (error != 0) {
+		return error;
+	}
+
+	error = ausmbus_write_byte(sc, cmd, I2C_F_READ);
+	if (error != 0) {
+		return error;
+	}
+
+	error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_READ);
+	if (error != 0) {
+		return error;
+	}
+
+	error = ausmbus_read_byte(sc, &low, 0);
+	if (error != 0) {
+		return error;
+	}
+
+	error = ausmbus_read_byte(sc, &high, I2C_F_STOP);
+	if (error != 0) {
+		return error;
+	}
+
+	*vp = (high << 8) | low;
+
+	return 0;
+}
+
+static int
 ausmbus_send_1(struct ausmbus_softc *sc, uint8_t val)
 {
 	int error;
@@ -339,6 +384,38 @@
 }
 
 static int
+ausmbus_write_2(struct ausmbus_softc *sc, uint8_t cmd, uint16_t val)
+{
+	int error;
+	uint8_t high, low;
+
+	high = (val >> 8) & 0xff;
+	low = val & 0xff;
+
+	error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_WRITE);
+	if (error != 0) {
+		return error;
+	}
+
+	error = ausmbus_write_byte(sc, cmd, 0);
+	if (error != 0) {
+		return error;
+	}
+
+	error = ausmbus_write_byte(sc, low, 0);
+	if (error != 0) {
+		return error;
+	}
+
+	error = ausmbus_write_byte(sc, high, I2C_F_STOP);
+	if (error != 0) {
+		return error;
+	}
+
+	return 0;
+}
+
+static int
 ausmbus_wait_mastertx(struct ausmbus_softc *sc)
 {
 	uint32_t v;

----Next_Part(Wed_Jun_14_01:40:54_2006_852)----