diff options
Diffstat (limited to 'ina2602.c')
| -rwxr-xr-x | ina2602.c | 297 |
1 files changed, 0 insertions, 297 deletions
diff --git a/ina2602.c b/ina2602.c deleted file mode 100755 index 0da08c1..0000000 --- a/ina2602.c +++ /dev/null @@ -1,297 +0,0 @@ -#include "linux/module.h" -#include "linux/uaccess.h" -#include "linux/i2c.h" -#include "linux/kobject.h" -#include "linux/slab.h" -#include "linux/kernel.h" -#include <linux/sysfs.h> -#include <linux/hwmon.h> - -// ina260 chip registers -#define INA260_REG_CONFIGURATION 0x00 -#define INA260_REG_CURRENT 0x01 -#define INA260_REG_VOLTAGE 0x02 -#define INA260_REG_POWER 0x03 -#define INA260_REG_MASKENABLE 0x06 -#define INA260_REG_ALERTLIMIT 0x07 -#define INA260_REG_MANUFACTURER 0xFE -#define INA260_REG_DIE 0xFF - -#undef current - -#define INA260_REG_SHOW(_attr,_reg) \ -static ssize_t _attr##_show(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - int rvalue; struct client_data *cdata=dev_get_drvdata(dev); \ - if(ina260_read_register(cdata,(_reg),&rvalue)) \ - return -1; \ - return sprintf(buf, "%x\n", rvalue); \ -} - -#define INA260_REG_STORE(_attr,_reg) \ -static ssize_t _attr##_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - int uvalue; struct client_data *cdata=dev_get_drvdata(dev); \ - if(kstrtoint(buf, 0,&uvalue)) \ - return -EINVAL; \ - if(ina260_write_register(cdata, (_reg), uvalue)) \ - return -1; \ - return count; \ -} - - -#define HWMON_CHANNEL_INFO(stype, ...) \ - (&(struct hwmon_channel_info) { \ - .type = hwmon_##stype, \ - .config = (u32 []) { \ - __VA_ARGS__, 0 \ - } \ - }) - -// ina260 average modes list -static int ina260_avgs[8]={ - 1,4,16,64,128,256,512,1024 -}; - -// ina260 operating modes list -static char ina260_modes[8][42]={ - "Power-Down (or Shutdown)","Shunt Current, Triggered", - "Bus Voltage, Triggered","Shunt Current and Bus Voltage, Triggered", - "Power-Down (or Shutdown)","Shunt Current, Continuous","Bus Voltage, Continuous", - "Shunt Current and Bus Voltage, Continuous" -}; - -// ina260 conversion times list -static char ina260_ishcts_vbusct[8][9]={ - "140 µs", "204 µs","332 µs", "588 µs","1.1 ms", "2.116 ms","4.156 ms","8.244 ms" -}; - - -// Data attached to i2c clients -struct client_data { - struct i2c_client *client; - unsigned char reg; // Slave selected register -}; - -static const struct i2c_device_id ina260_ids[] = { - { "ina260", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c,ina260_ids); - -/** - * @brief Read from ina260 registers - * - * @param cdata client data to use to communicate - * @param reg register to read - * @param value register content output - * @return int 0 on success, 1 on communication errors - */ -static int ina260_read_register(struct client_data* cdata, unsigned char reg, int *value){ - unsigned char bytes[2]; - if(cdata->reg == reg){ - if(i2c_master_recv(cdata->client,bytes,2)<0) - return 1; - } else { - if(i2c_master_send(cdata->client,®,1)<0) - return 1; - cdata->reg = reg; - if(i2c_master_recv(cdata->client,bytes,2)<0) - return 1; - } - *value=(bytes[0]<<8) | bytes[1]; - return 0; -} - -/** - * @brief Write to ina260 registers - * - * @param cdata client data to use to communicate - * @param reg register to write to - * @param value value to write in @a reg - * @return int 0 on success, 1 on communication errors - */ -static int ina260_write_register(struct client_data* cdata, unsigned char reg, int value){ - unsigned char data[3]; - data[0]=reg; - data[1]=(value>>8) & 0xFF; // MSB - data[2]=value & 0xFF; // LSB - if(i2c_master_send(cdata->client,data,3)<0) - return 1; - return 0; -} - - -static int ina260_hwmon_read(struct device *dev, enum hwmon_sensor_types type, - u32 attr, int channel, long *val) -{ - int rvalue; - struct client_data *cdata=dev_get_drvdata(dev); - if(type == hwmon_power){ - if(ina260_read_register(cdata, INA260_REG_POWER,&rvalue)) - return -1; - *val=10*rvalue*1000; - } else if (type == hwmon_curr){ - if(ina260_read_register(cdata, INA260_REG_CURRENT,&rvalue)) - return -1; - *val=((rvalue*25/100) + rvalue)*100+(rvalue*25%100); - *val/=100; - } else if (type == hwmon_in){ - if(ina260_read_register(cdata, INA260_REG_VOLTAGE,&rvalue)) - return -1; - - *val=((rvalue*25/100) + rvalue)*100+(rvalue*25%100); - *val/=100; - } - - return 0; -} - -static int ina260_hwmon_write(struct device *dev, enum hwmon_sensor_types type, - u32 attr, int channel, long val) -{ - return 0; -} - -INA260_REG_SHOW(configuration,INA260_REG_CONFIGURATION) -INA260_REG_SHOW(current,INA260_REG_CURRENT) -INA260_REG_SHOW(bus_voltage,INA260_REG_VOLTAGE) -INA260_REG_SHOW(power,INA260_REG_POWER) -INA260_REG_SHOW(mask_enable,INA260_REG_MASKENABLE) -INA260_REG_SHOW(alert_limit,INA260_REG_ALERTLIMIT) -INA260_REG_SHOW(manufacturer_id,INA260_REG_MANUFACTURER) -INA260_REG_SHOW(die_id,INA260_REG_DIE) - -INA260_REG_STORE(configuration,INA260_REG_CONFIGURATION) -INA260_REG_STORE(current,INA260_REG_CURRENT) -INA260_REG_STORE(bus_voltage,INA260_REG_VOLTAGE) -INA260_REG_STORE(power,INA260_REG_POWER) -INA260_REG_STORE(mask_enable,INA260_REG_MASKENABLE) -INA260_REG_STORE(alert_limit,INA260_REG_ALERTLIMIT) - - -static umode_t ina260_hwmon_is_visible(const void *drvdata, - enum hwmon_sensor_types type, - u32 attr, int channel){ - return 0444; - } -static const struct hwmon_channel_info * ina260_hwmon_info[] = { - HWMON_CHANNEL_INFO(in,HWMON_I_INPUT), - HWMON_CHANNEL_INFO(power,HWMON_P_INPUT), - HWMON_CHANNEL_INFO(curr,HWMON_C_INPUT), - NULL -}; -static const struct hwmon_ops ina260_hwmon_ops = { - .is_visible = ina260_hwmon_is_visible, - .read = ina260_hwmon_read, - .write = ina260_hwmon_write, -}; - -static const struct hwmon_chip_info ina260_chip_info = { - .ops = &ina260_hwmon_ops, - .info = ina260_hwmon_info, -}; -// ----- Registers ----- -static DEVICE_ATTR_RW(configuration); -static DEVICE_ATTR_RW(current); -static DEVICE_ATTR_RW(bus_voltage); -static DEVICE_ATTR_RW(power); -static DEVICE_ATTR_RW(mask_enable); -static DEVICE_ATTR_RW(alert_limit); -static DEVICE_ATTR_RO(manufacturer_id); -static DEVICE_ATTR_RO(die_id); -static struct attribute *registers_attrs[] = { - &dev_attr_configuration.attr, - &dev_attr_current.attr, - &dev_attr_bus_voltage.attr, - &dev_attr_power.attr, - &dev_attr_mask_enable.attr, - &dev_attr_alert_limit.attr, - &dev_attr_manufacturer_id.attr, - &dev_attr_die_id.attr, - NULL, -}; -static const struct attribute_group registers_group = { - .attrs = registers_attrs, - .name = "registers" -}; - - -/** - * @brief Compare on ina260 register to a supplied value - * - * @param client i2c client to use for communications - * @param reg register to use for comparison - * @param value register expected value - * @return int 0 if register contains value and 1 otherwise - */ -static int ina260_probe_register(struct i2c_client *client, unsigned char reg, int value){ - unsigned char bytes[2]; - if(i2c_master_send(client,®,1)<0) - return 1; - if(i2c_master_recv(client,bytes,2)<0) - return 1; - return ((bytes[0]<<8) | bytes[1])!=value; -} - -const struct attribute_group *extra_groups[] = { - ®isters_group, - NULL -}; - -static int ina260_probe_new(struct i2c_client *client){ - struct client_data *p; - struct device *hwmon_dev; - - // Attempt device discovery: - if(ina260_probe_register(client,INA260_REG_MANUFACTURER,0x5449) || - ina260_probe_register(client,INA260_REG_DIE,0x2270)){ - printk("ina260 probe fails bus=%d address=0x%02x\n",client->adapter->nr,client->addr); - return 1; - } - // Initialize client data: - printk("ina260 detected bus=%d address=0x%02x\n",client->adapter->nr,client->addr); - p=kzalloc(sizeof(struct client_data),GFP_KERNEL); - p->client=client; - p->reg=INA260_REG_DIE; // Maintain cache coherence - - hwmon_dev=hwmon_device_register_with_info(&client->dev,client->name,p, - &ina260_chip_info,extra_groups); - if (IS_ERR(hwmon_dev)) - return PTR_ERR(hwmon_dev); - return 0; -} - -static int ina260_remove(struct i2c_client *client){ - struct client_data *p=i2c_get_clientdata(client); - kfree(p); - hwmon_device_unregister(&client->dev); - printk("ina260 removed bus=%d address=0x%02x\n",client->adapter->nr,client->addr); - return 0; -} - -static struct i2c_driver ina260_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "ina260" - }, - .probe_new = ina260_probe_new, - .remove = ina260_remove, - .id_table = ina260_ids -}; - -static int __init ina260_init(void){ - i2c_add_driver(&ina260_driver); - return 0; -} - -static void __exit ina260_exit(void){ - i2c_del_driver(&ina260_driver); -} - -module_init(ina260_init); -module_exit(ina260_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Loïc Guegan"); -MODULE_DESCRIPTION("INA260 Texas Instruments"); -MODULE_VERSION("1.0"); |
