|
@@ -137,10 +137,11 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
|
|
|
};
|
|
|
|
|
|
/* SB800 globals */
|
|
|
+static DEFINE_MUTEX(piix4_mutex_sb800);
|
|
|
static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = {
|
|
|
- "SDA0", "SDA2", "SDA3", "SDA4"
|
|
|
+ " port 0", " port 2", " port 3", " port 4"
|
|
|
};
|
|
|
-static const char *piix4_aux_port_name_sb800 = "SDA1";
|
|
|
+static const char *piix4_aux_port_name_sb800 = " port 1";
|
|
|
|
|
|
struct i2c_piix4_adapdata {
|
|
|
unsigned short smba;
|
|
@@ -148,7 +149,6 @@ struct i2c_piix4_adapdata {
|
|
|
/* SB800 */
|
|
|
bool sb800_main;
|
|
|
unsigned short port;
|
|
|
- struct mutex *mutex;
|
|
|
};
|
|
|
|
|
|
static int piix4_setup(struct pci_dev *PIIX4_dev,
|
|
@@ -275,10 +275,12 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
|
|
|
else
|
|
|
smb_en = (aux) ? 0x28 : 0x2c;
|
|
|
|
|
|
+ mutex_lock(&piix4_mutex_sb800);
|
|
|
outb_p(smb_en, SB800_PIIX4_SMB_IDX);
|
|
|
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
|
|
|
outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
|
|
|
smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
|
|
|
+ mutex_unlock(&piix4_mutex_sb800);
|
|
|
|
|
|
if (!smb_en) {
|
|
|
smb_en_status = smba_en_lo & 0x10;
|
|
@@ -559,7 +561,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
|
|
|
u8 port;
|
|
|
int retval;
|
|
|
|
|
|
- mutex_lock(adapdata->mutex);
|
|
|
+ mutex_lock(&piix4_mutex_sb800);
|
|
|
|
|
|
outb_p(SB800_PIIX4_PORT_IDX, SB800_PIIX4_SMB_IDX);
|
|
|
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
|
|
@@ -574,7 +576,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
|
|
|
|
|
|
outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1);
|
|
|
|
|
|
- mutex_unlock(adapdata->mutex);
|
|
|
+ mutex_unlock(&piix4_mutex_sb800);
|
|
|
|
|
|
return retval;
|
|
|
}
|
|
@@ -625,6 +627,7 @@ static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS];
|
|
|
static struct i2c_adapter *piix4_aux_adapter;
|
|
|
|
|
|
static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
|
|
|
+ bool sb800_main, unsigned short port,
|
|
|
const char *name, struct i2c_adapter **padap)
|
|
|
{
|
|
|
struct i2c_adapter *adap;
|
|
@@ -639,7 +642,8 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
|
|
|
|
|
|
adap->owner = THIS_MODULE;
|
|
|
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
|
|
- adap->algo = &smbus_algorithm;
|
|
|
+ adap->algo = sb800_main ? &piix4_smbus_algorithm_sb800
|
|
|
+ : &smbus_algorithm;
|
|
|
|
|
|
adapdata = kzalloc(sizeof(*adapdata), GFP_KERNEL);
|
|
|
if (adapdata == NULL) {
|
|
@@ -649,12 +653,14 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
|
|
|
}
|
|
|
|
|
|
adapdata->smba = smba;
|
|
|
+ adapdata->sb800_main = sb800_main;
|
|
|
+ adapdata->port = port;
|
|
|
|
|
|
/* set up the sysfs linkage to our parent device */
|
|
|
adap->dev.parent = &dev->dev;
|
|
|
|
|
|
snprintf(adap->name, sizeof(adap->name),
|
|
|
- "SMBus PIIX4 adapter %s at %04x", name, smba);
|
|
|
+ "SMBus PIIX4 adapter%s at %04x", name, smba);
|
|
|
|
|
|
i2c_set_adapdata(adap, adapdata);
|
|
|
|
|
@@ -673,30 +679,16 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
|
|
|
|
|
|
static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba)
|
|
|
{
|
|
|
- struct mutex *mutex;
|
|
|
struct i2c_piix4_adapdata *adapdata;
|
|
|
int port;
|
|
|
int retval;
|
|
|
|
|
|
- mutex = kzalloc(sizeof(*mutex), GFP_KERNEL);
|
|
|
- if (mutex == NULL)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- mutex_init(mutex);
|
|
|
-
|
|
|
for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) {
|
|
|
- retval = piix4_add_adapter(dev, smba,
|
|
|
+ retval = piix4_add_adapter(dev, smba, true, port,
|
|
|
piix4_main_port_names_sb800[port],
|
|
|
&piix4_main_adapters[port]);
|
|
|
if (retval < 0)
|
|
|
goto error;
|
|
|
-
|
|
|
- piix4_main_adapters[port]->algo = &piix4_smbus_algorithm_sb800;
|
|
|
-
|
|
|
- adapdata = i2c_get_adapdata(piix4_main_adapters[port]);
|
|
|
- adapdata->sb800_main = true;
|
|
|
- adapdata->port = port;
|
|
|
- adapdata->mutex = mutex;
|
|
|
}
|
|
|
|
|
|
return retval;
|
|
@@ -714,19 +706,20 @@ error:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- kfree(mutex);
|
|
|
-
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|
|
{
|
|
|
int retval;
|
|
|
+ bool is_sb800 = false;
|
|
|
|
|
|
if ((dev->vendor == PCI_VENDOR_ID_ATI &&
|
|
|
dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
|
|
|
dev->revision >= 0x40) ||
|
|
|
dev->vendor == PCI_VENDOR_ID_AMD) {
|
|
|
+ is_sb800 = true;
|
|
|
+
|
|
|
if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) {
|
|
|
dev_err(&dev->dev,
|
|
|
"SMBus base address index region 0x%x already in use!\n",
|
|
@@ -756,7 +749,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|
|
return retval;
|
|
|
|
|
|
/* Try to register main SMBus adapter, give up if we can't */
|
|
|
- retval = piix4_add_adapter(dev, retval, "main",
|
|
|
+ retval = piix4_add_adapter(dev, retval, false, 0, "",
|
|
|
&piix4_main_adapters[0]);
|
|
|
if (retval < 0)
|
|
|
return retval;
|
|
@@ -783,7 +776,8 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|
|
if (retval > 0) {
|
|
|
/* Try to add the aux adapter if it exists,
|
|
|
* piix4_add_adapter will clean up if this fails */
|
|
|
- piix4_add_adapter(dev, retval, piix4_aux_port_name_sb800,
|
|
|
+ piix4_add_adapter(dev, retval, false, 0,
|
|
|
+ is_sb800 ? piix4_aux_port_name_sb800 : "",
|
|
|
&piix4_aux_adapter);
|
|
|
}
|
|
|
|
|
@@ -798,10 +792,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap)
|
|
|
i2c_del_adapter(adap);
|
|
|
if (adapdata->port == 0) {
|
|
|
release_region(adapdata->smba, SMBIOSIZE);
|
|
|
- if (adapdata->sb800_main) {
|
|
|
- kfree(adapdata->mutex);
|
|
|
+ if (adapdata->sb800_main)
|
|
|
release_region(SB800_PIIX4_SMB_IDX, 2);
|
|
|
- }
|
|
|
}
|
|
|
kfree(adapdata);
|
|
|
kfree(adap);
|