Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: Add support for Lattice's POWR1220 power manager IC

This patch adds support for Lattice's POWR1220 power manager IC. Read
access to all the ADCs on the chip are supported through the hwmon
sysfs files.

Signed-off-by: Scott Kanowitz <skanowitz@echo360.com>
[Guenter Roeck: Removed some extra ( )]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

authored by

Scott Kanowitz and committed by
Guenter Roeck
f4ff4155 99765db2

+449
+45
Documentation/hwmon/powr1220
··· 1 + Kernel driver powr1220 2 + ================== 3 + 4 + Supported chips: 5 + * Lattice POWR1220AT8 6 + Prefix: 'powr1220' 7 + Addresses scanned: none 8 + Datasheet: Publicly available at the Lattice website 9 + http://www.latticesemi.com/ 10 + 11 + Author: Scott Kanowitz <scott.kanowitz@gmail.com> 12 + 13 + Description 14 + ----------- 15 + 16 + This driver supports the Lattice POWR1220AT8 chip. The POWR1220 17 + includes voltage monitoring for 14 inputs as well as trim settings 18 + for output voltages and GPIOs. This driver implements the voltage 19 + monitoring portion of the chip. 20 + 21 + Voltages are sampled by a 12-bit ADC with a step size of 2 mV. 22 + An in-line attenuator allows measurements from 0 to 6 V. The 23 + attenuator is enabled or disabled depending on the setting of the 24 + input's max value. The driver will enable the attenuator for any 25 + value over the low measurement range maximum of 2 V. 26 + 27 + The input naming convention is as follows: 28 + 29 + driver name pin name 30 + in0 VMON1 31 + in1 VMON2 32 + in2 VMON3 33 + in2 VMON4 34 + in4 VMON5 35 + in5 VMON6 36 + in6 VMON7 37 + in7 VMON8 38 + in8 VMON9 39 + in9 VMON10 40 + in10 VMON11 41 + in11 VMON12 42 + in12 VCCA 43 + in13 VCCINP 44 + 45 + The ADC readings are updated on request with a minimum period of 1s.
+12
drivers/hwmon/Kconfig
··· 608 608 This driver can also be built as a module. If so, the module 609 609 will be called jc42. 610 610 611 + config SENSORS_POWR1220 612 + tristate "Lattice POWR1220 Power Monitoring" 613 + depends on I2C 614 + default n 615 + help 616 + If you say yes here you get access to the hardware monitoring 617 + functions of the Lattice POWR1220 isp Power Supply Monitoring, 618 + Sequencing and Margining Controller. 619 + 620 + This driver can also be built as a module. If so, the module 621 + will be called powr1220. 622 + 611 623 config SENSORS_LINEAGE 612 624 tristate "Lineage Compact Power Line Power Entry Module" 613 625 depends on I2C
+1
drivers/hwmon/Makefile
··· 120 120 obj-$(CONFIG_SENSORS_PC87360) += pc87360.o 121 121 obj-$(CONFIG_SENSORS_PC87427) += pc87427.o 122 122 obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o 123 + obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o 123 124 obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o 124 125 obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o 125 126 obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
+391
drivers/hwmon/powr1220.c
··· 1 + /* 2 + * powr1220.c - Driver for the Lattice POWR1220 programmable power supply 3 + * and monitor. Users can read all ADC inputs along with their labels 4 + * using the sysfs nodes. 5 + * 6 + * Copyright (c) 2014 Echo360 http://www.echo360.com 7 + * Scott Kanowitz <skanowitz@echo360.com> <scott.kanowitz@gmail.com> 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation; either version 2 of the License, or 12 + * (at your option) any later version. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + */ 19 + 20 + #include <linux/module.h> 21 + #include <linux/init.h> 22 + #include <linux/slab.h> 23 + #include <linux/jiffies.h> 24 + #include <linux/i2c.h> 25 + #include <linux/hwmon.h> 26 + #include <linux/hwmon-sysfs.h> 27 + #include <linux/err.h> 28 + #include <linux/mutex.h> 29 + #include <linux/delay.h> 30 + 31 + #define ADC_STEP_MV 2 32 + #define ADC_MAX_LOW_MEASUREMENT_MV 2000 33 + 34 + enum powr1220_regs { 35 + VMON_STATUS0, 36 + VMON_STATUS1, 37 + VMON_STATUS2, 38 + OUTPUT_STATUS0, 39 + OUTPUT_STATUS1, 40 + OUTPUT_STATUS2, 41 + INPUT_STATUS, 42 + ADC_VALUE_LOW, 43 + ADC_VALUE_HIGH, 44 + ADC_MUX, 45 + UES_BYTE0, 46 + UES_BYTE1, 47 + UES_BYTE2, 48 + UES_BYTE3, 49 + GP_OUTPUT1, 50 + GP_OUTPUT2, 51 + GP_OUTPUT3, 52 + INPUT_VALUE, 53 + RESET, 54 + TRIM1_TRIM, 55 + TRIM2_TRIM, 56 + TRIM3_TRIM, 57 + TRIM4_TRIM, 58 + TRIM5_TRIM, 59 + TRIM6_TRIM, 60 + TRIM7_TRIM, 61 + TRIM8_TRIM, 62 + MAX_POWR1220_REGS 63 + }; 64 + 65 + enum powr1220_adc_values { 66 + VMON1, 67 + VMON2, 68 + VMON3, 69 + VMON4, 70 + VMON5, 71 + VMON6, 72 + VMON7, 73 + VMON8, 74 + VMON9, 75 + VMON10, 76 + VMON11, 77 + VMON12, 78 + VCCA, 79 + VCCINP, 80 + MAX_POWR1220_ADC_VALUES 81 + }; 82 + 83 + struct powr1220_data { 84 + struct i2c_client *client; 85 + struct mutex update_lock; 86 + bool adc_valid[MAX_POWR1220_ADC_VALUES]; 87 + /* the next value is in jiffies */ 88 + unsigned long adc_last_updated[MAX_POWR1220_ADC_VALUES]; 89 + 90 + /* values */ 91 + int adc_maxes[MAX_POWR1220_ADC_VALUES]; 92 + int adc_values[MAX_POWR1220_ADC_VALUES]; 93 + }; 94 + 95 + static const char * const input_names[] = { 96 + [VMON1] = "vmon1", 97 + [VMON2] = "vmon2", 98 + [VMON3] = "vmon3", 99 + [VMON4] = "vmon4", 100 + [VMON5] = "vmon5", 101 + [VMON6] = "vmon6", 102 + [VMON7] = "vmon7", 103 + [VMON8] = "vmon8", 104 + [VMON9] = "vmon9", 105 + [VMON10] = "vmon10", 106 + [VMON11] = "vmon11", 107 + [VMON12] = "vmon12", 108 + [VCCA] = "vcca", 109 + [VCCINP] = "vccinp", 110 + }; 111 + 112 + /* Reads the specified ADC channel */ 113 + static int powr1220_read_adc(struct device *dev, int ch_num) 114 + { 115 + struct powr1220_data *data = dev_get_drvdata(dev); 116 + int reading; 117 + int result; 118 + int adc_range = 0; 119 + 120 + mutex_lock(&data->update_lock); 121 + 122 + if (time_after(jiffies, data->adc_last_updated[ch_num] + HZ) || 123 + !data->adc_valid[ch_num]) { 124 + /* 125 + * figure out if we need to use the attenuator for 126 + * high inputs or inputs that we don't yet have a measurement 127 + * for. We dynamically set the attenuator depending on the 128 + * max reading. 129 + */ 130 + if (data->adc_maxes[ch_num] > ADC_MAX_LOW_MEASUREMENT_MV || 131 + data->adc_maxes[ch_num] == 0) 132 + adc_range = 1 << 4; 133 + 134 + /* set the attenuator and mux */ 135 + result = i2c_smbus_write_byte_data(data->client, ADC_MUX, 136 + adc_range | ch_num); 137 + if (result) 138 + goto exit; 139 + 140 + /* 141 + * wait at least Tconvert time (200 us) for the 142 + * conversion to complete 143 + */ 144 + udelay(200); 145 + 146 + /* get the ADC reading */ 147 + result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_LOW); 148 + if (result < 0) 149 + goto exit; 150 + 151 + reading = result >> 4; 152 + 153 + /* get the upper half of the reading */ 154 + result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_HIGH); 155 + if (result < 0) 156 + goto exit; 157 + 158 + reading |= result << 4; 159 + 160 + /* now convert the reading to a voltage */ 161 + reading *= ADC_STEP_MV; 162 + data->adc_values[ch_num] = reading; 163 + data->adc_valid[ch_num] = true; 164 + data->adc_last_updated[ch_num] = jiffies; 165 + result = reading; 166 + 167 + if (reading > data->adc_maxes[ch_num]) 168 + data->adc_maxes[ch_num] = reading; 169 + } else { 170 + result = data->adc_values[ch_num]; 171 + } 172 + 173 + exit: 174 + mutex_unlock(&data->update_lock); 175 + 176 + return result; 177 + } 178 + 179 + /* Shows the voltage associated with the specified ADC channel */ 180 + static ssize_t powr1220_show_voltage(struct device *dev, 181 + struct device_attribute *dev_attr, char *buf) 182 + { 183 + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); 184 + int adc_val = powr1220_read_adc(dev, attr->index); 185 + 186 + if (adc_val < 0) 187 + return adc_val; 188 + 189 + return sprintf(buf, "%d\n", adc_val); 190 + } 191 + 192 + /* Shows the maximum setting associated with the specified ADC channel */ 193 + static ssize_t powr1220_show_max(struct device *dev, 194 + struct device_attribute *dev_attr, char *buf) 195 + { 196 + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); 197 + struct powr1220_data *data = dev_get_drvdata(dev); 198 + 199 + return sprintf(buf, "%d\n", data->adc_maxes[attr->index]); 200 + } 201 + 202 + /* Shows the label associated with the specified ADC channel */ 203 + static ssize_t powr1220_show_label(struct device *dev, 204 + struct device_attribute *dev_attr, char *buf) 205 + { 206 + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); 207 + 208 + return sprintf(buf, "%s\n", input_names[attr->index]); 209 + } 210 + 211 + static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, powr1220_show_voltage, NULL, 212 + VMON1); 213 + static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, powr1220_show_voltage, NULL, 214 + VMON2); 215 + static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, powr1220_show_voltage, NULL, 216 + VMON3); 217 + static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, powr1220_show_voltage, NULL, 218 + VMON4); 219 + static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, powr1220_show_voltage, NULL, 220 + VMON5); 221 + static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, powr1220_show_voltage, NULL, 222 + VMON6); 223 + static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, powr1220_show_voltage, NULL, 224 + VMON7); 225 + static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, powr1220_show_voltage, NULL, 226 + VMON8); 227 + static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, powr1220_show_voltage, NULL, 228 + VMON9); 229 + static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, powr1220_show_voltage, NULL, 230 + VMON10); 231 + static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, powr1220_show_voltage, NULL, 232 + VMON11); 233 + static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, powr1220_show_voltage, NULL, 234 + VMON12); 235 + static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, powr1220_show_voltage, NULL, 236 + VCCA); 237 + static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, powr1220_show_voltage, NULL, 238 + VCCINP); 239 + 240 + static SENSOR_DEVICE_ATTR(in0_highest, S_IRUGO, powr1220_show_max, NULL, 241 + VMON1); 242 + static SENSOR_DEVICE_ATTR(in1_highest, S_IRUGO, powr1220_show_max, NULL, 243 + VMON2); 244 + static SENSOR_DEVICE_ATTR(in2_highest, S_IRUGO, powr1220_show_max, NULL, 245 + VMON3); 246 + static SENSOR_DEVICE_ATTR(in3_highest, S_IRUGO, powr1220_show_max, NULL, 247 + VMON4); 248 + static SENSOR_DEVICE_ATTR(in4_highest, S_IRUGO, powr1220_show_max, NULL, 249 + VMON5); 250 + static SENSOR_DEVICE_ATTR(in5_highest, S_IRUGO, powr1220_show_max, NULL, 251 + VMON6); 252 + static SENSOR_DEVICE_ATTR(in6_highest, S_IRUGO, powr1220_show_max, NULL, 253 + VMON7); 254 + static SENSOR_DEVICE_ATTR(in7_highest, S_IRUGO, powr1220_show_max, NULL, 255 + VMON8); 256 + static SENSOR_DEVICE_ATTR(in8_highest, S_IRUGO, powr1220_show_max, NULL, 257 + VMON9); 258 + static SENSOR_DEVICE_ATTR(in9_highest, S_IRUGO, powr1220_show_max, NULL, 259 + VMON10); 260 + static SENSOR_DEVICE_ATTR(in10_highest, S_IRUGO, powr1220_show_max, NULL, 261 + VMON11); 262 + static SENSOR_DEVICE_ATTR(in11_highest, S_IRUGO, powr1220_show_max, NULL, 263 + VMON12); 264 + static SENSOR_DEVICE_ATTR(in12_highest, S_IRUGO, powr1220_show_max, NULL, 265 + VCCA); 266 + static SENSOR_DEVICE_ATTR(in13_highest, S_IRUGO, powr1220_show_max, NULL, 267 + VCCINP); 268 + 269 + static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, powr1220_show_label, NULL, 270 + VMON1); 271 + static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, powr1220_show_label, NULL, 272 + VMON2); 273 + static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, powr1220_show_label, NULL, 274 + VMON3); 275 + static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, powr1220_show_label, NULL, 276 + VMON4); 277 + static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, powr1220_show_label, NULL, 278 + VMON5); 279 + static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, powr1220_show_label, NULL, 280 + VMON6); 281 + static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, powr1220_show_label, NULL, 282 + VMON7); 283 + static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, powr1220_show_label, NULL, 284 + VMON8); 285 + static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, powr1220_show_label, NULL, 286 + VMON9); 287 + static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, powr1220_show_label, NULL, 288 + VMON10); 289 + static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, powr1220_show_label, NULL, 290 + VMON11); 291 + static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, powr1220_show_label, NULL, 292 + VMON12); 293 + static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, powr1220_show_label, NULL, 294 + VCCA); 295 + static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, powr1220_show_label, NULL, 296 + VCCINP); 297 + 298 + static struct attribute *powr1220_attrs[] = { 299 + &sensor_dev_attr_in0_input.dev_attr.attr, 300 + &sensor_dev_attr_in1_input.dev_attr.attr, 301 + &sensor_dev_attr_in2_input.dev_attr.attr, 302 + &sensor_dev_attr_in3_input.dev_attr.attr, 303 + &sensor_dev_attr_in4_input.dev_attr.attr, 304 + &sensor_dev_attr_in5_input.dev_attr.attr, 305 + &sensor_dev_attr_in6_input.dev_attr.attr, 306 + &sensor_dev_attr_in7_input.dev_attr.attr, 307 + &sensor_dev_attr_in8_input.dev_attr.attr, 308 + &sensor_dev_attr_in9_input.dev_attr.attr, 309 + &sensor_dev_attr_in10_input.dev_attr.attr, 310 + &sensor_dev_attr_in11_input.dev_attr.attr, 311 + &sensor_dev_attr_in12_input.dev_attr.attr, 312 + &sensor_dev_attr_in13_input.dev_attr.attr, 313 + 314 + &sensor_dev_attr_in0_highest.dev_attr.attr, 315 + &sensor_dev_attr_in1_highest.dev_attr.attr, 316 + &sensor_dev_attr_in2_highest.dev_attr.attr, 317 + &sensor_dev_attr_in3_highest.dev_attr.attr, 318 + &sensor_dev_attr_in4_highest.dev_attr.attr, 319 + &sensor_dev_attr_in5_highest.dev_attr.attr, 320 + &sensor_dev_attr_in6_highest.dev_attr.attr, 321 + &sensor_dev_attr_in7_highest.dev_attr.attr, 322 + &sensor_dev_attr_in8_highest.dev_attr.attr, 323 + &sensor_dev_attr_in9_highest.dev_attr.attr, 324 + &sensor_dev_attr_in10_highest.dev_attr.attr, 325 + &sensor_dev_attr_in11_highest.dev_attr.attr, 326 + &sensor_dev_attr_in12_highest.dev_attr.attr, 327 + &sensor_dev_attr_in13_highest.dev_attr.attr, 328 + 329 + &sensor_dev_attr_in0_label.dev_attr.attr, 330 + &sensor_dev_attr_in1_label.dev_attr.attr, 331 + &sensor_dev_attr_in2_label.dev_attr.attr, 332 + &sensor_dev_attr_in3_label.dev_attr.attr, 333 + &sensor_dev_attr_in4_label.dev_attr.attr, 334 + &sensor_dev_attr_in5_label.dev_attr.attr, 335 + &sensor_dev_attr_in6_label.dev_attr.attr, 336 + &sensor_dev_attr_in7_label.dev_attr.attr, 337 + &sensor_dev_attr_in8_label.dev_attr.attr, 338 + &sensor_dev_attr_in9_label.dev_attr.attr, 339 + &sensor_dev_attr_in10_label.dev_attr.attr, 340 + &sensor_dev_attr_in11_label.dev_attr.attr, 341 + &sensor_dev_attr_in12_label.dev_attr.attr, 342 + &sensor_dev_attr_in13_label.dev_attr.attr, 343 + 344 + NULL 345 + }; 346 + 347 + ATTRIBUTE_GROUPS(powr1220); 348 + 349 + static int powr1220_probe(struct i2c_client *client, 350 + const struct i2c_device_id *id) 351 + { 352 + struct powr1220_data *data; 353 + struct device *hwmon_dev; 354 + 355 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 356 + return -ENODEV; 357 + 358 + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 359 + if (!data) 360 + return -ENOMEM; 361 + 362 + mutex_init(&data->update_lock); 363 + data->client = client; 364 + 365 + hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, 366 + client->name, data, powr1220_groups); 367 + 368 + return PTR_ERR_OR_ZERO(hwmon_dev); 369 + } 370 + 371 + static const struct i2c_device_id powr1220_ids[] = { 372 + { "powr1220", 0, }, 373 + { } 374 + }; 375 + 376 + MODULE_DEVICE_TABLE(i2c, powr1220_ids); 377 + 378 + static struct i2c_driver powr1220_driver = { 379 + .class = I2C_CLASS_HWMON, 380 + .driver = { 381 + .name = "powr1220", 382 + }, 383 + .probe = powr1220_probe, 384 + .id_table = powr1220_ids, 385 + }; 386 + 387 + module_i2c_driver(powr1220_driver); 388 + 389 + MODULE_AUTHOR("Scott Kanowitz"); 390 + MODULE_DESCRIPTION("POWR1220 driver"); 391 + MODULE_LICENSE("GPL");