Subject: Re: NVIDIA nForce2/3/4 SMBus controller
To: KIYOHARA Takashi <kiyohara@kk.iij4u.or.jp>
From: Nicolas Joly <njoly@pasteur.fr>
List: current-users
Date: 07/14/2007 22:56:59
On Thu, Jul 05, 2007 at 02:33:07PM +0200, Nicolas Joly wrote:
> On Sat, Jun 30, 2007 at 04:06:00PM -0700, Paul Goyette wrote:
> > 
> > It successfully probes the devices.  I'm not sure if it does anything 
> > useful, since I don't have anything to actually access the I2C bus...
> 
> You should see the memory modules, using the small (attached) driver
> `spdmem' i wrote when i was trying to add support for some SMBus
> controllers.
> 
> It simply tries to detect memory modules using `Serial Presence
> Detect' (SPD) datas found on modules eeproms (i2c addr 0x50,0x51,...).
> 
> The first memory module (this machine has 32GB (16 x 2GB) of RAM)
> seems to be correctly detected :
> 
> nfsmbc0 at pci0 dev 1 function 1: NVIDIA nForce4 SMBus (rev. 0xa2)
> nfsmb0 at nfsmbc0 SMBus 1
> iic0 at nfsmb0: I2C bus
> spdmem0 at iic0 addr 0x50: DDR2 SDRAM memory module
> nfsmb1 at nfsmbc0 SMBus 2
> iic1 at nfsmb1: I2C bus

For the record, i forgot to say that i needed a slightly patched
version of nfsmb_check_done() to make it work (taken from FreeBSD):

Index: sys/dev/pci/nfsmb.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/nfsmb.c,v
retrieving revision 1.1
diff -u -r1.1 nfsmb.c
--- sys/dev/pci/nfsmb.c	11 Jul 2007 07:53:29 -0000	1.1
+++ sys/dev/pci/nfsmb.c	14 Jul 2007 20:46:37 -0000
@@ -291,21 +291,19 @@
 static int
 nfsmb_check_done(struct nfsmb_softc *sc)
 {
+	int i;
 	uint8_t stat;
 
-	stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_STATUS);
-
-	if (~stat & NFORCE_SMB_STATUS_DONE) {
+	for (i = 10000; i > 0; i--) {
+		stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_PROTOCOL);
+		if (stat == 0)
+			break;
 		delay(500);
-		stat =
-		    bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_STATUS);
-	}
-	if (~stat & NFORCE_SMB_STATUS_DONE) {
-		tsleep(sc, PCATCH, "nfsmb", hz / 100);
-		stat =
-		    bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_STATUS);
 	}
+	if (i == 0)
+		return -1;
 
+	stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_STATUS);
 	if ((stat & NFORCE_SMB_STATUS_DONE) &&
 	    !(stat & NFORCE_SMB_STATUS_STATUS))
 		return 0;

Here is the output with some i2c device adresses scanning :

nfsmbc0 at pci0 dev 1 function 1: NVIDIA nForce4 SMBus (rev. 0xa2)
nfsmb0 at nfsmbc0 SMBus 1
iic0 at nfsmb0: I2C bus
iic0: devices at 0x18 0x30 0x31 0x32 0x33 0x50 0x51 0x52 0x53
spdmem0 at iic0 addr 0x50: DDR2 SDRAM memory module
spdmem1 at iic0 addr 0x51: DDR2 SDRAM memory module
spdmem2 at iic0 addr 0x52: DDR2 SDRAM memory module
spdmem3 at iic0 addr 0x53: DDR2 SDRAM memory module
nfsmb1 at nfsmbc0 SMBus 2
iic1 at nfsmb1: I2C bus
iic1: devices at 0x19 0x2d 0x48

Thanks for working on it.

-- 
Nicolas Joly

Biological Software and Databanks.
Institut Pasteur, Paris.