root/drivers/hwmon/pcf8591.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. out0_output_show
  2. out0_output_store
  3. out0_enable_show
  4. out0_enable_store
  5. pcf8591_probe
  6. pcf8591_remove
  7. pcf8591_init_client
  8. pcf8591_read_channel
  9. pcf8591_init
  10. pcf8591_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net>
   4  * Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
   5  * the help of Jean Delvare <jdelvare@suse.de>
   6  */
   7 
   8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9 
  10 #include <linux/module.h>
  11 #include <linux/init.h>
  12 #include <linux/slab.h>
  13 #include <linux/i2c.h>
  14 #include <linux/mutex.h>
  15 #include <linux/err.h>
  16 #include <linux/hwmon.h>
  17 
  18 /* Insmod parameters */
  19 
  20 static int input_mode;
  21 module_param(input_mode, int, 0);
  22 MODULE_PARM_DESC(input_mode,
  23         "Analog input mode:\n"
  24         " 0 = four single ended inputs\n"
  25         " 1 = three differential inputs\n"
  26         " 2 = single ended and differential mixed\n"
  27         " 3 = two differential inputs\n");
  28 
  29 /*
  30  * The PCF8591 control byte
  31  *      7    6    5    4    3    2    1    0
  32  *   |  0 |AOEF|   AIP   |  0 |AINC|  AICH   |
  33  */
  34 
  35 /* Analog Output Enable Flag (analog output active if 1) */
  36 #define PCF8591_CONTROL_AOEF            0x40
  37 
  38 /*
  39  * Analog Input Programming
  40  * 0x00 = four single ended inputs
  41  * 0x10 = three differential inputs
  42  * 0x20 = single ended and differential mixed
  43  * 0x30 = two differential inputs
  44  */
  45 #define PCF8591_CONTROL_AIP_MASK        0x30
  46 
  47 /* Autoincrement Flag (switch on if 1) */
  48 #define PCF8591_CONTROL_AINC            0x04
  49 
  50 /*
  51  * Channel selection
  52  * 0x00 = channel 0
  53  * 0x01 = channel 1
  54  * 0x02 = channel 2
  55  * 0x03 = channel 3
  56  */
  57 #define PCF8591_CONTROL_AICH_MASK       0x03
  58 
  59 /* Initial values */
  60 #define PCF8591_INIT_CONTROL    ((input_mode << 4) | PCF8591_CONTROL_AOEF)
  61 #define PCF8591_INIT_AOUT       0       /* DAC out = 0 */
  62 
  63 /* Conversions */
  64 #define REG_TO_SIGNED(reg)      (((reg) & 0x80) ? ((reg) - 256) : (reg))
  65 
  66 struct pcf8591_data {
  67         struct device *hwmon_dev;
  68         struct mutex update_lock;
  69 
  70         u8 control;
  71         u8 aout;
  72 };
  73 
  74 static void pcf8591_init_client(struct i2c_client *client);
  75 static int pcf8591_read_channel(struct device *dev, int channel);
  76 
  77 /* following are the sysfs callback functions */
  78 #define show_in_channel(channel)                                        \
  79 static ssize_t show_in##channel##_input(struct device *dev,             \
  80                                         struct device_attribute *attr,  \
  81                                         char *buf)                      \
  82 {                                                                       \
  83         return sprintf(buf, "%d\n", pcf8591_read_channel(dev, channel));\
  84 }                                                                       \
  85 static DEVICE_ATTR(in##channel##_input, S_IRUGO,                        \
  86                    show_in##channel##_input, NULL);
  87 
  88 show_in_channel(0);
  89 show_in_channel(1);
  90 show_in_channel(2);
  91 show_in_channel(3);
  92 
  93 static ssize_t out0_output_show(struct device *dev,
  94                                 struct device_attribute *attr, char *buf)
  95 {
  96         struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
  97         return sprintf(buf, "%d\n", data->aout * 10);
  98 }
  99 
 100 static ssize_t out0_output_store(struct device *dev,
 101                                  struct device_attribute *attr,
 102                                  const char *buf, size_t count)
 103 {
 104         unsigned long val;
 105         struct i2c_client *client = to_i2c_client(dev);
 106         struct pcf8591_data *data = i2c_get_clientdata(client);
 107         int err;
 108 
 109         err = kstrtoul(buf, 10, &val);
 110         if (err)
 111                 return err;
 112 
 113         val /= 10;
 114         if (val > 255)
 115                 return -EINVAL;
 116 
 117         data->aout = val;
 118         i2c_smbus_write_byte_data(client, data->control, data->aout);
 119         return count;
 120 }
 121 
 122 static DEVICE_ATTR_RW(out0_output);
 123 
 124 static ssize_t out0_enable_show(struct device *dev,
 125                                 struct device_attribute *attr, char *buf)
 126 {
 127         struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
 128         return sprintf(buf, "%u\n", !(!(data->control & PCF8591_CONTROL_AOEF)));
 129 }
 130 
 131 static ssize_t out0_enable_store(struct device *dev,
 132                                  struct device_attribute *attr,
 133                                  const char *buf, size_t count)
 134 {
 135         struct i2c_client *client = to_i2c_client(dev);
 136         struct pcf8591_data *data = i2c_get_clientdata(client);
 137         unsigned long val;
 138         int err;
 139 
 140         err = kstrtoul(buf, 10, &val);
 141         if (err)
 142                 return err;
 143 
 144         mutex_lock(&data->update_lock);
 145         if (val)
 146                 data->control |= PCF8591_CONTROL_AOEF;
 147         else
 148                 data->control &= ~PCF8591_CONTROL_AOEF;
 149         i2c_smbus_write_byte(client, data->control);
 150         mutex_unlock(&data->update_lock);
 151         return count;
 152 }
 153 
 154 static DEVICE_ATTR_RW(out0_enable);
 155 
 156 static struct attribute *pcf8591_attributes[] = {
 157         &dev_attr_out0_enable.attr,
 158         &dev_attr_out0_output.attr,
 159         &dev_attr_in0_input.attr,
 160         &dev_attr_in1_input.attr,
 161         NULL
 162 };
 163 
 164 static const struct attribute_group pcf8591_attr_group = {
 165         .attrs = pcf8591_attributes,
 166 };
 167 
 168 static struct attribute *pcf8591_attributes_opt[] = {
 169         &dev_attr_in2_input.attr,
 170         &dev_attr_in3_input.attr,
 171         NULL
 172 };
 173 
 174 static const struct attribute_group pcf8591_attr_group_opt = {
 175         .attrs = pcf8591_attributes_opt,
 176 };
 177 
 178 /*
 179  * Real code
 180  */
 181 
 182 static int pcf8591_probe(struct i2c_client *client,
 183                          const struct i2c_device_id *id)
 184 {
 185         struct pcf8591_data *data;
 186         int err;
 187 
 188         data = devm_kzalloc(&client->dev, sizeof(struct pcf8591_data),
 189                             GFP_KERNEL);
 190         if (!data)
 191                 return -ENOMEM;
 192 
 193         i2c_set_clientdata(client, data);
 194         mutex_init(&data->update_lock);
 195 
 196         /* Initialize the PCF8591 chip */
 197         pcf8591_init_client(client);
 198 
 199         /* Register sysfs hooks */
 200         err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group);
 201         if (err)
 202                 return err;
 203 
 204         /* Register input2 if not in "two differential inputs" mode */
 205         if (input_mode != 3) {
 206                 err = device_create_file(&client->dev, &dev_attr_in2_input);
 207                 if (err)
 208                         goto exit_sysfs_remove;
 209         }
 210 
 211         /* Register input3 only in "four single ended inputs" mode */
 212         if (input_mode == 0) {
 213                 err = device_create_file(&client->dev, &dev_attr_in3_input);
 214                 if (err)
 215                         goto exit_sysfs_remove;
 216         }
 217 
 218         data->hwmon_dev = hwmon_device_register(&client->dev);
 219         if (IS_ERR(data->hwmon_dev)) {
 220                 err = PTR_ERR(data->hwmon_dev);
 221                 goto exit_sysfs_remove;
 222         }
 223 
 224         return 0;
 225 
 226 exit_sysfs_remove:
 227         sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
 228         sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
 229         return err;
 230 }
 231 
 232 static int pcf8591_remove(struct i2c_client *client)
 233 {
 234         struct pcf8591_data *data = i2c_get_clientdata(client);
 235 
 236         hwmon_device_unregister(data->hwmon_dev);
 237         sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
 238         sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
 239         return 0;
 240 }
 241 
 242 /* Called when we have found a new PCF8591. */
 243 static void pcf8591_init_client(struct i2c_client *client)
 244 {
 245         struct pcf8591_data *data = i2c_get_clientdata(client);
 246         data->control = PCF8591_INIT_CONTROL;
 247         data->aout = PCF8591_INIT_AOUT;
 248 
 249         i2c_smbus_write_byte_data(client, data->control, data->aout);
 250 
 251         /*
 252          * The first byte transmitted contains the conversion code of the
 253          * previous read cycle. FLUSH IT!
 254          */
 255         i2c_smbus_read_byte(client);
 256 }
 257 
 258 static int pcf8591_read_channel(struct device *dev, int channel)
 259 {
 260         u8 value;
 261         struct i2c_client *client = to_i2c_client(dev);
 262         struct pcf8591_data *data = i2c_get_clientdata(client);
 263 
 264         mutex_lock(&data->update_lock);
 265 
 266         if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) {
 267                 data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK)
 268                               | channel;
 269                 i2c_smbus_write_byte(client, data->control);
 270 
 271                 /*
 272                  * The first byte transmitted contains the conversion code of
 273                  * the previous read cycle. FLUSH IT!
 274                  */
 275                 i2c_smbus_read_byte(client);
 276         }
 277         value = i2c_smbus_read_byte(client);
 278 
 279         mutex_unlock(&data->update_lock);
 280 
 281         if ((channel == 2 && input_mode == 2) ||
 282             (channel != 3 && (input_mode == 1 || input_mode == 3)))
 283                 return 10 * REG_TO_SIGNED(value);
 284         else
 285                 return 10 * value;
 286 }
 287 
 288 static const struct i2c_device_id pcf8591_id[] = {
 289         { "pcf8591", 0 },
 290         { }
 291 };
 292 MODULE_DEVICE_TABLE(i2c, pcf8591_id);
 293 
 294 static struct i2c_driver pcf8591_driver = {
 295         .driver = {
 296                 .name   = "pcf8591",
 297         },
 298         .probe          = pcf8591_probe,
 299         .remove         = pcf8591_remove,
 300         .id_table       = pcf8591_id,
 301 };
 302 
 303 static int __init pcf8591_init(void)
 304 {
 305         if (input_mode < 0 || input_mode > 3) {
 306                 pr_warn("invalid input_mode (%d)\n", input_mode);
 307                 input_mode = 0;
 308         }
 309         return i2c_add_driver(&pcf8591_driver);
 310 }
 311 
 312 static void __exit pcf8591_exit(void)
 313 {
 314         i2c_del_driver(&pcf8591_driver);
 315 }
 316 
 317 MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
 318 MODULE_DESCRIPTION("PCF8591 driver");
 319 MODULE_LICENSE("GPL");
 320 
 321 module_init(pcf8591_init);
 322 module_exit(pcf8591_exit);

/* [<][>][^][v][top][bottom][index][help] */