Module Name: src Committed By: msaitoh Date: Thu Jan 9 12:49:12 UTC 2020
Modified Files: src/sys/dev/pci: piixpm.c piixpmreg.h Log Message: Acquire/release host semaphore to share SMBus between the host and the embedded controller (IMC). Without this change, "shutdown -r" does power off and not boot on ECS HDC-I2. This change fixes the problem. To generate a diff of this commit: cvs rdiff -u -r1.60 -r1.61 src/sys/dev/pci/piixpm.c cvs rdiff -u -r1.10 -r1.11 src/sys/dev/pci/piixpmreg.h 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.60 src/sys/dev/pci/piixpm.c:1.61 --- src/sys/dev/pci/piixpm.c:1.60 Tue Dec 24 06:27:17 2019 +++ src/sys/dev/pci/piixpm.c Thu Jan 9 12:49:12 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: piixpm.c,v 1.60 2019/12/24 06:27:17 thorpej Exp $ */ +/* $NetBSD: piixpm.c,v 1.61 2020/01/09 12:49:12 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.60 2019/12/24 06:27:17 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.61 2020/01/09 12:49:12 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -71,6 +71,8 @@ __KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1 #define PIIXPM_IS_FCHGRP(sc) (PIIXPM_IS_HUDSON(sc) || PIIXPM_IS_KERNCZ(sc)) +#define PIIX_SB800_TIMEOUT 500 + struct piixpm_smbus { int sda; struct piixpm_softc *softc; @@ -124,8 +126,8 @@ static bool piixpm_resume(device_t, cons static int piixpm_sb800_init(struct piixpm_softc *); static void piixpm_csb5_reset(void *); -static int piixpm_i2c_acquire_bus(void *, int); -static void piixpm_i2c_release_bus(void *, int); +static int piixpm_i2c_sb800_acquire_bus(void *, int); +static void piixpm_i2c_sb800_release_bus(void *, int); static int piixpm_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, void *, size_t, int); @@ -332,17 +334,24 @@ piixpm_rescan(device_t self, const char /* Attach I2C bus */ for (i = 0; i < sc->sc_numbusses; i++) { + struct i2c_controller *tag = &sc->sc_i2c_tags[i]; + if (sc->sc_i2c_device[i]) continue; sc->sc_busses[i].sda = i; sc->sc_busses[i].softc = sc; - iic_tag_init(&sc->sc_i2c_tags[i]); - sc->sc_i2c_tags[i].ic_cookie = &sc->sc_busses[i]; - sc->sc_i2c_tags[i].ic_acquire_bus = piixpm_i2c_acquire_bus; - sc->sc_i2c_tags[i].ic_release_bus = piixpm_i2c_release_bus; - sc->sc_i2c_tags[i].ic_exec = piixpm_i2c_exec; + iic_tag_init(tag); + tag->ic_cookie = &sc->sc_busses[i]; + if (PIIXPM_IS_SB800GRP(sc) || PIIXPM_IS_FCHGRP(sc)) { + tag->ic_acquire_bus = piixpm_i2c_sb800_acquire_bus; + tag->ic_release_bus = piixpm_i2c_sb800_release_bus; + } else { + tag->ic_acquire_bus = NULL; + tag->ic_release_bus = NULL; + } + tag->ic_exec = piixpm_i2c_exec; memset(&iba, 0, sizeof(iba)); - iba.iba_tag = &sc->sc_i2c_tags[i]; + iba.iba_tag = tag; sc->sc_i2c_device[i] = config_found_ia(self, ifattr, &iba, piixpm_iicbus_print); } @@ -485,17 +494,39 @@ piixpm_csb5_reset(void *arg) } static int -piixpm_i2c_acquire_bus(void *cookie, int flags) +piixpm_i2c_sb800_acquire_bus(void *cookie, int flags) { struct piixpm_smbus *smbus = cookie; struct piixpm_softc *sc = smbus->softc; + uint8_t sctl; + int i; + + sctl = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_SC); + for (i = 0; i < PIIX_SB800_TIMEOUT; i++) { + /* Try to acquire the host semaphore */ + sctl &= ~PIIX_SMB_SC_SEMMASK; + bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_SC, + sctl | PIIX_SMB_SC_HOSTSEM); + + sctl = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, + PIIX_SMB_SC); + if ((sctl & PIIX_SMB_SC_HOSTSEM) != 0) + break; + + delay(1000); + } + if (i >= PIIX_SB800_TIMEOUT) { + device_printf(sc->sc_dev, + "Failed to acquire the host semaphore\n"); + 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); - } else if (PIIXPM_IS_SB800GRP(sc) || PIIXPM_IS_HUDSON(sc)) { + } else { if (sc->sc_sb800_selen) { bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, SB800_INDIRECTIO_INDEX, SB800_PM_SMBUS0SEL); @@ -519,10 +550,11 @@ piixpm_i2c_acquire_bus(void *cookie, int } static void -piixpm_i2c_release_bus(void *cookie, int flags) +piixpm_i2c_sb800_release_bus(void *cookie, int flags) { struct piixpm_smbus *smbus = cookie; struct piixpm_softc *sc = smbus->softc; + uint8_t sctl; if (PIIXPM_IS_KERNCZ(sc)) { bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, @@ -530,7 +562,7 @@ piixpm_i2c_release_bus(void *cookie, int /* Set to port 0 */ bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, SB800_INDIRECTIO_DATA, 0); - } else if (PIIXPM_IS_SB800GRP(sc) || PIIXPM_IS_HUDSON(sc)) { + } else { if (sc->sc_sb800_selen) { bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, SB800_INDIRECTIO_INDEX, SB800_PM_SMBUS0SEL); @@ -551,6 +583,12 @@ piixpm_i2c_release_bus(void *cookie, int SB800_INDIRECTIO_DATA, data); } } + + /* Relase the host semaphore */ + sctl = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_SC); + sctl &= ~PIIX_SMB_SC_SEMMASK; + bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_SC, + sctl | PIIX_SMB_SC_CLRHOSTSEM); } static int Index: src/sys/dev/pci/piixpmreg.h diff -u src/sys/dev/pci/piixpmreg.h:1.10 src/sys/dev/pci/piixpmreg.h:1.11 --- src/sys/dev/pci/piixpmreg.h:1.10 Tue Dec 24 03:43:34 2019 +++ src/sys/dev/pci/piixpmreg.h Thu Jan 9 12:49:12 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: piixpmreg.h,v 1.10 2019/12/24 03:43:34 msaitoh Exp $ */ +/* $NetBSD: piixpmreg.h,v 1.11 2020/01/09 12:49:12 msaitoh Exp $ */ /* $OpenBSD: piixreg.h,v 1.3 2006/01/03 22:39:03 grange Exp $ */ /*- @@ -95,6 +95,11 @@ #define PIIX_SMB_HBDB 0x07 /* host block data byte */ #define PIIX_SMB_SC 0x08 /* slave control */ #define PIIX_SMB_SC_ALERTEN (1 << 3) /* enable SMBALERT# */ +#define PIIX_SMB_SC_HOSTSEM (1 << 4) /* (W1S) HostSemaphore */ +#define PIIX_SMB_SC_CLRHOSTSEM (1 << 5) /* (W1C) ClrHostSemaphore */ +#define PIIX_SMB_SC_ECSEM (1 << 6) /* (W1S) EcSemaphore */ +#define PIIX_SMB_SC_CLRECSEM (1 << 7) /* (W1C) ClrEcSemaphore */ +#define PIIX_SMB_SC_SEMMASK 0xf0 /* Semaphore bits */ /* Power management I/O registers */ #define PIIX_PM_PMTMR 0x08 /* power management timer */