Blame view

drivers/hwmon/iio_hwmon.c 4.97 KB
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /* Hwmon client for industrial I/O devices
   *
   * Copyright (c) 2011 Jonathan Cameron
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 as published by
   * the Free Software Foundation.
   */
  
  #include <linux/kernel.h>
  #include <linux/slab.h>
  #include <linux/module.h>
  #include <linux/err.h>
  #include <linux/platform_device.h>
  #include <linux/hwmon.h>
3465a2248   Guenter Roeck   staging/iio: iio_...
16
  #include <linux/of.h>
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
17
  #include <linux/hwmon-sysfs.h>
06458e277   Jonathan Cameron   IIO: Move core he...
18
19
  #include <linux/iio/consumer.h>
  #include <linux/iio/types.h>
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  
  /**
   * struct iio_hwmon_state - device instance state
   * @channels:		filled with array of channels from iio
   * @num_channels:	number of channels in channels (saves counting twice)
   * @hwmon_dev:		associated hwmon device
   * @attr_group:	the group of attributes
   * @attrs:		null terminated array of attribute pointers.
   */
  struct iio_hwmon_state {
  	struct iio_channel *channels;
  	int num_channels;
  	struct device *hwmon_dev;
  	struct attribute_group attr_group;
4b49cca36   Guenter Roeck   hwmon: (iio_hwmon...
34
  	const struct attribute_group *groups[2];
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
35
36
37
38
39
40
41
42
43
44
45
46
  	struct attribute **attrs;
  };
  
  /*
   * Assumes that IIO and hwmon operate in the same base units.
   * This is supposed to be true, but needs verification for
   * new channel types.
   */
  static ssize_t iio_hwmon_read_val(struct device *dev,
  				  struct device_attribute *attr,
  				  char *buf)
  {
a0e545e0e   Lars-Peter Clausen   staging:iio:hwmon...
47
48
  	int result;
  	int ret;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
49
50
  	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
  	struct iio_hwmon_state *state = dev_get_drvdata(dev);
a0e545e0e   Lars-Peter Clausen   staging:iio:hwmon...
51
52
  	ret = iio_read_channel_processed(&state->channels[sattr->index],
  					&result);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
53
54
  	if (ret < 0)
  		return ret;
a0e545e0e   Lars-Peter Clausen   staging:iio:hwmon...
55
56
  	return sprintf(buf, "%d
  ", result);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
57
  }
4ae1c61ff   Bill Pemberton   staging: iio: rem...
58
  static int iio_hwmon_probe(struct platform_device *pdev)
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
59
  {
c4ac7b98b   Guenter Roeck   staging/iio: (iio...
60
  	struct device *dev = &pdev->dev;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
61
62
63
  	struct iio_hwmon_state *st;
  	struct sensor_device_attribute *a;
  	int ret, i;
61bb53bcb   Guenter Roeck   hwmon: (iio_hwmon...
64
  	int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
65
  	enum iio_chan_type type;
ca7d98dbd   Guenter Roeck   iio: Update iio_c...
66
  	struct iio_channel *channels;
4b49cca36   Guenter Roeck   hwmon: (iio_hwmon...
67
  	const char *name = "iio_hwmon";
b92fe9e33   Sanchayan Maity   hwmon: (iio_hwmon...
68
  	char *sname;
4b49cca36   Guenter Roeck   hwmon: (iio_hwmon...
69
70
71
  
  	if (dev->of_node && dev->of_node->name)
  		name = dev->of_node->name;
ca7d98dbd   Guenter Roeck   iio: Update iio_c...
72
73
  
  	channels = iio_channel_get_all(dev);
9417fefe6   Quentin Schulz   hwmon: (iio_hwmon...
74
75
76
  	if (IS_ERR(channels)) {
  		if (PTR_ERR(channels) == -ENODEV)
  			return -EPROBE_DEFER;
ca7d98dbd   Guenter Roeck   iio: Update iio_c...
77
  		return PTR_ERR(channels);
9417fefe6   Quentin Schulz   hwmon: (iio_hwmon...
78
  	}
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
79

c4ac7b98b   Guenter Roeck   staging/iio: (iio...
80
  	st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
4510d198f   Axel Lin   hwmon: (iio_hwmon...
81
82
83
84
  	if (st == NULL) {
  		ret = -ENOMEM;
  		goto error_release_channels;
  	}
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
85

ca7d98dbd   Guenter Roeck   iio: Update iio_c...
86
  	st->channels = channels;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
87
88
89
90
  
  	/* count how many attributes we have */
  	while (st->channels[st->num_channels].indio_dev)
  		st->num_channels++;
c4ac7b98b   Guenter Roeck   staging/iio: (iio...
91
  	st->attrs = devm_kzalloc(dev,
4b49cca36   Guenter Roeck   hwmon: (iio_hwmon...
92
  				 sizeof(*st->attrs) * (st->num_channels + 1),
c4ac7b98b   Guenter Roeck   staging/iio: (iio...
93
  				 GFP_KERNEL);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
94
95
96
97
  	if (st->attrs == NULL) {
  		ret = -ENOMEM;
  		goto error_release_channels;
  	}
c4ac7b98b   Guenter Roeck   staging/iio: (iio...
98

e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
99
  	for (i = 0; i < st->num_channels; i++) {
c4ac7b98b   Guenter Roeck   staging/iio: (iio...
100
  		a = devm_kzalloc(dev, sizeof(*a), GFP_KERNEL);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
101
102
  		if (a == NULL) {
  			ret = -ENOMEM;
c4ac7b98b   Guenter Roeck   staging/iio: (iio...
103
  			goto error_release_channels;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
104
105
106
  		}
  
  		sysfs_attr_init(&a->dev_attr.attr);
314be14bb   Jonathan Cameron   iio: Rename _st_ ...
107
  		ret = iio_get_channel_type(&st->channels[i], &type);
c4ac7b98b   Guenter Roeck   staging/iio: (iio...
108
109
  		if (ret < 0)
  			goto error_release_channels;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
110
111
  		switch (type) {
  		case IIO_VOLTAGE:
5d17d3b4b   Quentin Schulz   hwmon: (iio_hwmon...
112
113
114
  			a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
  							       "in%d_input",
  							       in_i++);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
115
116
  			break;
  		case IIO_TEMP:
5d17d3b4b   Quentin Schulz   hwmon: (iio_hwmon...
117
118
119
  			a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
  							       "temp%d_input",
  							       temp_i++);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
120
121
  			break;
  		case IIO_CURRENT:
5d17d3b4b   Quentin Schulz   hwmon: (iio_hwmon...
122
123
124
  			a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
  							       "curr%d_input",
  							       curr_i++);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
125
  			break;
61bb53bcb   Guenter Roeck   hwmon: (iio_hwmon...
126
  		case IIO_HUMIDITYRELATIVE:
5d17d3b4b   Quentin Schulz   hwmon: (iio_hwmon...
127
128
129
  			a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
  							       "humidity%d_input",
  							       humidity_i++);
61bb53bcb   Guenter Roeck   hwmon: (iio_hwmon...
130
  			break;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
131
132
  		default:
  			ret = -EINVAL;
c4ac7b98b   Guenter Roeck   staging/iio: (iio...
133
  			goto error_release_channels;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
134
135
  		}
  		if (a->dev_attr.attr.name == NULL) {
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
136
  			ret = -ENOMEM;
c4ac7b98b   Guenter Roeck   staging/iio: (iio...
137
  			goto error_release_channels;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
138
139
140
141
142
143
  		}
  		a->dev_attr.show = iio_hwmon_read_val;
  		a->dev_attr.attr.mode = S_IRUGO;
  		a->index = i;
  		st->attrs[i] = &a->dev_attr.attr;
  	}
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
144

4b49cca36   Guenter Roeck   hwmon: (iio_hwmon...
145
146
  	st->attr_group.attrs = st->attrs;
  	st->groups[0] = &st->attr_group;
b92fe9e33   Sanchayan Maity   hwmon: (iio_hwmon...
147
148
149
150
151
152
153
154
155
  
  	sname = devm_kstrdup(dev, name, GFP_KERNEL);
  	if (!sname) {
  		ret = -ENOMEM;
  		goto error_release_channels;
  	}
  
  	strreplace(sname, '-', '_');
  	st->hwmon_dev = hwmon_device_register_with_groups(dev, sname, st,
4b49cca36   Guenter Roeck   hwmon: (iio_hwmon...
156
  							  st->groups);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
157
158
  	if (IS_ERR(st->hwmon_dev)) {
  		ret = PTR_ERR(st->hwmon_dev);
4b49cca36   Guenter Roeck   hwmon: (iio_hwmon...
159
  		goto error_release_channels;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
160
  	}
4b49cca36   Guenter Roeck   hwmon: (iio_hwmon...
161
  	platform_set_drvdata(pdev, st);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
162
  	return 0;
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
163
  error_release_channels:
159c8cddd   Axel Lin   hwmon: (iio_hwmon...
164
  	iio_channel_release_all(channels);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
165
166
  	return ret;
  }
447d4f29e   Bill Pemberton   staging: iio: rem...
167
  static int iio_hwmon_remove(struct platform_device *pdev)
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
168
169
170
171
  {
  	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
  
  	hwmon_device_unregister(st->hwmon_dev);
314be14bb   Jonathan Cameron   iio: Rename _st_ ...
172
  	iio_channel_release_all(st->channels);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
173
174
175
  
  	return 0;
  }
cfe03d641   Jingoo Han   hwmon: (iio_hwmon...
176
  static const struct of_device_id iio_hwmon_of_match[] = {
a11e619b8   Guenter Roeck   staging/iio: (iio...
177
178
179
  	{ .compatible = "iio-hwmon", },
  	{ }
  };
2ec281962   Sebastian Andrzej Siewior   hwmon: (iio_hwmon...
180
  MODULE_DEVICE_TABLE(of, iio_hwmon_of_match);
a11e619b8   Guenter Roeck   staging/iio: (iio...
181

e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
182
183
184
  static struct platform_driver __refdata iio_hwmon_driver = {
  	.driver = {
  		.name = "iio_hwmon",
a11e619b8   Guenter Roeck   staging/iio: (iio...
185
  		.of_match_table = iio_hwmon_of_match,
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
186
187
  	},
  	.probe = iio_hwmon_probe,
e543acf07   Bill Pemberton   staging: iio: rem...
188
  	.remove = iio_hwmon_remove,
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
189
  };
d16f6dbdd   Devendra Naga   staging/iio: use ...
190
  module_platform_driver(iio_hwmon_driver);
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
191

0f8c96200   Jonathan Cameron   staging:iio: Upda...
192
  MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
e0f8a24e0   Jonathan Cameron   staging:iio::hwmo...
193
194
  MODULE_DESCRIPTION("IIO to hwmon driver");
  MODULE_LICENSE("GPL v2");