svn commit: r306218 - in head: share/man/man4 sys/dev/amdsbwd sys/dev/intpm

Andriy Gapon avg at FreeBSD.org
Thu Sep 22 21:34:37 UTC 2016


Author: avg
Date: Thu Sep 22 21:34:35 2016
New Revision: 306218
URL: https://svnweb.freebsd.org/changeset/base/306218

Log:
  amdsbwd, intpm: unify bits specific to AMD chipsets (FCHs, southbridges)
  
  AMD chipsets have proprietary mechanisms for dicovering resources.
  Those resources are not discoverable via plug-and-play mechanisms
  like PCI configuration registers or ACPI.
  For this reason a chipset-specific knowledge of proprietary registers
  is required.
  
  At present there are two FreeBSD drivers that require the proprietary
  resource discovery.  One is amdsbwd which is a driver for the watchdog
  timer in the AMD chipsets.  The other is intpm SMBus driver when it
  attaches to the newer AMD chipsets where the resources of the SMBus HBA
  are not described in the regular PCI way.
  
  In both cases the resources are discovered by accessing AMD PMIO space.
  Thus, many definitions are shared between the two drivers.
  This change puts those defintions into a common header file.
  
  As an added benefit, intpm driver now supports newest FCHs built into
  AMD processors of Family 15h, models 70h-7Fh and Family 16h, models
  30h-3Fh.
  
  Reviewed by:	kib
  MFC after:	1 week
  Differential Revision: https://reviews.freebsd.org/D8004

Added:
  head/sys/dev/amdsbwd/amd_chipset.h   (contents, props changed)
Modified:
  head/share/man/man4/intpm.4
  head/sys/dev/amdsbwd/amdsbwd.c
  head/sys/dev/intpm/intpm.c

Modified: head/share/man/man4/intpm.4
==============================================================================
--- head/share/man/man4/intpm.4	Thu Sep 22 21:23:28 2016	(r306217)
+++ head/share/man/man4/intpm.4	Thu Sep 22 21:34:35 2016	(r306218)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 20, 2016
+.Dd September 22, 2016
 .Dt INTPM 4
 .Os
 .Sh NAME
@@ -59,7 +59,9 @@ AMD SB600/7x0/8x0/9x0 southbridges
 .It
 AMD Axx/Hudson/Bolton FCHs
 .It
-AMD FCH integrated into Family 16h Models 00h-0Fh Processors
+AMD FCH integrated into Family 15h Models 60h-6Fh, 70h-7Fh Processors
+.It
+AMD FCH integrated into Family 16h Models 00h-0Fh, 30h-3Fh Processors
 .El
 .Sh SEE ALSO
 .Xr amdpm 4 ,

