[PATCH 2.6] scx200_acb: Use PCI I/O resource when appropriate

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

 



The CS5535 and CS5536 both define the I/O base for the SMBUS device in a 
PCI header.  This patch uses that header for the I/O base rather then 
using the MSR backdoor.

This patch isn't as urgent as the other one, so it can probably take the 
usual trip up through Greg's tree.

-- 
Jordan Crouse
Senior Linux Engineer
AMD - Personal Connectivity Solutions Group
<www.amd.com/embeddedprocessors>
[PATCH] scx200_acb:  Use PCI I/O resource when appropriate

From: Jordan Crouse <[email protected]>

On the CS5535 and CS5536, the I/O resource is allocated through PCI,
so use that instead of using the MSR backdoor.

Signed-off-by: Jordan Crouse <[email protected]>
---

 drivers/i2c/busses/scx200_acb.c |  114 +++++++++++++++++++++++++++------------
 1 files changed, 78 insertions(+), 36 deletions(-)

diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index e7a2225..454492f 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -33,7 +33,6 @@
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include <asm/io.h>
-#include <asm/msr.h>
 
 #include <linux/scx200.h>
 
@@ -85,6 +84,10 @@ struct scx200_acb_iface {
 	u8 *ptr;
 	char needs_reset;
 	unsigned len;
+
+	/* PCI device info */
+	struct pci_dev *pdev;
+	int bar;
 };
 
 /* Register Definitions */
@@ -417,7 +420,8 @@ static int scx200_acb_probe(struct scx20
 	return 0;
 }
 
-static int  __init scx200_acb_create(const char *text, int base, int index)
+static int __init scx200_acb_create(char *text, unsigned int base, int index,
+				    struct pci_dev *pdev, int bar)
 {
 	struct scx200_acb_iface *iface;
 	struct i2c_adapter *adapter;
@@ -444,13 +448,31 @@ static int  __init scx200_acb_create(con
 	snprintf(description, sizeof(description), "%s ACCESS.bus [%s]",
 		 text, adapter->name);
 
-	if (request_region(base, 8, description) == 0) {
-		printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n",
-			base, base + 8-1);
-		rc = -EBUSY;
-		goto errout_free;
+	if (pdev != NULL) {
+
+		iface->pdev = pdev;
+		iface->bar = bar;
+
+		pci_enable_device_bars(iface->pdev, 1 << iface->bar);
+
+		if (pci_request_region(iface->pdev, iface->bar, description)) {
+			printk(KERN_ERR NAME ": can't allocate PCI region %d\n",
+			       iface->bar);
+			rc = -EBUSY;
+			goto errout_free;
+		}
+
+		iface->base = pci_resource_start(iface->pdev, iface->bar);
+	} else {
+		if (request_region(base, 8, description) == 0) {
+			printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n",
+			       base, base + 8 - 1);
+			rc = -EBUSY;
+			goto errout_free;
+		}
+
+		iface->base = base;
 	}
-	iface->base = base;
 
 	rc = scx200_acb_probe(iface);
 	if (rc) {
@@ -474,7 +496,11 @@ static int  __init scx200_acb_create(con
 	return 0;
 
  errout_release:
-	release_region(iface->base, 8);
+	if (iface->pdev != NULL)
+		pci_release_region(iface->pdev, iface->bar);
+	else
+		release_region(iface->base, 8);
+
  errout_free:
 	kfree(iface);
  errout:
@@ -487,49 +513,60 @@ static struct pci_device_id scx200[] = {
 	{ },
 };
 
-static struct pci_device_id divil_pci[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS,  PCI_DEVICE_ID_NS_CS5535_ISA) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
-	{ } /* NULL entry */
+/* On the CS5535 and CS5536, the SMBUS I/0 base is a PCI resource, so
+   we should allocate that resource through the PCI
+   subsystem. rather then going through the MSR back door.
+*/
+
+static struct {
+	unsigned int vendor;
+	unsigned int device;
+	char *name;
+	int bar;
+} divil_pci[] = {
+	{
+	PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA, "CS5535", 0}, {
+	PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, "CS5536", 0}
 };
 
-#define MSR_LBAR_SMB		0x5140000B
+#define DIVIL_LENGTH (sizeof(divil_pci) / sizeof(divil_pci[0]))
 
 static int scx200_add_cs553x(void)
 {
-	u32	low, hi;
-	u32	smb_base;
-
-	/* Grab & reserve the SMB I/O range */
-	rdmsr(MSR_LBAR_SMB, low, hi);
+	int dev;
+	struct pci_dev *pdev;
 
-	/* Check the IO mask and whether SMB is enabled */
-	if (hi != 0x0000F001) {
-		printk(KERN_WARNING NAME ": SMBus not enabled\n");
-		return -ENODEV;
+	for (dev = 0; dev < DIVIL_LENGTH; dev++) {
+		pdev =
+		    pci_find_device(divil_pci[dev].vendor,
+				    divil_pci[dev].device, NULL);
+		if (pdev != NULL)
+			break;
 	}
 
-	/* SMBus IO size is 8 bytes */
-	smb_base = low & 0x0000FFF8;
+	if (pdev == NULL)
+		return -ENODEV;
 
-	return scx200_acb_create("CS5535", smb_base, 0);
+	return scx200_acb_create(divil_pci[dev].name, 0, 0, pdev,
+				 divil_pci[dev].bar);
 }
 
 static int __init scx200_acb_init(void)
 {
 	int i;
-	int	rc = -ENODEV;
+	int rc     = -ENODEV;
 
 	pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
 
-	/* Verify that this really is a SCx200 processor */
-	if (pci_dev_present(scx200)) {
-		for (i = 0; i < MAX_DEVICES; ++i) {
-			if (base[i] > 0)
-				rc = scx200_acb_create("SCx200", base[i], i);
-		}
-	} else if (pci_dev_present(divil_pci))
-		rc = scx200_add_cs553x();
+	/* If this is a CS5535 or CS5536, then probe the PCI header */
+
+	if (!pci_dev_present(scx200))
+		return scx200_add_cs553x();
+
+	for (i = 0; i < MAX_DEVICES; ++i) {
+		if (base[i] > 0)
+			rc = scx200_acb_create("SCx200", base[i], i, NULL, 0);
+	}
 
 	return rc;
 }
@@ -544,7 +581,12 @@ static void __exit scx200_acb_cleanup(vo
 		up(&scx200_acb_list_mutex);
 
 		i2c_del_adapter(&iface->adapter);
-		release_region(iface->base, 8);
+
+		if (iface->pdev != NULL)
+			pci_release_region(iface->pdev, iface->bar);
+		else
+			release_region(iface->base, 8);
+
 		kfree(iface);
 		down(&scx200_acb_list_mutex);
 	}

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux