Module Name:    src
Committed By:   soren
Date:           Mon Jul 22 13:27:14 UTC 2013

Modified Files:
        src/sys/dev/pci: piixpm.c piixpmreg.h

Log Message:
The SB800 SMBus controller has four selectable SDA lines.
Expose them as four iic busses.


To generate a diff of this commit:
cvs rdiff -u -r1.41 -r1.42 src/sys/dev/pci/piixpm.c
cvs rdiff -u -r1.5 -r1.6 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.41 src/sys/dev/pci/piixpm.c:1.42
--- src/sys/dev/pci/piixpm.c:1.41	Thu Jul 18 22:14:54 2013
+++ src/sys/dev/pci/piixpm.c	Mon Jul 22 13:27:14 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: piixpm.c,v 1.41 2013/07/18 22:14:54 soren Exp $ */
+/* $NetBSD: piixpm.c,v 1.42 2013/07/22 13:27:14 soren Exp $ */
 /*	$OpenBSD: piixpm.c,v 1.20 2006/02/27 08:25:02 grange Exp $	*/
 
 /*
@@ -22,7 +22,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.41 2013/07/18 22:14:54 soren Exp $");
+__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.42 2013/07/22 13:27:14 soren Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -55,40 +55,37 @@ __KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1
 #define PIIXPM_DELAY	200
 #define PIIXPM_TIMEOUT	1
 
-#define PIIXPM_INDIRECTIO_BASE	0xcd6
-#define PIIXPM_INDIRECTIO_SIZE	2
-#define PIIXPM_INDIRECTIO_INDEX	0
-#define PIIXPM_INDIRECTIO_DATA	1
-
-#define SB800_PM_SMBUS0EN_LO	0x2c
-#define SB800_PM_SMBUS0EN_HI	0x2d
-
-#define SB800_PM_SMBUS0EN_ENABLE	0x0001
-#define SB800_PM_SMBUS0EN_BADDR		0xffe0
+struct piixpm_smbus {
+	int			sda;
+	struct			piixpm_softc *softc;
+};
 
 struct piixpm_softc {
 	device_t		sc_dev;
 
-	bus_space_tag_t		sc_smb_iot;
+	bus_space_tag_t		sc_iot;
+#define	sc_pm_iot sc_iot
+#define sc_smb_iot sc_iot
+	bus_space_handle_t	sc_pm_ioh;
+	bus_space_handle_t	sc_sb800_ioh;
 	bus_space_handle_t	sc_smb_ioh;
 	void *			sc_smb_ih;
 	int			sc_poll;
 
-	bus_space_tag_t		sc_pm_iot;
-	bus_space_handle_t	sc_pm_ioh;
-
 	pci_chipset_tag_t	sc_pc;
 	pcitag_t		sc_pcitag;
 	pcireg_t		sc_id;
 
-	struct i2c_controller	sc_i2c_tag;
+	struct piixpm_smbus	sc_busses[4];
+	struct i2c_controller	sc_i2c_tags[4];
+
 	kmutex_t		sc_i2c_mutex;
 	struct {
-		i2c_op_t     op;
-		void *      buf;
-		size_t       len;
-		int          flags;
-		volatile int error;
+		i2c_op_t	op;
+		void *		buf;
+		size_t		len;
+		int		flags;
+		volatile int	error;
 	}			sc_i2c_xfer;
 
 	pcireg_t		sc_devact[2];
@@ -100,8 +97,7 @@ static void	piixpm_attach(device_t, devi
 static bool	piixpm_suspend(device_t, const pmf_qual_t *);
 static bool	piixpm_resume(device_t, const pmf_qual_t *);
 
-static int	piixpm_sb800_init(struct piixpm_softc *,
-    struct pci_attach_args *);
+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);
@@ -159,8 +155,10 @@ piixpm_attach(device_t parent, device_t 
 	pcireg_t pmmisc;
 	pci_intr_handle_t ih;
 	const char *intrstr = NULL;
+	int i, numbusses = 1;
 
 	sc->sc_dev = self;
+	sc->sc_iot = pa->pa_iot;
 	sc->sc_id = pa->pa_id;
 	sc->sc_pc = pa->pa_pc;
 	sc->sc_pcitag = pa->pa_tag;
@@ -183,7 +181,6 @@ piixpm_attach(device_t parent, device_t 
 	if (!(pmmisc & 1))
 		goto nopowermanagement;
 
-	sc->sc_pm_iot = pa->pa_iot;
 	/* Map I/O space */
 	base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_PM_BASE);
 	if (bus_space_map(sc->sc_pm_iot, PCI_MAPREG_IO_ADDR(base),
@@ -207,8 +204,10 @@ nopowermanagement:
 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI &&
 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB600_SMB &&
 	    PCI_REVISION(pa->pa_class) >= 0x40) {
-		if (piixpm_sb800_init(sc, pa) == 0)
+		if (piixpm_sb800_init(sc) == 0) {
+			numbusses = 4;
 			goto attach_i2c;
+		}
 		aprint_normal_dev(self, "SMBus disabled\n");
 		return;
 	}
@@ -219,7 +218,6 @@ nopowermanagement:
 	}
 
 	/* Map I/O space */
