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 */