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