// SPDX-License-Identifier: GPL-2.0-or-later /* Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>
*/
/* Note: we assume there can only be one SIS5595 with one SMBus interface */
/* Note: all have mfr. ID 0x1039. SUPPORTED PCI ID 5595 0008
Note: these chips contain a 0008 device which is incompatible with the 5595. We recognize these by the presence of the listed "blacklist" PCI ID and refuse to load.
staticint blacklist[] = {
PCI_DEVICE_ID_SI_540,
PCI_DEVICE_ID_SI_550,
PCI_DEVICE_ID_SI_630,
PCI_DEVICE_ID_SI_645,
PCI_DEVICE_ID_SI_646,
PCI_DEVICE_ID_SI_648,
PCI_DEVICE_ID_SI_650,
PCI_DEVICE_ID_SI_651,
PCI_DEVICE_ID_SI_730,
PCI_DEVICE_ID_SI_735,
PCI_DEVICE_ID_SI_745,
PCI_DEVICE_ID_SI_746,
PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but that ID shows up in other chips so we use the 5511
ID for recognition */
PCI_DEVICE_ID_SI_5597,
PCI_DEVICE_ID_SI_5598,
0, /* terminates the list */
};
/* If force_addr is set to anything different from 0, we forcibly enable
the device at the given address. */ static u16 force_addr;
module_param_hw(force_addr, ushort, ioport, 0);
MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
staticint sis5595_setup(struct pci_dev *SIS5595_dev)
{
u16 a;
u8 val; int *i; int retval;
/* Look for imposters */ for (i = blacklist; *i != 0; i++) { struct pci_dev *dev;
dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL); if (dev) {
dev_err(&SIS5595_dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i);
pci_dev_put(dev); return -ENODEV;
}
}
/* Determine the address of the SMBus areas */
pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base); if (sis5595_base == 0 && force_addr == 0) {
dev_err(&SIS5595_dev->dev, "ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); return -ENODEV;
}
if (force_addr)
sis5595_base = force_addr & ~(SIS5595_EXTENT - 1);
dev_dbg(&SIS5595_dev->dev, "ACPI Base address: %04x\n", sis5595_base);
/* NB: We grab just the two SMBus registers here, but this may still
* interfere with ACPI :-( */
retval = acpi_check_region(sis5595_base + SMB_INDEX, 2,
sis5595_driver.name); if (retval) return retval;
/* start the transaction by setting bit 4 */
sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
/* We will always wait for a fraction of a second! */ do {
msleep(1);
temp = sis5595_read(SMB_STS_LO);
} while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
if (temp & 0x10) {
dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
result = -ENXIO;
}
if (temp & 0x20) {
dev_err(&adap->dev, "Bus collision! SMBus may be locked until " "next hard reset (or not...)\n"); /* Clock stops and target is stuck in mid-transmission */
result = -EIO;
}
temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); if (temp != 0x00)
dev_dbg(&adap->dev, "Failed reset at end of transaction (%02x)\n", temp);
return result;
}
/* Return negative errno on error. */ static s32 sis5595_access(struct i2c_adapter *adap, u16 addr, unsignedshort flags, char read_write,
u8 command, int size, union i2c_smbus_data *data)
{ int status;
/* Always return failure here. This is to allow other drivers to bind * to this pci device. We don't really want to have control over the * pci device, we only wanted to read as few register values from it.
*/
sis5595_pdev = pci_dev_get(dev); return -ENODEV;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.