aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-piix4.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-piix4.c')
-rw-r--r--drivers/i2c/busses/i2c-piix4.c77
1 files changed, 75 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 761f9dd53620..0249a7d762b9 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -20,7 +20,7 @@
20/* 20/*
21 Supports: 21 Supports:
22 Intel PIIX4, 440MX 22 Intel PIIX4, 440MX
23 Serverworks OSB4, CSB5, CSB6, HT-1000 23 Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
24 ATI IXP200, IXP300, IXP400, SB600, SB700, SB800 24 ATI IXP200, IXP300, IXP400, SB600, SB700, SB800
25 SMSC Victory66 25 SMSC Victory66
26 26
@@ -226,6 +226,70 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
226 return 0; 226 return 0;
227} 227}
228 228
229static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
230 const struct pci_device_id *id)
231{
232 unsigned short smba_idx = 0xcd6;
233 u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c;
234
235 /* SB800 SMBus does not support forcing address */
236 if (force || force_addr) {
237 dev_err(&PIIX4_dev->dev, "SB800 SMBus does not support "
238 "forcing address!\n");
239 return -EINVAL;
240 }
241
242 /* Determine the address of the SMBus areas */
243 if (!request_region(smba_idx, 2, "smba_idx")) {
244 dev_err(&PIIX4_dev->dev, "SMBus base address index region "
245 "0x%x already in use!\n", smba_idx);
246 return -EBUSY;
247 }
248 outb_p(smb_en, smba_idx);
249 smba_en_lo = inb_p(smba_idx + 1);
250 outb_p(smb_en + 1, smba_idx);
251 smba_en_hi = inb_p(smba_idx + 1);
252 release_region(smba_idx, 2);
253
254 if ((smba_en_lo & 1) == 0) {
255 dev_err(&PIIX4_dev->dev,
256 "Host SMBus controller not enabled!\n");
257 return -ENODEV;
258 }
259
260 piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
261 if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
262 return -EBUSY;
263
264 if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
265 dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
266 piix4_smba);
267 return -EBUSY;
268 }
269
270 /* Request the SMBus I2C bus config region */
271 if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) {
272 dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region "
273 "0x%x already in use!\n", piix4_smba + i2ccfg_offset);
274 release_region(piix4_smba, SMBIOSIZE);
275 piix4_smba = 0;
276 return -EBUSY;
277 }
278 i2ccfg = inb_p(piix4_smba + i2ccfg_offset);
279 release_region(piix4_smba + i2ccfg_offset, 1);
280
281 if (i2ccfg & 1)
282 dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus.\n");
283 else
284 dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus.\n");
285
286 dev_info(&PIIX4_dev->dev,
287 "SMBus Host Controller at 0x%x, revision %d\n",
288 piix4_smba, i2ccfg >> 4);
289
290 return 0;
291}
292
229static int piix4_transaction(void) 293static int piix4_transaction(void)
230{ 294{
231 int temp; 295 int temp;
@@ -423,6 +487,8 @@ static struct pci_device_id piix4_ids[] = {
423 PCI_DEVICE_ID_SERVERWORKS_CSB6) }, 487 PCI_DEVICE_ID_SERVERWORKS_CSB6) },
424 { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, 488 { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
425 PCI_DEVICE_ID_SERVERWORKS_HT1000SB) }, 489 PCI_DEVICE_ID_SERVERWORKS_HT1000SB) },
490 { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
491 PCI_DEVICE_ID_SERVERWORKS_HT1100LD) },
426 { 0, } 492 { 0, }
427}; 493};
428 494
@@ -433,7 +499,14 @@ static int __devinit piix4_probe(struct pci_dev *dev,
433{ 499{
434 int retval; 500 int retval;
435 501
436 retval = piix4_setup(dev, id); 502 if ((dev->vendor == PCI_VENDOR_ID_ATI) &&
503 (dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS) &&
504 (dev->revision >= 0x40))
505 /* base address location etc changed in SB800 */
506 retval = piix4_setup_sb800(dev, id);
507 else
508 retval = piix4_setup(dev, id);
509
437 if (retval) 510 if (retval)
438 return retval; 511 return retval;
439 512