forked from mirrors/linux
		
	hwmon: (lm80) Add detection of NatSemi/TI LM96080
Add detection of the National Semiconductor (now Texas Instruments) LM96080. It is functionally compatible with the LM80 but detection is completely different. Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: Frans Meulenbroeks <fransmeulenbroeks@gmail.com> Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
This commit is contained in:
		
							parent
							
								
									0e190b7fa3
								
							
						
					
					
						commit
						9908ad4cd4
					
				
					 3 changed files with 45 additions and 12 deletions
				
			
		| 
						 | 
					@ -7,6 +7,11 @@ Supported chips:
 | 
				
			||||||
    Addresses scanned: I2C 0x28 - 0x2f
 | 
					    Addresses scanned: I2C 0x28 - 0x2f
 | 
				
			||||||
    Datasheet: Publicly available at the National Semiconductor website
 | 
					    Datasheet: Publicly available at the National Semiconductor website
 | 
				
			||||||
               http://www.national.com/
 | 
					               http://www.national.com/
 | 
				
			||||||
 | 
					  * National Semiconductor LM96080
 | 
				
			||||||
 | 
					    Prefix: 'lm96080'
 | 
				
			||||||
 | 
					    Addresses scanned: I2C 0x28 - 0x2f
 | 
				
			||||||
 | 
					    Datasheet: Publicly available at the National Semiconductor website
 | 
				
			||||||
 | 
					               http://www.national.com/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Authors:
 | 
					Authors:
 | 
				
			||||||
        Frodo Looijaard <frodol@dds.nl>,
 | 
					        Frodo Looijaard <frodol@dds.nl>,
 | 
				
			||||||
| 
						 | 
					@ -17,7 +22,9 @@ Description
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This driver implements support for the National Semiconductor LM80.
 | 
					This driver implements support for the National Semiconductor LM80.
 | 
				
			||||||
It is described as a 'Serial Interface ACPI-Compatible Microprocessor
 | 
					It is described as a 'Serial Interface ACPI-Compatible Microprocessor
 | 
				
			||||||
System Hardware Monitor'.
 | 
					System Hardware Monitor'. The LM96080 is a more recent incarnation,
 | 
				
			||||||
 | 
					it is pin and register compatible, with a few additional features not
 | 
				
			||||||
 | 
					yet supported by the driver.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The LM80 implements one temperature sensor, two fan rotation speed sensors,
 | 
					The LM80 implements one temperature sensor, two fan rotation speed sensors,
 | 
				
			||||||
seven voltage sensors, alarms, and some miscellaneous stuff.
 | 
					seven voltage sensors, alarms, and some miscellaneous stuff.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -598,11 +598,11 @@ config SENSORS_LM78
 | 
				
			||||||
	  will be called lm78.
 | 
						  will be called lm78.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config SENSORS_LM80
 | 
					config SENSORS_LM80
 | 
				
			||||||
	tristate "National Semiconductor LM80"
 | 
						tristate "National Semiconductor LM80 and LM96080"
 | 
				
			||||||
	depends on I2C
 | 
						depends on I2C
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  If you say yes here you get support for National Semiconductor
 | 
						  If you say yes here you get support for National Semiconductor
 | 
				
			||||||
	  LM80 sensor chips.
 | 
						  LM80 and LM96080 sensor chips.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  This driver can also be built as a module.  If so, the module
 | 
						  This driver can also be built as a module.  If so, the module
 | 
				
			||||||
	  will be called lm80.
 | 
						  will be called lm80.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,6 +60,10 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
 | 
				
			||||||
#define LM80_REG_FANDIV			0x05
 | 
					#define LM80_REG_FANDIV			0x05
 | 
				
			||||||
#define LM80_REG_RES			0x06
 | 
					#define LM80_REG_RES			0x06
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LM96080_REG_CONV_RATE		0x07
 | 
				
			||||||
 | 
					#define LM96080_REG_MAN_ID		0x3e
 | 
				
			||||||
 | 
					#define LM96080_REG_DEV_ID		0x3f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Conversions. Rounding and limit checking is only done on the TO_REG
 | 
					 * Conversions. Rounding and limit checking is only done on the TO_REG
 | 
				
			||||||
| 
						 | 
					@ -147,6 +151,7 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct i2c_device_id lm80_id[] = {
 | 
					static const struct i2c_device_id lm80_id[] = {
 | 
				
			||||||
	{ "lm80", 0 },
 | 
						{ "lm80", 0 },
 | 
				
			||||||
 | 
						{ "lm96080", 1 },
 | 
				
			||||||
	{ }
 | 
						{ }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
MODULE_DEVICE_TABLE(i2c, lm80_id);
 | 
					MODULE_DEVICE_TABLE(i2c, lm80_id);
 | 
				
			||||||
| 
						 | 
					@ -490,14 +495,32 @@ static const struct attribute_group lm80_group = {
 | 
				
			||||||
static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info)
 | 
					static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct i2c_adapter *adapter = client->adapter;
 | 
						struct i2c_adapter *adapter = client->adapter;
 | 
				
			||||||
	int i, cur;
 | 
						int i, cur, man_id, dev_id;
 | 
				
			||||||
 | 
						const char *name = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 | 
						if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Now, we do the remaining detection. It is lousy. */
 | 
						/* First check for unused bits, common to both chip types */
 | 
				
			||||||
	if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0)
 | 
						if ((lm80_read_value(client, LM80_REG_ALARM2) & 0xc0)
 | 
				
			||||||
 | 
						 || (lm80_read_value(client, LM80_REG_CONFIG) & 0x80))
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * The LM96080 has manufacturer and stepping/die rev registers so we
 | 
				
			||||||
 | 
						 * can just check that. The LM80 does not have such registers so we
 | 
				
			||||||
 | 
						 * have to use a more expensive trick.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						man_id = lm80_read_value(client, LM96080_REG_MAN_ID);
 | 
				
			||||||
 | 
						dev_id = lm80_read_value(client, LM96080_REG_DEV_ID);
 | 
				
			||||||
 | 
						if (man_id == 0x01 && dev_id == 0x08) {
 | 
				
			||||||
 | 
							/* Check more unused bits for confirmation */
 | 
				
			||||||
 | 
							if (lm80_read_value(client, LM96080_REG_CONV_RATE) & 0xfe)
 | 
				
			||||||
 | 
								return -ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							name = "lm96080";
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* Check 6-bit addressing */
 | 
				
			||||||
		for (i = 0x2a; i <= 0x3d; i++) {
 | 
							for (i = 0x2a; i <= 0x3d; i++) {
 | 
				
			||||||
			cur = i2c_smbus_read_byte_data(client, i);
 | 
								cur = i2c_smbus_read_byte_data(client, i);
 | 
				
			||||||
			if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur)
 | 
								if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur)
 | 
				
			||||||
| 
						 | 
					@ -506,7 +529,10 @@ static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info)
 | 
				
			||||||
				return -ENODEV;
 | 
									return -ENODEV;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	strlcpy(info->type, "lm80", I2C_NAME_SIZE);
 | 
							name = "lm80";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strlcpy(info->type, name, I2C_NAME_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue