Module Name:    src
Committed By:   msaitoh
Date:           Tue Jan 14 15:42:03 UTC 2020

Modified Files:
        src/sys/dev/pci: piixpm.c

Log Message:
Save/restore port number before selecting port. Linux driver says it must
be required on some systems.


To generate a diff of this commit:
cvs rdiff -u -r1.62 -r1.63 src/sys/dev/pci/piixpm.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/piixpm.c
diff -u src/sys/dev/pci/piixpm.c:1.62 src/sys/dev/pci/piixpm.c:1.63
--- src/sys/dev/pci/piixpm.c:1.62	Tue Jan 14 15:36:54 2020
+++ src/sys/dev/pci/piixpm.c	Tue Jan 14 15:42:03 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: piixpm.c,v 1.62 2020/01/14 15:36:54 msaitoh Exp $ */
+/* $NetBSD: piixpm.c,v 1.63 2020/01/14 15:42:03 msaitoh Exp $ */
 /*	$OpenBSD: piixpm.c,v 1.39 2013/10/01 20:06:02 sf Exp $	*/
 
 /*
@@ -22,7 +22,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.62 2020/01/14 15:36:54 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.63 2020/01/14 15:42:03 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -75,6 +75,7 @@ __KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1
 
 struct piixpm_smbus {
 	int			sda;
+	int			sda_save;
 	struct			piixpm_softc *softc;
 };
 
@@ -498,7 +499,7 @@ piixpm_i2c_sb800_acquire_bus(void *cooki
 {
 	struct piixpm_smbus *smbus = cookie;
 	struct piixpm_softc *sc = smbus->softc;
-	uint8_t sctl;
+	uint8_t sctl, old_sda, index, mask, reg;
 	int i;
 
 	sctl = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_SC);
@@ -521,29 +522,34 @@ piixpm_i2c_sb800_acquire_bus(void *cooki
 		return -1;
 	}
 
-	if (PIIXPM_IS_KERNCZ(sc)) {
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_INDEX, AMDFCH41_PM_PORT_INDEX);
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_DATA, smbus->sda << 3);
+	if (PIIXPM_IS_KERNCZ(sc) ||
+	    (PIIXPM_IS_HUDSON(sc) && (sc->sc_rev >= 0x1f))) {
+		index = AMDFCH41_PM_PORT_INDEX;
+		mask = AMDFCH41_SMBUS_PORTMASK;
 	} else if (sc->sc_sb800_selen) {
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_INDEX, SB800_PM_SMBUS0SEL);
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_DATA,
-		    __SHIFTIN(smbus->sda, SB800_PM_SMBUS0_MASK_E));
+		index = SB800_PM_SMBUS0SEL;
+		mask = SB800_PM_SMBUS0_MASK_E;
 	} else {
-		uint8_t data;
+		index = SB800_PM_SMBUS0EN_LO;
+		mask = SB800_PM_SMBUS0_MASK_C;
+	}
 
+	bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
+	    SB800_INDIRECTIO_INDEX, index);
+	reg = bus_space_read_1(sc->sc_iot, sc->sc_sb800_ioh,
+	    SB800_INDIRECTIO_DATA);
+
+	old_sda = __SHIFTOUT(reg, mask);
+	if (smbus->sda != old_sda) {
+		reg &= ~mask;
+		reg |= __SHIFTIN(smbus->sda, mask);
 		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_INDEX, SB800_PM_SMBUS0EN_LO);
-		data = bus_space_read_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_DATA) & ~SB800_PM_SMBUS0_MASK_C;
-		data |= __SHIFTIN(smbus->sda, SB800_PM_SMBUS0_MASK_C);
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_DATA, data);
+		    SB800_INDIRECTIO_DATA, reg);
 	}
 
+	/* Save the old port number */
+	smbus->sda_save = old_sda;
+
 	return 0;
 }
 
@@ -552,32 +558,30 @@ piixpm_i2c_sb800_release_bus(void *cooki
 {
 	struct piixpm_smbus *smbus = cookie;
 	struct piixpm_softc *sc = smbus->softc;
-	uint8_t sctl;
+	uint8_t sctl, index, mask, reg;
 
-	if (PIIXPM_IS_KERNCZ(sc)) {
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_INDEX, AMDFCH41_PM_PORT_INDEX);
-		/* Set to port 0 */
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_DATA, 0);
+	if (PIIXPM_IS_KERNCZ(sc) ||
+	    (PIIXPM_IS_HUDSON(sc) && (sc->sc_rev >= 0x1f))) {
+		index = AMDFCH41_PM_PORT_INDEX;
+		mask = AMDFCH41_SMBUS_PORTMASK;
 	} else if (sc->sc_sb800_selen) {
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_INDEX, SB800_PM_SMBUS0SEL);
-
-		/* Set to port 0 */
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_DATA, 0);
+		index = SB800_PM_SMBUS0SEL;
+		mask = SB800_PM_SMBUS0_MASK_E;
 	} else {
-		uint8_t data;
-
-		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_INDEX, SB800_PM_SMBUS0EN_LO);
+		index = SB800_PM_SMBUS0EN_LO;
+		mask = SB800_PM_SMBUS0_MASK_C;
+	}
 
-		/* Set to port 0 */
-		data = bus_space_read_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_DATA) & ~SB800_PM_SMBUS0_MASK_C;
+	bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
+	    SB800_INDIRECTIO_INDEX, index);
+	if (smbus->sda != smbus->sda_save) {
+		/* Restore the port number */
+		reg = bus_space_read_1(sc->sc_iot, sc->sc_sb800_ioh,
+		    SB800_INDIRECTIO_DATA);
+		reg &= ~mask;
+		reg |= __SHIFTIN(smbus->sda_save, mask);
 		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-		    SB800_INDIRECTIO_DATA, data);
+		    SB800_INDIRECTIO_DATA, reg);
 	}
 
 	/* Relase the host semaphore */

Reply via email to