Added: head/sys/dev/amdsbwd/amd_chipset.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/amdsbwd/amd_chipset.h	Thu Sep 22 21:34:35 2016	(r306218)
@@ -0,0 +1,139 @@
+/*-
+ * Copyright (c) 2016 Andriy Gapon <avg at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * The following registers, bits and magic values are defined in Register
+ * Reference Guide documents for SB600, SB7x0, SB8x0, SB9x0 southbridges and
+ * various versions of Fusion Controller Hubs (FCHs).  FCHs integrated into
+ * CPUs are documented in BIOS and Kernel Development Guide documents for
+ * the corresponding processor families.
+ *
+ * At present there are three classes of supported chipsets:
+ * - SB600 and S7x0 southbridges where the SMBus controller device has
+ *   a PCI Device ID of 0x43851002 and a revision less than 0x40
+ * - SB8x0, SB9x0 southbridges and FCHs where the SMBus controller device has
+ *   a PCI Device ID of 0x43851002 and a revision greater than or equal to 0x40
+ *   or the controller has an ID of 0x780b1022 and a revision less than 0x41
+ * - FCHs where the SMBus controller device has a PCI Device ID of 0x780b1022
+ *   and a revision greater than or equal to 0x41
+ * The register definitions are compatible within the classes and may be
+ * incompatible accross them.
+ * So far there is no public documentation for "KERNCZ" FCH where the SMBus
+ * controller has a PCI ID of 0x790b1022.  Based on some code in Linux it is
+ * assumed that revisions less than 0x49 are compatible with the SB8x0 class
+ * and revisions greater than or equal to 0x49 are compatible with the class
+ * of FCHs with 0x41+ revisions.
+ */
+
+/*
+ * IO registers for accessing the PMIO space.
+ * See SB7xx RRG 2.3.3.1.1, for instance.
+ */
+#define	AMDSB_PMIO_INDEX		0xcd6
+#define	AMDSB_PMIO_DATA			(PMIO_INDEX + 1)
+#define	AMDSB_PMIO_WIDTH		2
+
+/*
+ * SB7x0 and compatible registers in the PMIO space.
+ * See SB7xx RRG 2.3.3.2.
+ */
+#define	AMDSB_PM_RESET_STATUS0		0x44
+#define	AMDSB_PM_RESET_STATUS1		0x45
+#define		AMDSB_WD_RST_STS	0x02
+#define	AMDSB_PM_WDT_CTRL		0x69
+#define		AMDSB_WDT_DISABLE	0x01
+#define		AMDSB_WDT_RES_MASK	(0x02 | 0x04)
+#define		AMDSB_WDT_RES_32US	0x00
+#define		AMDSB_WDT_RES_10MS	0x02
+#define		AMDSB_WDT_RES_100MS	0x04
+#define		AMDSB_WDT_RES_1S	0x06
+#define	AMDSB_PM_WDT_BASE_LSB		0x6c
+#define	AMDSB_PM_WDT_BASE_MSB		0x6f
+
+/*
+ * SB8x0 and compatible registers in the PMIO space.
+ * See SB8xx RRG 2.3.3, for instance.
+ */
+#define	AMDSB8_PM_SMBUS_EN		0x2c
+#define		AMDSB8_SMBUS_EN		0x01
+#define		AMDSB8_SMBUS_ADDR_MASK	0xffe0u
+#define	AMDSB8_PM_WDT_EN		0x48
+#define		AMDSB8_WDT_DEC_EN	0x01
+#define		AMDSB8_WDT_DISABLE	0x02
+#define	AMDSB8_PM_WDT_CTRL		0x4c
+#define		AMDSB8_WDT_32KHZ	0x00
+#define		AMDSB8_WDT_1HZ		0x03
+#define		AMDSB8_WDT_RES_MASK	0x03
+#define	AMDSB8_PM_RESET_STATUS0		0xc0
+#define	AMDSB8_PM_RESET_STATUS1		0xc1
+#define		AMDSB8_WD_RST_STS	0x20
+
+/*
+ * Newer FCH registers in the PMIO space.
+ * See BKDG for Family 16h Models 30h-3Fh 3.26.13 PMx00 and PMx04.
+ */
+#define AMDFCH41_PM_DECODE_EN0		0x00
+#define		AMDFCH41_SMBUS_EN	0x10
+#define		AMDFCH41_WDT_EN		0x80
+#define AMDFCH41_PM_DECODE_EN1		0x01
+#define	AMDFCH41_PM_DECODE_EN3		0x03
+#define		AMDFCH41_WDT_RES_MASK	0x03
+#define		AMDFCH41_WDT_RES_32US	0x00
+#define		AMDFCH41_WDT_RES_10MS	0x01
+#define		AMDFCH41_WDT_RES_100MS	0x02
+#define		AMDFCH41_WDT_RES_1S	0x03
+#define		AMDFCH41_WDT_EN_MASK	0x0c
+#define		AMDFCH41_WDT_ENABLE	0x00
+#define	AMDFCH41_PM_ISA_CTRL		0x04
+#define		AMDFCH41_MMIO_EN	0x02
+
+/*
+ * Fixed MMIO addresses for accessing Watchdog and SMBus registers.
+ * See BKDG for Family 16h Models 30h-3Fh 3.26.13 PMx00 and PMx04.
+ */
+#define	AMDFCH41_WDT_FIXED_ADDR		0xfeb00000u
+#define	AMDFCH41_MMIO_ADDR		0xfed80000u
+#define AMDFCH41_MMIO_SMBUS_OFF		0x0a00
+#define AMDFCH41_MMIO_WDT_OFF		0x0b00
+
+/*
+ * PCI Device IDs and revisions.
+ * SB600 RRG 2.3.1.1,
+ * SB7xx RRG 2.3.1.1,
+ * SB8xx RRG 2.3.1,
+ * BKDG for Family 16h Models 00h-0Fh 3.26.7.1,
+ * BKDG for Family 16h Models 30h-3Fh 3.26.7.1.
+ * Also, see i2c-piix4 aka piix4_smbus Linux driver.
+ */
+#define	AMDSB_SMBUS_DEVID		0x43851002
+#define	AMDSB8_SMBUS_REVID		0x40
+#define	AMDFCH_SMBUS_DEVID		0x780b1022
+#define	AMDFCH41_SMBUS_REVID		0x41
+#define	AMDCZ_SMBUS_DEVID		0x790b1022
+#define	AMDCZ49_SMBUS_REVID		0x49
+

