|
@@ -24,6 +24,9 @@
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/iio/iio.h>
|
|
|
#include <linux/iio/sysfs.h>
|
|
|
+#include <linux/iio/buffer.h>
|
|
|
+#include <linux/iio/trigger_consumer.h>
|
|
|
+#include <linux/iio/triggered_buffer.h>
|
|
|
#include <linux/gpio/consumer.h>
|
|
|
#include <linux/regulator/consumer.h>
|
|
|
|
|
@@ -89,6 +92,11 @@ struct hx711_data {
|
|
|
int gain_set; /* gain set on device */
|
|
|
int gain_chan_a; /* gain for channel A */
|
|
|
struct mutex lock;
|
|
|
+ /*
|
|
|
+ * triggered buffer
|
|
|
+ * 2x32-bit channel + 64-bit timestamp
|
|
|
+ */
|
|
|
+ u32 buffer[4];
|
|
|
};
|
|
|
|
|
|
static int hx711_cycle(struct hx711_data *hx711_data)
|
|
@@ -236,34 +244,40 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int hx711_reset_read(struct hx711_data *hx711_data, int chan)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ int val;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * hx711_reset() must be called from here
|
|
|
+ * because it could be calling hx711_read() by itself
|
|
|
+ */
|
|
|
+ if (hx711_reset(hx711_data)) {
|
|
|
+ dev_err(hx711_data->dev, "reset failed!");
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = hx711_set_gain_for_channel(hx711_data, chan);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ val = hx711_read(hx711_data);
|
|
|
+
|
|
|
+ return val;
|
|
|
+}
|
|
|
+
|
|
|
static int hx711_read_raw(struct iio_dev *indio_dev,
|
|
|
const struct iio_chan_spec *chan,
|
|
|
int *val, int *val2, long mask)
|
|
|
{
|
|
|
struct hx711_data *hx711_data = iio_priv(indio_dev);
|
|
|
- int ret;
|
|
|
|
|
|
switch (mask) {
|
|
|
case IIO_CHAN_INFO_RAW:
|
|
|
mutex_lock(&hx711_data->lock);
|
|
|
|
|
|
- /*
|
|
|
- * hx711_reset() must be called from here
|
|
|
- * because it could be calling hx711_read() by itself
|
|
|
- */
|
|
|
- if (hx711_reset(hx711_data)) {
|
|
|
- mutex_unlock(&hx711_data->lock);
|
|
|
- dev_err(hx711_data->dev, "reset failed!");
|
|
|
- return -EIO;
|
|
|
- }
|
|
|
-
|
|
|
- ret = hx711_set_gain_for_channel(hx711_data, chan->channel);
|
|
|
- if (ret < 0) {
|
|
|
- mutex_unlock(&hx711_data->lock);
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- *val = hx711_read(hx711_data);
|
|
|
+ *val = hx711_reset_read(hx711_data, chan->channel);
|
|
|
|
|
|
mutex_unlock(&hx711_data->lock);
|
|
|
|
|
@@ -339,6 +353,36 @@ static int hx711_write_raw_get_fmt(struct iio_dev *indio_dev,
|
|
|
return IIO_VAL_INT_PLUS_NANO;
|
|
|
}
|
|
|
|
|
|
+static irqreturn_t hx711_trigger(int irq, void *p)
|
|
|
+{
|
|
|
+ struct iio_poll_func *pf = p;
|
|
|
+ struct iio_dev *indio_dev = pf->indio_dev;
|
|
|
+ struct hx711_data *hx711_data = iio_priv(indio_dev);
|
|
|
+ int i, j = 0;
|
|
|
+
|
|
|
+ mutex_lock(&hx711_data->lock);
|
|
|
+
|
|
|
+ memset(hx711_data->buffer, 0, sizeof(hx711_data->buffer));
|
|
|
+
|
|
|
+ for (i = 0; i < indio_dev->masklength; i++) {
|
|
|
+ if (!test_bit(i, indio_dev->active_scan_mask))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ hx711_data->buffer[j] = hx711_reset_read(hx711_data,
|
|
|
+ indio_dev->channels[i].channel);
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+
|
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, hx711_data->buffer,
|
|
|
+ pf->timestamp);
|
|
|
+
|
|
|
+ mutex_unlock(&hx711_data->lock);
|
|
|
+
|
|
|
+ iio_trigger_notify_done(indio_dev->trig);
|
|
|
+
|
|
|
+ return IRQ_HANDLED;
|
|
|
+}
|
|
|
+
|
|
|
static ssize_t hx711_scale_available_show(struct device *dev,
|
|
|
struct device_attribute *attr,
|
|
|
char *buf)
|
|
@@ -387,6 +431,13 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
|
|
|
.indexed = 1,
|
|
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
|
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
|
|
|
+ .scan_index = 0,
|
|
|
+ .scan_type = {
|
|
|
+ .sign = 'u',
|
|
|
+ .realbits = 24,
|
|
|
+ .storagebits = 32,
|
|
|
+ .endianness = IIO_CPU,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.type = IIO_VOLTAGE,
|
|
@@ -394,7 +445,15 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
|
|
|
.indexed = 1,
|
|
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
|
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
|
|
|
+ .scan_index = 1,
|
|
|
+ .scan_type = {
|
|
|
+ .sign = 'u',
|
|
|
+ .realbits = 24,
|
|
|
+ .storagebits = 32,
|
|
|
+ .endianness = IIO_CPU,
|
|
|
+ },
|
|
|
},
|
|
|
+ IIO_CHAN_SOFT_TIMESTAMP(2),
|
|
|
};
|
|
|
|
|
|
static int hx711_probe(struct platform_device *pdev)
|
|
@@ -459,10 +518,9 @@ static int hx711_probe(struct platform_device *pdev)
|
|
|
* 1 LSB = (AVDD * 100) / GAIN / 1678 [10^-9 mV]
|
|
|
*/
|
|
|
ret = regulator_get_voltage(hx711_data->reg_avdd);
|
|
|
- if (ret < 0) {
|
|
|
- regulator_disable(hx711_data->reg_avdd);
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ if (ret < 0)
|
|
|
+ goto error_regulator;
|
|
|
+
|
|
|
/* we need 10^-9 mV */
|
|
|
ret *= 100;
|
|
|
|
|
@@ -482,12 +540,27 @@ static int hx711_probe(struct platform_device *pdev)
|
|
|
indio_dev->channels = hx711_chan_spec;
|
|
|
indio_dev->num_channels = ARRAY_SIZE(hx711_chan_spec);
|
|
|
|
|
|
+ ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time,
|
|
|
+ hx711_trigger, NULL);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(dev, "setup of iio triggered buffer failed\n");
|
|
|
+ goto error_regulator;
|
|
|
+ }
|
|
|
+
|
|
|
ret = iio_device_register(indio_dev);
|
|
|
if (ret < 0) {
|
|
|
dev_err(dev, "Couldn't register the device\n");
|
|
|
- regulator_disable(hx711_data->reg_avdd);
|
|
|
+ goto error_buffer;
|
|
|
}
|
|
|
|
|
|
+ return 0;
|
|
|
+
|
|
|
+error_buffer:
|
|
|
+ iio_triggered_buffer_cleanup(indio_dev);
|
|
|
+
|
|
|
+error_regulator:
|
|
|
+ regulator_disable(hx711_data->reg_avdd);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -501,6 +574,8 @@ static int hx711_remove(struct platform_device *pdev)
|
|
|
|
|
|
iio_device_unregister(indio_dev);
|
|
|
|
|
|
+ iio_triggered_buffer_cleanup(indio_dev);
|
|
|
+
|
|
|
regulator_disable(hx711_data->reg_avdd);
|
|
|
|
|
|
return 0;
|