[PATCH] hwmon: (it87) Manage device specific features with table

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This simplifies the code, improves runtime performance, reduces
code size (about 300 bytes on x86_64), and makes it easier
to add support for new devices.

Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx>
---
This patch applies on top of the previously submitted patch series for it87.

 drivers/hwmon/it87.c |  217 ++++++++++++++++++++++++++------------------------
 1 file changed, 111 insertions(+), 106 deletions(-)

diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index e7b604c..560f9a9 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -61,8 +61,8 @@
 
 #define DRVNAME "it87"
 
-enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8782,
-	     it8783 };
+enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8726, it8728,
+	     it8782, it8783 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -228,6 +228,74 @@ static const u8 IT87_REG_FANX_MIN[]	= { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
 #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i))
 #define IT87_REG_AUTO_PWM(nr, i)  (0x65 + (nr) * 8 + (i))
 
+struct it87_devices {
+	const char * const name;
+	u16 id;
+	u16 features;
+};
+
+#define	FEAT_12MV_ADC		(1 << 0)
+#define	FEAT_NEWER_AUTOPWM	(1 << 1)
+#define	FEAT_OLD_AUTOPWM	(1 << 2)
+#define	FEAT_16BIT_FAN		(1 << 3)
+
+static const struct it87_devices it87_devices[] = {
+	[it87] = {
+		.name = "it87",
+		.id = IT8705F_DEVID,
+		.features = FEAT_OLD_AUTOPWM,	/* may need to override */
+	},
+	[it8712] = {
+		.name = "it8712",
+		.id = IT8712F_DEVID,
+		.features = FEAT_OLD_AUTOPWM,	/* may need to overwrite */
+	},
+	[it8716] = {
+		.name = "it8716",
+		.id = IT8716F_DEVID,
+		.features = FEAT_16BIT_FAN,
+	},
+	[it8718] = {
+		.name = "it8718",
+		.id = IT8718F_DEVID,
+		.features = FEAT_16BIT_FAN,
+	},
+	[it8720] = {
+		.name = "it8720",
+		.id = IT8720F_DEVID,
+		.features = FEAT_16BIT_FAN,
+	},
+	[it8721] = {
+		.name = "it8721",
+		.id = IT8721F_DEVID,
+		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FAN,
+	},
+	[it8726] = {
+		.name = "it8726",
+		.id = IT8726F_DEVID,
+		.features = FEAT_16BIT_FAN,
+	},
+	[it8728] = {
+		.name = "it8728",
+		.id = IT8728F_DEVID,
+		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FAN,
+	},
+	[it8782] = {
+		.name = "it8782",
+		.id = IT8782F_DEVID,
+		.features = FEAT_16BIT_FAN,
+	},
+	[it8783] = {
+		.name = "it8783",
+		.id = IT8783E_DEVID,
+		.features = FEAT_16BIT_FAN,
+	},
+};
+
+#define has_16bit_fans(data)	((data)->features & FEAT_16BIT_FAN)
+#define has_12mv_adc(data)	((data)->features & FEAT_12MV_ADC)
+#define has_newer_autopwm(data)	((data)->features & FEAT_NEWER_AUTOPWM)
+#define has_old_autopwm(data)	((data)->features & FEAT_OLD_AUTOPWM)
 
 struct it87_sio_data {
 	enum chips type;
@@ -251,8 +319,7 @@ struct it87_sio_data {
 struct it87_data {
 	struct device *hwmon_dev;
 	enum chips type;
-	bool has_16bit_fans;
-	u8 revision;
+	u32 features;
 
 	unsigned short addr;
 	const char *name;
@@ -294,26 +361,6 @@ struct it87_data {
 	s8 auto_temp[3][5];	/* [nr][0] is point1_temp_hyst */
 };
 
-static inline int has_12mv_adc(const struct it87_data *data)
-{
-	/*
-	 * IT8721F and later have a 12 mV ADC, also with internal scaling
-	 * on selected inputs.
-	 */
-	return data->type == it8721
-	    || data->type == it8728;
-}
-
-static inline int has_newer_autopwm(const struct it87_data *data)
-{
-	/*
-	 * IT8721F and later have separate registers for the temperature
-	 * mapping and the manual duty cycle.
-	 */
-	return data->type == it8721
-	    || data->type == it8728;
-}
-
 static int adc_lsb(const struct it87_data *data, int nr)
 {
 	int lsb = has_12mv_adc(data) ? 12 : 16;
@@ -396,35 +443,6 @@ static const unsigned int pwm_freq[8] = {
 	750000 / 128,
 };
 
-static inline int has_16bit_fans(const struct it87_data *data)
-{
-	/*
-	 * IT8705F Datasheet 0.4.1, 3h == Version G.
-	 * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
-	 * These are the first revisions with 16-bit tachometer support.
-	 */
-	return (data->type == it87 && data->revision >= 0x03)
-	    || (data->type == it8712 && data->revision >= 0x08)
-	    || data->type == it8716
-	    || data->type == it8718
-	    || data->type == it8720
-	    || data->type == it8721
-	    || data->type == it8728
-	    || data->type == it8782
-	    || data->type == it8783;
-}
-
-static inline int has_old_autopwm(const struct it87_data *data)
-{
-	/*
-	 * The old automatic fan speed control interface is implemented
-	 * by IT8705F chips up to revision F and IT8712F chips up to
-	 * revision G.
-	 */
-	return (data->type == it87 && data->revision < 0x03)
-	    || (data->type == it8712 && data->revision < 0x08);
-}
-
 static int it87_probe(struct platform_device *pdev);
 static int __devexit it87_remove(struct platform_device *pdev);
 
@@ -642,7 +660,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
 	int speed;
 	struct it87_data *data = it87_update_device(dev);
 
-	speed = data->has_16bit_fans ?
+	speed = has_16bit_fans(data) ?
 		FAN16_FROM_REG(data->fan[nr][index]) :
 		FAN_FROM_REG(data->fan[nr][index],
 			     DIV_FROM_REG(data->fan_div[nr]));
@@ -702,7 +720,7 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
 
 	mutex_lock(&data->update_lock);
 
-	if (!data->has_16bit_fans) {
+	if (!has_16bit_fans(data)) {
 		reg = it87_read_value(data, IT87_REG_FAN_DIV);
 		switch (nr) {
 		case 0:
@@ -1576,7 +1594,7 @@ static const struct attribute_group it87_group_label = {
 static int __init it87_find(unsigned short *address,
 	struct it87_sio_data *sio_data)
 {
-	int err;
+	int i, err;
 	u16 chip_type;
 	const char *board_vendor, *board_name;
 
@@ -1587,38 +1605,16 @@ static int __init it87_find(unsigned short *address,
 	err = -ENODEV;
 	chip_type = force_id ? force_id : superio_inw(DEVID);
 
-	switch (chip_type) {
-	case IT8705F_DEVID:
-		sio_data->type = it87;
-		break;
-	case IT8712F_DEVID:
-		sio_data->type = it8712;
-		break;
-	case IT8716F_DEVID:
-	case IT8726F_DEVID:
-		sio_data->type = it8716;
-		break;
-	case IT8718F_DEVID:
-		sio_data->type = it8718;
-		break;
-	case IT8720F_DEVID:
-		sio_data->type = it8720;
-		break;
-	case IT8721F_DEVID:
-		sio_data->type = it8721;
-		break;
-	case IT8728F_DEVID:
-		sio_data->type = it8728;
-		break;
-	case IT8782F_DEVID:
-		sio_data->type = it8782;
-		break;
-	case IT8783E_DEVID:
-		sio_data->type = it8783;
-		break;
-	case 0xffff:	/* No device at all */
+	if (chip_type == 0xffff)
 		goto exit;
-	default:
+
+	for (i = 0; i < ARRAY_SIZE(it87_devices); i++) {
+		if (chip_type == it87_devices[i].id) {
+			sio_data->type = i;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(it87_devices)) {
 		pr_debug("Unsupported chip (DEVID=0x%x)\n", chip_type);
 		goto exit;
 	}
@@ -1860,7 +1856,7 @@ static void it87_remove_files(struct device *dev)
 		if (sio_data->beep_pin)
 			sysfs_remove_file(&dev->kobj,
 					  it87_attributes_fan_beep[i]);
-		if (i < 3 && !data->has_16bit_fans)
+		if (i < 3 && !has_16bit_fans(data))
 			sysfs_remove_file(&dev->kobj,
 					  it87_attributes_fan_div[i]);
 	}
@@ -1886,17 +1882,6 @@ static int __devinit it87_probe(struct platform_device *pdev)
 	int err = 0, i;
 	int enable_pwm_interface;
 	int fan_beep_need_rw;
-	static const char * const names[] = {
-		"it87",
-		"it8712",
-		"it8716",
-		"it8718",
-		"it8720",
-		"it8721",
-		"it8728",
-		"it8782",
-		"it8783",
-	};
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT,
@@ -1913,8 +1898,29 @@ static int __devinit it87_probe(struct platform_device *pdev)
 
 	data->addr = res->start;
 	data->type = sio_data->type;
-	data->revision = sio_data->revision;
-	data->name = names[sio_data->type];
+	data->features = it87_devices[data->type].features;
+	data->name = it87_devices[sio_data->type].name;
+	/*
+	 * IT8705F Datasheet 0.4.1, 3h == Version G.
+	 * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
+	 * These are the first revisions with 16-bit tachometer support.
+	 */
+	switch (data->type) {
+	case it87:
+		if (sio_data->revision >= 0x03) {
+			data->features &= ~FEAT_OLD_AUTOPWM;
+			data->features |= FEAT_16BIT_FAN;
+		}
+		break;
+	case it8712:
+		if (sio_data->revision >= 0x08) {
+			data->features &= ~FEAT_OLD_AUTOPWM;
+			data->features |= FEAT_16BIT_FAN;
+		}
+		break;
+	default:
+		break;
+	}
 
 	/* Now, we do the remaining detection. */
 	if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80)
@@ -1995,7 +2001,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
 		if (err)
 			goto error;
 
-		if (i < 3 && !data->has_16bit_fans) {
+		if (i < 3 && !has_16bit_fans(data)) {
 			err = sysfs_create_file(&dev->kobj,
 						it87_attributes_fan_div[i]);
 			if (err)
@@ -2232,10 +2238,9 @@ static void __devinit it87_init_device(struct platform_device *pdev)
 				 data->fan_main_ctrl);
 	}
 	data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
-	data->has_16bit_fans = has_16bit_fans(data);
 
 	/* Set tachometers to 16-bit mode if needed */
-	if (data->has_16bit_fans) {
+	if (has_16bit_fans(data)) {
 		tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
 		if (~tmp & 0x07 & data->has_fan) {
 			dev_dbg(&pdev->dev,
@@ -2326,7 +2331,7 @@ static struct it87_data *it87_update_device(struct device *dev)
 			data->fan[i][0] = it87_read_value(data,
 				       IT87_REG_FAN[i]);
 			/* Add high byte if in 16-bit mode */
-			if (data->has_16bit_fans) {
+			if (has_16bit_fans(data)) {
 				data->fan[i][0] |= it87_read_value(data,
 						IT87_REG_FANX[i]) << 8;
 				data->fan[i][1] |= it87_read_value(data,
@@ -2347,7 +2352,7 @@ static struct it87_data *it87_update_device(struct device *dev)
 		}
 
 		/* Newer chips don't have clock dividers */
-		if ((data->has_fan & 0x07) && !data->has_16bit_fans) {
+		if ((data->has_fan & 0x07) && !has_16bit_fans(data)) {
 			i = it87_read_value(data, IT87_REG_FAN_DIV);
 			data->fan_div[0] = i & 0x07;
 			data->fan_div[1] = (i >> 3) & 0x07;
-- 
1.7.9.7


_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors


[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux