aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2011-03-10 07:26:47 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-03-14 14:50:28 -0400
commitbbed4dc791036e97cbe844935dece153fdace0dc (patch)
tree15a79b283066f4b324cfee1f36b17a22b810dda3 /drivers/staging
parentbd51c0b078eb3edeee9e48eb236d5831d7ae34cf (diff)
staging: IIO: DAC: AD5446: Add power down support
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Acked-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/iio/dac/ad5446.c153
-rw-r--r--drivers/staging/iio/dac/ad5446.h19
2 files changed, 153 insertions, 19 deletions
diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c
index 4f1d8813272..861a7eacdaf 100644
--- a/drivers/staging/iio/dac/ad5446.c
+++ b/drivers/staging/iio/dac/ad5446.c
@@ -48,6 +48,20 @@ static void ad5660_store_sample(struct ad5446_state *st, unsigned val)
48 st->data.d24[2] = val & 0xFF; 48 st->data.d24[2] = val & 0xFF;
49} 49}
50 50
51static void ad5620_store_pwr_down(struct ad5446_state *st, unsigned mode)
52{
53 st->data.d16 = cpu_to_be16(mode << 14);
54}
55
56static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode)
57{
58 unsigned val = mode << 16;
59
60 st->data.d24[0] = (val >> 16) & 0xFF;
61 st->data.d24[1] = (val >> 8) & 0xFF;
62 st->data.d24[2] = val & 0xFF;
63}
64
51static ssize_t ad5446_write(struct device *dev, 65static ssize_t ad5446_write(struct device *dev,
52 struct device_attribute *attr, 66 struct device_attribute *attr,
53 const char *buf, 67 const char *buf,
@@ -68,6 +82,7 @@ static ssize_t ad5446_write(struct device *dev,
68 } 82 }
69 83
70 mutex_lock(&dev_info->mlock); 84 mutex_lock(&dev_info->mlock);
85 st->cached_val = val;
71 st->chip_info->store_sample(st, val); 86 st->chip_info->store_sample(st, val);
72 ret = spi_sync(st->spi, &st->msg); 87 ret = spi_sync(st->spi, &st->msg);
73 mutex_unlock(&dev_info->mlock); 88 mutex_unlock(&dev_info->mlock);
@@ -102,15 +117,119 @@ static ssize_t ad5446_show_name(struct device *dev,
102} 117}
103static IIO_DEVICE_ATTR(name, S_IRUGO, ad5446_show_name, NULL, 0); 118static IIO_DEVICE_ATTR(name, S_IRUGO, ad5446_show_name, NULL, 0);
104 119
120static ssize_t ad5446_write_powerdown_mode(struct device *dev,
121 struct device_attribute *attr,
122 const char *buf, size_t len)
123{
124 struct iio_dev *dev_info = dev_get_drvdata(dev);
125 struct ad5446_state *st = dev_info->dev_data;
126
127 if (sysfs_streq(buf, "1kohm_to_gnd"))
128 st->pwr_down_mode = MODE_PWRDWN_1k;
129 else if (sysfs_streq(buf, "100kohm_to_gnd"))
130 st->pwr_down_mode = MODE_PWRDWN_100k;
131 else if (sysfs_streq(buf, "three_state"))
132 st->pwr_down_mode = MODE_PWRDWN_TRISTATE;
133 else
134 return -EINVAL;
135
136 return len;
137}
138
139static ssize_t ad5446_read_powerdown_mode(struct device *dev,
140 struct device_attribute *attr, char *buf)
141{
142 struct iio_dev *dev_info = dev_get_drvdata(dev);
143 struct ad5446_state *st = dev_info->dev_data;
144
145 char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
146
147 return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
148}
149
150static ssize_t ad5446_read_dac_powerdown(struct device *dev,
151 struct device_attribute *attr,
152 char *buf)
153{
154 struct iio_dev *dev_info = dev_get_drvdata(dev);
155 struct ad5446_state *st = dev_info->dev_data;
156
157 return sprintf(buf, "%d\n", st->pwr_down);
158}
159
160static ssize_t ad5446_write_dac_powerdown(struct device *dev,
161 struct device_attribute *attr,
162 const char *buf, size_t len)
163{
164 struct iio_dev *dev_info = dev_get_drvdata(dev);
165 struct ad5446_state *st = dev_info->dev_data;
166 unsigned long readin;
167 int ret;
168
169 ret = strict_strtol(buf, 10, &readin);
170 if (ret)
171 return ret;
172
173 if (readin > 1)
174 ret = -EINVAL;
175
176 mutex_lock(&dev_info->mlock);
177 st->pwr_down = readin;
178
179 if (st->pwr_down)
180 st->chip_info->store_pwr_down(st, st->pwr_down_mode);
181 else
182 st->chip_info->store_sample(st, st->cached_val);
183
184 ret = spi_sync(st->spi, &st->msg);
185 mutex_unlock(&dev_info->mlock);
186
187 return ret ? ret : len;
188}
189
190static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | S_IWUSR,
191 ad5446_read_powerdown_mode,
192 ad5446_write_powerdown_mode, 0);
193
194static IIO_CONST_ATTR(out_powerdown_mode_available,
195 "1kohm_to_gnd 100kohm_to_gnd three_state");
196
197static IIO_DEVICE_ATTR(out0_powerdown, S_IRUGO | S_IWUSR,
198 ad5446_read_dac_powerdown,
199 ad5446_write_dac_powerdown, 0);
200
105static struct attribute *ad5446_attributes[] = { 201static struct attribute *ad5446_attributes[] = {
106 &iio_dev_attr_out0_raw.dev_attr.attr, 202 &iio_dev_attr_out0_raw.dev_attr.attr,
107 &iio_dev_attr_out_scale.dev_attr.attr, 203 &iio_dev_attr_out_scale.dev_attr.attr,
204 &iio_dev_attr_out0_powerdown.dev_attr.attr,
205 &iio_dev_attr_out_powerdown_mode.dev_attr.attr,
206 &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
108 &iio_dev_attr_name.dev_attr.attr, 207 &iio_dev_attr_name.dev_attr.attr,
109 NULL, 208 NULL,
110}; 209};
111 210
211static mode_t ad5446_attr_is_visible(struct kobject *kobj,
212 struct attribute *attr, int n)
213{
214 struct device *dev = container_of(kobj, struct device, kobj);
215 struct iio_dev *dev_info = dev_get_drvdata(dev);
216 struct ad5446_state *st = iio_dev_get_devdata(dev_info);
217
218 mode_t mode = attr->mode;
219
220 if (!st->chip_info->store_pwr_down &&
221 (attr == &iio_dev_attr_out0_powerdown.dev_attr.attr ||
222 attr == &iio_dev_attr_out_powerdown_mode.dev_attr.attr ||
223 attr ==
224 &iio_const_attr_out_powerdown_mode_available.dev_attr.attr))
225 mode = 0;
226
227 return mode;
228}
229
112static const struct attribute_group ad5446_attribute_group = { 230static const struct attribute_group ad5446_attribute_group = {
113 .attrs = ad5446_attributes, 231 .attrs = ad5446_attributes,
232 .is_visible = ad5446_attr_is_visible,
114}; 233};
115 234
116static const struct ad5446_chip_info ad5446_chip_info_tbl[] = { 235static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
@@ -156,6 +275,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
156 .left_shift = 2, 275 .left_shift = 2,
157 .int_vref_mv = 2500, 276 .int_vref_mv = 2500,
158 .store_sample = ad5620_store_sample, 277 .store_sample = ad5620_store_sample,
278 .store_pwr_down = ad5620_store_pwr_down,
159 }, 279 },
160 [ID_AD5620_1250] = { 280 [ID_AD5620_1250] = {
161 .bits = 12, 281 .bits = 12,
@@ -163,6 +283,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
163 .left_shift = 2, 283 .left_shift = 2,
164 .int_vref_mv = 1250, 284 .int_vref_mv = 1250,
165 .store_sample = ad5620_store_sample, 285 .store_sample = ad5620_store_sample,
286 .store_pwr_down = ad5620_store_pwr_down,
166 }, 287 },
167 [ID_AD5640_2500] = { 288 [ID_AD5640_2500] = {
168 .bits = 14, 289 .bits = 14,
@@ -170,6 +291,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
170 .left_shift = 0, 291 .left_shift = 0,
171 .int_vref_mv = 2500, 292 .int_vref_mv = 2500,
172 .store_sample = ad5620_store_sample, 293 .store_sample = ad5620_store_sample,
294 .store_pwr_down = ad5620_store_pwr_down,
173 }, 295 },
174 [ID_AD5640_1250] = { 296 [ID_AD5640_1250] = {
175 .bits = 14, 297 .bits = 14,
@@ -177,6 +299,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
177 .left_shift = 0, 299 .left_shift = 0,
178 .int_vref_mv = 1250, 300 .int_vref_mv = 1250,
179 .store_sample = ad5620_store_sample, 301 .store_sample = ad5620_store_sample,
302 .store_pwr_down = ad5620_store_pwr_down,
180 }, 303 },
181 [ID_AD5660_2500] = { 304 [ID_AD5660_2500] = {
182 .bits = 16, 305 .bits = 16,
@@ -184,6 +307,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
184 .left_shift = 0, 307 .left_shift = 0,
185 .int_vref_mv = 2500, 308 .int_vref_mv = 2500,
186 .store_sample = ad5660_store_sample, 309 .store_sample = ad5660_store_sample,
310 .store_pwr_down = ad5660_store_pwr_down,
187 }, 311 },
188 [ID_AD5660_1250] = { 312 [ID_AD5660_1250] = {
189 .bits = 16, 313 .bits = 16,
@@ -191,6 +315,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
191 .left_shift = 0, 315 .left_shift = 0,
192 .int_vref_mv = 1250, 316 .int_vref_mv = 1250,
193 .store_sample = ad5660_store_sample, 317 .store_sample = ad5660_store_sample,
318 .store_pwr_down = ad5660_store_pwr_down,
194 }, 319 },
195}; 320};
196 321
@@ -243,20 +368,20 @@ static int __devinit ad5446_probe(struct spi_device *spi)
243 spi_message_add_tail(&st->xfer, &st->msg); 368 spi_message_add_tail(&st->xfer, &st->msg);
244 369
245 switch (spi_get_device_id(spi)->driver_data) { 370 switch (spi_get_device_id(spi)->driver_data) {
246 case ID_AD5620_2500: 371 case ID_AD5620_2500:
247 case ID_AD5620_1250: 372 case ID_AD5620_1250:
248 case ID_AD5640_2500: 373 case ID_AD5640_2500:
249 case ID_AD5640_1250: 374 case ID_AD5640_1250:
250 case ID_AD5660_2500: 375 case ID_AD5660_2500:
251 case ID_AD5660_1250: 376 case ID_AD5660_1250:
252 st->vref_mv = st->chip_info->int_vref_mv; 377 st->vref_mv = st->chip_info->int_vref_mv;
253 break; 378 break;
254 default: 379 default:
255 if (voltage_uv) 380 if (voltage_uv)
256 st->vref_mv = voltage_uv / 1000; 381 st->vref_mv = voltage_uv / 1000;
257 else 382 else
258 dev_warn(&spi->dev, 383 dev_warn(&spi->dev,
259 "reference voltage unspecified\n"); 384 "reference voltage unspecified\n");
260 } 385 }
261 386
262 ret = iio_device_register(st->indio_dev); 387 ret = iio_device_register(st->indio_dev);
diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h
index 0cb9c14279e..e9397a6783c 100644
--- a/drivers/staging/iio/dac/ad5446.h
+++ b/drivers/staging/iio/dac/ad5446.h
@@ -27,6 +27,10 @@
27 27
28#define RES_MASK(bits) ((1 << (bits)) - 1) 28#define RES_MASK(bits) ((1 << (bits)) - 1)
29 29
30#define MODE_PWRDWN_1k 0x1
31#define MODE_PWRDWN_100k 0x2
32#define MODE_PWRDWN_TRISTATE 0x3
33
30/** 34/**
31 * struct ad5446_state - driver instance specific data 35 * struct ad5446_state - driver instance specific data
32 * @indio_dev: the industrial I/O device 36 * @indio_dev: the industrial I/O device
@@ -47,6 +51,9 @@ struct ad5446_state {
47 struct regulator *reg; 51 struct regulator *reg;
48 struct work_struct poll_work; 52 struct work_struct poll_work;
49 unsigned short vref_mv; 53 unsigned short vref_mv;
54 unsigned cached_val;
55 unsigned pwr_down_mode;
56 unsigned pwr_down;
50 struct spi_transfer xfer; 57 struct spi_transfer xfer;
51 struct spi_message msg; 58 struct spi_message msg;
52 union { 59 union {
@@ -62,14 +69,16 @@ struct ad5446_state {
62 * @left_shift: number of bits the datum must be shifted 69 * @left_shift: number of bits the datum must be shifted
63 * @int_vref_mv: AD5620/40/60: the internal reference voltage 70 * @int_vref_mv: AD5620/40/60: the internal reference voltage
64 * @store_sample: chip specific helper function to store the datum 71 * @store_sample: chip specific helper function to store the datum
72 * @store_sample: chip specific helper function to store the powerpown cmd
65 */ 73 */
66 74
67struct ad5446_chip_info { 75struct ad5446_chip_info {
68 u8 bits; 76 u8 bits;
69 u8 storagebits; 77 u8 storagebits;
70 u8 left_shift; 78 u8 left_shift;
71 u16 int_vref_mv; 79 u16 int_vref_mv;
72 void (*store_sample) (struct ad5446_state *st, unsigned val); 80 void (*store_sample) (struct ad5446_state *st, unsigned val);
81 void (*store_pwr_down) (struct ad5446_state *st, unsigned mode);
73}; 82};
74 83
75/** 84/**