aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorShane Huang <shane.huang@amd.com>2009-03-28 16:34:46 -0400
committerJean Delvare <khali@linux-fr.org>2009-03-28 16:34:46 -0400
commit87e1960e93fe792c4f4344a6f3a970f9573c76aa (patch)
treef639de840f26b45f395ec7ef2c8e92f2935a37a4 /drivers/i2c
parent6b110d13aacc9c4ef5f01af12a5e2b7f1d23f106 (diff)
i2c-piix4: Add support to SB800 SMBus changes
Add support for the AMD SB800 Family series of products. Major changes include the changes to addressing the SMBus registers at different location from the locations in the previous compatible parts from AMD such as SB400/SB600/SB700. For SB800, the main features and register definitions of SMBus and other interfaces are still compatible with the previous products with the only change being in how to access the internal registers for these blocks. Signed-off-by: Shane Huang <shane.huang@amd.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-piix4.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 761f9dd53620..63d5e5978046 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -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;
@@ -433,7 +497,14 @@ static int __devinit piix4_probe(struct pci_dev *dev,
433{ 497{
434 int retval; 498 int retval;
435 499
436 retval = piix4_setup(dev, id); 500 if ((dev->vendor == PCI_VENDOR_ID_ATI) &&
501 (dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS) &&
502 (dev->revision >= 0x40))
503 /* base address location etc changed in SB800 */
504 retval = piix4_setup_sb800(dev, id);
505 else
506 retval = piix4_setup(dev, id);
507
437 if (retval) 508 if (retval)
438 return retval; 509 return retval;
439 510