linux/drivers/hwmon/ina2xx.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Driver for Texas Instruments INA219, INA226 power monitor chips
 *
 * INA219:
 * Zero Drift Bi-Directional Current/Power Monitor with I2C Interface
 * Datasheet: https://www.ti.com/product/ina219
 *
 * INA220:
 * Bi-Directional Current/Power Monitor with I2C Interface
 * Datasheet: https://www.ti.com/product/ina220
 *
 * INA226:
 * Bi-Directional Current/Power Monitor with I2C Interface
 * Datasheet: https://www.ti.com/product/ina226
 *
 * INA230:
 * Bi-directional Current/Power Monitor with I2C Interface
 * Datasheet: https://www.ti.com/product/ina230
 *
 * Copyright (C) 2012 Lothar Felten <[email protected]>
 * Thanks to Jan Volkering
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/jiffies.h>
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/util_macros.h>
#include <linux/regmap.h>

#include <linux/platform_data/ina2xx.h>

/* common register definitions */
#define INA2XX_CONFIG
#define INA2XX_SHUNT_VOLTAGE
#define INA2XX_BUS_VOLTAGE
#define INA2XX_POWER
#define INA2XX_CURRENT
#define INA2XX_CALIBRATION

/* INA226 register definitions */
#define INA226_MASK_ENABLE
#define INA226_ALERT_LIMIT
#define INA226_DIE_ID

/* register count */
#define INA219_REGISTERS
#define INA226_REGISTERS

#define INA2XX_MAX_REGISTERS

/* settings - depend on use case */
#define INA219_CONFIG_DEFAULT
#define INA226_CONFIG_DEFAULT

/* worst case is 68.10 ms (~14.6Hz, ina219) */
#define INA2XX_CONVERSION_RATE
#define INA2XX_MAX_DELAY

#define INA2XX_RSHUNT_DEFAULT

/* bit mask for reading the averaging setting in the configuration register */
#define INA226_AVG_RD_MASK

#define INA226_READ_AVG(reg)
#define INA226_SHIFT_AVG(val)

#define INA226_ALERT_POLARITY_MASK
#define INA226_SHIFT_ALERT_POLARITY(val)
#define INA226_ALERT_POL_LOW
#define INA226_ALERT_POL_HIGH

/* bit number of alert functions in Mask/Enable Register */
#define INA226_SHUNT_OVER_VOLTAGE_BIT
#define INA226_SHUNT_UNDER_VOLTAGE_BIT
#define INA226_BUS_OVER_VOLTAGE_BIT
#define INA226_BUS_UNDER_VOLTAGE_BIT
#define INA226_POWER_OVER_LIMIT_BIT

/* bit mask for alert config bits of Mask/Enable Register */
#define INA226_ALERT_CONFIG_MASK
#define INA226_ALERT_FUNCTION_FLAG

/* common attrs, ina226 attrs and NULL */
#define INA2XX_MAX_ATTRIBUTE_GROUPS

/*
 * Both bus voltage and shunt voltage conversion times for ina226 are set
 * to 0b0100 on POR, which translates to 2200 microseconds in total.
 */
#define INA226_TOTAL_CONV_TIME_DEFAULT

static struct regmap_config ina2xx_regmap_config =;

enum ina2xx_ids {};

struct ina2xx_config {};

struct ina2xx_data {};

static const struct ina2xx_config ina2xx_config[] =;

/*
 * Available averaging rates for ina226. The indices correspond with
 * the bit values expected by the chip (according to the ina226 datasheet,
 * table 3 AVG bit settings, found at
 * https://www.ti.com/lit/ds/symlink/ina226.pdf.
 */
static const int ina226_avg_tab[] =;

static int ina226_reg_to_interval(u16 config)
{}

/*
 * Return the new, shifted AVG field value of CONFIG register,
 * to use with regmap_update_bits
 */
static u16 ina226_interval_to_reg(int interval)
{}

static int ina2xx_set_alert_polarity(struct ina2xx_data *data,
				     unsigned long val)
{}

/*
 * Calibration register is set to the best value, which eliminates
 * truncation errors on calculating current register in hardware.
 * According to datasheet (eq. 3) the best values are 2048 for
 * ina226 and 4096 for ina219. They are hardcoded as calibration_value.
 */
static int ina2xx_calibrate(struct ina2xx_data *data)
{}

/*
 * Initialize the configuration and calibration registers.
 */
static int ina2xx_init(struct ina2xx_data *data)
{}

static int ina2xx_read_reg(struct device *dev, int reg, unsigned int *regval)
{}

static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
			    unsigned int regval)
{}

static ssize_t ina2xx_value_show(struct device *dev,
				 struct device_attribute *da, char *buf)
{}

static int ina226_reg_to_alert(struct ina2xx_data *data, u8 bit, u16 regval)
{}

