#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h>
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
#define SMSC47M192_REG_IN(nr) ((nr) < 6 ? (0x20 + (nr)) : \
#define SMSC47M192_REG_IN_MAX(nr) ((nr) < 6 ? (0x2b + (nr) * 2) : \
(0x54 + (((nr) - 6) * 2)))
#define SMSC47M192_REG_IN_MIN(nr) ((nr) < 6 ? (0x2c + (nr) * 2) : \
(0x55 + (((nr) - 6) * 2)))
static u8 SMSC47M192_REG_TEMP[3] = { 0x27, 0x26, 0x52 };
static u8 SMSC47M192_REG_TEMP_MAX[3] = { 0x39, 0x37, 0x58 };
static u8 SMSC47M192_REG_TEMP_MIN[3] = { 0x3A, 0x38, 0x59 };
#define SMSC47M192_REG_TEMP_OFFSET(nr) ((nr) == 2 ? 0x1e : 0x1f)
#define SMSC47M192_REG_ALARM1 0x41
#define SMSC47M192_REG_ALARM2 0x42
#define SMSC47M192_REG_VID 0x47
#define SMSC47M192_REG_VID4 0x49
#define SMSC47M192_REG_CONFIG 0x40
#define SMSC47M192_REG_SFR 0x4f
#define SMSC47M192_REG_COMPANY_ID 0x3e
#define SMSC47M192_REG_VERSION 0x3f
static inline int SCALE(long val, int mul, int div)
return (val * mul - div / 2) / div;
return (val * mul + div / 2) / div;
static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 };
static inline unsigned int IN_FROM_REG(u8 reg, int n)
return SCALE(reg, nom_mv[n], 192);
static inline u8 IN_TO_REG(unsigned long val, int n)
val = clamp_val(val, 0, nom_mv[n] * 255 / 192);
return SCALE(val, 192, nom_mv[n]);
static inline s8 TEMP_TO_REG(long val)
return SCALE(clamp_val(val, -128000, 127000), 1, 1000);