-	sc->sc_smb_iot = pa->pa_iot;
 	base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_BASE) & 0xffff;
 	if (bus_space_map(sc->sc_smb_iot, PCI_MAPREG_IO_ADDR(base),
 	    PIIX_SMB_SIZE, 0, &sc->sc_smb_ioh)) {
@@ -252,17 +250,20 @@ nopowermanagement:
 attach_i2c:
 	/* Attach I2C bus */
 	mutex_init(&sc->sc_i2c_mutex, MUTEX_DEFAULT, IPL_NONE);
-	sc->sc_i2c_tag.ic_cookie = sc;
-	sc->sc_i2c_tag.ic_acquire_bus = piixpm_i2c_acquire_bus;
-	sc->sc_i2c_tag.ic_release_bus = piixpm_i2c_release_bus;
-	sc->sc_i2c_tag.ic_exec = piixpm_i2c_exec;
-
-	memset(&iba, 0, sizeof(iba));
-	iba.iba_type = I2C_TYPE_SMBUS;
-	iba.iba_tag = &sc->sc_i2c_tag;
-	config_found_ia(self, "i2cbus", &iba, iicbus_print);
 
-	return;
+	for (i = 0; i < numbusses; i++) {
+		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;
+
+		memset(&iba, 0, sizeof(iba));
+		iba.iba_type = I2C_TYPE_SMBUS;
+		iba.iba_tag = &sc->sc_i2c_tags[i];
+		config_found_ia(self, "i2cbus", &iba, iicbus_print);
+	}
 }
 
 static bool
