Merge 4.13-rc2 into staging-next
[sfrench/cifs-2.6.git] / drivers / iio / humidity / hts221_buffer.c
1 /*
2  * STMicroelectronics hts221 sensor driver
3  *
4  * Copyright 2016 STMicroelectronics Inc.
5  *
6  * Lorenzo Bianconi <lorenzo.bianconi@st.com>
7  *
8  * Licensed under the GPL-2.
9  */
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/device.h>
13 #include <linux/interrupt.h>
14 #include <linux/irqreturn.h>
15
16 #include <linux/iio/iio.h>
17 #include <linux/iio/trigger.h>
18 #include <linux/iio/events.h>
19 #include <linux/iio/trigger_consumer.h>
20 #include <linux/iio/triggered_buffer.h>
21 #include <linux/iio/buffer.h>
22
23 #include "hts221.h"
24
25 #define HTS221_REG_STATUS_ADDR          0x27
26 #define HTS221_RH_DRDY_MASK             BIT(1)
27 #define HTS221_TEMP_DRDY_MASK           BIT(0)
28
29 static int hts221_trig_set_state(struct iio_trigger *trig, bool state)
30 {
31         struct iio_dev *iio_dev = iio_trigger_get_drvdata(trig);
32         struct hts221_hw *hw = iio_priv(iio_dev);
33
34         return hts221_config_drdy(hw, state);
35 }
36
37 static const struct iio_trigger_ops hts221_trigger_ops = {
38         .owner = THIS_MODULE,
39         .set_trigger_state = hts221_trig_set_state,
40 };
41
42 static irqreturn_t hts221_trigger_handler_thread(int irq, void *private)
43 {
44         struct hts221_hw *hw = private;
45         u8 status;
46         int err;
47
48         err = hw->tf->read(hw->dev, HTS221_REG_STATUS_ADDR, sizeof(status),
49                            &status);
50         if (err < 0)
51                 return IRQ_HANDLED;
52
53         /* 
54          * H_DA bit (humidity data available) is routed to DRDY line.
55          * Humidity sample is computed after temperature one.
56          * Here we can assume data channels are both available if H_DA bit
57          * is set in status register
58          */
59         if (!(status & HTS221_RH_DRDY_MASK))
60                 return IRQ_NONE;
61
62         iio_trigger_poll_chained(hw->trig);
63
64         return IRQ_HANDLED;
65 }
66
67 int hts221_allocate_trigger(struct hts221_hw *hw)
68 {
69         struct iio_dev *iio_dev = iio_priv_to_dev(hw);
70         unsigned long irq_type;
71         int err;
72
73         irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
74
75         switch (irq_type) {
76         case IRQF_TRIGGER_HIGH:
77         case IRQF_TRIGGER_RISING:
78                 break;
79         default:
80                 dev_info(hw->dev,
81                          "mode %lx unsupported, using IRQF_TRIGGER_RISING\n",
82                          irq_type);
83                 irq_type = IRQF_TRIGGER_RISING;
84                 break;
85         }
86
87         err = devm_request_threaded_irq(hw->dev, hw->irq, NULL,
88                                         hts221_trigger_handler_thread,
89                                         irq_type | IRQF_ONESHOT,
90                                         hw->name, hw);
91         if (err) {
92                 dev_err(hw->dev, "failed to request trigger irq %d\n",
93                         hw->irq);
94                 return err;
95         }
96
97         hw->trig = devm_iio_trigger_alloc(hw->dev, "%s-trigger",
98                                           iio_dev->name);
99         if (!hw->trig)
100                 return -ENOMEM;
101
102         iio_trigger_set_drvdata(hw->trig, iio_dev);
103         hw->trig->ops = &hts221_trigger_ops;
104         hw->trig->dev.parent = hw->dev;
105         iio_dev->trig = iio_trigger_get(hw->trig);
106
107         return devm_iio_trigger_register(hw->dev, hw->trig);
108 }
109
110 static int hts221_buffer_preenable(struct iio_dev *iio_dev)
111 {
112         return hts221_power_on(iio_priv(iio_dev));
113 }
114
115 static int hts221_buffer_postdisable(struct iio_dev *iio_dev)
116 {
117         return hts221_power_off(iio_priv(iio_dev));
118 }
119
120 static const struct iio_buffer_setup_ops hts221_buffer_ops = {
121         .preenable = hts221_buffer_preenable,
122         .postenable = iio_triggered_buffer_postenable,
123         .predisable = iio_triggered_buffer_predisable,
124         .postdisable = hts221_buffer_postdisable,
125 };
126
127 static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
128 {
129         u8 buffer[ALIGN(2 * HTS221_DATA_SIZE, sizeof(s64)) + sizeof(s64)];
130         struct iio_poll_func *pf = p;
131         struct iio_dev *iio_dev = pf->indio_dev;
132         struct hts221_hw *hw = iio_priv(iio_dev);
133         struct iio_chan_spec const *ch;
134         int err;
135
136         /* humidity data */
137         ch = &iio_dev->channels[HTS221_SENSOR_H];
138         err = hw->tf->read(hw->dev, ch->address, HTS221_DATA_SIZE,
139                            buffer);
140         if (err < 0)
141                 goto out;
142
143         /* temperature data */
144         ch = &iio_dev->channels[HTS221_SENSOR_T];
145         err = hw->tf->read(hw->dev, ch->address, HTS221_DATA_SIZE,
146                            buffer + HTS221_DATA_SIZE);
147         if (err < 0)
148                 goto out;
149
150         iio_push_to_buffers_with_timestamp(iio_dev, buffer,
151                                            iio_get_time_ns(iio_dev));
152
153 out:
154         iio_trigger_notify_done(hw->trig);
155
156         return IRQ_HANDLED;
157 }
158
159 int hts221_allocate_buffers(struct hts221_hw *hw)
160 {
161         return devm_iio_triggered_buffer_setup(hw->dev, iio_priv_to_dev(hw),
162                                         NULL, hts221_buffer_handler_thread,
163                                         &hts221_buffer_ops);
164 }
165
166 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
167 MODULE_DESCRIPTION("STMicroelectronics hts221 buffer driver");
168 MODULE_LICENSE("GPL v2");