2012-05-12 12:36:38 +04:00
/*
* Driver for Texas Instruments INA219 , INA226 power monitor chips
*
* INA219 :
* Zero Drift Bi - Directional Current / Power Monitor with I2C Interface
* Datasheet : http : //www.ti.com/product/ina219
*
2012-05-12 22:33:11 +04:00
* INA220 :
* Bi - Directional Current / Power Monitor with I2C Interface
* Datasheet : http : //www.ti.com/product/ina220
*
2012-05-12 12:36:38 +04:00
* INA226 :
* Bi - Directional Current / Power Monitor with I2C Interface
* Datasheet : http : //www.ti.com/product/ina226
*
2012-05-12 22:33:11 +04:00
* INA230 :
* Bi - directional Current / Power Monitor with I2C Interface
* Datasheet : http : //www.ti.com/product/ina230
*
2012-05-12 12:36:38 +04:00
* Copyright ( C ) 2012 Lothar Felten < l - felten @ ti . com >
* Thanks to Jan Volkering
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; version 2 of the License .
*/
# 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>
2012-10-10 17:25:56 +04:00
# include <linux/jiffies.h>
2017-02-24 16:13:00 +03:00
# include <linux/of_device.h>
2013-06-19 10:50:20 +04:00
# include <linux/of.h>
2015-01-05 17:20:52 +03:00
# include <linux/delay.h>
2015-04-16 22:43:34 +03:00
# include <linux/util_macros.h>
2015-10-28 14:04:53 +03:00
# include <linux/regmap.h>
2012-05-12 12:36:38 +04:00
# include <linux/platform_data/ina2xx.h>
/* common register definitions */
# define INA2XX_CONFIG 0x00
# define INA2XX_SHUNT_VOLTAGE 0x01 /* readonly */
# define INA2XX_BUS_VOLTAGE 0x02 /* readonly */
# define INA2XX_POWER 0x03 /* readonly */
# define INA2XX_CURRENT 0x04 /* readonly */
# define INA2XX_CALIBRATION 0x05
/* INA226 register definitions */
# define INA226_MASK_ENABLE 0x06
# define INA226_ALERT_LIMIT 0x07
# define INA226_DIE_ID 0xFF
/* register count */
# define INA219_REGISTERS 6
# define INA226_REGISTERS 8
# define INA2XX_MAX_REGISTERS 8
/* settings - depend on use case */
# define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */
# define INA226_CONFIG_DEFAULT 0x4527 /* averages=16 */
/* worst case is 68.10 ms (~14.6Hz, ina219) */
# define INA2XX_CONVERSION_RATE 15
2015-01-05 17:20:52 +03:00
# define INA2XX_MAX_DELAY 69 /* worst case delay in ms */
# define INA2XX_RSHUNT_DEFAULT 10000
2012-05-12 12:36:38 +04:00
2015-01-09 19:03:42 +03:00
/* bit mask for reading the averaging setting in the configuration register */
# define INA226_AVG_RD_MASK 0x0E00
# define INA226_READ_AVG(reg) (((reg) & INA226_AVG_RD_MASK) >> 9)
# define INA226_SHIFT_AVG(val) ((val) << 9)
/* common attrs, ina226 attrs and NULL */
# define INA2XX_MAX_ATTRIBUTE_GROUPS 3
/*
* Both bus voltage and shunt voltage conversion times for ina226 are set
* to 0 b0100 on POR , which translates to 2200 microseconds in total .
*/
# define INA226_TOTAL_CONV_TIME_DEFAULT 2200
2015-10-28 14:04:53 +03:00
static struct regmap_config ina2xx_regmap_config = {
. reg_bits = 8 ,
. val_bits = 16 ,
} ;
2012-05-12 12:36:38 +04:00
enum ina2xx_ids { ina219 , ina226 } ;
2012-05-12 22:21:01 +04:00
struct ina2xx_config {
u16 config_default ;
2017-11-22 18:32:15 +03:00
int calibration_value ;
2012-05-12 22:21:01 +04:00
int registers ;
int shunt_div ;
int bus_voltage_shift ;
int bus_voltage_lsb ; /* uV */
2017-11-22 18:32:15 +03:00
int power_lsb_factor ;
2012-05-12 22:21:01 +04:00
} ;
2012-05-12 12:36:38 +04:00
struct ina2xx_data {
2012-05-12 22:21:01 +04:00
const struct ina2xx_config * config ;
2012-05-12 12:36:38 +04:00
2015-01-05 17:20:52 +03:00
long rshunt ;
2017-11-22 18:32:15 +03:00
long current_lsb_uA ;
long power_lsb_uW ;
2015-10-28 14:04:53 +03:00
struct mutex config_lock ;
struct regmap * regmap ;
2012-05-12 12:36:38 +04:00
2015-01-09 19:03:42 +03:00
const struct attribute_group * groups [ INA2XX_MAX_ATTRIBUTE_GROUPS ] ;
2012-05-12 12:36:38 +04:00
} ;
2012-05-12 22:21:01 +04:00
static const struct ina2xx_config ina2xx_config [ ] = {
[ ina219 ] = {
. config_default = INA219_CONFIG_DEFAULT ,
2017-11-22 18:32:15 +03:00
. calibration_value = 4096 ,
2012-05-12 22:21:01 +04:00
. registers = INA219_REGISTERS ,
. shunt_div = 100 ,
. bus_voltage_shift = 3 ,
. bus_voltage_lsb = 4000 ,
2017-11-22 18:32:15 +03:00
. power_lsb_factor = 20 ,
2012-05-12 22:21:01 +04:00
} ,
[ ina226 ] = {
. config_default = INA226_CONFIG_DEFAULT ,
2017-11-22 18:32:15 +03:00
. calibration_value = 2048 ,
2012-05-12 22:21:01 +04:00
. registers = INA226_REGISTERS ,
. shunt_div = 400 ,
. bus_voltage_shift = 0 ,
. bus_voltage_lsb = 1250 ,
2017-11-22 18:32:15 +03:00
. power_lsb_factor = 25 ,
2012-05-12 22:21:01 +04:00
} ,
} ;
2015-01-09 19:03:42 +03:00
/*
* 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
* http : //www.ti.com/lit/ds/symlink/ina226.pdf.
*/
static const int ina226_avg_tab [ ] = { 1 , 4 , 16 , 64 , 128 , 256 , 512 , 1024 } ;
static int ina226_reg_to_interval ( u16 config )
{
int avg = ina226_avg_tab [ INA226_READ_AVG ( config ) ] ;
/*
* Multiply the total conversion time by the number of averages .
* Return the result in milliseconds .
*/
return DIV_ROUND_CLOSEST ( avg * INA226_TOTAL_CONV_TIME_DEFAULT , 1000 ) ;
}
2015-10-28 14:04:53 +03:00
/*
* Return the new , shifted AVG field value of CONFIG register ,
* to use with regmap_update_bits
*/
static u16 ina226_interval_to_reg ( int interval )
2015-01-09 19:03:42 +03:00
{
int avg , avg_bits ;
avg = DIV_ROUND_CLOSEST ( interval * 1000 ,
INA226_TOTAL_CONV_TIME_DEFAULT ) ;
2015-04-16 22:43:34 +03:00
avg_bits = find_closest ( avg , ina226_avg_tab ,
ARRAY_SIZE ( ina226_avg_tab ) ) ;
2015-01-09 19:03:42 +03:00
2015-10-28 14:04:53 +03:00
return INA226_SHIFT_AVG ( avg_bits ) ;
2015-01-09 19:03:42 +03:00
}
2017-11-22 18:32:15 +03:00
/*
* 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 .
*/
2015-01-05 17:20:55 +03:00
static int ina2xx_calibrate ( struct ina2xx_data * data )
{
2017-11-22 18:32:15 +03:00
return regmap_write ( data - > regmap , INA2XX_CALIBRATION ,
data - > config - > calibration_value ) ;
2015-01-05 17:20:55 +03:00
}
2015-01-05 17:20:52 +03:00
/*
* Initialize the configuration and calibration registers .
*/
static int ina2xx_init ( struct ina2xx_data * data )
2012-05-12 12:36:38 +04:00
{
2015-10-28 14:04:53 +03:00
int ret = regmap_write ( data - > regmap , INA2XX_CONFIG ,
data - > config - > config_default ) ;
2015-01-05 17:20:52 +03:00
if ( ret < 0 )
return ret ;
2012-05-12 12:36:38 +04:00
2015-01-05 17:20:55 +03:00
return ina2xx_calibrate ( data ) ;
2015-01-05 17:20:52 +03:00
}
2012-05-12 12:36:38 +04:00
2015-10-28 14:04:53 +03:00
static int ina2xx_read_reg ( struct device * dev , int reg , unsigned int * regval )
2015-01-05 17:20:52 +03:00
{
struct ina2xx_data * data = dev_get_drvdata ( dev ) ;
2015-10-28 14:04:53 +03:00
int ret , retry ;
2012-05-12 12:36:38 +04:00
2015-10-28 14:04:53 +03:00
dev_dbg ( dev , " Starting register %d read \n " , reg ) ;
2012-05-12 12:36:38 +04:00
2015-01-05 17:20:52 +03:00
for ( retry = 5 ; retry ; retry - - ) {
2015-10-28 14:04:53 +03:00
ret = regmap_read ( data - > regmap , reg , regval ) ;
if ( ret < 0 )
return ret ;
dev_dbg ( dev , " read %d, val = 0x%04x \n " , reg , * regval ) ;
2015-01-05 17:20:52 +03:00
/*
* If the current value in the calibration register is 0 , the
* power and current registers will also remain at 0. In case
* the chip has been reset let ' s check the calibration
* register and reinitialize if needed .
2015-10-28 14:04:53 +03:00
* We do that extra read of the calibration register if there
* is some hint of a chip reset .
2015-01-05 17:20:52 +03:00
*/
2015-10-28 14:04:53 +03:00
if ( * regval = = 0 ) {
unsigned int cal ;
ret = regmap_read ( data - > regmap , INA2XX_CALIBRATION ,
& cal ) ;
if ( ret < 0 )
return ret ;
if ( cal = = 0 ) {
dev_warn ( dev , " chip not calibrated, reinitializing \n " ) ;
ret = ina2xx_init ( data ) ;
if ( ret < 0 )
return ret ;
/*
* Let ' s make sure the power and current
* registers have been updated before trying
* again .
*/
msleep ( INA2XX_MAX_DELAY ) ;
continue ;
}
2015-01-05 17:20:52 +03:00
}
return 0 ;
2012-05-12 12:36:38 +04:00
}
2015-01-05 17:20:52 +03:00
/*
* If we ' re here then although all write operations succeeded , the
* chip still returns 0 in the calibration register . Nothing more we
* can do here .
*/
dev_err ( dev , " unable to reinitialize the chip \n " ) ;
return - ENODEV ;
}
2015-10-28 14:04:53 +03:00
static int ina2xx_get_value ( struct ina2xx_data * data , u8 reg ,
unsigned int regval )
2012-05-12 12:36:38 +04:00
{
2012-05-12 22:21:01 +04:00
int val ;
2012-05-12 12:36:38 +04:00
switch ( reg ) {
case INA2XX_SHUNT_VOLTAGE :
2014-06-09 01:06:24 +04:00
/* signed register */
2015-10-28 14:04:53 +03:00
val = DIV_ROUND_CLOSEST ( ( s16 ) regval , data - > config - > shunt_div ) ;
2012-05-12 12:36:38 +04:00
break ;
case INA2XX_BUS_VOLTAGE :
2015-10-28 14:04:53 +03:00
val = ( regval > > data - > config - > bus_voltage_shift )
2012-05-12 22:21:01 +04:00
* data - > config - > bus_voltage_lsb ;
val = DIV_ROUND_CLOSEST ( val , 1000 ) ;
2012-05-12 12:36:38 +04:00
break ;
case INA2XX_POWER :
2017-11-22 18:32:15 +03:00
val = regval * data - > power_lsb_uW ;
2012-05-12 12:36:38 +04:00
break ;
case INA2XX_CURRENT :
2017-11-22 18:32:15 +03:00
/* signed register, result in mA */
val = regval * data - > current_lsb_uA ;
val = DIV_ROUND_CLOSEST ( val , 1000 ) ;
2012-05-12 12:36:38 +04:00
break ;
2015-01-05 17:20:55 +03:00
case INA2XX_CALIBRATION :
2017-11-22 18:32:15 +03:00
val = regval ;
2015-01-05 17:20:55 +03:00
break ;
2012-05-12 12:36:38 +04:00
default :
/* programmer goofed */
WARN_ON_ONCE ( 1 ) ;
val = 0 ;
break ;
}
return val ;
}
static ssize_t ina2xx_show_value ( struct device * dev ,
struct device_attribute * da , char * buf )
{
struct sensor_device_attribute * attr = to_sensor_dev_attr ( da ) ;
2015-10-28 14:04:53 +03:00
struct ina2xx_data * data = dev_get_drvdata ( dev ) ;
unsigned int regval ;
2012-05-12 12:36:38 +04:00
2015-10-28 14:04:53 +03:00
int err = ina2xx_read_reg ( dev , attr - > index , & regval ) ;
if ( err < 0 )
return err ;
2012-05-12 12:36:38 +04:00
2012-05-12 22:21:01 +04:00
return snprintf ( buf , PAGE_SIZE , " %d \n " ,
2015-10-28 14:04:53 +03:00
ina2xx_get_value ( data , attr - > index , regval ) ) ;
2012-05-12 12:36:38 +04:00
}
2017-11-22 18:32:15 +03:00
/*
* 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 )
{
unsigned int dividend = DIV_ROUND_CLOSEST ( 1000000000 ,
data - > config - > shunt_div ) ;
if ( val < = 0 | | val > dividend )
return - EINVAL ;
mutex_lock ( & data - > config_lock ) ;
data - > rshunt = val ;
data - > current_lsb_uA = DIV_ROUND_CLOSEST ( dividend , val ) ;
data - > power_lsb_uW = data - > config - > power_lsb_factor *
data - > current_lsb_uA ;
mutex_unlock ( & data - > config_lock ) ;
return 0 ;
}
static ssize_t ina2xx_store_shunt ( struct device * dev ,
struct device_attribute * da ,
const char * buf , size_t count )
2015-01-05 17:20:55 +03:00
{
unsigned long val ;
int status ;
2015-10-28 14:04:53 +03:00
struct ina2xx_data * data = dev_get_drvdata ( dev ) ;
2015-01-05 17:20:55 +03:00
status = kstrtoul ( buf , 10 , & val ) ;
if ( status < 0 )
return status ;
2017-11-22 18:32:15 +03:00
status = ina2xx_set_shunt ( data , val ) ;
2015-01-05 17:20:55 +03:00
if ( status < 0 )
return status ;
return count ;
}
2015-01-09 19:03:42 +03:00
static ssize_t ina226_set_interval ( struct device * dev ,
struct device_attribute * da ,
const char * buf , size_t count )
{
struct ina2xx_data * data = dev_get_drvdata ( dev ) ;
unsigned long val ;
int status ;
status = kstrtoul ( buf , 10 , & val ) ;
if ( status < 0 )
return status ;
if ( val > INT_MAX | | val = = 0 )
return - EINVAL ;
2015-10-28 14:04:53 +03:00
status = regmap_update_bits ( data - > regmap , INA2XX_CONFIG ,
INA226_AVG_RD_MASK ,
ina226_interval_to_reg ( val ) ) ;
2015-01-09 19:03:42 +03:00
if ( status < 0 )
return status ;
return count ;
}
static ssize_t ina226_show_interval ( struct device * dev ,
struct device_attribute * da , char * buf )
{
2015-10-28 14:04:53 +03:00
struct ina2xx_data * data = dev_get_drvdata ( dev ) ;
int status ;
unsigned int regval ;
2015-01-09 19:03:42 +03:00
2015-10-28 14:04:53 +03:00
status = regmap_read ( data - > regmap , INA2XX_CONFIG , & regval ) ;
if ( status )
return status ;
2015-01-09 19:03:42 +03:00
2015-10-28 14:04:53 +03:00
return snprintf ( buf , PAGE_SIZE , " %d \n " , ina226_reg_to_interval ( regval ) ) ;
2015-01-09 19:03:42 +03:00
}
2012-05-12 12:36:38 +04:00
/* shunt voltage */
2013-01-10 22:04:06 +04:00
static SENSOR_DEVICE_ATTR ( in0_input , S_IRUGO , ina2xx_show_value , NULL ,
INA2XX_SHUNT_VOLTAGE ) ;
2012-05-12 12:36:38 +04:00
/* bus voltage */
2013-01-10 22:04:06 +04:00
static SENSOR_DEVICE_ATTR ( in1_input , S_IRUGO , ina2xx_show_value , NULL ,
INA2XX_BUS_VOLTAGE ) ;
2012-05-12 12:36:38 +04:00
/* calculated current */
2013-01-10 22:04:06 +04:00
static SENSOR_DEVICE_ATTR ( curr1_input , S_IRUGO , ina2xx_show_value , NULL ,
INA2XX_CURRENT ) ;
2012-05-12 12:36:38 +04:00
/* calculated power */
2013-01-10 22:04:06 +04:00
static SENSOR_DEVICE_ATTR ( power1_input , S_IRUGO , ina2xx_show_value , NULL ,
INA2XX_POWER ) ;
2012-05-12 12:36:38 +04:00
2015-01-05 17:20:55 +03:00
/* shunt resistance */
static SENSOR_DEVICE_ATTR ( shunt_resistor , S_IRUGO | S_IWUSR ,
2017-11-22 18:32:15 +03:00
ina2xx_show_value , ina2xx_store_shunt ,
2015-01-05 17:20:55 +03:00
INA2XX_CALIBRATION ) ;
2015-01-09 19:03:42 +03:00
/* update interval (ina226 only) */
static SENSOR_DEVICE_ATTR ( update_interval , S_IRUGO | S_IWUSR ,
ina226_show_interval , ina226_set_interval , 0 ) ;
2012-05-12 12:36:38 +04:00
/* pointers to created device attributes */
2013-09-03 00:16:19 +04:00
static struct attribute * ina2xx_attrs [ ] = {
2012-05-12 12:36:38 +04:00
& sensor_dev_attr_in0_input . dev_attr . attr ,
& sensor_dev_attr_in1_input . dev_attr . attr ,
& sensor_dev_attr_curr1_input . dev_attr . attr ,
& sensor_dev_attr_power1_input . dev_attr . attr ,
2015-01-05 17:20:55 +03:00
& sensor_dev_attr_shunt_resistor . dev_attr . attr ,
2012-05-12 12:36:38 +04:00
NULL ,
} ;
2015-01-09 19:03:42 +03:00
static const struct attribute_group ina2xx_group = {
. attrs = ina2xx_attrs ,
} ;
static struct attribute * ina226_attrs [ ] = {
& sensor_dev_attr_update_interval . dev_attr . attr ,
NULL ,
} ;
static const struct attribute_group ina226_group = {
. attrs = ina226_attrs ,
} ;
2012-05-12 12:36:38 +04:00
static int ina2xx_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
2013-09-03 00:16:19 +04:00
struct device * dev = & client - > dev ;
struct ina2xx_data * data ;
struct device * hwmon_dev ;
u32 val ;
2015-01-09 19:03:42 +03:00
int ret , group = 0 ;
2017-02-24 16:13:00 +03:00
enum ina2xx_ids chip ;
if ( client - > dev . of_node )
chip = ( enum ina2xx_ids ) of_device_get_match_data ( & client - > dev ) ;
else
chip = id - > driver_data ;
2012-05-12 12:36:38 +04:00
2013-09-03 00:16:19 +04:00
data = devm_kzalloc ( dev , sizeof ( * data ) , GFP_KERNEL ) ;
2012-05-12 12:36:38 +04:00
if ( ! data )
return - ENOMEM ;
/* set the device type */
2017-02-24 16:13:00 +03:00
data - > config = & ina2xx_config [ chip ] ;
2018-01-15 16:58:21 +03:00
mutex_init ( & data - > config_lock ) ;
2015-01-09 19:03:42 +03:00
2015-10-27 12:51:08 +03:00
if ( of_property_read_u32 ( dev - > of_node , " shunt-resistor " , & val ) < 0 ) {
struct ina2xx_platform_data * pdata = dev_get_platdata ( dev ) ;
if ( pdata )
val = pdata - > shunt_uohms ;
else
val = INA2XX_RSHUNT_DEFAULT ;
}
2017-11-22 18:32:15 +03:00
ina2xx_set_shunt ( data , val ) ;
2015-10-27 12:51:08 +03:00
2015-10-28 14:04:53 +03:00
ina2xx_regmap_config . max_register = data - > config - > registers ;
data - > regmap = devm_regmap_init_i2c ( client , & ina2xx_regmap_config ) ;
if ( IS_ERR ( data - > regmap ) ) {
dev_err ( dev , " failed to allocate register map \n " ) ;
return PTR_ERR ( data - > regmap ) ;
}
2015-01-05 17:20:52 +03:00
ret = ina2xx_init ( data ) ;
2014-11-27 12:59:06 +03:00
if ( ret < 0 ) {
2015-01-05 17:20:52 +03:00
dev_err ( dev , " error configuring the device: %d \n " , ret ) ;
2014-11-27 12:59:06 +03:00
return - ENODEV ;
}
2012-05-12 12:36:38 +04:00
2015-01-09 19:03:42 +03:00
data - > groups [ group + + ] = & ina2xx_group ;
2015-10-29 12:07:17 +03:00
if ( id - > driver_data = = ina226 )
2015-01-09 19:03:42 +03:00
data - > groups [ group + + ] = & ina226_group ;
2013-09-03 00:16:19 +04:00
hwmon_dev = devm_hwmon_device_register_with_groups ( dev , client - > name ,
2015-01-09 19:03:42 +03:00
data , data - > groups ) ;
2013-09-03 00:16:19 +04:00
if ( IS_ERR ( hwmon_dev ) )
return PTR_ERR ( hwmon_dev ) ;
2012-05-12 12:36:38 +04:00
2013-09-03 00:16:19 +04:00
dev_info ( dev , " power monitor %s (Rshunt = %li uOhm) \n " ,
2015-01-05 17:20:52 +03:00
id - > name , data - > rshunt ) ;
2012-05-12 22:21:01 +04:00
2012-05-12 12:36:38 +04:00
return 0 ;
}
static const struct i2c_device_id ina2xx_id [ ] = {
{ " ina219 " , ina219 } ,
2012-05-12 22:33:11 +04:00
{ " ina220 " , ina219 } ,
2012-05-12 12:36:38 +04:00
{ " ina226 " , ina226 } ,
2012-05-12 22:33:11 +04:00
{ " ina230 " , ina226 } ,
2015-01-15 04:34:58 +03:00
{ " ina231 " , ina226 } ,
2012-05-12 12:36:38 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , ina2xx_id ) ;
2017-02-24 16:13:00 +03:00
static const struct of_device_id ina2xx_of_match [ ] = {
{
. compatible = " ti,ina219 " ,
. data = ( void * ) ina219
} ,
{
. compatible = " ti,ina220 " ,
. data = ( void * ) ina219
} ,
{
. compatible = " ti,ina226 " ,
. data = ( void * ) ina226
} ,
{
. compatible = " ti,ina230 " ,
. data = ( void * ) ina226
} ,
{
. compatible = " ti,ina231 " ,
. data = ( void * ) ina226
} ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , ina2xx_of_match ) ;
2012-05-12 12:36:38 +04:00
static struct i2c_driver ina2xx_driver = {
. driver = {
. name = " ina2xx " ,
2017-02-24 16:13:00 +03:00
. of_match_table = of_match_ptr ( ina2xx_of_match ) ,
2012-05-12 12:36:38 +04:00
} ,
. probe = ina2xx_probe ,
. id_table = ina2xx_id ,
} ;
2012-10-08 16:40:35 +04:00
module_i2c_driver ( ina2xx_driver ) ;
2012-05-12 12:36:38 +04:00
MODULE_AUTHOR ( " Lothar Felten <l-felten@ti.com> " ) ;
MODULE_DESCRIPTION ( " ina2xx driver " ) ;
MODULE_LICENSE ( " GPL " ) ;