Whenever I load the i2c-i801 smbus controller module I get a resource
conflict with the ACPI:
-----------------------
ACPI Warning: SystemIO range 0x000000000000F040-0x000000000000F05F
conflicts with OpRegion 0x000000000000F040-0x000000000000F04F
(\_SB_.PCI0.SBUS.SMBI) (20150619/utaddress-254)
-----------------------
As the resource conflict is about the IO resource, I overworked the
i2c-i801 module to use the MEM resource which is altough available.
This is IMHO the better alternative to using the
"acpi_enforce_resources=lax" boot parameter.
The patched module is working on my machine.
cheers,
Thilo
From f242a59a2b2085f8e1acbd5f108c9c60de483291 Mon Sep 17 00:00:00 2001
From: Thilo Cestonaro <thilo@xxxxxxxxxx>
Date: Mon, 11 Apr 2016 10:38:48 +0200
Subject: [PATCH] i2c-i801: use MEM resource instead of IO resource
When using the IO resource the module has a conflict with some BIOS, as Intel
requests this resource in their ACPI ASL Code.
ACPI Warning: SystemIO range 0x000000000000F040-0x000000000000F05F conflicts
with OpRegion 0x000000000000F040-0x000000000000F04F (\_SB_.PCI0.SBUS.SMBI)
One can either use acpi_enforce_resources=lax to be able to use the IO resource
base module or use this patch to use the smbus controller via MEM resource.
Signed-off-by: Thilo Cestonaro <thilo@xxxxxxxxxx>
---
drivers/i2c/busses/i2c-i801.c | 146 +++++++++++++++++++++---------------------
1 file changed, 73 insertions(+), 73 deletions(-)
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 585a3b7..5d05b5d 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -114,7 +114,7 @@
#define SMBAUXCTL(p) (13 + (p)->smba) /* ICH4 and later */
/* PCI Address Constants */
-#define SMBBAR 4
+#define SMBBAR 0 /* use MEM Resource */
#define SMBPCICTL 0x004
#define SMBPCISTS 0x006
#define SMBHSTCFG 0x040
@@ -222,7 +222,7 @@ struct i801_mux_config {
struct i801_priv {
struct i2c_adapter adapter;
- unsigned long smba;
+ void __iomem *smba;
unsigned char original_hstcfg;
struct pci_dev *pci_dev;
unsigned int features;
@@ -277,7 +277,7 @@ static int i801_check_pre(struct i801_priv *priv)
{
int status;
- status = inb_p(SMBHSTSTS(priv));
+ status = readb(SMBHSTSTS(priv));
if (status & SMBHSTSTS_HOST_BUSY) {
dev_err(&priv->pci_dev->dev, "SMBus is busy, can't use it!\n");
return -EBUSY;
@@ -287,8 +287,8 @@ static int i801_check_pre(struct i801_priv *priv)
if (status) {
dev_dbg(&priv->pci_dev->dev, "Clearing status flags (%02x)\n",
status);
- outb_p(status, SMBHSTSTS(priv));
- status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
+ writeb(status, SMBHSTSTS(priv));
+ status = readb(SMBHSTSTS(priv)) & STATUS_FLAGS;
if (status) {
dev_err(&priv->pci_dev->dev,
"Failed clearing status flags (%02x)\n",
@@ -319,19 +319,19 @@ static int i801_check_post(struct i801_priv *priv, int status)
dev_err(&priv->pci_dev->dev, "Transaction timeout\n");
/* try to stop the current command */
dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
- outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
+ writeb(readb(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
SMBHSTCNT(priv));
usleep_range(1000, 2000);
- outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
+ writeb(readb(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
SMBHSTCNT(priv));
/* Check if it worked */
- status = inb_p(SMBHSTSTS(priv));
+ status = readb(SMBHSTSTS(priv));
if ((status & SMBHSTSTS_HOST_BUSY) ||
!(status & SMBHSTSTS_FAILED))
dev_err(&priv->pci_dev->dev,
"Failed terminating the transaction\n");
- outb_p(STATUS_FLAGS, SMBHSTSTS(priv));
+ writeb(STATUS_FLAGS, SMBHSTSTS(priv));
return -ETIMEDOUT;
}
@@ -349,7 +349,7 @@ static int i801_check_post(struct i801_priv *priv, int status)
}
/* Clear status flags except BYTE_DONE, to be cleared by caller */
- outb_p(status, SMBHSTSTS(priv));
+ writeb(status, SMBHSTSTS(priv));
return result;
}
@@ -363,7 +363,7 @@ static int i801_wait_intr(struct i801_priv *priv)
/* We will always wait for a fraction of a second! */
do {
usleep_range(250, 500);
- status = inb_p(SMBHSTSTS(priv));
+ status = readb(SMBHSTSTS(priv));
} while (((status & SMBHSTSTS_HOST_BUSY) ||
!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR))) &&
(timeout++ < MAX_RETRIES));
@@ -384,7 +384,7 @@ static int i801_wait_byte_done(struct i801_priv *priv)
/* We will always wait for a fraction of a second! */
do {
usleep_range(250, 500);
- status = inb_p(SMBHSTSTS(priv));
+ status = readb(SMBHSTSTS(priv));
} while (!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) &&
(timeout++ < MAX_RETRIES));
@@ -406,7 +406,7 @@ static int i801_transaction(struct i801_priv *priv, int xact)
return result;
if (priv->features & FEATURE_IRQ) {
- outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START,
+ writeb(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START,
SMBHSTCNT(priv));
result = wait_event_timeout(priv->waitq,
(status = priv->status),
@@ -422,7 +422,7 @@ static int i801_transaction(struct i801_priv *priv, int xact)
/* the current contents of SMBHSTCNT can be overwritten, since PEC,
* SMBSCMD are passed in xact */
- outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv));
+ writeb(xact | SMBHSTCNT_START, SMBHSTCNT(priv));
status = i801_wait_intr(priv);
return i801_check_post(priv, status);
@@ -435,14 +435,14 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
int i, len;
int status;
- inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
+ readb(SMBHSTCNT(priv)); /* reset the data buffer index */
/* Use 32-byte buffer to process this transaction */
if (read_write == I2C_SMBUS_WRITE) {
len = data->block[0];
- outb_p(len, SMBHSTDAT0(priv));
+ writeb(len, SMBHSTDAT0(priv));
for (i = 0; i < len; i++)
- outb_p(data->block[i+1], SMBBLKDAT(priv));
+ writeb(data->block[i+1], SMBBLKDAT(priv));
}
status = i801_transaction(priv, I801_BLOCK_DATA |
@@ -451,13 +451,13 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
return status;
if (read_write == I2C_SMBUS_READ) {
- len = inb_p(SMBHSTDAT0(priv));
+ len = readb(SMBHSTDAT0(priv));
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
data->block[0] = len;
for (i = 0; i < len; i++)
- data->block[i + 1] = inb_p(SMBBLKDAT(priv));
+ data->block[i + 1] = readb(SMBBLKDAT(priv));
}
return 0;
}
@@ -468,7 +468,7 @@ static void i801_isr_byte_done(struct i801_priv *priv)
/* For SMBus block reads, length is received with first byte */
if (((priv->cmd & 0x1c) == I801_BLOCK_DATA) &&
(priv->count == 0)) {
- priv->len = inb_p(SMBHSTDAT0(priv));
+ priv->len = readb(SMBHSTDAT0(priv));
if (priv->len < 1 || priv->len > I2C_SMBUS_BLOCK_MAX) {
dev_err(&priv->pci_dev->dev,
"Illegal SMBus block read size %d\n",
@@ -485,22 +485,22 @@ static void i801_isr_byte_done(struct i801_priv *priv)
/* Read next byte */
if (priv->count < priv->len)
- priv->data[priv->count++] = inb(SMBBLKDAT(priv));
+ priv->data[priv->count++] = readb(SMBBLKDAT(priv));
else
dev_dbg(&priv->pci_dev->dev,
"Discarding extra byte on block read\n");
/* Set LAST_BYTE for last byte of read transaction */
if (priv->count == priv->len - 1)
- outb_p(priv->cmd | SMBHSTCNT_LAST_BYTE,
+ writeb(priv->cmd | SMBHSTCNT_LAST_BYTE,
SMBHSTCNT(priv));
} else if (priv->count < priv->len - 1) {
/* Write next byte, except for IRQ after last byte */
- outb_p(priv->data[++priv->count], SMBBLKDAT(priv));
+ writeb(priv->data[++priv->count], SMBBLKDAT(priv));
}
/* Clear BYTE_DONE to continue with next byte */
- outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
+ writeb(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
}
/*
@@ -528,7 +528,7 @@ static irqreturn_t i801_isr(int irq, void *dev_id)
if (!(pcists & SMBPCISTS_INTS))
return IRQ_NONE;
- status = inb_p(SMBHSTSTS(priv));
+ status = readb(SMBHSTSTS(priv));
if (status & SMBHSTSTS_BYTE_DONE)
i801_isr_byte_done(priv);
@@ -538,7 +538,7 @@ static irqreturn_t i801_isr(int irq, void *dev_id)
*/
status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS;
if (status) {
- outb_p(status, SMBHSTSTS(priv));
+ writeb(status, SMBHSTSTS(priv));
priv->status |= status;
wake_up(&priv->waitq);
}
@@ -569,8 +569,8 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
len = data->block[0];
if (read_write == I2C_SMBUS_WRITE) {
- outb_p(len, SMBHSTDAT0(priv));
- outb_p(data->block[1], SMBBLKDAT(priv));
+ writeb(len, SMBHSTDAT0(priv));
+ writeb(data->block[1], SMBBLKDAT(priv));
}
if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
@@ -588,7 +588,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
priv->count = 0;
priv->data = &data->block[1];
- outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv));
+ writeb(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv));
result = wait_event_timeout(priv->waitq,
(status = priv->status),
adap->timeout);
@@ -604,10 +604,10 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
for (i = 1; i <= len; i++) {
if (i == len && read_write == I2C_SMBUS_READ)
smbcmd |= SMBHSTCNT_LAST_BYTE;
- outb_p(smbcmd, SMBHSTCNT(priv));
+ writeb(smbcmd, SMBHSTCNT(priv));
if (i == 1)
- outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START,
+ writeb(readb(SMBHSTCNT(priv)) | SMBHSTCNT_START,
SMBHSTCNT(priv));
status = i801_wait_byte_done(priv);
@@ -616,17 +616,17 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
if (i == 1 && read_write == I2C_SMBUS_READ
&& command != I2C_SMBUS_I2C_BLOCK_DATA) {
- len = inb_p(SMBHSTDAT0(priv));
+ len = readb(SMBHSTDAT0(priv));
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
dev_err(&priv->pci_dev->dev,
"Illegal SMBus block read size %d\n",
len);
/* Recover */
- while (inb_p(SMBHSTSTS(priv)) &
+ while (readb(SMBHSTSTS(priv)) &
SMBHSTSTS_HOST_BUSY)
- outb_p(SMBHSTSTS_BYTE_DONE,
+ writeb(SMBHSTSTS_BYTE_DONE,
SMBHSTSTS(priv));
- outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
+ writeb(SMBHSTSTS_INTR, SMBHSTSTS(priv));
return -EPROTO;
}
data->block[0] = len;
@@ -634,12 +634,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
/* Retrieve/store value in SMBBLKDAT */
if (read_write == I2C_SMBUS_READ)
- data->block[i] = inb_p(SMBBLKDAT(priv));
+ data->block[i] = readb(SMBBLKDAT(priv));
if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
- outb_p(data->block[i+1], SMBBLKDAT(priv));
+ writeb(data->block[i+1], SMBBLKDAT(priv));
/* signals SMBBLKDAT ready */
- outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
+ writeb(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
}
status = i801_wait_intr(priv);
@@ -649,8 +649,8 @@ exit:
static int i801_set_block_buffer_mode(struct i801_priv *priv)
{
- outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
- if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0)
+ writeb(readb(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
+ if ((readb(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0)
return -EIO;
return 0;
}
@@ -723,51 +723,51 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
switch (size) {
case I2C_SMBUS_QUICK:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ writeb(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD(priv));
xact = I801_QUICK;
break;
case I2C_SMBUS_BYTE:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ writeb(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD(priv));
if (read_write == I2C_SMBUS_WRITE)
- outb_p(command, SMBHSTCMD(priv));
+ writeb(command, SMBHSTCMD(priv));
xact = I801_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ writeb(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD(priv));
- outb_p(command, SMBHSTCMD(priv));
+ writeb(command, SMBHSTCMD(priv));
if (read_write == I2C_SMBUS_WRITE)
- outb_p(data->byte, SMBHSTDAT0(priv));
+ writeb(data->byte, SMBHSTDAT0(priv));
xact = I801_BYTE_DATA;
break;
case I2C_SMBUS_WORD_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ writeb(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD(priv));
- outb_p(command, SMBHSTCMD(priv));
+ writeb(command, SMBHSTCMD(priv));
if (read_write == I2C_SMBUS_WRITE) {
- outb_p(data->word & 0xff, SMBHSTDAT0(priv));
- outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
+ writeb(data->word & 0xff, SMBHSTDAT0(priv));
+ writeb((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
}
xact = I801_WORD_DATA;
break;
case I2C_SMBUS_BLOCK_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ writeb(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD(priv));
- outb_p(command, SMBHSTCMD(priv));
+ writeb(command, SMBHSTCMD(priv));
block = 1;
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/* NB: page 240 of ICH5 datasheet shows that the R/#W
* bit should be cleared here, even when reading */
- outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
+ writeb((addr & 0x7f) << 1, SMBHSTADD(priv));
if (read_write == I2C_SMBUS_READ) {
/* NB: page 240 of ICH5 datasheet also shows
* that DATA1 is the cmd field when reading */
- outb_p(command, SMBHSTDAT1(priv));
+ writeb(command, SMBHSTDAT1(priv));
} else
- outb_p(command, SMBHSTCMD(priv));
+ writeb(command, SMBHSTCMD(priv));
block = 1;
break;
default:
@@ -777,9 +777,9 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
}
if (hwpec) /* enable/disable hardware PEC */
- outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
+ writeb(readb(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
else
- outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
+ writeb(readb(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
SMBAUXCTL(priv));
if (block)
@@ -792,7 +792,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
time, so we forcibly disable it after every transaction. Turn off
E32B for the same reason. */
if (hwpec || block)
- outb_p(inb_p(SMBAUXCTL(priv)) &
+ writeb(readb(SMBAUXCTL(priv)) &
~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
if (block)
@@ -805,11 +805,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
switch (xact & 0x7f) {
case I801_BYTE: /* Result put in SMBHSTDAT0 */
case I801_BYTE_DATA:
- data->byte = inb_p(SMBHSTDAT0(priv));
+ data->byte = readb(SMBHSTDAT0(priv));
break;
case I801_WORD_DATA:
- data->word = inb_p(SMBHSTDAT0(priv)) +
- (inb_p(SMBHSTDAT1(priv)) << 8);
+ data->word = readb(SMBHSTDAT0(priv)) +
+ (readb(SMBHSTDAT1(priv)) << 8);
break;
}
return 0;
@@ -1320,14 +1320,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
}
pcim_pin_device(dev);
- /* Determine the address of the SMBus area */
- priv->smba = pci_resource_start(dev, SMBBAR);
- if (!priv->smba) {
- dev_err(&dev->dev,
- "SMBus base address uninitialized, upgrade BIOS\n");
- return -ENODEV;
- }
-
err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
if (err) {
return -ENODEV;
@@ -1337,12 +1329,20 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
dev_driver_string(&dev->dev));
if (err) {
dev_err(&dev->dev,
- "Failed to request SMBus region 0x%lx-0x%Lx\n",
- priv->smba,
+ "Failed to request SMBus region 0x%Lx-0x%Lx\n",
+ (unsigned long long)pci_resource_start(dev, SMBBAR),
(unsigned long long)pci_resource_end(dev, SMBBAR));
return err;
}
+ /* Determine the address of the SMBus area */
+ priv->smba = pcim_iomap_table(dev)[SMBBAR];
+ if (!priv->smba) {
+ dev_err(&dev->dev,
+ "SMBus base address uninitialized, upgrade BIOS\n");
+ return -ENODEV;
+ }
+
pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp);
priv->original_hstcfg = temp;
temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
@@ -1360,7 +1360,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
/* Clear special mode bits */
if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
- outb_p(inb_p(SMBAUXCTL(priv)) &
+ writeb(readb(SMBAUXCTL(priv)) &
~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
/* Default timeout in interrupt mode: 200 ms */
@@ -1400,7 +1400,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
i801_add_tco(priv);
snprintf(priv->adapter.name, sizeof(priv->adapter.name),
- "SMBus I801 adapter at %04lx", priv->smba);
+ "SMBus I801 adapter at 0x%p", priv->smba);
err = i2c_add_adapter(&priv->adapter);
if (err) {
dev_err(&dev->dev, "Failed to add SMBus adapter\n");
--
2.7.4