max197.c (8727B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Maxim MAX197 A/D Converter driver 4 * 5 * Copyright (c) 2012 Savoir-faire Linux Inc. 6 * Vivien Didelot <vivien.didelot@savoirfairelinux.com> 7 * 8 * For further information, see the Documentation/hwmon/max197.rst file. 9 */ 10 11#include <linux/kernel.h> 12#include <linux/module.h> 13#include <linux/mod_devicetable.h> 14#include <linux/init.h> 15#include <linux/err.h> 16#include <linux/slab.h> 17#include <linux/mutex.h> 18#include <linux/device.h> 19#include <linux/sysfs.h> 20#include <linux/hwmon.h> 21#include <linux/hwmon-sysfs.h> 22#include <linux/platform_device.h> 23#include <linux/platform_data/max197.h> 24 25#define MAX199_LIMIT 4000 /* 4V */ 26#define MAX197_LIMIT 10000 /* 10V */ 27 28#define MAX197_NUM_CH 8 /* 8 Analog Input Channels */ 29 30/* Control byte format */ 31#define MAX197_BIP (1 << 3) /* Bipolarity */ 32#define MAX197_RNG (1 << 4) /* Full range */ 33 34#define MAX197_SCALE 12207 /* Scale coefficient for raw data */ 35 36/* List of supported chips */ 37enum max197_chips { max197, max199 }; 38 39/** 40 * struct max197_data - device instance specific data 41 * @pdata: Platform data. 42 * @hwmon_dev: The hwmon device. 43 * @lock: Read/Write mutex. 44 * @limit: Max range value (10V for MAX197, 4V for MAX199). 45 * @scale: Need to scale. 46 * @ctrl_bytes: Channels control byte. 47 */ 48struct max197_data { 49 struct max197_platform_data *pdata; 50 struct device *hwmon_dev; 51 struct mutex lock; 52 int limit; 53 bool scale; 54 u8 ctrl_bytes[MAX197_NUM_CH]; 55}; 56 57static inline void max197_set_unipolarity(struct max197_data *data, int channel) 58{ 59 data->ctrl_bytes[channel] &= ~MAX197_BIP; 60} 61 62static inline void max197_set_bipolarity(struct max197_data *data, int channel) 63{ 64 data->ctrl_bytes[channel] |= MAX197_BIP; 65} 66 67static inline void max197_set_half_range(struct max197_data *data, int channel) 68{ 69 data->ctrl_bytes[channel] &= ~MAX197_RNG; 70} 71 72static inline void max197_set_full_range(struct max197_data *data, int channel) 73{ 74 data->ctrl_bytes[channel] |= MAX197_RNG; 75} 76 77static inline bool max197_is_bipolar(struct max197_data *data, int channel) 78{ 79 return data->ctrl_bytes[channel] & MAX197_BIP; 80} 81 82static inline bool max197_is_full_range(struct max197_data *data, int channel) 83{ 84 return data->ctrl_bytes[channel] & MAX197_RNG; 85} 86 87/* Function called on read access on in{0,1,2,3,4,5,6,7}_{min,max} */ 88static ssize_t max197_show_range(struct device *dev, 89 struct device_attribute *devattr, char *buf) 90{ 91 struct max197_data *data = dev_get_drvdata(dev); 92 struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); 93 int channel = attr->index; 94 bool is_min = attr->nr; 95 int range; 96 97 if (mutex_lock_interruptible(&data->lock)) 98 return -ERESTARTSYS; 99 100 range = max197_is_full_range(data, channel) ? 101 data->limit : data->limit / 2; 102 if (is_min) { 103 if (max197_is_bipolar(data, channel)) 104 range = -range; 105 else 106 range = 0; 107 } 108 109 mutex_unlock(&data->lock); 110 111 return sprintf(buf, "%d\n", range); 112} 113 114/* Function called on write access on in{0,1,2,3,4,5,6,7}_{min,max} */ 115static ssize_t max197_store_range(struct device *dev, 116 struct device_attribute *devattr, 117 const char *buf, size_t count) 118{ 119 struct max197_data *data = dev_get_drvdata(dev); 120 struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); 121 int channel = attr->index; 122 bool is_min = attr->nr; 123 long value; 124 int half = data->limit / 2; 125 int full = data->limit; 126 127 if (kstrtol(buf, 10, &value)) 128 return -EINVAL; 129 130 if (is_min) { 131 if (value <= -full) 132 value = -full; 133 else if (value < 0) 134 value = -half; 135 else 136 value = 0; 137 } else { 138 if (value >= full) 139 value = full; 140 else 141 value = half; 142 } 143 144 if (mutex_lock_interruptible(&data->lock)) 145 return -ERESTARTSYS; 146 147 if (value == 0) { 148 /* We can deduce only the polarity */ 149 max197_set_unipolarity(data, channel); 150 } else if (value == -half) { 151 max197_set_bipolarity(data, channel); 152 max197_set_half_range(data, channel); 153 } else if (value == -full) { 154 max197_set_bipolarity(data, channel); 155 max197_set_full_range(data, channel); 156 } else if (value == half) { 157 /* We can deduce only the range */ 158 max197_set_half_range(data, channel); 159 } else if (value == full) { 160 /* We can deduce only the range */ 161 max197_set_full_range(data, channel); 162 } 163 164 mutex_unlock(&data->lock); 165 166 return count; 167} 168 169/* Function called on read access on in{0,1,2,3,4,5,6,7}_input */ 170static ssize_t max197_show_input(struct device *dev, 171 struct device_attribute *devattr, 172 char *buf) 173{ 174 struct max197_data *data = dev_get_drvdata(dev); 175 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 176 int channel = attr->index; 177 s32 value; 178 int ret; 179 180 if (mutex_lock_interruptible(&data->lock)) 181 return -ERESTARTSYS; 182 183 ret = data->pdata->convert(data->ctrl_bytes[channel]); 184 if (ret < 0) { 185 dev_err(dev, "conversion failed\n"); 186 goto unlock; 187 } 188 value = ret; 189 190 /* 191 * Coefficient to apply on raw value. 192 * See Table 1. Full Scale and Zero Scale in the MAX197 datasheet. 193 */ 194 if (data->scale) { 195 value *= MAX197_SCALE; 196 if (max197_is_full_range(data, channel)) 197 value *= 2; 198 value /= 10000; 199 } 200 201 ret = sprintf(buf, "%d\n", value); 202 203unlock: 204 mutex_unlock(&data->lock); 205 return ret; 206} 207 208static ssize_t name_show(struct device *dev, struct device_attribute *attr, 209 char *buf) 210{ 211 struct platform_device *pdev = to_platform_device(dev); 212 return sprintf(buf, "%s\n", pdev->name); 213} 214 215#define MAX197_SENSOR_DEVICE_ATTR_CH(chan) \ 216 static SENSOR_DEVICE_ATTR(in##chan##_input, S_IRUGO, \ 217 max197_show_input, NULL, chan); \ 218 static SENSOR_DEVICE_ATTR_2(in##chan##_min, S_IRUGO | S_IWUSR, \ 219 max197_show_range, \ 220 max197_store_range, \ 221 true, chan); \ 222 static SENSOR_DEVICE_ATTR_2(in##chan##_max, S_IRUGO | S_IWUSR, \ 223 max197_show_range, \ 224 max197_store_range, \ 225 false, chan) 226 227#define MAX197_SENSOR_DEV_ATTR_IN(chan) \ 228 &sensor_dev_attr_in##chan##_input.dev_attr.attr, \ 229 &sensor_dev_attr_in##chan##_max.dev_attr.attr, \ 230 &sensor_dev_attr_in##chan##_min.dev_attr.attr 231 232static DEVICE_ATTR_RO(name); 233 234MAX197_SENSOR_DEVICE_ATTR_CH(0); 235MAX197_SENSOR_DEVICE_ATTR_CH(1); 236MAX197_SENSOR_DEVICE_ATTR_CH(2); 237MAX197_SENSOR_DEVICE_ATTR_CH(3); 238MAX197_SENSOR_DEVICE_ATTR_CH(4); 239MAX197_SENSOR_DEVICE_ATTR_CH(5); 240MAX197_SENSOR_DEVICE_ATTR_CH(6); 241MAX197_SENSOR_DEVICE_ATTR_CH(7); 242 243static const struct attribute_group max197_sysfs_group = { 244 .attrs = (struct attribute *[]) { 245 &dev_attr_name.attr, 246 MAX197_SENSOR_DEV_ATTR_IN(0), 247 MAX197_SENSOR_DEV_ATTR_IN(1), 248 MAX197_SENSOR_DEV_ATTR_IN(2), 249 MAX197_SENSOR_DEV_ATTR_IN(3), 250 MAX197_SENSOR_DEV_ATTR_IN(4), 251 MAX197_SENSOR_DEV_ATTR_IN(5), 252 MAX197_SENSOR_DEV_ATTR_IN(6), 253 MAX197_SENSOR_DEV_ATTR_IN(7), 254 NULL 255 }, 256}; 257 258static int max197_probe(struct platform_device *pdev) 259{ 260 int ch, ret; 261 struct max197_data *data; 262 struct max197_platform_data *pdata = dev_get_platdata(&pdev->dev); 263 enum max197_chips chip = platform_get_device_id(pdev)->driver_data; 264 265 if (pdata == NULL) { 266 dev_err(&pdev->dev, "no platform data supplied\n"); 267 return -EINVAL; 268 } 269 270 if (pdata->convert == NULL) { 271 dev_err(&pdev->dev, "no convert function supplied\n"); 272 return -EINVAL; 273 } 274 275 data = devm_kzalloc(&pdev->dev, sizeof(struct max197_data), GFP_KERNEL); 276 if (!data) 277 return -ENOMEM; 278 279 data->pdata = pdata; 280 mutex_init(&data->lock); 281 282 if (chip == max197) { 283 data->limit = MAX197_LIMIT; 284 data->scale = true; 285 } else { 286 data->limit = MAX199_LIMIT; 287 data->scale = false; 288 } 289 290 for (ch = 0; ch < MAX197_NUM_CH; ch++) 291 data->ctrl_bytes[ch] = (u8) ch; 292 293 platform_set_drvdata(pdev, data); 294 295 ret = sysfs_create_group(&pdev->dev.kobj, &max197_sysfs_group); 296 if (ret) { 297 dev_err(&pdev->dev, "sysfs create group failed\n"); 298 return ret; 299 } 300 301 data->hwmon_dev = hwmon_device_register(&pdev->dev); 302 if (IS_ERR(data->hwmon_dev)) { 303 ret = PTR_ERR(data->hwmon_dev); 304 dev_err(&pdev->dev, "hwmon device register failed\n"); 305 goto error; 306 } 307 308 return 0; 309 310error: 311 sysfs_remove_group(&pdev->dev.kobj, &max197_sysfs_group); 312 return ret; 313} 314 315static int max197_remove(struct platform_device *pdev) 316{ 317 struct max197_data *data = platform_get_drvdata(pdev); 318 319 hwmon_device_unregister(data->hwmon_dev); 320 sysfs_remove_group(&pdev->dev.kobj, &max197_sysfs_group); 321 322 return 0; 323} 324 325static const struct platform_device_id max197_device_ids[] = { 326 { "max197", max197 }, 327 { "max199", max199 }, 328 { } 329}; 330MODULE_DEVICE_TABLE(platform, max197_device_ids); 331 332static struct platform_driver max197_driver = { 333 .driver = { 334 .name = "max197", 335 }, 336 .probe = max197_probe, 337 .remove = max197_remove, 338 .id_table = max197_device_ids, 339}; 340module_platform_driver(max197_driver); 341 342MODULE_LICENSE("GPL"); 343MODULE_AUTHOR("Savoir-faire Linux Inc. <kernel@savoirfairelinux.com>"); 344MODULE_DESCRIPTION("Maxim MAX197 A/D Converter driver");