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