Modified: head/sys/dev/amdsbwd/amdsbwd.c
==============================================================================
--- head/sys/dev/amdsbwd/amdsbwd.c	Thu Sep 22 21:23:28 2016	(r306217)
+++ head/sys/dev/amdsbwd/amdsbwd.c	Thu Sep 22 21:34:35 2016	(r306218)
@@ -59,38 +59,13 @@ __FBSDID("$FreeBSD$");
 #include <sys/watchdog.h>
 
 #include <dev/pci/pcivar.h>
+#include <dev/amdsbwd/amd_chipset.h>
 #include <isa/isavar.h>
 
-/* SB7xx RRG 2.3.3.1.1. */
-#define	AMDSB_PMIO_INDEX		0xcd6
-#define	AMDSB_PMIO_DATA			(PMIO_INDEX + 1)
-#define	AMDSB_PMIO_WIDTH		2
-/* SB7xx RRG 2.3.3.2. */
-#define	AMDSB_PM_RESET_STATUS0		0x44
-#define	AMDSB_PM_RESET_STATUS1		0x45
-#define		AMDSB_WD_RST_STS	0x02
-/* SB7xx RRG 2.3.3.2, RPR 2.36. */
-#define	AMDSB_PM_WDT_CTRL		0x69
-#define		AMDSB_WDT_DISABLE	0x01
-#define		AMDSB_WDT_RES_MASK	(0x02 | 0x04)
-#define		AMDSB_WDT_RES_32US	0x00
-#define		AMDSB_WDT_RES_10MS	0x02
-#define		AMDSB_WDT_RES_100MS	0x04
-#define		AMDSB_WDT_RES_1S	0x06
-#define	AMDSB_PM_WDT_BASE_LSB		0x6c
-#define	AMDSB_PM_WDT_BASE_MSB		0x6f
-/* SB8xx RRG 2.3.3. */
-#define	AMDSB8_PM_WDT_EN		0x48
-#define		AMDSB8_WDT_DEC_EN	0x01
-#define		AMDSB8_WDT_DISABLE	0x02
-#define	AMDSB8_PM_WDT_CTRL		0x4c
-#define		AMDSB8_WDT_32KHZ	0x00
-#define		AMDSB8_WDT_1HZ		0x03
-#define		AMDSB8_WDT_RES_MASK	0x03
-#define	AMDSB8_PM_RESET_STATUS0		0xC0
-#define	AMDSB8_PM_RESET_STATUS1		0xC1
-#define		AMDSB8_WD_RST_STS	0x20
-/* SB7xx RRG 2.3.4, WDRT. */
+/*
+ * Registers in the Watchdog IO space.
+ * See SB7xx RRG 2.3.4, WDRT.
+ */
 #define	AMDSB_WD_CTRL			0x00
 #define		AMDSB_WD_RUN		0x01
 #define		AMDSB_WD_FIRED		0x02
@@ -101,28 +76,6 @@ __FBSDID("$FreeBSD$");
 #define	AMDSB_WD_COUNT			0x04
 #define		AMDSB_WD_COUNT_MASK	0xffff
 #define	AMDSB_WDIO_REG_WIDTH		4
