Source
x
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* emc6w201.c - Hardware monitoring driver for the SMSC EMC6W201
* Copyright (C) 2011 Jean Delvare <jdelvare@suse.de>
*/
/*
* Addresses to scan
*/
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
/*
* The EMC6W201 registers
*/
enum subfeature { input, min, max };
/*
* Per-device data
*/
struct emc6w201_data {
struct i2c_client *client;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
/* registers values */
u8 in[3][6];
s8 temp[3][6];
u16 fan[2][5];
};
/*
* Combine LSB and MSB registers in a single value
* Locking: must be called with data->update_lock held
*/
static u16 emc6w201_read16(struct i2c_client *client, u8 reg)
{
int lsb, msb;
lsb = i2c_smbus_read_byte_data(client, reg);
msb = i2c_smbus_read_byte_data(client, reg + 1);
if (unlikely(lsb < 0 || msb < 0)) {
dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
16, "read", reg);
return 0xFFFF; /* Arbitrary value */
}
return (msb << 8) | lsb;
}
/*
* Write 16-bit value to LSB and MSB registers
* Locking: must be called with data->update_lock held
*/
static int emc6w201_write16(struct i2c_client *client, u8 reg, u16 val)
{
int err;
err = i2c_smbus_write_byte_data(client, reg, val & 0xff);
if (likely(!err))
err = i2c_smbus_write_byte_data(client, reg + 1, val >> 8);
if (unlikely(err < 0))
dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
16, "write", reg);
return err;
}