diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-viapro.c')
-rw-r--r-- | drivers/i2c/busses/i2c-viapro.c | 122 |
1 files changed, 41 insertions, 81 deletions
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index b420e752b1dc..5cf8fe182806 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | #include <linux/kernel.h> | 40 | #include <linux/kernel.h> |
41 | #include <linux/stddef.h> | 41 | #include <linux/stddef.h> |
42 | #include <linux/sched.h> | ||
43 | #include <linux/ioport.h> | 42 | #include <linux/ioport.h> |
44 | #include <linux/i2c.h> | 43 | #include <linux/i2c.h> |
45 | #include <linux/init.h> | 44 | #include <linux/init.h> |
@@ -54,34 +53,22 @@ static struct pci_dev *vt596_pdev; | |||
54 | /* SMBus address offsets */ | 53 | /* SMBus address offsets */ |
55 | static unsigned short vt596_smba; | 54 | static unsigned short vt596_smba; |
56 | #define SMBHSTSTS (vt596_smba + 0) | 55 | #define SMBHSTSTS (vt596_smba + 0) |
57 | #define SMBHSLVSTS (vt596_smba + 1) | ||
58 | #define SMBHSTCNT (vt596_smba + 2) | 56 | #define SMBHSTCNT (vt596_smba + 2) |
59 | #define SMBHSTCMD (vt596_smba + 3) | 57 | #define SMBHSTCMD (vt596_smba + 3) |
60 | #define SMBHSTADD (vt596_smba + 4) | 58 | #define SMBHSTADD (vt596_smba + 4) |
61 | #define SMBHSTDAT0 (vt596_smba + 5) | 59 | #define SMBHSTDAT0 (vt596_smba + 5) |
62 | #define SMBHSTDAT1 (vt596_smba + 6) | 60 | #define SMBHSTDAT1 (vt596_smba + 6) |
63 | #define SMBBLKDAT (vt596_smba + 7) | 61 | #define SMBBLKDAT (vt596_smba + 7) |
64 | #define SMBSLVCNT (vt596_smba + 8) | ||
65 | #define SMBSHDWCMD (vt596_smba + 9) | ||
66 | #define SMBSLVEVT (vt596_smba + 0xA) | ||
67 | #define SMBSLVDAT (vt596_smba + 0xC) | ||
68 | 62 | ||
69 | /* PCI Address Constants */ | 63 | /* PCI Address Constants */ |
70 | 64 | ||
71 | /* SMBus data in configuration space can be found in two places, | 65 | /* SMBus data in configuration space can be found in two places, |
72 | We try to select the better one */ | 66 | We try to select the better one */ |
73 | 67 | ||
74 | static unsigned short smb_cf_hstcfg = 0xD2; | 68 | static unsigned short SMBHSTCFG = 0xD2; |
75 | |||
76 | #define SMBHSTCFG (smb_cf_hstcfg) | ||
77 | #define SMBSLVC (smb_cf_hstcfg + 1) | ||
78 | #define SMBSHDW1 (smb_cf_hstcfg + 2) | ||
79 | #define SMBSHDW2 (smb_cf_hstcfg + 3) | ||
80 | #define SMBREV (smb_cf_hstcfg + 4) | ||
81 | 69 | ||
82 | /* Other settings */ | 70 | /* Other settings */ |
83 | #define MAX_TIMEOUT 500 | 71 | #define MAX_TIMEOUT 500 |
84 | #define ENABLE_INT9 0 | ||
85 | 72 | ||
86 | /* VT82C596 constants */ | 73 | /* VT82C596 constants */ |
87 | #define VT596_QUICK 0x00 | 74 | #define VT596_QUICK 0x00 |
@@ -107,12 +94,13 @@ MODULE_PARM_DESC(force_addr, | |||
107 | "EXTREMELY DANGEROUS!"); | 94 | "EXTREMELY DANGEROUS!"); |
108 | 95 | ||
109 | 96 | ||
97 | static struct pci_driver vt596_driver; | ||
110 | static struct i2c_adapter vt596_adapter; | 98 | static struct i2c_adapter vt596_adapter; |
111 | 99 | ||
112 | #define FEATURE_I2CBLOCK (1<<0) | 100 | #define FEATURE_I2CBLOCK (1<<0) |
113 | static unsigned int vt596_features; | 101 | static unsigned int vt596_features; |
114 | 102 | ||
115 | /* Another internally used function */ | 103 | /* Return -1 on error, 0 on success */ |
116 | static int vt596_transaction(void) | 104 | static int vt596_transaction(void) |
117 | { | 105 | { |
118 | int temp; | 106 | int temp; |
@@ -127,23 +115,21 @@ static int vt596_transaction(void) | |||
127 | /* Make sure the SMBus host is ready to start transmitting */ | 115 | /* Make sure the SMBus host is ready to start transmitting */ |
128 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { | 116 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { |
129 | dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). " | 117 | dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). " |
130 | "Resetting...\n", temp); | 118 | "Resetting... ", temp); |
131 | 119 | ||
132 | outb_p(temp, SMBHSTSTS); | 120 | outb_p(temp, SMBHSTSTS); |
133 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { | 121 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { |
134 | dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp); | 122 | printk("Failed! (0x%02x)\n", temp); |
135 | |||
136 | return -1; | 123 | return -1; |
137 | } else { | 124 | } else { |
138 | dev_dbg(&vt596_adapter.dev, "Successfull!\n"); | 125 | printk("Successful!\n"); |
139 | } | 126 | } |
140 | } | 127 | } |
141 | 128 | ||
142 | /* start the transaction by setting bit 6 */ | 129 | /* Start the transaction by setting bit 6 */ |
143 | outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); | 130 | outb_p(inb(SMBHSTCNT) | 0x40, SMBHSTCNT); |
144 | 131 | ||
145 | /* We will always wait for a fraction of a second! | 132 | /* We will always wait for a fraction of a second */ |
146 | I don't know if VIA needs this, Intel did */ | ||
147 | do { | 133 | do { |
148 | msleep(1); | 134 | msleep(1); |
149 | temp = inb_p(SMBHSTSTS); | 135 | temp = inb_p(SMBHSTSTS); |
@@ -152,33 +138,32 @@ static int vt596_transaction(void) | |||
152 | /* If the SMBus is still busy, we give up */ | 138 | /* If the SMBus is still busy, we give up */ |
153 | if (timeout >= MAX_TIMEOUT) { | 139 | if (timeout >= MAX_TIMEOUT) { |
154 | result = -1; | 140 | result = -1; |
155 | dev_dbg(&vt596_adapter.dev, "SMBus Timeout!\n"); | 141 | dev_err(&vt596_adapter.dev, "SMBus timeout!\n"); |
156 | } | 142 | } |
157 | 143 | ||
158 | if (temp & 0x10) { | 144 | if (temp & 0x10) { |
159 | result = -1; | 145 | result = -1; |
160 | dev_dbg(&vt596_adapter.dev, "Error: Failed bus transaction\n"); | 146 | dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n", |
147 | inb_p(SMBHSTCNT) & 0x3C); | ||
161 | } | 148 | } |
162 | 149 | ||
163 | if (temp & 0x08) { | 150 | if (temp & 0x08) { |
164 | result = -1; | 151 | result = -1; |
165 | dev_info(&vt596_adapter.dev, "Bus collision! SMBus may be " | 152 | dev_err(&vt596_adapter.dev, "SMBus collision!\n"); |
166 | "locked until next hard\nreset. (sorry!)\n"); | ||
167 | /* Clock stops and slave is stuck in mid-transmission */ | ||
168 | } | 153 | } |
169 | 154 | ||
170 | if (temp & 0x04) { | 155 | if (temp & 0x04) { |
171 | result = -1; | 156 | result = -1; |
172 | dev_dbg(&vt596_adapter.dev, "Error: no response!\n"); | 157 | /* Quick commands are used to probe for chips, so |
158 | errors are expected, and we don't want to frighten the | ||
159 | user. */ | ||
160 | if ((inb_p(SMBHSTCNT) & 0x3C) != VT596_QUICK) | ||
161 | dev_err(&vt596_adapter.dev, "Transaction error!\n"); | ||
173 | } | 162 | } |
174 | 163 | ||
175 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { | 164 | /* Resetting status register */ |
165 | if (temp & 0x1F) | ||
176 | outb_p(temp, SMBHSTSTS); | 166 | outb_p(temp, SMBHSTSTS); |
177 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { | ||
178 | dev_warn(&vt596_adapter.dev, "Failed reset at end " | ||
179 | "of transaction (%02x)\n", temp); | ||
180 | } | ||
181 | } | ||
182 | 167 | ||
183 | dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " | 168 | dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " |
184 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), | 169 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), |
@@ -188,41 +173,29 @@ static int vt596_transaction(void) | |||
188 | return result; | 173 | return result; |
189 | } | 174 | } |
190 | 175 | ||
191 | /* Return -1 on error. */ | 176 | /* Return -1 on error, 0 on success */ |
192 | static s32 vt596_access(struct i2c_adapter *adap, u16 addr, | 177 | static s32 vt596_access(struct i2c_adapter *adap, u16 addr, |
193 | unsigned short flags, char read_write, u8 command, | 178 | unsigned short flags, char read_write, u8 command, |
194 | int size, union i2c_smbus_data *data) | 179 | int size, union i2c_smbus_data *data) |
195 | { | 180 | { |
196 | int i, len; | 181 | int i; |
197 | 182 | ||
198 | switch (size) { | 183 | switch (size) { |
199 | case I2C_SMBUS_PROC_CALL: | ||
200 | dev_info(&vt596_adapter.dev, | ||
201 | "I2C_SMBUS_PROC_CALL not supported!\n"); | ||
202 | return -1; | ||
203 | case I2C_SMBUS_QUICK: | 184 | case I2C_SMBUS_QUICK: |
204 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
205 | SMBHSTADD); | ||
206 | size = VT596_QUICK; | 185 | size = VT596_QUICK; |
207 | break; | 186 | break; |
208 | case I2C_SMBUS_BYTE: | 187 | case I2C_SMBUS_BYTE: |
209 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
210 | SMBHSTADD); | ||
211 | if (read_write == I2C_SMBUS_WRITE) | 188 | if (read_write == I2C_SMBUS_WRITE) |
212 | outb_p(command, SMBHSTCMD); | 189 | outb_p(command, SMBHSTCMD); |
213 | size = VT596_BYTE; | 190 | size = VT596_BYTE; |
214 | break; | 191 | break; |
215 | case I2C_SMBUS_BYTE_DATA: | 192 | case I2C_SMBUS_BYTE_DATA: |
216 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
217 | SMBHSTADD); | ||
218 | outb_p(command, SMBHSTCMD); | 193 | outb_p(command, SMBHSTCMD); |
219 | if (read_write == I2C_SMBUS_WRITE) | 194 | if (read_write == I2C_SMBUS_WRITE) |
220 | outb_p(data->byte, SMBHSTDAT0); | 195 | outb_p(data->byte, SMBHSTDAT0); |
221 | size = VT596_BYTE_DATA; | 196 | size = VT596_BYTE_DATA; |
222 | break; | 197 | break; |
223 | case I2C_SMBUS_WORD_DATA: | 198 | case I2C_SMBUS_WORD_DATA: |
224 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
225 | SMBHSTADD); | ||
226 | outb_p(command, SMBHSTCMD); | 199 | outb_p(command, SMBHSTCMD); |
227 | if (read_write == I2C_SMBUS_WRITE) { | 200 | if (read_write == I2C_SMBUS_WRITE) { |
228 | outb_p(data->word & 0xff, SMBHSTDAT0); | 201 | outb_p(data->word & 0xff, SMBHSTDAT0); |
@@ -232,31 +205,30 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, | |||
232 | break; | 205 | break; |
233 | case I2C_SMBUS_I2C_BLOCK_DATA: | 206 | case I2C_SMBUS_I2C_BLOCK_DATA: |
234 | if (!(vt596_features & FEATURE_I2CBLOCK)) | 207 | if (!(vt596_features & FEATURE_I2CBLOCK)) |
235 | return -1; | 208 | goto exit_unsupported; |
236 | if (read_write == I2C_SMBUS_READ) | 209 | if (read_write == I2C_SMBUS_READ) |
237 | outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0); | 210 | outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0); |
238 | /* Fall through */ | 211 | /* Fall through */ |
239 | case I2C_SMBUS_BLOCK_DATA: | 212 | case I2C_SMBUS_BLOCK_DATA: |
240 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
241 | SMBHSTADD); | ||
242 | outb_p(command, SMBHSTCMD); | 213 | outb_p(command, SMBHSTCMD); |
243 | if (read_write == I2C_SMBUS_WRITE) { | 214 | if (read_write == I2C_SMBUS_WRITE) { |
244 | len = data->block[0]; | 215 | u8 len = data->block[0]; |
245 | if (len < 0) | ||
246 | len = 0; | ||
247 | if (len > I2C_SMBUS_BLOCK_MAX) | 216 | if (len > I2C_SMBUS_BLOCK_MAX) |
248 | len = I2C_SMBUS_BLOCK_MAX; | 217 | len = I2C_SMBUS_BLOCK_MAX; |
249 | outb_p(len, SMBHSTDAT0); | 218 | outb_p(len, SMBHSTDAT0); |
250 | i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ | 219 | inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ |
251 | for (i = 1; i <= len; i++) | 220 | for (i = 1; i <= len; i++) |
252 | outb_p(data->block[i], SMBBLKDAT); | 221 | outb_p(data->block[i], SMBBLKDAT); |
253 | } | 222 | } |
254 | size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ? | 223 | size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ? |
255 | VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA; | 224 | VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA; |
256 | break; | 225 | break; |
226 | default: | ||
227 | goto exit_unsupported; | ||
257 | } | 228 | } |
258 | 229 | ||
259 | outb_p((size & 0x3C) + (ENABLE_INT9 & 1), SMBHSTCNT); | 230 | outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD); |
231 | outb_p((size & 0x3C), SMBHSTCNT); | ||
260 | 232 | ||
261 | if (vt596_transaction()) /* Error in transaction */ | 233 | if (vt596_transaction()) /* Error in transaction */ |
262 | return -1; | 234 | return -1; |
@@ -266,12 +238,6 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, | |||
266 | 238 | ||
267 | switch (size) { | 239 | switch (size) { |
268 | case VT596_BYTE: | 240 | case VT596_BYTE: |
269 | /* Where is the result put? I assume here it is in | ||
270 | * SMBHSTDAT0 but it might just as well be in the | ||
271 | * SMBHSTCMD. No clue in the docs | ||
272 | */ | ||
273 | data->byte = inb_p(SMBHSTDAT0); | ||
274 | break; | ||
275 | case VT596_BYTE_DATA: | 241 | case VT596_BYTE_DATA: |
276 | data->byte = inb_p(SMBHSTDAT0); | 242 | data->byte = inb_p(SMBHSTDAT0); |
277 | break; | 243 | break; |
@@ -283,12 +249,17 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, | |||
283 | data->block[0] = inb_p(SMBHSTDAT0); | 249 | data->block[0] = inb_p(SMBHSTDAT0); |
284 | if (data->block[0] > I2C_SMBUS_BLOCK_MAX) | 250 | if (data->block[0] > I2C_SMBUS_BLOCK_MAX) |
285 | data->block[0] = I2C_SMBUS_BLOCK_MAX; | 251 | data->block[0] = I2C_SMBUS_BLOCK_MAX; |
286 | i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ | 252 | inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ |
287 | for (i = 1; i <= data->block[0]; i++) | 253 | for (i = 1; i <= data->block[0]; i++) |
288 | data->block[i] = inb_p(SMBBLKDAT); | 254 | data->block[i] = inb_p(SMBBLKDAT); |
289 | break; | 255 | break; |
290 | } | 256 | } |
291 | return 0; | 257 | return 0; |
258 | |||
259 | exit_unsupported: | ||
260 | dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n", | ||
261 | size); | ||
262 | return -1; | ||
292 | } | 263 | } |
293 | 264 | ||
294 | static u32 vt596_func(struct i2c_adapter *adapter) | 265 | static u32 vt596_func(struct i2c_adapter *adapter) |
@@ -311,7 +282,6 @@ static struct i2c_adapter vt596_adapter = { | |||
311 | .owner = THIS_MODULE, | 282 | .owner = THIS_MODULE, |
312 | .class = I2C_CLASS_HWMON, | 283 | .class = I2C_CLASS_HWMON, |
313 | .algo = &smbus_algorithm, | 284 | .algo = &smbus_algorithm, |
314 | .name = "unset", | ||
315 | }; | 285 | }; |
316 | 286 | ||
317 | static int __devinit vt596_probe(struct pci_dev *pdev, | 287 | static int __devinit vt596_probe(struct pci_dev *pdev, |
@@ -328,12 +298,12 @@ static int __devinit vt596_probe(struct pci_dev *pdev, | |||
328 | } | 298 | } |
329 | 299 | ||
330 | if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) || | 300 | if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) || |
331 | !(vt596_smba & 0x1)) { | 301 | !(vt596_smba & 0x0001)) { |
332 | /* try 2nd address and config reg. for 596 */ | 302 | /* try 2nd address and config reg. for 596 */ |
333 | if (id->device == PCI_DEVICE_ID_VIA_82C596_3 && | 303 | if (id->device == PCI_DEVICE_ID_VIA_82C596_3 && |
334 | !pci_read_config_word(pdev, SMBBA2, &vt596_smba) && | 304 | !pci_read_config_word(pdev, SMBBA2, &vt596_smba) && |
335 | (vt596_smba & 0x1)) { | 305 | (vt596_smba & 0x0001)) { |
336 | smb_cf_hstcfg = 0x84; | 306 | SMBHSTCFG = 0x84; |
337 | } else { | 307 | } else { |
338 | /* no matches at all */ | 308 | /* no matches at all */ |
339 | dev_err(&pdev->dev, "Cannot configure " | 309 | dev_err(&pdev->dev, "Cannot configure " |
@@ -351,7 +321,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev, | |||
351 | } | 321 | } |
352 | 322 | ||
353 | found: | 323 | found: |
354 | if (!request_region(vt596_smba, 8, "viapro-smbus")) { | 324 | if (!request_region(vt596_smba, 8, vt596_driver.name)) { |
355 | dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n", | 325 | dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n", |
356 | vt596_smba); | 326 | vt596_smba); |
357 | return -ENODEV; | 327 | return -ENODEV; |
@@ -366,7 +336,7 @@ found: | |||
366 | pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); | 336 | pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); |
367 | dev_warn(&pdev->dev, "WARNING: SMBus interface set to new " | 337 | dev_warn(&pdev->dev, "WARNING: SMBus interface set to new " |
368 | "address 0x%04x!\n", vt596_smba); | 338 | "address 0x%04x!\n", vt596_smba); |
369 | } else if ((temp & 1) == 0) { | 339 | } else if (!(temp & 0x01)) { |
370 | if (force) { | 340 | if (force) { |
371 | /* NOTE: This assumes I/O space and other allocations | 341 | /* NOTE: This assumes I/O space and other allocations |
372 | * WERE done by the Bios! Don't complain if your | 342 | * WERE done by the Bios! Don't complain if your |
@@ -374,7 +344,7 @@ found: | |||
374 | * :') Check for Bios updates before resorting to | 344 | * :') Check for Bios updates before resorting to |
375 | * this. | 345 | * this. |
376 | */ | 346 | */ |
377 | pci_write_config_byte(pdev, SMBHSTCFG, temp | 1); | 347 | pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); |
378 | dev_info(&pdev->dev, "Enabling SMBus device\n"); | 348 | dev_info(&pdev->dev, "Enabling SMBus device\n"); |
379 | } else { | 349 | } else { |
380 | dev_err(&pdev->dev, "SMBUS: Error: Host SMBus " | 350 | dev_err(&pdev->dev, "SMBUS: Error: Host SMBus " |
@@ -384,16 +354,6 @@ found: | |||
384 | } | 354 | } |
385 | } | 355 | } |
386 | 356 | ||
387 | if ((temp & 0x0E) == 8) | ||
388 | dev_dbg(&pdev->dev, "using Interrupt 9 for SMBus.\n"); | ||
389 | else if ((temp & 0x0E) == 0) | ||
390 | dev_dbg(&pdev->dev, "using Interrupt SMI# for SMBus.\n"); | ||
391 | else | ||
392 | dev_dbg(&pdev->dev, "Illegal Interrupt configuration " | ||
393 | "(or code out of date)!\n"); | ||
394 | |||
395 | pci_read_config_byte(pdev, SMBREV, &temp); | ||
396 | dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp); | ||
397 | dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba); | 357 | dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba); |
398 | 358 | ||
399 | switch (pdev->device) { | 359 | switch (pdev->device) { |