Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Acquire/release host semaphore to share SMBus be...



details:   https://anonhg.NetBSD.org/src/rev/1f34e39a4124
branches:  trunk
changeset: 968270:1f34e39a4124
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Jan 09 12:49:12 2020 +0000

description:
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.

diffstat:

 sys/dev/pci/piixpm.c    |  66 ++++++++++++++++++++++++++++++++++++++----------
 sys/dev/pci/piixpmreg.h |   7 ++++-
 2 files changed, 58 insertions(+), 15 deletions(-)

diffs (167 lines):

diff -r 706fbe571a37 -r 1f34e39a4124 sys/dev/pci/piixpm.c
--- a/sys/dev/pci/piixpm.c      Thu Jan 09 10:54:16 2020 +0000
+++ b/sys/dev/pci/piixpm.c      Thu Jan 09 12:49:12 2020 +0000
@@ -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 @@
 
 #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 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 @@
        /* 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 @@
 }
 
 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 @@
 }
 
 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 @@
                /* 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 @@
                            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
diff -r 706fbe571a37 -r 1f34e39a4124 sys/dev/pci/piixpmreg.h
--- a/sys/dev/pci/piixpmreg.h   Thu Jan 09 10:54:16 2020 +0000
+++ b/sys/dev/pci/piixpmreg.h   Thu Jan 09 12:49:12 2020 +0000
@@ -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 */



Home | Main Index | Thread Index | Old Index