Re: 2byte read/write on SMBus

KIYOHARA Takashi <[email protected]>
Newsgroups gmane.os.netbsd.ports.evbmips
Message-ID <[email protected]>
Hi! tsutsui-san,


Once again! ;-)

Thanks,
--
kiyohara


From: KIYOHARA Takashi <[email protected]>
Date: Sat, 27 May 2006 11:39:11 +0900 (JST)

> From: Izumi Tsutsui <[email protected]>
> Date: Tue, 23 May 2006 18:45:33 +0900
> 
> > [email protected] 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.
ausmbus_psc.diff (text/plain, 3.7 KB)
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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.