Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 310eb776 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pyll hwmon fixes from Guenter Roeck:
 "Two patches: Fix build warning in ads1015 driver, and fix bogus power
  values with current BIOSes in fam15h_power driver."

* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
  hwmon: (ads1015) Fix build warning
  hwmon: fam15h_power: fix bogus values with current BIOSes
parents 277b5fb3 1196573f
Loading
Loading
Loading
Loading
+16 −17
Original line number Original line Diff line number Diff line
@@ -59,14 +59,11 @@ struct ads1015_data {
	struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
	struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
};
};


static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
static int ads1015_read_adc(struct i2c_client *client, unsigned int channel)
			      int *value)
{
{
	u16 config;
	u16 config;
	s16 conversion;
	struct ads1015_data *data = i2c_get_clientdata(client);
	struct ads1015_data *data = i2c_get_clientdata(client);
	unsigned int pga = data->channel_data[channel].pga;
	unsigned int pga = data->channel_data[channel].pga;
	int fullscale;
	unsigned int data_rate = data->channel_data[channel].data_rate;
	unsigned int data_rate = data->channel_data[channel].data_rate;
	unsigned int conversion_time_ms;
	unsigned int conversion_time_ms;
	int res;
	int res;
@@ -78,7 +75,6 @@ static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
	if (res < 0)
	if (res < 0)
		goto err_unlock;
		goto err_unlock;
	config = res;
	config = res;
	fullscale = fullscale_table[pga];
	conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]);
	conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]);


	/* setup and start single conversion */
	/* setup and start single conversion */
@@ -105,33 +101,36 @@ static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
	}
	}


	res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION);
	res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION);
	if (res < 0)
		goto err_unlock;
	conversion = res;

	mutex_unlock(&data->update_lock);

	*value = DIV_ROUND_CLOSEST(conversion * fullscale, 0x7ff0);

	return 0;


err_unlock:
err_unlock:
	mutex_unlock(&data->update_lock);
	mutex_unlock(&data->update_lock);
	return res;
	return res;
}
}


static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel,
			     s16 reg)
{
	struct ads1015_data *data = i2c_get_clientdata(client);
	unsigned int pga = data->channel_data[channel].pga;
	int fullscale = fullscale_table[pga];

	return DIV_ROUND_CLOSEST(reg * fullscale, 0x7ff0);
}

/* sysfs callback function */
/* sysfs callback function */
static ssize_t show_in(struct device *dev, struct device_attribute *da,
static ssize_t show_in(struct device *dev, struct device_attribute *da,
	char *buf)
	char *buf)
{
{
	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
	struct i2c_client *client = to_i2c_client(dev);
	struct i2c_client *client = to_i2c_client(dev);
	int in;
	int res;
	int res;
	int index = attr->index;


	res = ads1015_read_value(client, attr->index, &in);
	res = ads1015_read_adc(client, index);
	if (res < 0)
		return res;


	return (res < 0) ? res : sprintf(buf, "%d\n", in);
	return sprintf(buf, "%d\n", ads1015_reg_to_mv(client, index, res));
}
}


static const struct sensor_device_attribute ads1015_in[] = {
static const struct sensor_device_attribute ads1015_in[] = {
+39 −0
Original line number Original line Diff line number Diff line
@@ -122,6 +122,38 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
	return true;
	return true;
}
}


/*
 * Newer BKDG versions have an updated recommendation on how to properly
 * initialize the running average range (was: 0xE, now: 0x9). This avoids
 * counter saturations resulting in bogus power readings.
 * We correct this value ourselves to cope with older BIOSes.
 */
static void __devinit tweak_runavg_range(struct pci_dev *pdev)
{
	u32 val;
	const struct pci_device_id affected_device = {
		PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) };

	/*
	 * let this quirk apply only to the current version of the
	 * northbridge, since future versions may change the behavior
	 */
	if (!pci_match_id(&affected_device, pdev))
		return;

	pci_bus_read_config_dword(pdev->bus,
		PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
		REG_TDP_RUNNING_AVERAGE, &val);
	if ((val & 0xf) != 0xe)
		return;

	val &= ~0xf;
	val |=  0x9;
	pci_bus_write_config_dword(pdev->bus,
		PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
		REG_TDP_RUNNING_AVERAGE, val);
}

static void __devinit fam15h_power_init_data(struct pci_dev *f4,
static void __devinit fam15h_power_init_data(struct pci_dev *f4,
					     struct fam15h_power_data *data)
					     struct fam15h_power_data *data)
{
{
@@ -155,6 +187,13 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev,
	struct device *dev;
	struct device *dev;
	int err;
	int err;


	/*
	 * though we ignore every other northbridge, we still have to
	 * do the tweaking on _each_ node in MCM processors as the counters
	 * are working hand-in-hand
	 */
	tweak_runavg_range(pdev);

	if (!fam15h_power_is_internal_node0(pdev)) {
	if (!fam15h_power_is_internal_node0(pdev)) {
		err = -ENODEV;
		err = -ENODEV;
		goto exit;
		goto exit;