174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2fb4504feSJean Delvare /*
357256088SGuenter Roeck * Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net>
457256088SGuenter Roeck * Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
57c81c60fSJean Delvare * the help of Jean Delvare <jdelvare@suse.de>
6fb4504feSJean Delvare */
7fb4504feSJean Delvare
82caec134SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
92caec134SJoe Perches
10fb4504feSJean Delvare #include <linux/module.h>
11fb4504feSJean Delvare #include <linux/init.h>
12fb4504feSJean Delvare #include <linux/slab.h>
13fb4504feSJean Delvare #include <linux/i2c.h>
14fb4504feSJean Delvare #include <linux/mutex.h>
154275fcd6SJean Delvare #include <linux/err.h>
164275fcd6SJean Delvare #include <linux/hwmon.h>
1725f98688SChristophe JAILLET #include <linux/kstrtox.h>
18fb4504feSJean Delvare
19fb4504feSJean Delvare /* Insmod parameters */
20fb4504feSJean Delvare
21fb4504feSJean Delvare static int input_mode;
22fb4504feSJean Delvare module_param(input_mode, int, 0);
23fb4504feSJean Delvare MODULE_PARM_DESC(input_mode,
24fb4504feSJean Delvare "Analog input mode:\n"
25fb4504feSJean Delvare " 0 = four single ended inputs\n"
26fb4504feSJean Delvare " 1 = three differential inputs\n"
27fb4504feSJean Delvare " 2 = single ended and differential mixed\n"
28fb4504feSJean Delvare " 3 = two differential inputs\n");
29fb4504feSJean Delvare
3057256088SGuenter Roeck /*
3157256088SGuenter Roeck * The PCF8591 control byte
3257256088SGuenter Roeck * 7 6 5 4 3 2 1 0
3357256088SGuenter Roeck * | 0 |AOEF| AIP | 0 |AINC| AICH |
3457256088SGuenter Roeck */
35fb4504feSJean Delvare
36fb4504feSJean Delvare /* Analog Output Enable Flag (analog output active if 1) */
37fb4504feSJean Delvare #define PCF8591_CONTROL_AOEF 0x40
38fb4504feSJean Delvare
3957256088SGuenter Roeck /*
4057256088SGuenter Roeck * Analog Input Programming
4157256088SGuenter Roeck * 0x00 = four single ended inputs
4257256088SGuenter Roeck * 0x10 = three differential inputs
4357256088SGuenter Roeck * 0x20 = single ended and differential mixed
4457256088SGuenter Roeck * 0x30 = two differential inputs
4557256088SGuenter Roeck */
46fb4504feSJean Delvare #define PCF8591_CONTROL_AIP_MASK 0x30
47fb4504feSJean Delvare
48fb4504feSJean Delvare /* Autoincrement Flag (switch on if 1) */
49fb4504feSJean Delvare #define PCF8591_CONTROL_AINC 0x04
50fb4504feSJean Delvare
5157256088SGuenter Roeck /*
5257256088SGuenter Roeck * Channel selection
5357256088SGuenter Roeck * 0x00 = channel 0
5457256088SGuenter Roeck * 0x01 = channel 1
5557256088SGuenter Roeck * 0x02 = channel 2
5657256088SGuenter Roeck * 0x03 = channel 3
5757256088SGuenter Roeck */
58fb4504feSJean Delvare #define PCF8591_CONTROL_AICH_MASK 0x03
59fb4504feSJean Delvare
60fb4504feSJean Delvare /* Initial values */
61fb4504feSJean Delvare #define PCF8591_INIT_CONTROL ((input_mode << 4) | PCF8591_CONTROL_AOEF)
62fb4504feSJean Delvare #define PCF8591_INIT_AOUT 0 /* DAC out = 0 */
63fb4504feSJean Delvare
64fb4504feSJean Delvare /* Conversions */
65fb4504feSJean Delvare #define REG_TO_SIGNED(reg) (((reg) & 0x80) ? ((reg) - 256) : (reg))
66fb4504feSJean Delvare
67fb4504feSJean Delvare struct pcf8591_data {
684275fcd6SJean Delvare struct device *hwmon_dev;
69fb4504feSJean Delvare struct mutex update_lock;
70fb4504feSJean Delvare
71fb4504feSJean Delvare u8 control;
72fb4504feSJean Delvare u8 aout;
73fb4504feSJean Delvare };
74fb4504feSJean Delvare
75fb4504feSJean Delvare static void pcf8591_init_client(struct i2c_client *client);
76fb4504feSJean Delvare static int pcf8591_read_channel(struct device *dev, int channel);
77fb4504feSJean Delvare
78fb4504feSJean Delvare /* following are the sysfs callback functions */
79fb4504feSJean Delvare #define show_in_channel(channel) \
8057256088SGuenter Roeck static ssize_t show_in##channel##_input(struct device *dev, \
8157256088SGuenter Roeck struct device_attribute *attr, \
8257256088SGuenter Roeck char *buf) \
83fb4504feSJean Delvare { \
84fb4504feSJean Delvare return sprintf(buf, "%d\n", pcf8591_read_channel(dev, channel));\
85fb4504feSJean Delvare } \
86fb4504feSJean Delvare static DEVICE_ATTR(in##channel##_input, S_IRUGO, \
87fb4504feSJean Delvare show_in##channel##_input, NULL);
88fb4504feSJean Delvare
89fb4504feSJean Delvare show_in_channel(0);
90fb4504feSJean Delvare show_in_channel(1);
91fb4504feSJean Delvare show_in_channel(2);
92fb4504feSJean Delvare show_in_channel(3);
93fb4504feSJean Delvare
out0_output_show(struct device * dev,struct device_attribute * attr,char * buf)94309c675eSJulia Lawall static ssize_t out0_output_show(struct device *dev,
9557256088SGuenter Roeck struct device_attribute *attr, char *buf)
96fb4504feSJean Delvare {
97fb4504feSJean Delvare struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
98fb4504feSJean Delvare return sprintf(buf, "%d\n", data->aout * 10);
99fb4504feSJean Delvare }
100fb4504feSJean Delvare
out0_output_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)101309c675eSJulia Lawall static ssize_t out0_output_store(struct device *dev,
10257256088SGuenter Roeck struct device_attribute *attr,
10357256088SGuenter Roeck const char *buf, size_t count)
104fb4504feSJean Delvare {
10557256088SGuenter Roeck unsigned long val;
106fb4504feSJean Delvare struct i2c_client *client = to_i2c_client(dev);
107fb4504feSJean Delvare struct pcf8591_data *data = i2c_get_clientdata(client);
10857256088SGuenter Roeck int err;
10957256088SGuenter Roeck
11057256088SGuenter Roeck err = kstrtoul(buf, 10, &val);
11157256088SGuenter Roeck if (err)
11257256088SGuenter Roeck return err;
11357256088SGuenter Roeck
11457256088SGuenter Roeck val /= 10;
11557256088SGuenter Roeck if (val > 255)
11657256088SGuenter Roeck return -EINVAL;
11757256088SGuenter Roeck
11857256088SGuenter Roeck data->aout = val;
119fb4504feSJean Delvare i2c_smbus_write_byte_data(client, data->control, data->aout);
120fb4504feSJean Delvare return count;
121fb4504feSJean Delvare }
122fb4504feSJean Delvare
123309c675eSJulia Lawall static DEVICE_ATTR_RW(out0_output);
124fb4504feSJean Delvare
out0_enable_show(struct device * dev,struct device_attribute * attr,char * buf)125309c675eSJulia Lawall static ssize_t out0_enable_show(struct device *dev,
12657256088SGuenter Roeck struct device_attribute *attr, char *buf)
127fb4504feSJean Delvare {
128fb4504feSJean Delvare struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
129fb4504feSJean Delvare return sprintf(buf, "%u\n", !(!(data->control & PCF8591_CONTROL_AOEF)));
130fb4504feSJean Delvare }
131fb4504feSJean Delvare
out0_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)132309c675eSJulia Lawall static ssize_t out0_enable_store(struct device *dev,
13357256088SGuenter Roeck struct device_attribute *attr,
13457256088SGuenter Roeck const char *buf, size_t count)
135fb4504feSJean Delvare {
136fb4504feSJean Delvare struct i2c_client *client = to_i2c_client(dev);
137fb4504feSJean Delvare struct pcf8591_data *data = i2c_get_clientdata(client);
13857256088SGuenter Roeck unsigned long val;
13957256088SGuenter Roeck int err;
14057256088SGuenter Roeck
14157256088SGuenter Roeck err = kstrtoul(buf, 10, &val);
14257256088SGuenter Roeck if (err)
14357256088SGuenter Roeck return err;
144fb4504feSJean Delvare
145fb4504feSJean Delvare mutex_lock(&data->update_lock);
146fb4504feSJean Delvare if (val)
147fb4504feSJean Delvare data->control |= PCF8591_CONTROL_AOEF;
148fb4504feSJean Delvare else
149fb4504feSJean Delvare data->control &= ~PCF8591_CONTROL_AOEF;
150fb4504feSJean Delvare i2c_smbus_write_byte(client, data->control);
151fb4504feSJean Delvare mutex_unlock(&data->update_lock);
152fb4504feSJean Delvare return count;
153fb4504feSJean Delvare }
154fb4504feSJean Delvare
155309c675eSJulia Lawall static DEVICE_ATTR_RW(out0_enable);
156fb4504feSJean Delvare
157fb4504feSJean Delvare static struct attribute *pcf8591_attributes[] = {
158fb4504feSJean Delvare &dev_attr_out0_enable.attr,
159fb4504feSJean Delvare &dev_attr_out0_output.attr,
160fb4504feSJean Delvare &dev_attr_in0_input.attr,
161fb4504feSJean Delvare &dev_attr_in1_input.attr,
162fb4504feSJean Delvare NULL
163fb4504feSJean Delvare };
164fb4504feSJean Delvare
165fb4504feSJean Delvare static const struct attribute_group pcf8591_attr_group = {
166fb4504feSJean Delvare .attrs = pcf8591_attributes,
167fb4504feSJean Delvare };
168fb4504feSJean Delvare
169fb4504feSJean Delvare static struct attribute *pcf8591_attributes_opt[] = {
170fb4504feSJean Delvare &dev_attr_in2_input.attr,
171fb4504feSJean Delvare &dev_attr_in3_input.attr,
172fb4504feSJean Delvare NULL
173fb4504feSJean Delvare };
174fb4504feSJean Delvare
175fb4504feSJean Delvare static const struct attribute_group pcf8591_attr_group_opt = {
176fb4504feSJean Delvare .attrs = pcf8591_attributes_opt,
177fb4504feSJean Delvare };
178fb4504feSJean Delvare
179fb4504feSJean Delvare /*
180fb4504feSJean Delvare * Real code
181fb4504feSJean Delvare */
182fb4504feSJean Delvare
pcf8591_probe(struct i2c_client * client)18367487038SStephen Kitt static int pcf8591_probe(struct i2c_client *client)
184fb4504feSJean Delvare {
185fb4504feSJean Delvare struct pcf8591_data *data;
186fb4504feSJean Delvare int err;
187fb4504feSJean Delvare
18860c2b569SGuenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct pcf8591_data),
18960c2b569SGuenter Roeck GFP_KERNEL);
19060c2b569SGuenter Roeck if (!data)
19160c2b569SGuenter Roeck return -ENOMEM;
192fb4504feSJean Delvare
193fb4504feSJean Delvare i2c_set_clientdata(client, data);
194fb4504feSJean Delvare mutex_init(&data->update_lock);
195fb4504feSJean Delvare
196fb4504feSJean Delvare /* Initialize the PCF8591 chip */
197fb4504feSJean Delvare pcf8591_init_client(client);
198fb4504feSJean Delvare
199fb4504feSJean Delvare /* Register sysfs hooks */
200fb4504feSJean Delvare err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group);
201fb4504feSJean Delvare if (err)
20260c2b569SGuenter Roeck return err;
203fb4504feSJean Delvare
204fb4504feSJean Delvare /* Register input2 if not in "two differential inputs" mode */
205fb4504feSJean Delvare if (input_mode != 3) {
20657256088SGuenter Roeck err = device_create_file(&client->dev, &dev_attr_in2_input);
20757256088SGuenter Roeck if (err)
208fb4504feSJean Delvare goto exit_sysfs_remove;
209fb4504feSJean Delvare }
210fb4504feSJean Delvare
211fb4504feSJean Delvare /* Register input3 only in "four single ended inputs" mode */
212fb4504feSJean Delvare if (input_mode == 0) {
21357256088SGuenter Roeck err = device_create_file(&client->dev, &dev_attr_in3_input);
21457256088SGuenter Roeck if (err)
215fb4504feSJean Delvare goto exit_sysfs_remove;
216fb4504feSJean Delvare }
217fb4504feSJean Delvare
2184275fcd6SJean Delvare data->hwmon_dev = hwmon_device_register(&client->dev);
2194275fcd6SJean Delvare if (IS_ERR(data->hwmon_dev)) {
2204275fcd6SJean Delvare err = PTR_ERR(data->hwmon_dev);
2214275fcd6SJean Delvare goto exit_sysfs_remove;
2224275fcd6SJean Delvare }
2234275fcd6SJean Delvare
224fb4504feSJean Delvare return 0;
225fb4504feSJean Delvare
226fb4504feSJean Delvare exit_sysfs_remove:
227fb4504feSJean Delvare sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
228fb4504feSJean Delvare sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
229fb4504feSJean Delvare return err;
230fb4504feSJean Delvare }
231fb4504feSJean Delvare
pcf8591_remove(struct i2c_client * client)232ed5c2f5fSUwe Kleine-König static void pcf8591_remove(struct i2c_client *client)
233fb4504feSJean Delvare {
2344275fcd6SJean Delvare struct pcf8591_data *data = i2c_get_clientdata(client);
2354275fcd6SJean Delvare
2364275fcd6SJean Delvare hwmon_device_unregister(data->hwmon_dev);
237fb4504feSJean Delvare sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
238fb4504feSJean Delvare sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
239fb4504feSJean Delvare }
240fb4504feSJean Delvare
241fb4504feSJean Delvare /* Called when we have found a new PCF8591. */
pcf8591_init_client(struct i2c_client * client)242fb4504feSJean Delvare static void pcf8591_init_client(struct i2c_client *client)
243fb4504feSJean Delvare {
244fb4504feSJean Delvare struct pcf8591_data *data = i2c_get_clientdata(client);
245fb4504feSJean Delvare data->control = PCF8591_INIT_CONTROL;
246fb4504feSJean Delvare data->aout = PCF8591_INIT_AOUT;
247fb4504feSJean Delvare
248fb4504feSJean Delvare i2c_smbus_write_byte_data(client, data->control, data->aout);
249fb4504feSJean Delvare
25057256088SGuenter Roeck /*
25157256088SGuenter Roeck * The first byte transmitted contains the conversion code of the
25257256088SGuenter Roeck * previous read cycle. FLUSH IT!
25357256088SGuenter Roeck */
254fb4504feSJean Delvare i2c_smbus_read_byte(client);
255fb4504feSJean Delvare }
256fb4504feSJean Delvare
pcf8591_read_channel(struct device * dev,int channel)257fb4504feSJean Delvare static int pcf8591_read_channel(struct device *dev, int channel)
258fb4504feSJean Delvare {
259fb4504feSJean Delvare u8 value;
260fb4504feSJean Delvare struct i2c_client *client = to_i2c_client(dev);
261fb4504feSJean Delvare struct pcf8591_data *data = i2c_get_clientdata(client);
262fb4504feSJean Delvare
263fb4504feSJean Delvare mutex_lock(&data->update_lock);
264fb4504feSJean Delvare
265fb4504feSJean Delvare if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) {
266fb4504feSJean Delvare data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK)
267fb4504feSJean Delvare | channel;
268fb4504feSJean Delvare i2c_smbus_write_byte(client, data->control);
269fb4504feSJean Delvare
27057256088SGuenter Roeck /*
27157256088SGuenter Roeck * The first byte transmitted contains the conversion code of
27257256088SGuenter Roeck * the previous read cycle. FLUSH IT!
27357256088SGuenter Roeck */
274fb4504feSJean Delvare i2c_smbus_read_byte(client);
275fb4504feSJean Delvare }
276fb4504feSJean Delvare value = i2c_smbus_read_byte(client);
277fb4504feSJean Delvare
278fb4504feSJean Delvare mutex_unlock(&data->update_lock);
279fb4504feSJean Delvare
280fb4504feSJean Delvare if ((channel == 2 && input_mode == 2) ||
281fb4504feSJean Delvare (channel != 3 && (input_mode == 1 || input_mode == 3)))
2827fe83ad8SFrans Meulenbroeks return 10 * REG_TO_SIGNED(value);
283fb4504feSJean Delvare else
2847fe83ad8SFrans Meulenbroeks return 10 * value;
285fb4504feSJean Delvare }
286fb4504feSJean Delvare
287fb4504feSJean Delvare static const struct i2c_device_id pcf8591_id[] = {
288fb4504feSJean Delvare { "pcf8591", 0 },
289fb4504feSJean Delvare { }
290fb4504feSJean Delvare };
291fb4504feSJean Delvare MODULE_DEVICE_TABLE(i2c, pcf8591_id);
292fb4504feSJean Delvare
293fb4504feSJean Delvare static struct i2c_driver pcf8591_driver = {
294fb4504feSJean Delvare .driver = {
295fb4504feSJean Delvare .name = "pcf8591",
296fb4504feSJean Delvare },
297*1975d167SUwe Kleine-König .probe = pcf8591_probe,
298fb4504feSJean Delvare .remove = pcf8591_remove,
299fb4504feSJean Delvare .id_table = pcf8591_id,
300fb4504feSJean Delvare };
301fb4504feSJean Delvare
pcf8591_init(void)302fb4504feSJean Delvare static int __init pcf8591_init(void)
303fb4504feSJean Delvare {
304fb4504feSJean Delvare if (input_mode < 0 || input_mode > 3) {
3052caec134SJoe Perches pr_warn("invalid input_mode (%d)\n", input_mode);
306fb4504feSJean Delvare input_mode = 0;
307fb4504feSJean Delvare }
308fb4504feSJean Delvare return i2c_add_driver(&pcf8591_driver);
309fb4504feSJean Delvare }
310fb4504feSJean Delvare
pcf8591_exit(void)311fb4504feSJean Delvare static void __exit pcf8591_exit(void)
312fb4504feSJean Delvare {
313fb4504feSJean Delvare i2c_del_driver(&pcf8591_driver);
314fb4504feSJean Delvare }
315fb4504feSJean Delvare
316fb4504feSJean Delvare MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
317fb4504feSJean Delvare MODULE_DESCRIPTION("PCF8591 driver");
318fb4504feSJean Delvare MODULE_LICENSE("GPL");
319fb4504feSJean Delvare
320fb4504feSJean Delvare module_init(pcf8591_init);
321fb4504feSJean Delvare module_exit(pcf8591_exit);
322