338 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * powr1220.c - Driver for the Lattice POWR1220 programmable power supply4 * and monitor. Users can read all ADC inputs along with their labels5 * using the sysfs nodes.6 *7 * Copyright (c) 2014 Echo360 https://www.echo360.com8 * Scott Kanowitz <skanowitz@echo360.com> <scott.kanowitz@gmail.com>9 */10 11#include <linux/module.h>12#include <linux/init.h>13#include <linux/slab.h>14#include <linux/jiffies.h>15#include <linux/i2c.h>16#include <linux/hwmon.h>17#include <linux/hwmon-sysfs.h>18#include <linux/err.h>19#include <linux/mutex.h>20#include <linux/delay.h>21 22#define ADC_STEP_MV 223#define ADC_MAX_LOW_MEASUREMENT_MV 200024 25enum powr1xxx_chips { powr1014, powr1220 };26 27enum powr1220_regs {28 VMON_STATUS0,29 VMON_STATUS1,30 VMON_STATUS2,31 OUTPUT_STATUS0,32 OUTPUT_STATUS1,33 OUTPUT_STATUS2,34 INPUT_STATUS,35 ADC_VALUE_LOW,36 ADC_VALUE_HIGH,37 ADC_MUX,38 UES_BYTE0,39 UES_BYTE1,40 UES_BYTE2,41 UES_BYTE3,42 GP_OUTPUT1,43 GP_OUTPUT2,44 GP_OUTPUT3,45 INPUT_VALUE,46 RESET,47 TRIM1_TRIM,48 TRIM2_TRIM,49 TRIM3_TRIM,50 TRIM4_TRIM,51 TRIM5_TRIM,52 TRIM6_TRIM,53 TRIM7_TRIM,54 TRIM8_TRIM,55 MAX_POWR1220_REGS56};57 58enum powr1220_adc_values {59 VMON1,60 VMON2,61 VMON3,62 VMON4,63 VMON5,64 VMON6,65 VMON7,66 VMON8,67 VMON9,68 VMON10,69 VMON11,70 VMON12,71 VCCA,72 VCCINP,73 MAX_POWR1220_ADC_VALUES74};75 76struct powr1220_data {77 struct i2c_client *client;78 struct mutex update_lock;79 u8 max_channels;80 bool adc_valid[MAX_POWR1220_ADC_VALUES];81 /* the next value is in jiffies */82 unsigned long adc_last_updated[MAX_POWR1220_ADC_VALUES];83 84 /* values */85 int adc_maxes[MAX_POWR1220_ADC_VALUES];86 int adc_values[MAX_POWR1220_ADC_VALUES];87};88 89static const char * const input_names[] = {90 [VMON1] = "vmon1",91 [VMON2] = "vmon2",92 [VMON3] = "vmon3",93 [VMON4] = "vmon4",94 [VMON5] = "vmon5",95 [VMON6] = "vmon6",96 [VMON7] = "vmon7",97 [VMON8] = "vmon8",98 [VMON9] = "vmon9",99 [VMON10] = "vmon10",100 [VMON11] = "vmon11",101 [VMON12] = "vmon12",102 [VCCA] = "vcca",103 [VCCINP] = "vccinp",104};105 106/* Reads the specified ADC channel */107static int powr1220_read_adc(struct device *dev, int ch_num)108{109 struct powr1220_data *data = dev_get_drvdata(dev);110 int reading;111 int result;112 int adc_range = 0;113 114 mutex_lock(&data->update_lock);115 116 if (time_after(jiffies, data->adc_last_updated[ch_num] + HZ) ||117 !data->adc_valid[ch_num]) {118 /*119 * figure out if we need to use the attenuator for120 * high inputs or inputs that we don't yet have a measurement121 * for. We dynamically set the attenuator depending on the122 * max reading.123 */124 if (data->adc_maxes[ch_num] > ADC_MAX_LOW_MEASUREMENT_MV ||125 data->adc_maxes[ch_num] == 0)126 adc_range = 1 << 4;127 128 /* set the attenuator and mux */129 result = i2c_smbus_write_byte_data(data->client, ADC_MUX,130 adc_range | ch_num);131 if (result)132 goto exit;133 134 /*135 * wait at least Tconvert time (200 us) for the136 * conversion to complete137 */138 udelay(200);139 140 /* get the ADC reading */141 result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_LOW);142 if (result < 0)143 goto exit;144 145 reading = result >> 4;146 147 /* get the upper half of the reading */148 result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_HIGH);149 if (result < 0)150 goto exit;151 152 reading |= result << 4;153 154 /* now convert the reading to a voltage */155 reading *= ADC_STEP_MV;156 data->adc_values[ch_num] = reading;157 data->adc_valid[ch_num] = true;158 data->adc_last_updated[ch_num] = jiffies;159 result = reading;160 161 if (reading > data->adc_maxes[ch_num])162 data->adc_maxes[ch_num] = reading;163 } else {164 result = data->adc_values[ch_num];165 }166 167exit:168 mutex_unlock(&data->update_lock);169 170 return result;171}172 173static umode_t174powr1220_is_visible(const void *data, enum hwmon_sensor_types type, u32175 attr, int channel)176{177 struct powr1220_data *chip_data = (struct powr1220_data *)data;178 179 if (channel >= chip_data->max_channels)180 return 0;181 182 switch (type) {183 case hwmon_in:184 switch (attr) {185 case hwmon_in_input:186 case hwmon_in_highest:187 case hwmon_in_label:188 return 0444;189 default:190 break;191 }192 break;193 default:194 break;195 }196 197 return 0;198}199 200static int201powr1220_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,202 int channel, const char **str)203{204 switch (type) {205 case hwmon_in:206 switch (attr) {207 case hwmon_in_label:208 *str = input_names[channel];209 return 0;210 default:211 return -EOPNOTSUPP;212 }213 break;214 default:215 return -EOPNOTSUPP;216 }217 218 return -EOPNOTSUPP;219}220 221static int222powr1220_read(struct device *dev, enum hwmon_sensor_types type, u32223 attr, int channel, long *val)224{225 struct powr1220_data *data = dev_get_drvdata(dev);226 int ret;227 228 switch (type) {229 case hwmon_in:230 switch (attr) {231 case hwmon_in_input:232 ret = powr1220_read_adc(dev, channel);233 if (ret < 0)234 return ret;235 *val = ret;236 break;237 case hwmon_in_highest:238 *val = data->adc_maxes[channel];239 break;240 default:241 return -EOPNOTSUPP;242 }243 break;244 default:245 return -EOPNOTSUPP;246}247 248 return 0;249}250 251static const struct hwmon_channel_info * const powr1220_info[] = {252 HWMON_CHANNEL_INFO(in,253 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,254 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,255 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,256 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,257 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,258 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,259 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,260 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,261 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,262 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,263 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,264 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,265 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,266 HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL),267 268 NULL269};270 271static const struct hwmon_ops powr1220_hwmon_ops = {272 .read = powr1220_read,273 .read_string = powr1220_read_string,274 .is_visible = powr1220_is_visible,275};276 277static const struct hwmon_chip_info powr1220_chip_info = {278 .ops = &powr1220_hwmon_ops,279 .info = powr1220_info,280};281 282static int powr1220_probe(struct i2c_client *client)283{284 struct powr1220_data *data;285 struct device *hwmon_dev;286 enum powr1xxx_chips chip;287 288 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))289 return -ENODEV;290 291 data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);292 if (!data)293 return -ENOMEM;294 295 chip = (uintptr_t)i2c_get_match_data(client);296 switch (chip) {297 case powr1014:298 data->max_channels = 10;299 break;300 default:301 data->max_channels = 12;302 break;303 }304 305 mutex_init(&data->update_lock);306 data->client = client;307 308 hwmon_dev = devm_hwmon_device_register_with_info(&client->dev,309 client->name,310 data,311 &powr1220_chip_info,312 NULL);313 314 return PTR_ERR_OR_ZERO(hwmon_dev);315}316 317static const struct i2c_device_id powr1220_ids[] = {318 { "powr1014", powr1014, },319 { "powr1220", powr1220, },320 { }321};322 323MODULE_DEVICE_TABLE(i2c, powr1220_ids);324 325static struct i2c_driver powr1220_driver = {326 .driver = {327 .name = "powr1220",328 },329 .probe = powr1220_probe,330 .id_table = powr1220_ids,331};332 333module_i2c_driver(powr1220_driver);334 335MODULE_AUTHOR("Scott Kanowitz");336MODULE_DESCRIPTION("POWR1220 driver");337MODULE_LICENSE("GPL");338