@@ -298,9 +299,9 @@ piixpm_resume(device_t dv, const pmf_qua
  * called once it uses indirect I/O for simplicity.
  */
 static int
-piixpm_sb800_init(struct piixpm_softc *sc, struct pci_attach_args *pa)
+piixpm_sb800_init(struct piixpm_softc *sc)
 {
-	bus_space_tag_t iot = pa->pa_iot;
+	bus_space_tag_t iot = sc->sc_iot;
 	bus_space_handle_t ioh;	/* indirect I/O handle */
 	uint16_t val, base_addr;
 
@@ -316,7 +317,7 @@ piixpm_sb800_init(struct piixpm_softc *s
 	bus_space_write_1(iot, ioh, PIIXPM_INDIRECTIO_INDEX,
 	    SB800_PM_SMBUS0EN_HI);
 	val |= bus_space_read_1(iot, ioh, PIIXPM_INDIRECTIO_DATA) << 8;
-	bus_space_unmap(iot, ioh, 2);
+	sc->sc_sb800_ioh = ioh;
 
 	if ((val & SB800_PM_SMBUS0EN_ENABLE) == 0)
 		return ENOENT;
@@ -325,8 +326,10 @@ piixpm_sb800_init(struct piixpm_softc *s
 
 	aprint_debug_dev(sc->sc_dev, "SMBus @ 0x%04x\n", base_addr);
 
-	sc->sc_smb_iot = iot;
-	if (bus_space_map(sc->sc_smb_iot, PCI_MAPREG_IO_ADDR(base_addr),
+	bus_space_write_1(iot, ioh, PIIXPM_INDIRECTIO_INDEX, SB800_PM_SMBUS0SELEN);
+	bus_space_write_1(iot, ioh, PIIXPM_INDIRECTIO_DATA, 1); /* SMBUS0SEL */
+
+	if (bus_space_map(iot, PCI_MAPREG_IO_ADDR(base_addr),
 	    PIIX_SMB_SIZE, 0, &sc->sc_smb_ioh)) {
 		aprint_error_dev(sc->sc_dev, "can't map smbus I/O space\n");
 		return EBUSY;
@@ -361,18 +364,40 @@ piixpm_csb5_reset(void *arg)
 static int
 piixpm_i2c_acquire_bus(void *cookie, int flags)
 {
-	struct piixpm_softc *sc = cookie;
+	struct piixpm_smbus *smbus = cookie;
+	struct piixpm_softc *sc = smbus->softc;
 
 	if (!cold)
 		mutex_enter(&sc->sc_i2c_mutex);
 
+	if (smbus->sda > 0)	/* SB800 */
+	{
+		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
+		    PIIXPM_INDIRECTIO_INDEX, SB800_PM_SMBUS0SEL);
+		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
+		    PIIXPM_INDIRECTIO_DATA, smbus->sda << 1);
+	}
+
 	return 0;
 }
 
 static void
 piixpm_i2c_release_bus(void *cookie, int flags)
 {
-	struct piixpm_softc *sc = cookie;
+	struct piixpm_smbus *smbus = cookie;
+	struct piixpm_softc *sc = smbus->softc;
+
+	if (smbus->sda > 0)	/* SB800 */
+	{
+		/*
+		 * 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,
+		    PIIXPM_INDIRECTIO_INDEX, SB800_PM_SMBUS0SEL);
+		bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
+		    PIIXPM_INDIRECTIO_DATA, 0);
+	}
 
 	if (!cold)
 		mutex_exit(&sc->sc_i2c_mutex);
@@ -382,7 +407,8 @@ static int
 piixpm_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
     const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
 {
-	struct piixpm_softc *sc = cookie;
+	struct piixpm_smbus *smbus = cookie;
+	struct piixpm_softc *sc = smbus->softc;
 	const u_int8_t *b;
 	u_int8_t ctl = 0, st;
 	int retries;
@@ -394,7 +420,7 @@ piixpm_i2c_exec(void *cookie, i2c_op_t o
 	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, 
 	    PIIX_SMB_HS_INTR | PIIX_SMB_HS_DEVERR | 
 	    PIIX_SMB_HS_BUSERR | PIIX_SMB_HS_FAILED);
-        bus_space_barrier(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, 1,
+	bus_space_barrier(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, 1,
 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
 
 	/* Wait for bus to be idle */
@@ -481,7 +507,7 @@ piixpm_i2c_exec(void *cookie, i2c_op_t o
 		}
 		if (st & PIIX_SMB_HS_BUSY)
 			goto timeout;
-		piixpm_intr(sc);
+		piixpm_intr(smbus);
 	} else {
 		/* Wait for interrupt */
 		if (tsleep(sc, PRIBIO, "iicexec", PIIXPM_TIMEOUT * hz))
@@ -516,7 +542,8 @@ timeout:
 static int
 piixpm_intr(void *arg)
 {
-	struct piixpm_softc *sc = arg;
+	struct piixpm_smbus *smbus = arg;
+	struct piixpm_softc *sc = smbus->softc;
 	u_int8_t st;
 	u_int8_t *b;
 	size_t len;

Index: src/sys/dev/pci/piixpmreg.h
diff -u src/sys/dev/pci/piixpmreg.h:1.5 src/sys/dev/pci/piixpmreg.h:1.6
--- src/sys/dev/pci/piixpmreg.h:1.5	Sun Feb 13 11:20:12 2011
+++ src/sys/dev/pci/piixpmreg.h	Mon Jul 22 13:27:14 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: piixpmreg.h,v 1.5 2011/02/13 11:20:12 hannken Exp $ */
+/* $NetBSD: piixpmreg.h,v 1.6 2013/07/22 13:27:14 soren Exp $ */
 /*	$OpenBSD: piixreg.h,v 1.3 2006/01/03 22:39:03 grange Exp $	*/
 
 /*
@@ -75,4 +75,17 @@
 #define PIIX_PM_SIZE	0x38		/* Power management I/O space size */
 #define PIIX_SMB_SIZE	0x10		/* SMBus I/O space size */
 
+#define PIIXPM_INDIRECTIO_BASE	0xcd6
+#define PIIXPM_INDIRECTIO_SIZE	2 
+#define PIIXPM_INDIRECTIO_INDEX	0
+#define PIIXPM_INDIRECTIO_DATA	1
+ 
+#define SB800_PM_SMBUS0EN_LO	0x2c
+#define SB800_PM_SMBUS0EN_HI	0x2d
+#define SB800_PM_SMBUS0SEL	0x2e 
+#define SB800_PM_SMBUS0SELEN	0x2f 
+                                      
+#define SB800_PM_SMBUS0EN_ENABLE 0x0001
+#define SB800_PM_SMBUS0EN_BADDR	0xffe0
+
 #endif	/* !_DEV_PCI_PIIXREG_H_ */

Reply via email to