diff options
author | Crestez Dan Leonard <leonard.crestez@intel.com> | 2016-04-11 10:24:27 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2016-04-17 05:46:50 -0400 |
commit | 08e05d1fce5c87e5eaf16655c45db6beb4d93701 (patch) | |
tree | 865d39ed4afe2dfe0c3c0aa26cdff776428e9be6 | |
parent | a6b5ec887b85df039055be316420b1520c23eb6b (diff) |
ti-adc081c: Initial triggered buffer support
Using this requires software triggers like CONFIG_IIO_HRTIMER_TRIGGER.
The device can be configured to do internal periodic sampling but does not
offer some sort of interrupt on data ready. Interrupts can only trigger when
values get out of a specific range.
Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r-- | drivers/iio/adc/ti-adc081c.c | 77 |
1 files changed, 64 insertions, 13 deletions
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index b977340fbdb8..9fd032d9f402 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c | |||
@@ -24,6 +24,9 @@ | |||
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | 25 | ||
26 | #include <linux/iio/iio.h> | 26 | #include <linux/iio/iio.h> |
27 | #include <linux/iio/buffer.h> | ||
28 | #include <linux/iio/trigger_consumer.h> | ||
29 | #include <linux/iio/triggered_buffer.h> | ||
27 | #include <linux/regulator/consumer.h> | 30 | #include <linux/regulator/consumer.h> |
28 | 31 | ||
29 | struct adc081c { | 32 | struct adc081c { |
@@ -69,21 +72,42 @@ static int adc081c_read_raw(struct iio_dev *iio, | |||
69 | return -EINVAL; | 72 | return -EINVAL; |
70 | } | 73 | } |
71 | 74 | ||
72 | static const struct iio_chan_spec adc081c_channel = { | 75 | #define ADCxx1C_CHAN(_bits) { \ |
73 | .type = IIO_VOLTAGE, | 76 | .type = IIO_VOLTAGE, \ |
74 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), | 77 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
75 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | 78 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
76 | }; | 79 | .scan_type = { \ |
80 | .sign = 'u', \ | ||
81 | .realbits = (_bits), \ | ||
82 | .storagebits = 16, \ | ||
83 | .shift = 12 - (_bits), \ | ||
84 | .endianness = IIO_CPU, \ | ||
85 | }, \ | ||
86 | } | ||
87 | |||
88 | #define DEFINE_ADCxx1C_CHANNELS(_name, _bits) \ | ||
89 | static const struct iio_chan_spec _name ## _channels[] = { \ | ||
90 | ADCxx1C_CHAN((_bits)), \ | ||
91 | IIO_CHAN_SOFT_TIMESTAMP(1), \ | ||
92 | }; \ | ||
93 | |||
94 | #define ADC081C_NUM_CHANNELS 2 | ||
77 | 95 | ||
78 | struct adcxx1c_model { | 96 | struct adcxx1c_model { |
97 | const struct iio_chan_spec* channels; | ||
79 | int bits; | 98 | int bits; |
80 | }; | 99 | }; |
81 | 100 | ||
82 | #define ADCxx1C_MODEL(_bits) \ | 101 | #define ADCxx1C_MODEL(_name, _bits) \ |
83 | { \ | 102 | { \ |
103 | .channels = _name ## _channels, \ | ||
84 | .bits = (_bits), \ | 104 | .bits = (_bits), \ |
85 | } | 105 | } |
86 | 106 | ||
107 | DEFINE_ADCxx1C_CHANNELS(adc081c, 8); | ||
108 | DEFINE_ADCxx1C_CHANNELS(adc101c, 10); | ||
109 | DEFINE_ADCxx1C_CHANNELS(adc121c, 12); | ||
110 | |||
87 | /* Model ids are indexes in _models array */ | 111 | /* Model ids are indexes in _models array */ |
88 | enum adcxx1c_model_id { | 112 | enum adcxx1c_model_id { |
89 | ADC081C = 0, | 113 | ADC081C = 0, |
@@ -92,9 +116,9 @@ enum adcxx1c_model_id { | |||
92 | }; | 116 | }; |
93 | 117 | ||
94 | static struct adcxx1c_model adcxx1c_models[] = { | 118 | static struct adcxx1c_model adcxx1c_models[] = { |
95 | ADCxx1C_MODEL( 8), | 119 | ADCxx1C_MODEL(adc081c, 8), |
96 | ADCxx1C_MODEL(10), | 120 | ADCxx1C_MODEL(adc101c, 10), |
97 | ADCxx1C_MODEL(12), | 121 | ADCxx1C_MODEL(adc121c, 12), |
98 | }; | 122 | }; |
99 | 123 | ||
100 | static const struct iio_info adc081c_info = { | 124 | static const struct iio_info adc081c_info = { |
@@ -102,6 +126,24 @@ static const struct iio_info adc081c_info = { | |||
102 | .driver_module = THIS_MODULE, | 126 | .driver_module = THIS_MODULE, |
103 | }; | 127 | }; |
104 | 128 | ||
129 | static irqreturn_t adc081c_trigger_handler(int irq, void *p) | ||
130 | { | ||
131 | struct iio_poll_func *pf = p; | ||
132 | struct iio_dev *indio_dev = pf->indio_dev; | ||
133 | struct adc081c *data = iio_priv(indio_dev); | ||
134 | u16 buf[8]; /* 2 bytes data + 6 bytes padding + 8 bytes timestamp */ | ||
135 | int ret; | ||
136 | |||
137 | ret = i2c_smbus_read_word_swapped(data->i2c, REG_CONV_RES); | ||
138 | if (ret < 0) | ||
139 | goto out; | ||
140 | buf[0] = ret; | ||
141 | iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); | ||
142 | out: | ||
143 | iio_trigger_notify_done(indio_dev->trig); | ||
144 | return IRQ_HANDLED; | ||
145 | } | ||
146 | |||
105 | static int adc081c_probe(struct i2c_client *client, | 147 | static int adc081c_probe(struct i2c_client *client, |
106 | const struct i2c_device_id *id) | 148 | const struct i2c_device_id *id) |
107 | { | 149 | { |
@@ -134,18 +176,26 @@ static int adc081c_probe(struct i2c_client *client, | |||
134 | iio->modes = INDIO_DIRECT_MODE; | 176 | iio->modes = INDIO_DIRECT_MODE; |
135 | iio->info = &adc081c_info; | 177 | iio->info = &adc081c_info; |
136 | 178 | ||
137 | iio->channels = &adc081c_channel; | 179 | iio->channels = model->channels; |
138 | iio->num_channels = 1; | 180 | iio->num_channels = ADC081C_NUM_CHANNELS; |
181 | |||
182 | err = iio_triggered_buffer_setup(iio, NULL, adc081c_trigger_handler, NULL); | ||
183 | if (err < 0) { | ||
184 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); | ||
185 | goto err_regulator_disable; | ||
186 | } | ||
139 | 187 | ||
140 | err = iio_device_register(iio); | 188 | err = iio_device_register(iio); |
141 | if (err < 0) | 189 | if (err < 0) |
142 | goto regulator_disable; | 190 | goto err_buffer_cleanup; |
143 | 191 | ||
144 | i2c_set_clientdata(client, iio); | 192 | i2c_set_clientdata(client, iio); |
145 | 193 | ||
146 | return 0; | 194 | return 0; |
147 | 195 | ||
148 | regulator_disable: | 196 | err_buffer_cleanup: |
197 | iio_triggered_buffer_cleanup(iio); | ||
198 | err_regulator_disable: | ||
149 | regulator_disable(adc->ref); | 199 | regulator_disable(adc->ref); |
150 | 200 | ||
151 | return err; | 201 | return err; |
@@ -157,6 +207,7 @@ static int adc081c_remove(struct i2c_client *client) | |||
157 | struct adc081c *adc = iio_priv(iio); | 207 | struct adc081c *adc = iio_priv(iio); |
158 | 208 | ||
159 | iio_device_unregister(iio); | 209 | iio_device_unregister(iio); |
210 | iio_triggered_buffer_cleanup(iio); | ||
160 | regulator_disable(adc->ref); | 211 | regulator_disable(adc->ref); |
161 | 212 | ||
162 | return 0; | 213 | return 0; |