// SPDX-License-Identifier: GPL-2.0-or-later
/*
* asc7621.c - Part of lm_sensors, Linux kernel modules for hardware monitoring
* Copyright (c) 2007, 2010 George Joseph <george.joseph@fairview5.com>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */
static const unsigned short normal_i2c[] = {
0x2c, 0x2d, 0x2e, I2C_CLIENT_END
};
enum asc7621_type {
asc7621,
asc7621a
};
#define INTERVAL_HIGH (HZ + HZ / 2)
#define INTERVAL_LOW (1 * 60 * HZ)
#define PRI_NONE 0
#define PRI_LOW 1
#define PRI_HIGH 2
#define FIRST_CHIP asc7621
#define LAST_CHIP asc7621a
struct asc7621_chip {
char *name;
enum asc7621_type chip_type;
u8 company_reg;
u8 company_id;
u8 verstep_reg;
u8 verstep_id;
const unsigned short *addresses;
};
static struct asc7621_chip asc7621_chips[] = {
{
.name = "asc7621",
.chip_type = asc7621,
.company_reg = 0x3e,
.company_id = 0x61,
.verstep_reg = 0x3f,
.verstep_id = 0x6c,
.addresses = normal_i2c,
},
{
.name = "asc7621a",
.chip_type = asc7621a,
.company_reg = 0x3e,
.company_id = 0x61,
.verstep_reg = 0x3f,
.verstep_id = 0x6d,
.addresses = normal_i2c,
},
};
/*
* Defines the highest register to be used, not the count.
* The actual count will probably be smaller because of gaps
* in the implementation (unused register locations).
* This define will safely set the array size of both the parameter
* and data arrays.
* This comes from the data sheet register description table.
*/
#define LAST_REGISTER 0xff
struct asc7621_data {
struct i2c_client client;
struct device *class_dev;
struct mutex update_lock;
bool valid; /* true if following fields are valid */
unsigned long last_high_reading; /* In jiffies */
unsigned long last_low_reading; /* In jiffies */
/*
* Registers we care about occupy the corresponding index
* in the array. Registers we don't care about are left
* at 0.
*/
u8 reg[LAST_REGISTER + 1];
};
/*
* Macro to get the parent asc7621_param structure
* from a sensor_device_attribute passed into the
* show/store functions.
*/
#define to_asc7621_param(_sda) \
container_of(_sda, struct asc7621_param, sda)
/*
* Each parameter to be retrieved needs an asc7621_param structure
* allocated. It contains the sensor_device_attribute structure
* and the control info needed to retrieve the value from the register map.
*/
struct asc7621_param {
struct sensor_device_attribute sda;
u8 priority;
u8 msb[3];
u8 lsb[3];
u8 mask[3];
u8 shift[3];
};
/*
* This is the map that ultimately indicates whether we'll be
* retrieving a register value or not, and at what frequency.
*/
static u8 asc7621_register_priorities[255];
static struct asc7621_data *asc7621_update_device(struct device *dev);
static inline u8 read_byte(struct i2c_client *client, u8 reg)
{
int res = i2c_smbus_read_byte_data(client, reg);
if (res < 0) {
dev_err(&client->dev,
"Unable to read from register 0x%02x.\n", reg);
return 0;
}
return res & 0xff;
}
static inline int write_byte(struct i2c_client *client, u8 reg, u8 data)
{
int res = i2c_smbus_write_byte_data(client, reg, data);
if (res < 0) {
dev_err(&client->dev,
"Unable to write value 0x%02x to register 0x%02x.\n",
data, reg);
}
return res;
}
/*
* Data Handlers
* Each function handles the formatting, storage
* and retrieval of like parameters.
*/
#define SETUP_SHOW_DATA_PARAM(d, a) \
struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
struct asc7621_data *data = asc7621_update_device(d); \
struct asc7621_param *param = to_asc7621_param(sda)
#define SETUP_STORE_DATA_PARAM(d, a) \
struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
struct i2c_client *client = to_i2c_client(d); \
struct asc7621_data *data = i2c_get_clientdata(client); \
struct asc7621_param *param = to_asc7621_param(sda)
/*
* u8 is just what it sounds like...an unsigned byte with no
* special formatting.
*/
static ssize_t show_u8(struct device *<