aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/ina2xx.c
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2012-05-12 14:21:01 -0400
committerGuenter Roeck <linux@roeck-us.net>2012-09-24 00:08:34 -0400
commit6106db25c27550337a1d701631093cdfc645aa7b (patch)
tree22797d324f513dd903c702801d70248be24159cf /drivers/hwmon/ina2xx.c
parent9224c38a312a339f1c9c2115a1f379c9f8f1731e (diff)
hwmon: (ina2xx) Use structure array to distinguish chip types
Replace per-device initialization and per-device calculation code with per-device configuration data, which is then used to configure the chip and perform calculations based on that data. This patch reduces code size by more than 400 bytes on x86_64. Cc: Lothar Felten <l-felten@ti.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Acked-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/ina2xx.c')
-rw-r--r--drivers/hwmon/ina2xx.c159
1 files changed, 56 insertions, 103 deletions
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 602148299f68..de8f2c6c6b66 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -57,18 +57,49 @@
57 57
58enum ina2xx_ids { ina219, ina226 }; 58enum ina2xx_ids { ina219, ina226 };
59 59
60struct ina2xx_config {
61 u16 config_default;
62 int calibration_factor;
63 int registers;
64 int shunt_div;
65 int bus_voltage_shift;
66 int bus_voltage_lsb; /* uV */
67 int power_lsb; /* uW */
68};
69
60struct ina2xx_data { 70struct ina2xx_data {
61 struct device *hwmon_dev; 71 struct device *hwmon_dev;
72 const struct ina2xx_config *config;
62 73
63 struct mutex update_lock; 74 struct mutex update_lock;
64 bool valid; 75 bool valid;
65 unsigned long last_updated; 76 unsigned long last_updated;
66 77
67 int kind; 78 int kind;
68 int registers;
69 u16 regs[INA2XX_MAX_REGISTERS]; 79 u16 regs[INA2XX_MAX_REGISTERS];
70}; 80};
71 81
82static const struct ina2xx_config ina2xx_config[] = {
83 [ina219] = {
84 .config_default = INA219_CONFIG_DEFAULT,
85 .calibration_factor = 40960000,
86 .registers = INA219_REGISTERS,
87 .shunt_div = 100,
88 .bus_voltage_shift = 3,
89 .bus_voltage_lsb = 4000,
90 .power_lsb = 20000,
91 },
92 [ina226] = {
93 .config_default = INA226_CONFIG_DEFAULT,
94 .calibration_factor = 5120000,
95 .registers = INA226_REGISTERS,
96 .shunt_div = 400,
97 .bus_voltage_shift = 0,
98 .bus_voltage_lsb = 1250,
99 .power_lsb = 25000,
100 },
101};
102
72static struct ina2xx_data *ina2xx_update_device(struct device *dev) 103static struct ina2xx_data *ina2xx_update_device(struct device *dev)
73{ 104{
74 struct i2c_client *client = to_i2c_client(dev); 105 struct i2c_client *client = to_i2c_client(dev);
@@ -85,7 +116,7 @@ static struct ina2xx_data *ina2xx_update_device(struct device *dev)
85 dev_dbg(&client->dev, "Starting ina2xx update\n"); 116 dev_dbg(&client->dev, "Starting ina2xx update\n");
86 117
87 /* Read all registers */ 118 /* Read all registers */
88 for (i = 0; i < data->registers; i++) { 119 for (i = 0; i < data->config->registers; i++) {
89 int rv = i2c_smbus_read_word_swapped(client, i); 120 int rv = i2c_smbus_read_word_swapped(client, i);
90 if (rv < 0) { 121 if (rv < 0) {
91 ret = ERR_PTR(rv); 122 ret = ERR_PTR(rv);
@@ -101,73 +132,26 @@ abort:
101 return ret; 132 return ret;
102} 133}
103 134
104static int ina219_get_value(struct ina2xx_data *data, u8 reg) 135static int ina2xx_get_value(struct ina2xx_data *data, u8 reg)
105{
106 /*
107 * calculate exact value for the given register
108 * we assume default power-on reset settings:
109 * bus voltage range 32V
110 * gain = /8
111 * adc 1 & 2 -> conversion time 532uS
112 * mode is continuous shunt and bus
113 * calibration value is INA219_CALIBRATION_VALUE
114 */
115 int val = data->regs[reg];
116
117 switch (reg) {
118 case INA2XX_SHUNT_VOLTAGE:
119 /* LSB=10uV. Convert to mV. */
120 val = DIV_ROUND_CLOSEST(val, 100);
121 break;
122 case INA2XX_BUS_VOLTAGE:
123 /* LSB=4mV. Register is not right aligned, convert to mV. */
124 val = (val >> 3) * 4;
125 break;
126 case INA2XX_POWER:
127 /* LSB=20mW. Convert to uW */
128 val = val * 20 * 1000;
129 break;
130 case INA2XX_CURRENT:
131 /* LSB=1mA (selected). Is in mA */
132 break;
133 default:
134 /* programmer goofed */
135 WARN_ON_ONCE(1);
136 val = 0;
137 break;
138 }
139
140 return val;
141}
142
143static int ina226_get_value(struct ina2xx_data *data, u8 reg)
144{ 136{
145 /* 137 int val;
146 * calculate exact value for the given register
147 * we assume default power-on reset settings:
148 * bus voltage range 32V
149 * gain = /8
150 * adc 1 & 2 -> conversion time 532uS
151 * mode is continuous shunt and bus
152 * calibration value is INA226_CALIBRATION_VALUE
153 */
154 int val = data->regs[reg];
155 138
156 switch (reg) { 139 switch (reg) {
157 case INA2XX_SHUNT_VOLTAGE: 140 case INA2XX_SHUNT_VOLTAGE:
158 /* LSB=2.5uV. Convert to mV. */ 141 val = DIV_ROUND_CLOSEST(data->regs[reg],
159 val = DIV_ROUND_CLOSEST(val, 400); 142 data->config->shunt_div);
160 break; 143 break;
161 case INA2XX_BUS_VOLTAGE: 144 case INA2XX_BUS_VOLTAGE:
162 /* LSB=1.25mV. Convert to mV. */ 145 val = (data->regs[reg] >> data->config->bus_voltage_shift)
163 val = val + DIV_ROUND_CLOSEST(val, 4); 146 * data->config->bus_voltage_lsb;
147 val = DIV_ROUND_CLOSEST(val, 1000);
164 break; 148 break;
165 case INA2XX_POWER: 149 case INA2XX_POWER:
166 /* LSB=25mW. Convert to uW */ 150 val = data->regs[reg] * data->config->power_lsb;
167 val = val * 25 * 1000;
168 break; 151 break;
169 case INA2XX_CURRENT: 152 case INA2XX_CURRENT:
170 /* LSB=1mA (selected). Is in mA */ 153 /* LSB=1mA (selected). Is in mA */
154 val = data->regs[reg];
171 break; 155 break;
172 default: 156 default:
173 /* programmer goofed */ 157 /* programmer goofed */
@@ -184,23 +168,12 @@ static ssize_t ina2xx_show_value(struct device *dev,
184{ 168{
185 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 169 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
186 struct ina2xx_data *data = ina2xx_update_device(dev); 170 struct ina2xx_data *data = ina2xx_update_device(dev);
187 int value = 0;
188 171
189 if (IS_ERR(data)) 172 if (IS_ERR(data))
190 return PTR_ERR(data); 173 return PTR_ERR(data);
191 174
192 switch (data->kind) { 175 return snprintf(buf, PAGE_SIZE, "%d\n",
193 case ina219: 176 ina2xx_get_value(data, attr->index));
194 value = ina219_get_value(data, attr->index);
195 break;
196 case ina226:
197 value = ina226_get_value(data, attr->index);
198 break;
199 default:
200 WARN_ON_ONCE(1);
201 break;
202 }
203 return snprintf(buf, PAGE_SIZE, "%d\n", value);
204} 177}
205 178
206/* shunt voltage */ 179/* shunt voltage */
@@ -238,7 +211,7 @@ static int ina2xx_probe(struct i2c_client *client,
238 struct i2c_adapter *adapter = client->adapter; 211 struct i2c_adapter *adapter = client->adapter;
239 struct ina2xx_data *data; 212 struct ina2xx_data *data;
240 struct ina2xx_platform_data *pdata; 213 struct ina2xx_platform_data *pdata;
241 int ret = 0; 214 int ret;
242 long shunt = 10000; /* default shunt value 10mOhms */ 215 long shunt = 10000; /* default shunt value 10mOhms */
243 216
244 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) 217 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
@@ -259,38 +232,15 @@ static int ina2xx_probe(struct i2c_client *client,
259 232
260 /* set the device type */ 233 /* set the device type */
261 data->kind = id->driver_data; 234 data->kind = id->driver_data;
235 data->config = &ina2xx_config[data->kind];
262 236
263 switch (data->kind) { 237 /* device configuration */
264 case ina219: 238 i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
265 /* device configuration */ 239 data->config->config_default);
266 i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, 240 /* set current LSB to 1mA, shunt is in uOhms */
267 INA219_CONFIG_DEFAULT); 241 /* (equation 13 in datasheet) */
268 242 i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
269 /* set current LSB to 1mA, shunt is in uOhms */ 243 data->config->calibration_factor / shunt);
270 /* (equation 13 in datasheet) */
271 i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
272 40960000 / shunt);
273 dev_info(&client->dev,
274 "power monitor INA219 (Rshunt = %li uOhm)\n", shunt);
275 data->registers = INA219_REGISTERS;
276 break;
277 case ina226:
278 /* device configuration */
279 i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
280 INA226_CONFIG_DEFAULT);
281
282 /* set current LSB to 1mA, shunt is in uOhms */
283 /* (equation 1 in datasheet)*/
284 i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
285 5120000 / shunt);
286 dev_info(&client->dev,
287 "power monitor INA226 (Rshunt = %li uOhm)\n", shunt);
288 data->registers = INA226_REGISTERS;
289 break;
290 default:
291 /* unknown device id */
292 return -ENODEV;
293 }
294 244
295 i2c_set_clientdata(client, data); 245 i2c_set_clientdata(client, data);
296 mutex_init(&data->update_lock); 246 mutex_init(&data->update_lock);
@@ -305,6 +255,9 @@ static int ina2xx_probe(struct i2c_client *client,
305 goto out_err_hwmon; 255 goto out_err_hwmon;
306 } 256 }
307 257
258 dev_info(&client->dev, "power monitor %s (Rshunt = %li uOhm)\n",
259 id->name, shunt);
260
308 return 0; 261 return 0;
309 262
310out_err_hwmon: 263out_err_hwmon: