Source-Changes-HG archive

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

[src/netbsd-9]: src/sys/dev/pci Pull up the following revisions, requested by...



details:   https://anonhg.NetBSD.org/src/rev/56ba864bccc7
branches:  netbsd-9
changeset: 964021:56ba864bccc7
user:      martin <martin%NetBSD.org@localhost>
date:      Thu Jul 16 12:39:11 2020 +0000

description:
Pull up the following revisions, requested by msaitoh in ticket #1017:

        sys/dev/pci/piixpm.c                    1.57-1.59, 1.61-1.63 via patch
        sys/dev/pci/piixpmreg.h                 1.9-1.12

- Fix number of port for Hudson rev. 0x1f and newer.
- Read SB800_SMB_HOSTC correctly. This register is not in the PCI
  config space but in the I/O space.
- The bit 0 of SB800_SMB_HOSTC is 0 on SMI and 1 on IRQ, so invert the
  check.
- Don't force using SMBUS0SEL register.
- 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 some machines.
- Save/restore port number before selecting port.
- Modify comment.
- Whitespace fix.

diffstat:

 sys/dev/pci/piixpm.c    |  157 ++++++++++++++++++++++++++++++++++-------------
 sys/dev/pci/piixpmreg.h |   35 +++++++---
 2 files changed, 138 insertions(+), 54 deletions(-)

diffs (truncated from 344 to 300 lines):

diff -r 7de41cd5be08 -r 56ba864bccc7 sys/dev/pci/piixpm.c
--- a/sys/dev/pci/piixpm.c      Thu Jul 16 12:34:49 2020 +0000
+++ b/sys/dev/pci/piixpm.c      Thu Jul 16 12:39:11 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: piixpm.c,v 1.54 2019/07/13 09:24:17 msaitoh Exp $ */
+/* $NetBSD: piixpm.c,v 1.54.2.1 2020/07/16 12:39:11 martin 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.54 2019/07/13 09:24:17 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.54.2.1 2020/07/16 12:39:11 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -70,8 +70,11 @@
 
 #define PIIXPM_IS_FCHGRP(sc)   (PIIXPM_IS_HUDSON(sc) || PIIXPM_IS_KERNCZ(sc))
 
+#define PIIX_SB800_TIMEOUT 500
+
 struct piixpm_smbus {
        int                     sda;
+       int                     sda_save;
        struct                  piixpm_softc *softc;
 };
 
@@ -86,6 +89,7 @@
        bus_space_handle_t      sc_smb_ioh;
        void *                  sc_smb_ih;
        int                     sc_poll;
+       bool                    sc_sb800_selen; /* Use SMBUS0SEL */
 
        pci_chipset_tag_t       sc_pc;
        pcitag_t                sc_pcitag;
@@ -119,8 +123,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);
 
@@ -231,15 +235,10 @@
        /* SB800 rev 0x40+, AMD HUDSON and newer need special initialization */
        if (PIIXPM_IS_FCHGRP(sc) || PIIXPM_IS_SB800GRP(sc)) {
                if (piixpm_sb800_init(sc) == 0) {
-                       sc->sc_numbusses = 4;
-
                        /* Read configuration */
-                       conf = pci_conf_read(pa->pa_pc, pa->pa_tag,
-                           SB800_SMB_HOSTC);
-                       DPRINTF(("%s: conf 0x%08x\n", device_xname(self),
-                               conf));
-
-                       usesmi = conf & SB800_SMB_HOSTC_SMI;
+                       conf = bus_space_read_1(sc->sc_iot,
+                           sc->sc_smb_ioh, SB800_SMB_HOSTC);
+                       usesmi = ((conf & SB800_SMB_HOSTC_IRQ) == 0);
                        goto setintr;
                }
                aprint_normal_dev(self, "SMBus initialization failed\n");
@@ -328,17 +327,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;
-               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;
+               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_type = I2C_TYPE_SMBUS;
-               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);
        }
@@ -401,6 +407,12 @@
        uint16_t val, base_addr;
        bool enabled;
 
