diff options
| -rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 319 |
1 files changed, 175 insertions, 144 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 1fe30da653c3..56883f48c2e4 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker | 3 | Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker |
| 4 | <mdsxyz123@yahoo.com> | 4 | <mdsxyz123@yahoo.com> |
| 5 | Copyright (C) 2007, 2008 Jean Delvare <khali@linux-fr.org> | 5 | Copyright (C) 2007, 2008 Jean Delvare <khali@linux-fr.org> |
| 6 | Copyright (C) 2010 Intel Corporation, | ||
| 7 | David Woodhouse <dwmw2@infradead.org> | ||
| 6 | 8 | ||
| 7 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
| @@ -55,8 +57,6 @@ | |||
| 55 | See the file Documentation/i2c/busses/i2c-i801 for details. | 57 | See the file Documentation/i2c/busses/i2c-i801 for details. |
| 56 | */ | 58 | */ |
| 57 | 59 | ||
| 58 | /* Note: we assume there can only be one I801, with one SMBus interface */ | ||
| 59 | |||
| 60 | #include <linux/module.h> | 60 | #include <linux/module.h> |
| 61 | #include <linux/pci.h> | 61 | #include <linux/pci.h> |
| 62 | #include <linux/kernel.h> | 62 | #include <linux/kernel.h> |
| @@ -70,16 +70,16 @@ | |||
| 70 | #include <linux/dmi.h> | 70 | #include <linux/dmi.h> |
| 71 | 71 | ||
| 72 | /* I801 SMBus address offsets */ | 72 | /* I801 SMBus address offsets */ |
| 73 | #define SMBHSTSTS (0 + i801_smba) | 73 | #define SMBHSTSTS(p) (0 + (p)->smba) |
| 74 | #define SMBHSTCNT (2 + i801_smba) | 74 | #define SMBHSTCNT(p) (2 + (p)->smba) |
| 75 | #define SMBHSTCMD (3 + i801_smba) | 75 | #define SMBHSTCMD(p) (3 + (p)->smba) |
| 76 | #define SMBHSTADD (4 + i801_smba) | 76 | #define SMBHSTADD(p) (4 + (p)->smba) |
| 77 | #define SMBHSTDAT0 (5 + i801_smba) | 77 | #define SMBHSTDAT0(p) (5 + (p)->smba) |
| 78 | #define SMBHSTDAT1 (6 + i801_smba) | 78 | #define SMBHSTDAT1(p) (6 + (p)->smba) |
| 79 | #define SMBBLKDAT (7 + i801_smba) | 79 | #define SMBBLKDAT(p) (7 + (p)->smba) |
| 80 | #define SMBPEC (8 + i801_smba) /* ICH3 and later */ | 80 | #define SMBPEC(p) (8 + (p)->smba) /* ICH3 and later */ |
| 81 | #define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */ | 81 | #define SMBAUXSTS(p) (12 + (p)->smba) /* ICH4 and later */ |
| 82 | #define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */ | 82 | #define SMBAUXCTL(p) (13 + (p)->smba) /* ICH4 and later */ |
| 83 | 83 | ||
| 84 | /* PCI Address Constants */ | 84 | /* PCI Address Constants */ |
| 85 | #define SMBBAR 4 | 85 | #define SMBBAR 4 |
| @@ -128,16 +128,20 @@ | |||
| 128 | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ | 128 | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ |
| 129 | SMBHSTSTS_INTR) | 129 | SMBHSTSTS_INTR) |
| 130 | 130 | ||
| 131 | static unsigned long i801_smba; | 131 | struct i801_priv { |
| 132 | static unsigned char i801_original_hstcfg; | 132 | struct i2c_adapter adapter; |
| 133 | unsigned long smba; | ||
| 134 | unsigned char original_hstcfg; | ||
| 135 | struct pci_dev *pci_dev; | ||
| 136 | unsigned int features; | ||
| 137 | }; | ||
| 138 | |||
| 133 | static struct pci_driver i801_driver; | 139 | static struct pci_driver i801_driver; |
| 134 | static struct pci_dev *I801_dev; | ||
| 135 | 140 | ||
| 136 | #define FEATURE_SMBUS_PEC (1 << 0) | 141 | #define FEATURE_SMBUS_PEC (1 << 0) |
| 137 | #define FEATURE_BLOCK_BUFFER (1 << 1) | 142 | #define FEATURE_BLOCK_BUFFER (1 << 1) |
| 138 | #define FEATURE_BLOCK_PROC (1 << 2) | 143 | #define FEATURE_BLOCK_PROC (1 << 2) |
| 139 | #define FEATURE_I2C_BLOCK_READ (1 << 3) | 144 | #define FEATURE_I2C_BLOCK_READ (1 << 3) |
| 140 | static unsigned int i801_features; | ||
| 141 | 145 | ||
| 142 | static const char *i801_feature_names[] = { | 146 | static const char *i801_feature_names[] = { |
| 143 | "SMBus PEC", | 147 | "SMBus PEC", |
| @@ -152,24 +156,24 @@ MODULE_PARM_DESC(disable_features, "Disable selected driver features"); | |||
| 152 | 156 | ||
| 153 | /* Make sure the SMBus host is ready to start transmitting. | 157 | /* Make sure the SMBus host is ready to start transmitting. |
| 154 | Return 0 if it is, -EBUSY if it is not. */ | 158 | Return 0 if it is, -EBUSY if it is not. */ |
| 155 | static int i801_check_pre(void) | 159 | static int i801_check_pre(struct i801_priv *priv) |
| 156 | { | 160 | { |
| 157 | int status; | 161 | int status; |
| 158 | 162 | ||
| 159 | status = inb_p(SMBHSTSTS); | 163 | status = inb_p(SMBHSTSTS(priv)); |
| 160 | if (status & SMBHSTSTS_HOST_BUSY) { | 164 | if (status & SMBHSTSTS_HOST_BUSY) { |
| 161 | dev_err(&I801_dev->dev, "SMBus is busy, can't use it!\n"); | 165 | dev_err(&priv->pci_dev->dev, "SMBus is busy, can't use it!\n"); |
| 162 | return -EBUSY; | 166 | return -EBUSY; |
| 163 | } | 167 | } |
| 164 | 168 | ||
| 165 | status &= STATUS_FLAGS; | 169 | status &= STATUS_FLAGS; |
| 166 | if (status) { | 170 | if (status) { |
| 167 | dev_dbg(&I801_dev->dev, "Clearing status flags (%02x)\n", | 171 | dev_dbg(&priv->pci_dev->dev, "Clearing status flags (%02x)\n", |
| 168 | status); | 172 | status); |
| 169 | outb_p(status, SMBHSTSTS); | 173 | outb_p(status, SMBHSTSTS(priv)); |
| 170 | status = inb_p(SMBHSTSTS) & STATUS_FLAGS; | 174 | status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; |
| 171 | if (status) { | 175 | if (status) { |
| 172 | dev_err(&I801_dev->dev, | 176 | dev_err(&priv->pci_dev->dev, |
| 173 | "Failed clearing status flags (%02x)\n", | 177 | "Failed clearing status flags (%02x)\n", |
| 174 | status); | 178 | status); |
| 175 | return -EBUSY; | 179 | return -EBUSY; |
| @@ -180,48 +184,50 @@ static int i801_check_pre(void) | |||
| 180 | } | 184 | } |
| 181 | 185 | ||
| 182 | /* Convert the status register to an error code, and clear it. */ | 186 | /* Convert the status register to an error code, and clear it. */ |
| 183 | static int i801_check_post(int status, int timeout) | 187 | static int i801_check_post(struct i801_priv *priv, int status, int timeout) |
| 184 | { | 188 | { |
| 185 | int result = 0; | 189 | int result = 0; |
| 186 | 190 | ||
| 187 | /* If the SMBus is still busy, we give up */ | 191 | /* If the SMBus is still busy, we give up */ |
| 188 | if (timeout) { | 192 | if (timeout) { |
| 189 | dev_err(&I801_dev->dev, "Transaction timeout\n"); | 193 | dev_err(&priv->pci_dev->dev, "Transaction timeout\n"); |
| 190 | /* try to stop the current command */ | 194 | /* try to stop the current command */ |
| 191 | dev_dbg(&I801_dev->dev, "Terminating the current operation\n"); | 195 | dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n"); |
| 192 | outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); | 196 | outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, |
| 197 | SMBHSTCNT(priv)); | ||
| 193 | msleep(1); | 198 | msleep(1); |
| 194 | outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT); | 199 | outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), |
| 200 | SMBHSTCNT(priv)); | ||
| 195 | 201 | ||
| 196 | /* Check if it worked */ | 202 | /* Check if it worked */ |
| 197 | status = inb_p(SMBHSTSTS); | 203 | status = inb_p(SMBHSTSTS(priv)); |
| 198 | if ((status & SMBHSTSTS_HOST_BUSY) || | 204 | if ((status & SMBHSTSTS_HOST_BUSY) || |
| 199 | !(status & SMBHSTSTS_FAILED)) | 205 | !(status & SMBHSTSTS_FAILED)) |
| 200 | dev_err(&I801_dev->dev, | 206 | dev_err(&priv->pci_dev->dev, |
| 201 | "Failed terminating the transaction\n"); | 207 | "Failed terminating the transaction\n"); |
| 202 | outb_p(STATUS_FLAGS, SMBHSTSTS); | 208 | outb_p(STATUS_FLAGS, SMBHSTSTS(priv)); |
| 203 | return -ETIMEDOUT; | 209 | return -ETIMEDOUT; |
| 204 | } | 210 | } |
| 205 | 211 | ||
| 206 | if (status & SMBHSTSTS_FAILED) { | 212 | if (status & SMBHSTSTS_FAILED) { |
| 207 | result = -EIO; | 213 | result = -EIO; |
| 208 | dev_err(&I801_dev->dev, "Transaction failed\n"); | 214 | dev_err(&priv->pci_dev->dev, "Transaction failed\n"); |
| 209 | } | 215 | } |
| 210 | if (status & SMBHSTSTS_DEV_ERR) { | 216 | if (status & SMBHSTSTS_DEV_ERR) { |
| 211 | result = -ENXIO; | 217 | result = -ENXIO; |
| 212 | dev_dbg(&I801_dev->dev, "No response\n"); | 218 | dev_dbg(&priv->pci_dev->dev, "No response\n"); |
| 213 | } | 219 | } |
| 214 | if (status & SMBHSTSTS_BUS_ERR) { | 220 | if (status & SMBHSTSTS_BUS_ERR) { |
| 215 | result = -EAGAIN; | 221 | result = -EAGAIN; |
| 216 | dev_dbg(&I801_dev->dev, "Lost arbitration\n"); | 222 | dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n"); |
| 217 | } | 223 | } |
| 218 | 224 | ||
| 219 | if (result) { | 225 | if (result) { |
| 220 | /* Clear error flags */ | 226 | /* Clear error flags */ |
| 221 | outb_p(status & STATUS_FLAGS, SMBHSTSTS); | 227 | outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv)); |
| 222 | status = inb_p(SMBHSTSTS) & STATUS_FLAGS; | 228 | status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; |
| 223 | if (status) { | 229 | if (status) { |
| 224 | dev_warn(&I801_dev->dev, "Failed clearing status " | 230 | dev_warn(&priv->pci_dev->dev, "Failed clearing status " |
| 225 | "flags at end of transaction (%02x)\n", | 231 | "flags at end of transaction (%02x)\n", |
| 226 | status); | 232 | status); |
| 227 | } | 233 | } |
| @@ -230,86 +236,88 @@ static int i801_check_post(int status, int timeout) | |||
| 230 | return result; | 236 | return result; |
| 231 | } | 237 | } |
| 232 | 238 | ||