-/* WDRT */
-#define	MAXCOUNT_MIN_VALUE		511
-/* SB7xx RRG 2.3.1.1, SB600 RRG 2.3.1.1, SB8xx RRG 2.3.1.  */
-#define	AMDSB_SMBUS_DEVID		0x43851002
-#define	AMDSB8_SMBUS_REVID		0x40
-#define	AMDHUDSON_SMBUS_DEVID		0x780b1022
-#define	AMDKERNCZ_SMBUS_DEVID		0x790b1022
-/* BKDG Family 16h Models 30h - 3Fh */
-#define AMDFCH16H3XH_PM_WDT_EN		0x00
-#define		AMDFCH_WDT_DEC_EN	0x80
-#define	AMDFCH16H3XH_PM_WDT_CTRL	0x03
-#define		AMDFCH_WDT_RES_MASK	0x03
-#define		AMDFCH_WDT_RES_32US	0x00
-#define		AMDFCH_WDT_RES_10MS	0x01
-#define		AMDFCH_WDT_RES_100MS	0x02
-#define		AMDFCH_WDT_RES_1S	0x03
-#define		AMDFCH_WDT_ENABLE_MASK	0x0c
-#define		AMDFCH_WDT_ENABLE	0x00
-#define	AMDFCH16H3XH_PM_MMIO_CTRL	0x04
-#define		AMDFCH_WDT_MMIO_EN	0x02
-#define	AMDFCH16H3XH_WDT_ADDR1		0xfed80b00u
-#define	AMDFCH16H3XH_WDT_ADDR2		0xfeb00000u
 
 #define	amdsbwd_verbose_printf(dev, ...)	\
 	do {						\
@@ -297,8 +250,8 @@ amdsbwd_identify(driver_t *driver, devic
 	if (smb_dev == NULL)
 		return;
 	if (pci_get_devid(smb_dev) != AMDSB_SMBUS_DEVID &&
-	    pci_get_devid(smb_dev) != AMDHUDSON_SMBUS_DEVID &&
-	    pci_get_devid(smb_dev) != AMDKERNCZ_SMBUS_DEVID)
+	    pci_get_devid(smb_dev) != AMDFCH_SMBUS_DEVID &&
+	    pci_get_devid(smb_dev) != AMDCZ_SMBUS_DEVID)
 		return;
 
 	child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "amdsbwd", -1);
@@ -397,48 +350,48 @@ amdsbwd_probe_sb8xx(device_t dev, struct
 }
 
 static void