/*
 * Turns alert limit values into register values.
 * Opposite of the formula in ina2xx_get_value().
 */
static s16 ina226_alert_to_reg(struct ina2xx_data *data, u8 bit, int val)
{}

static ssize_t ina226_alert_show(struct device *dev,
				 struct device_attribute *da, char *buf)
{}

static ssize_t ina226_alert_store(struct device *dev,
				  struct device_attribute *da,
				  const char *buf, size_t count)
{}

static ssize_t ina226_alarm_show(struct device *dev,
				 struct device_attribute *da, char *buf)
{}

/*
 * In order to keep calibration register value fixed, the product
 * of current_lsb and shunt_resistor should also be fixed and equal
 * to shunt_voltage_lsb = 1 / shunt_div multiplied by 10^9 in order
 * to keep the scale.
 */
static int ina2xx_set_shunt(struct ina2xx_data *data, long val)
{}

static ssize_t ina2xx_shunt_show(struct device *dev,
				 struct device_attribute *da, char *buf)
{}

static ssize_t ina2xx_shunt_store(struct device *dev,
				  struct device_attribute *da,
				  const char *buf, size_t count)
{}

static ssize_t ina226_interval_store(struct device *dev,
				     struct device_attribute *da,
				     const char *buf, size_t count)
{}

static ssize_t ina226_interval_show(struct device *dev,
				    struct device_attribute *da, char *buf)
{}

/* shunt voltage */
static SENSOR_DEVICE_ATTR_RO(in0_input, ina2xx_value, INA2XX_SHUNT_VOLTAGE);
/* shunt voltage over/under voltage alert setting and alarm */
static SENSOR_DEVICE_ATTR_RW(in0_crit, ina226_alert,
			     INA226_SHUNT_OVER_VOLTAGE_BIT);
static SENSOR_DEVICE_ATTR_RW(in0_lcrit, ina226_alert,
			     INA226_SHUNT_UNDER_VOLTAGE_BIT);
static SENSOR_DEVICE_ATTR_RO(in0_crit_alarm, ina226_alarm,
			     INA226_SHUNT_OVER_VOLTAGE_BIT);
static SENSOR_DEVICE_ATTR_RO(in0_lcrit_alarm, ina226_alarm,
			     INA226_SHUNT_UNDER_VOLTAGE_BIT);

/* bus voltage */
static SENSOR_DEVICE_ATTR_RO(in1_input, ina2xx_value, INA2XX_BUS_VOLTAGE);
/* bus voltage over/under voltage alert setting and alarm */
static SENSOR_DEVICE_ATTR_RW(in1_crit, ina226_alert,
			     INA226_BUS_OVER_VOLTAGE_BIT);
static SENSOR_DEVICE_ATTR_RW(in1_lcrit, ina226_alert,
			     INA226_BUS_UNDER_VOLTAGE_BIT);
static SENSOR_DEVICE_ATTR_RO(in1_crit_alarm, ina226_alarm,
			     INA226_BUS_OVER_VOLTAGE_BIT);
static SENSOR_DEVICE_ATTR_RO(in1_lcrit_alarm, ina226_alarm,
			     INA226_BUS_UNDER_VOLTAGE_BIT);

/* calculated current */
static SENSOR_DEVICE_ATTR_RO(curr1_input, ina2xx_value, INA2XX_CURRENT);

/* calculated power */
static SENSOR_DEVICE_ATTR_RO(power1_input, ina2xx_value, INA2XX_POWER);
/* over-limit power alert setting and alarm */
static SENSOR_DEVICE_ATTR_RW(power1_crit, ina226_alert,
			     INA226_POWER_OVER_LIMIT_BIT);
static SENSOR_DEVICE_ATTR_RO(power1_crit_alarm, ina226_alarm,
			     INA226_POWER_OVER_LIMIT_BIT);

/* shunt resistance */
static SENSOR_DEVICE_ATTR_RW(shunt_resistor, ina2xx_shunt, INA2XX_CALIBRATION);

/* update interval (ina226 only) */
static SENSOR_DEVICE_ATTR_RW(update_interval, ina226_interval, 0);

/* pointers to created device attributes */
static struct attribute *ina2xx_attrs[] =;

static const struct attribute_group ina2xx_group =;

static struct attribute *ina226_attrs[] =;

static const struct attribute_group ina226_group =;

static int ina2xx_probe(struct i2c_client *client)
{}

static const struct i2c_device_id ina2xx_id[] =;
MODULE_DEVICE_TABLE(i2c, ina2xx_id);

static const struct of_device_id __maybe_unused ina2xx_of_match[] =;
MODULE_DEVICE_TABLE(of, ina2xx_of_match);

static struct i2c_driver ina2xx_driver =;

module_i2c_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();