aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2012-06-04 05:36:17 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-05 00:47:31 -0400
commitfe4586a8753117a089acb54f75870d07c8e474d0 (patch)
tree392cb4395c454bf8e4d179273a54857e1de97ac6 /drivers/staging/iio
parent66eb90505eaf38f3e88491eb9090cd7be7c2da03 (diff)
staging:iio:dac:ad5686: Convert to extended channel attributes
Use extended channel attributes instead of raw sysfs files for the additional channel attributes. This allows us to remove some boilerplate code. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/iio')
-rw-r--r--drivers/staging/iio/dac/ad5686.c196
1 files changed, 80 insertions, 116 deletions
diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c
index c1e903ebc7b..f07e19721c9 100644
--- a/drivers/staging/iio/dac/ad5686.c
+++ b/drivers/staging/iio/dac/ad5686.c
@@ -93,40 +93,6 @@ enum ad5686_supported_device_ids {
93 ID_AD5685, 93 ID_AD5685,
94 ID_AD5686, 94 ID_AD5686,
95}; 95};
96#define AD5868_CHANNEL(chan, bits, shift) { \
97 .type = IIO_VOLTAGE, \
98 .indexed = 1, \
99 .output = 1, \
100 .channel = chan, \
101 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
102 IIO_CHAN_INFO_SCALE_SHARED_BIT, \
103 .address = AD5686_ADDR_DAC(chan), \
104 .scan_type = IIO_ST('u', bits, 16, shift) \
105}
106static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
107 [ID_AD5684] = {
108 .channel[0] = AD5868_CHANNEL(0, 12, 4),
109 .channel[1] = AD5868_CHANNEL(1, 12, 4),
110 .channel[2] = AD5868_CHANNEL(2, 12, 4),
111 .channel[3] = AD5868_CHANNEL(3, 12, 4),
112 .int_vref_mv = 2500,
113 },
114 [ID_AD5685] = {
115 .channel[0] = AD5868_CHANNEL(0, 14, 2),
116 .channel[1] = AD5868_CHANNEL(1, 14, 2),
117 .channel[2] = AD5868_CHANNEL(2, 14, 2),
118 .channel[3] = AD5868_CHANNEL(3, 14, 2),
119 .int_vref_mv = 2500,
120 },
121 [ID_AD5686] = {
122 .channel[0] = AD5868_CHANNEL(0, 16, 0),
123 .channel[1] = AD5868_CHANNEL(1, 16, 0),
124 .channel[2] = AD5868_CHANNEL(2, 16, 0),
125 .channel[3] = AD5868_CHANNEL(3, 16, 0),
126 .int_vref_mv = 2500,
127 },
128};
129
130static int ad5686_spi_write(struct ad5686_state *st, 96static int ad5686_spi_write(struct ad5686_state *st,
131 u8 cmd, u8 addr, u16 val, u8 shift) 97 u8 cmd, u8 addr, u16 val, u8 shift)
132{ 98{
@@ -170,73 +136,63 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
170 return be32_to_cpu(st->data[2].d32); 136 return be32_to_cpu(st->data[2].d32);
171} 137}
172 138
173static ssize_t ad5686_read_powerdown_mode(struct device *dev, 139static const char * const ad5686_powerdown_modes[] = {
174 struct device_attribute *attr, char *buf) 140 "1kohm_to_gnd",
141 "100kohm_to_gnd",
142 "three_state"
143};
144
145static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev,
146 const struct iio_chan_spec *chan)
175{ 147{
176 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
177 struct ad5686_state *st = iio_priv(indio_dev); 148 struct ad5686_state *st = iio_priv(indio_dev);
178 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
179 149
180 char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"}; 150 return ((st->pwr_down_mode >> (chan->channel * 2)) & 0x3) - 1;
181
182 return sprintf(buf, "%s\n", mode[(st->pwr_down_mode >>
183 (this_attr->address * 2)) & 0x3]);
184} 151}
185 152
186static ssize_t ad5686_write_powerdown_mode(struct device *dev, 153static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev,
187 struct device_attribute *attr, 154 const struct iio_chan_spec *chan, unsigned int mode)
188 const char *buf, size_t len)
189{ 155{
190 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
191 struct ad5686_state *st = iio_priv(indio_dev); 156 struct ad5686_state *st = iio_priv(indio_dev);
192 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
193 unsigned mode;
194
195 if (sysfs_streq(buf, "1kohm_to_gnd"))
196 mode = AD5686_LDAC_PWRDN_1K;
197 else if (sysfs_streq(buf, "100kohm_to_gnd"))
198 mode = AD5686_LDAC_PWRDN_100K;
199 else if (sysfs_streq(buf, "three_state"))
200 mode = AD5686_LDAC_PWRDN_3STATE;
201 else
202 return -EINVAL;
203 157
204 st->pwr_down_mode &= ~(0x3 << (this_attr->address * 2)); 158 st->pwr_down_mode &= ~(0x3 << (chan->channel * 2));
205 st->pwr_down_mode |= (mode << (this_attr->address * 2)); 159 st->pwr_down_mode |= ((mode + 1) << (chan->channel * 2));
206 160
207 return len; 161 return 0;
208} 162}
209 163
210static ssize_t ad5686_read_dac_powerdown(struct device *dev, 164static const struct iio_enum ad5686_powerdown_mode_enum = {
211 struct device_attribute *attr, 165 .items = ad5686_powerdown_modes,
212 char *buf) 166 .num_items = ARRAY_SIZE(ad5686_powerdown_modes),
167 .get = ad5686_get_powerdown_mode,
168 .set = ad5686_set_powerdown_mode,
169};
170
171static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev,
172 uintptr_t private, const struct iio_chan_spec *chan, char *buf)
213{ 173{
214 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
215 struct ad5686_state *st = iio_priv(indio_dev); 174 struct ad5686_state *st = iio_priv(indio_dev);
216 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
217 175
218 return sprintf(buf, "%d\n", !!(st->pwr_down_mask & 176 return sprintf(buf, "%d\n", !!(st->pwr_down_mask &
219 (0x3 << (this_attr->address * 2)))); 177 (0x3 << (chan->channel * 2))));
220} 178}
221 179
222static ssize_t ad5686_write_dac_powerdown(struct device *dev, 180static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
223 struct device_attribute *attr, 181 uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
224 const char *buf, size_t len) 182 size_t len)
225{ 183{
226 bool readin; 184 bool readin;
227 int ret; 185 int ret;
228 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
229 struct ad5686_state *st = iio_priv(indio_dev); 186 struct ad5686_state *st = iio_priv(indio_dev);
230 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
231 187
232 ret = strtobool(buf, &readin); 188 ret = strtobool(buf, &readin);
233 if (ret) 189 if (ret)
234 return ret; 190 return ret;
235 191
236 if (readin == true) 192 if (readin == true)
237 st->pwr_down_mask |= (0x3 << (this_attr->address * 2)); 193 st->pwr_down_mask |= (0x3 << (chan->channel * 2));
238 else 194 else
239 st->pwr_down_mask &= ~(0x3 << (this_attr->address * 2)); 195 st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
240 196
241 ret = ad5686_spi_write(st, AD5686_CMD_POWERDOWN_DAC, 0, 197 ret = ad5686_spi_write(st, AD5686_CMD_POWERDOWN_DAC, 0,
242 st->pwr_down_mask & st->pwr_down_mode, 0); 198 st->pwr_down_mask & st->pwr_down_mode, 0);
@@ -244,48 +200,6 @@ static ssize_t ad5686_write_dac_powerdown(struct device *dev,
244 return ret ? ret : len; 200 return ret ? ret : len;
245} 201}
246 202
247static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
248 "1kohm_to_gnd 100kohm_to_gnd three_state");
249
250#define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_num) \
251 IIO_DEVICE_ATTR(out_voltage##_num##_powerdown_mode, \
252 S_IRUGO | S_IWUSR, \
253 ad5686_read_powerdown_mode, \
254 ad5686_write_powerdown_mode, _num)
255
256static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(0);
257static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1);
258static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2);
259static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3);
260
261#define IIO_DEV_ATTR_DAC_POWERDOWN(_num) \
262 IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \
263 S_IRUGO | S_IWUSR, \
264 ad5686_read_dac_powerdown, \
265 ad5686_write_dac_powerdown, _num)
266
267static IIO_DEV_ATTR_DAC_POWERDOWN(0);
268static IIO_DEV_ATTR_DAC_POWERDOWN(1);
269static IIO_DEV_ATTR_DAC_POWERDOWN(2);
270static IIO_DEV_ATTR_DAC_POWERDOWN(3);
271
272static struct attribute *ad5686_attributes[] = {
273 &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
274 &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr,
275 &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr,
276 &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr,
277 &iio_dev_attr_out_voltage0_powerdown_mode.dev_attr.attr,
278 &iio_dev_attr_out_voltage1_powerdown_mode.dev_attr.attr,
279 &iio_dev_attr_out_voltage2_powerdown_mode.dev_attr.attr,
280 &iio_dev_attr_out_voltage3_powerdown_mode.dev_attr.attr,
281 &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
282 NULL,
283};
284
285static const struct attribute_group ad5686_attribute_group = {
286 .attrs = ad5686_attributes,
287};
288
289static int ad5686_read_raw(struct iio_dev *indio_dev, 203static int ad5686_read_raw(struct iio_dev *indio_dev,
290 struct iio_chan_spec const *chan, 204 struct iio_chan_spec const *chan,
291 int *val, 205 int *val,
@@ -349,10 +263,57 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
349static const struct iio_info ad5686_info = { 263static const struct iio_info ad5686_info = {
350 .read_raw = ad5686_read_raw, 264 .read_raw = ad5686_read_raw,
351 .write_raw = ad5686_write_raw, 265 .write_raw = ad5686_write_raw,
352 .attrs = &ad5686_attribute_group,
353 .driver_module = THIS_MODULE, 266 .driver_module = THIS_MODULE,
354}; 267};
355 268
269static const struct iio_chan_spec_ext_info ad5686_ext_info[] = {
270 {
271 .name = "powerdown",
272 .read = ad5686_read_dac_powerdown,
273 .write = ad5686_write_dac_powerdown,
274 },
275 IIO_ENUM("powerdown_mode", false, &ad5686_powerdown_mode_enum),
276 IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum),
277 { },
278};
279
280#define AD5868_CHANNEL(chan, bits, shift) { \
281 .type = IIO_VOLTAGE, \
282 .indexed = 1, \
283 .output = 1, \
284 .channel = chan, \
285 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
286 IIO_CHAN_INFO_SCALE_SHARED_BIT, \
287 .address = AD5686_ADDR_DAC(chan), \
288 .scan_type = IIO_ST('u', bits, 16, shift), \
289 .ext_info = ad5686_ext_info, \
290}
291
292static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
293 [ID_AD5684] = {
294 .channel[0] = AD5868_CHANNEL(0, 12, 4),
295 .channel[1] = AD5868_CHANNEL(1, 12, 4),
296 .channel[2] = AD5868_CHANNEL(2, 12, 4),
297 .channel[3] = AD5868_CHANNEL(3, 12, 4),
298 .int_vref_mv = 2500,
299 },
300 [ID_AD5685] = {
301 .channel[0] = AD5868_CHANNEL(0, 14, 2),
302 .channel[1] = AD5868_CHANNEL(1, 14, 2),
303 .channel[2] = AD5868_CHANNEL(2, 14, 2),
304 .channel[3] = AD5868_CHANNEL(3, 14, 2),
305 .int_vref_mv = 2500,
306 },
307 [ID_AD5686] = {
308 .channel[0] = AD5868_CHANNEL(0, 16, 0),
309 .channel[1] = AD5868_CHANNEL(1, 16, 0),
310 .channel[2] = AD5868_CHANNEL(2, 16, 0),
311 .channel[3] = AD5868_CHANNEL(3, 16, 0),
312 .int_vref_mv = 2500,
313 },
314};
315
316
356static int __devinit ad5686_probe(struct spi_device *spi) 317static int __devinit ad5686_probe(struct spi_device *spi)
357{ 318{
358 struct ad5686_state *st; 319 struct ad5686_state *st;
@@ -385,6 +346,9 @@ static int __devinit ad5686_probe(struct spi_device *spi)
385 346
386 st->spi = spi; 347 st->spi = spi;
387 348
349 /* Set all the power down mode for all channels to 1K pulldown */
350 st->pwr_down_mode = 0x55;
351
388 indio_dev->dev.parent = &spi->dev; 352 indio_dev->dev.parent = &spi->dev;
389 indio_dev->name = spi_get_device_id(spi)->name; 353 indio_dev->name = spi_get_device_id(spi)->name;
390 indio_dev->info = &ad5686_info; 354 indio_dev->info = &ad5686_info;