-amdsbwd_probe_fch_16h_3xh(device_t dev, struct resource *pmres, uint32_t *addr)
+amdsbwd_probe_fch41(device_t dev, struct resource *pmres, uint32_t *addr)
 {
 	uint8_t	val;
 
-	val = pmio_read(pmres, AMDFCH16H3XH_PM_MMIO_CTRL);
-	if ((val & AMDFCH_WDT_MMIO_EN) != 0) {
+	val = pmio_read(pmres, AMDFCH41_PM_ISA_CTRL);
+	if ((val & AMDFCH41_MMIO_EN) != 0) {
 		/* Fixed offset for the watchdog within ACPI MMIO range. */
 		amdsbwd_verbose_printf(dev, "ACPI MMIO range is enabled\n");
-		*addr = AMDFCH16H3XH_WDT_ADDR1;
+		*addr = AMDFCH41_MMIO_ADDR + AMDFCH41_MMIO_WDT_OFF;
 	} else {
 		/*
 		 * Enable decoding of watchdog MMIO address.
 		 */
-		val = pmio_read(pmres, AMDFCH16H3XH_PM_WDT_EN);
-		val |= AMDFCH_WDT_DEC_EN;
-		pmio_write(pmres, AMDFCH16H3XH_PM_WDT_EN, val);
+		val = pmio_read(pmres, AMDFCH41_PM_DECODE_EN0);
+		val |= AMDFCH41_WDT_EN;
+		pmio_write(pmres, AMDFCH41_PM_DECODE_EN0, val);
 #ifdef AMDSBWD_DEBUG
-		val = pmio_read(pmres, AMDFCH16H3XH_PM_WDT_EN);
-		device_printf(dev, "AMDFCH16H3XH_PM_WDT_EN value = %#04x\n",
+		val = pmio_read(pmres, AMDFCH41_PM_DECODE_EN0);
+		device_printf(dev, "AMDFCH41_PM_DECODE_EN0 value = %#04x\n",
 		    val);
 #endif
 
 		/* Special fixed MMIO range for the watchdog. */
-		*addr = AMDFCH16H3XH_WDT_ADDR2;
+		*addr = AMDFCH41_WDT_FIXED_ADDR;
 	}
 
 	/*
 	 * Set watchdog timer tick to 1s and
 	 * enable the watchdog device (in stopped state).
 	 */
-	val = pmio_read(pmres, AMDFCH16H3XH_PM_WDT_CTRL);
-	val &= ~AMDFCH_WDT_RES_MASK;
-	val |= AMDFCH_WDT_RES_1S;
-	val &= ~AMDFCH_WDT_ENABLE_MASK;
-	val |= AMDFCH_WDT_ENABLE;
-	pmio_write(pmres, AMDFCH16H3XH_PM_WDT_CTRL, val);
+	val = pmio_read(pmres, AMDFCH41_PM_DECODE_EN3);
+	val &= ~AMDFCH41_WDT_RES_MASK;
+	val |= AMDFCH41_WDT_RES_1S;
+	val &= ~AMDFCH41_WDT_EN_MASK;
+	val |= AMDFCH41_WDT_ENABLE;
+	pmio_write(pmres, AMDFCH41_PM_DECODE_EN3, val);
 #ifdef AMDSBWD_DEBUG
-	val = pmio_read(pmres, AMDFCH16H3XH_PM_WDT_CTRL);
-	amdsbwd_verbose_printf(dev, "AMDFCH16H3XH_PM_WDT_CTRL value = %#04x\n",
+	val = pmio_read(pmres, AMDFCH41_PM_DECODE_EN3);
+	amdsbwd_verbose_printf(dev, "AMDFCH41_PM_DECODE_EN3 value = %#04x\n",
 	    val);
 #endif
-	device_set_desc(dev, "AMD FCH Rev 42h+ Watchdog Timer");
+	device_set_desc(dev, "AMD FCH Rev 41h+ Watchdog Timer");
 }
 
 static int
@@ -476,11 +429,12 @@ amdsbwd_probe(device_t dev)
 	revid = pci_get_revid(smb_dev);
 	if (devid == AMDSB_SMBUS_DEVID && revid < AMDSB8_SMBUS_REVID)
 		amdsbwd_probe_sb7xx(dev, res, &addr);
-	else if (devid == AMDSB_SMBUS_DEVID || devid == AMDKERNCZ_SMBUS_DEVID ||
-	    (devid == AMDHUDSON_SMBUS_DEVID && revid < 0x42))
+	else if (devid == AMDSB_SMBUS_DEVID ||
+	    (devid == AMDFCH_SMBUS_DEVID && revid < AMDFCH41_SMBUS_REVID) ||
+	    (devid == AMDCZ_SMBUS_DEVID  && revid < AMDCZ49_SMBUS_REVID))
 		amdsbwd_probe_sb8xx(dev, res, &addr);
 	else
-		amdsbwd_probe_fch_16h_3xh(dev, res, &addr);
+		amdsbwd_probe_fch41(dev, res, &addr);
 
 	bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
 	bus_delete_resource(dev, SYS_RES_IOPORT, rid);

Modified: head/sys/dev/intpm/intpm.c
==============================================================================
--- head/sys/dev/intpm/intpm.c	Thu Sep 22 21:23:28 2016	(r306217)
+++ head/sys/dev/intpm/intpm.c	Thu Sep 22 21:34:35 2016	(r306218)
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
 #include <dev/intpm/intpmreg.h>
+#include <dev/amdsbwd/amd_chipset.h>
 
 #include "opt_intpm.h"
 
@@ -103,12 +104,11 @@ intsmb_probe(device_t dev)
 	case 0x43721002:
 		device_set_desc(dev, "ATI IXP400 SMBus Controller");
 		break;
-	case 0x43851002:
+	case AMDSB_SMBUS_DEVID:
 		device_set_desc(dev, "AMD SB600/7xx/8xx/9xx SMBus Controller");
 		break;
-	case 0x780b1022:	/* AMD FCH */
-		if (pci_get_revid(dev) < 0x40)
-			return (ENXIO);
+	case AMDFCH_SMBUS_DEVID:	/* AMD FCH */
+	case AMDCZ_SMBUS_DEVID:		/* AMD Carizzo FCH */
 		device_set_desc(dev, "AMD FCH SMBus Controller");
 		break;
 	default:
@@ -119,7 +119,7 @@ intsmb_probe(device_t dev)
 }
 
 static uint8_t
-sb8xx_pmio_read(struct resource *res, uint8_t reg)
+amd_pmio_read(struct resource *res, uint8_t reg)
 {
 	bus_write_1(res, 0, reg);	/* Index */
 	return (bus_read_1(res, 1));	/* Data */
@@ -128,27 +128,18 @@ sb8xx_pmio_read(struct resource *res, ui
 static int
 sb8xx_attach(device_t dev)
 {
-	static const int	AMDSB_PMIO_INDEX = 0xcd6;
-	static const int	AMDSB_PMIO_WIDTH = 2;
-	static const int	AMDSB8_SMBUS_ADDR = 0x2c;
-	static const int		AMDSB8_SMBUS_EN = 0x01;
-	static const int		AMDSB8_SMBUS_ADDR_MASK = ~0x1fu;
 	static const int	AMDSB_SMBIO_WIDTH = 0x14;
-	static const int	AMDSB_SMBUS_CFG = 0x10;
-	static const int		AMDSB_SMBUS_IRQ = 0x01;
-	static const int		AMDSB_SMBUS_REV_MASK = ~0x0fu;
-	static const int		AMDSB_SMBUS_REV_SHIFT = 4;
-	static const int	AMDSB_IO_RID = 0;
-
 	struct intsmb_softc	*sc;
 	struct resource		*res;
+	uint32_t		devid;
+	uint8_t			revid;
 	uint16_t		addr;
-	uint8_t			cfg;
 	int			rid;
 	int			rc;
+	bool			enabled;
 
 	sc = device_get_softc(dev);
-	rid = AMDSB_IO_RID;
+	rid = 0;
 	rc = bus_set_resource(dev, SYS_RES_IOPORT, rid, AMDSB_PMIO_INDEX,
 	    AMDSB_PMIO_WIDTH);
 	if (rc != 0) {
@@ -156,26 +147,38 @@ sb8xx_attach(device_t dev)
 		return (ENXIO);
 	}
 	res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
-	    RF_ACTIVE | RF_SHAREABLE);
+	    RF_ACTIVE);
 	if (res == NULL) {
 		device_printf(dev, "bus_alloc_resource for PM IO failed\n");
 		return (ENXIO);
 	}
 
-	addr = sb8xx_pmio_read(res, AMDSB8_SMBUS_ADDR + 1);
-	addr <<= 8;
-	addr |= sb8xx_pmio_read(res, AMDSB8_SMBUS_ADDR);
+	devid = pci_get_devid(dev);
+	revid = pci_get_revid(dev);
+	if (devid == AMDSB_SMBUS_DEVID ||
+	    (devid == AMDFCH_SMBUS_DEVID && revid < AMDFCH41_SMBUS_REVID) ||
+	    (devid == AMDCZ_SMBUS_DEVID  && revid < AMDCZ49_SMBUS_REVID)) {
+		addr = amd_pmio_read(res, AMDSB8_PM_SMBUS_EN + 1);
+		addr <<= 8;
+		addr |= amd_pmio_read(res, AMDSB8_PM_SMBUS_EN);
+		enabled = (addr & AMDSB8_SMBUS_EN) != 0;
+		addr &= AMDSB8_SMBUS_ADDR_MASK;
+	} else {
+		addr = amd_pmio_read(res, AMDFCH41_PM_DECODE_EN0);
+		enabled = (addr & AMDFCH41_SMBUS_EN) != 0;
+		addr = amd_pmio_read(res, AMDFCH41_PM_DECODE_EN1);
+		addr <<= 8;
+	}
 
 	bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
 	bus_delete_resource(dev, SYS_RES_IOPORT, rid);
 
-	if ((addr & AMDSB8_SMBUS_EN) == 0) {
-		device_printf(dev, "SB8xx SMBus not enabled\n");
+	if (!enabled) {
+		device_printf(dev, "SB8xx/SB9xx/FCH SMBus not enabled\n");
 		return (ENXIO);
 	}
 
-	addr &= AMDSB8_SMBUS_ADDR_MASK;
-	sc->io_rid = AMDSB_IO_RID;
+	sc->io_rid = 0;
 	rc = bus_set_resource(dev, SYS_RES_IOPORT, sc->io_rid, addr,
 	    AMDSB_SMBIO_WIDTH);
 	if (rc != 0) {
@@ -187,15 +190,8 @@ sb8xx_attach(device_t dev)
 		return (ENXIO);
 	}
 	sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->io_rid,
-	    RF_ACTIVE | RF_SHAREABLE);
-	cfg = bus_read_1(sc->io_res, AMDSB_SMBUS_CFG);
-
+	    RF_ACTIVE);
 	sc->poll = 1;
-	device_printf(dev, "intr %s disabled ",
-	    (cfg & AMDSB_SMBUS_IRQ) != 0 ? "IRQ" : "SMI");
-	printf("revision %d\n",
-	    (cfg & AMDSB_SMBUS_REV_MASK) >> AMDSB_SMBUS_REV_SHIFT);
-
 	return (0);
 }
 
@@ -237,11 +233,12 @@ intsmb_attach(device_t dev)
 		sc->cfg_irq9 = 1;
 		break;
 #endif
-	case 0x43851002:
-		if (pci_get_revid(dev) >= 0x40)
+	case AMDSB_SMBUS_DEVID:
+		if (pci_get_revid(dev) >= AMDSB8_SMBUS_REVID)
 			sc->sb8xx = 1;
 		break;
-	case 0x780b1022:
+	case AMDFCH_SMBUS_DEVID:
+	case AMDCZ_SMBUS_DEVID:
 		sc->sb8xx = 1;
 		break;
 	}


More information about the svn-src-head mailing list