+       if (PIIXPM_IS_KERNCZ(sc) ||
+           (PIIXPM_IS_HUDSON(sc) && (sc->sc_rev >= 0x1f)))
+               sc->sc_numbusses = 2;
+       else
+               sc->sc_numbusses = 4;
+
        /* Fetch SMB base address */
        if (bus_space_map(iot,
            SB800_INDIRECTIO_BASE, SB800_INDIRECTIO_SIZE, 0, &ioh)) {
@@ -420,6 +432,8 @@
                val = bus_space_read_1(iot, ioh, SB800_INDIRECTIO_DATA) << 8;
                base_addr = val;
        } else {
+               uint8_t data;
+
                bus_space_write_1(iot, ioh, SB800_INDIRECTIO_INDEX,
                    SB800_PM_SMBUS0EN_LO);
                val = bus_space_read_1(iot, ioh, SB800_INDIRECTIO_DATA);
@@ -434,15 +448,16 @@
 
                bus_space_write_1(iot, ioh, SB800_INDIRECTIO_INDEX,
                    SB800_PM_SMBUS0SELEN);
-               bus_space_write_1(iot, ioh, SB800_INDIRECTIO_DATA,
-                   SB800_PM_SMBUS0EN_ENABLE);
+               data = bus_space_read_1(iot, ioh, SB800_INDIRECTIO_DATA);
+               if ((data & SB800_PM_USE_SMBUS0SEL) != 0)
+                       sc->sc_sb800_selen = true;
        }
 
        sc->sc_sb800_ioh = ioh;
        aprint_debug_dev(sc->sc_dev, "SMBus @ 0x%04x\n", base_addr);
 
        if (bus_space_map(iot, PCI_MAPREG_IO_ADDR(base_addr),
-           PIIX_SMB_SIZE, 0, &sc->sc_smb_ioh)) {
+           SB800_SMB_SIZE, 0, &sc->sc_smb_ioh)) {
                aprint_error_dev(sc->sc_dev, "can't map smbus I/O space\n");
                return EBUSY;
        }
@@ -472,51 +487,105 @@
 }
 
 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, old_sda, index, mask, reg;
+       int i;
+
 
        if (!cold)
                mutex_enter(&sc->sc_i2c_mutex);
 
-       if (PIIXPM_IS_KERNCZ(sc)) {
-               bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
-                   SB800_INDIRECTIO_INDEX, AMDFCH41_PM_PORT_INDEX);
+       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) ||
+           (PIIXPM_IS_HUDSON(sc) && (sc->sc_rev >= 0x1f))) {
+               index = AMDFCH41_PM_PORT_INDEX;
+               mask = AMDFCH41_SMBUS_PORTMASK;
+       } else if (sc->sc_sb800_selen) {
+               index = SB800_PM_SMBUS0SEL;
+               mask = SB800_PM_SMBUS0_MASK_E;
+       } else {
+               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_DATA, smbus->sda << 3);
-       } else if (PIIXPM_IS_SB800GRP(sc) || PIIXPM_IS_HUDSON(sc)) {
-               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, smbus->sda << 1);
+                   SB800_INDIRECTIO_DATA, reg);
        }
 
+       /* Save the old port number */
+       smbus->sda_save = old_sda;
+
        return 0;
 }
 
 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, 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);
+       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) {
+               index = SB800_PM_SMBUS0SEL;
+               mask = SB800_PM_SMBUS0_MASK_E;
+       } else {
+               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);
+       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, 0);
-       } else if (PIIXPM_IS_SB800GRP(sc) || PIIXPM_IS_HUDSON(sc)) {
-               /*
-                * HP Microserver hangs after reboot if not set to SDA0.
-                * Also add shutdown hook?
-                */
-               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, 0);
+                   SB800_INDIRECTIO_DATA, reg);
        }
 
+       /* 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);
+
        if (!cold)
                mutex_exit(&sc->sc_i2c_mutex);
 }
diff -r 7de41cd5be08 -r 56ba864bccc7 sys/dev/pci/piixpmreg.h
--- a/sys/dev/pci/piixpmreg.h   Thu Jul 16 12:34:49 2020 +0000
+++ b/sys/dev/pci/piixpmreg.h   Thu Jul 16 12:39:11 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: piixpmreg.h,v 1.8 2019/07/13 09:24:17 msaitoh Exp $ */
+/* $NetBSD: piixpmreg.h,v 1.8.2.1 2020/07/16 12:39:11 martin Exp $ */
 /*     $OpenBSD: piixreg.h,v 1.3 2006/01/03 22:39:03 grange Exp $      */
 
 /*-
@@ -66,7 +66,7 @@
 #define PIIX_SMB_HOSTC 0xd0            /* SMBus host configuration */
 #define PIIX_SMB_HOSTC_HSTEN   (1 << 16)       /* enable host controller */
 #define PIIX_SMB_HOSTC_SMI     (0 << 17)       /* SMI */
-#define PIIX_SMB_HOSTC_IRQ     (4 << 17)       /* IRQ */
+#define PIIX_SMB_HOSTC_IRQ     (4 << 17)       /* IRQ 9 */
 #define PIIX_SMB_HOSTC_INTMASK (7 << 17)
 
 /* SMBus I/O registers */
@@ -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