diff options
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 121 |
1 files changed, 55 insertions, 66 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 94a30f5de776..3e0d04d5a800 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -68,7 +68,6 @@ | |||
68 | /* PCI Address Constants */ | 68 | /* PCI Address Constants */ |
69 | #define SMBBAR 4 | 69 | #define SMBBAR 4 |
70 | #define SMBHSTCFG 0x040 | 70 | #define SMBHSTCFG 0x040 |
71 | #define SMBREV 0x008 | ||
72 | 71 | ||
73 | /* Host configuration bits for SMBHSTCFG */ | 72 | /* Host configuration bits for SMBHSTCFG */ |
74 | #define SMBHSTCFG_HST_EN 1 | 73 | #define SMBHSTCFG_HST_EN 1 |
@@ -102,68 +101,6 @@ static struct pci_driver i801_driver; | |||
102 | static struct pci_dev *I801_dev; | 101 | static struct pci_dev *I801_dev; |
103 | static int isich4; | 102 | static int isich4; |
104 | 103 | ||
105 | static int __devinit i801_setup(struct pci_dev *dev) | ||
106 | { | ||
107 | unsigned char temp; | ||
108 | int err; | ||
109 | |||
110 | I801_dev = dev; | ||
111 | if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || | ||
112 | (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || | ||
113 | (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) | ||
114 | isich4 = 1; | ||
115 | else | ||
116 | isich4 = 0; | ||
117 | |||
118 | err = pci_enable_device(dev); | ||
119 | if (err) { | ||
120 | dev_err(&dev->dev, "Failed to enable SMBus device (%d)\n", | ||
121 | err); | ||
122 | goto exit; | ||
123 | } | ||
124 | |||
125 | /* Determine the address of the SMBus area */ | ||
126 | i801_smba = pci_resource_start(dev, SMBBAR); | ||
127 | if (!i801_smba) { | ||
128 | dev_err(&dev->dev, "SMBus base address uninitialized, " | ||
129 | "upgrade BIOS\n"); | ||
130 | err = -ENODEV; | ||
131 | goto exit_disable; | ||
132 | } | ||
133 | |||
134 | err = pci_request_region(dev, SMBBAR, i801_driver.name); | ||
135 | if (err) { | ||
136 | dev_err(&dev->dev, "Failed to request SMBus region " | ||
137 | "0x%lx-0x%lx\n", i801_smba, | ||
138 | pci_resource_end(dev, SMBBAR)); | ||
139 | goto exit_disable; | ||
140 | } | ||
141 | |||
142 | pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); | ||
143 | temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ | ||
144 | if (!(temp & SMBHSTCFG_HST_EN)) { | ||
145 | dev_warn(&dev->dev, "enabling SMBus device\n"); | ||
146 | temp |= SMBHSTCFG_HST_EN; | ||
147 | } | ||
148 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp); | ||
149 | |||
150 | if (temp & SMBHSTCFG_SMB_SMI_EN) | ||
151 | dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n"); | ||
152 | else | ||
153 | dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n"); | ||
154 | |||
155 | pci_read_config_byte(I801_dev, SMBREV, &temp); | ||
156 | dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); | ||
157 | dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba); | ||
158 | |||
159 | return 0; | ||
160 | |||
161 | exit_disable: | ||
162 | pci_disable_device(dev); | ||
163 | exit: | ||
164 | return err; | ||
165 | } | ||
166 | |||
167 | static int i801_transaction(void) | 104 | static int i801_transaction(void) |
168 | { | 105 | { |
169 | int temp; | 106 | int temp; |
@@ -527,17 +464,69 @@ MODULE_DEVICE_TABLE (pci, i801_ids); | |||
527 | 464 | ||
528 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) | 465 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) |
529 | { | 466 | { |
467 | unsigned char temp; | ||
530 | int err; | 468 | int err; |
531 | 469 | ||
532 | if ((err = i801_setup(dev))) | 470 | I801_dev = dev; |
533 | return err; | 471 | if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || |
472 | (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || | ||
473 | (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) | ||
474 | isich4 = 1; | ||
475 | else | ||
476 | isich4 = 0; | ||
477 | |||
478 | err = pci_enable_device(dev); | ||
479 | if (err) { | ||
480 | dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n", | ||
481 | err); | ||
482 | goto exit; | ||
483 | } | ||
484 | |||
485 | /* Determine the address of the SMBus area */ | ||
486 | i801_smba = pci_resource_start(dev, SMBBAR); | ||
487 | if (!i801_smba) { | ||
488 | dev_err(&dev->dev, "SMBus base address uninitialized, " | ||
489 | "upgrade BIOS\n"); | ||
490 | err = -ENODEV; | ||
491 | goto exit_disable; | ||
492 | } | ||
493 | |||
494 | err = pci_request_region(dev, SMBBAR, i801_driver.name); | ||
495 | if (err) { | ||
496 | dev_err(&dev->dev, "Failed to request SMBus region " | ||
497 | "0x%lx-0x%lx\n", i801_smba, | ||
498 | pci_resource_end(dev, SMBBAR)); | ||
499 | goto exit_disable; | ||
500 | } | ||
501 | |||
502 | pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); | ||
503 | temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ | ||
504 | if (!(temp & SMBHSTCFG_HST_EN)) { | ||
505 | dev_info(&dev->dev, "Enabling SMBus device\n"); | ||
506 | temp |= SMBHSTCFG_HST_EN; | ||
507 | } | ||
508 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp); | ||
509 | |||
510 | if (temp & SMBHSTCFG_SMB_SMI_EN) | ||
511 | dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); | ||
512 | else | ||
513 | dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n"); | ||
534 | 514 | ||
535 | /* set up the driverfs linkage to our parent device */ | 515 | /* set up the driverfs linkage to our parent device */ |
536 | i801_adapter.dev.parent = &dev->dev; | 516 | i801_adapter.dev.parent = &dev->dev; |
537 | 517 | ||
538 | snprintf(i801_adapter.name, I2C_NAME_SIZE, | 518 | snprintf(i801_adapter.name, I2C_NAME_SIZE, |
539 | "SMBus I801 adapter at %04lx", i801_smba); | 519 | "SMBus I801 adapter at %04lx", i801_smba); |
540 | return i2c_add_adapter(&i801_adapter); | 520 | err = i2c_add_adapter(&i801_adapter); |
521 | if (err) { | ||
522 | dev_err(&dev->dev, "Failed to add SMBus adapter\n"); | ||
523 | goto exit_disable; | ||
524 | } | ||
525 | |||
526 | exit_disable: | ||
527 | pci_disable_device(dev); | ||
528 | exit: | ||
529 | return err; | ||
541 | } | 530 | } |
542 | 531 | ||
543 | static void __devexit i801_remove(struct pci_dev *dev) | 532 | static void __devexit i801_remove(struct pci_dev *dev) |