66 *
77 * 7-bit I2C slave address 0x4c
88 *
9- * TODO: interrupt
109 * https://media.digikey.com/pdf/Data%20Sheets/RF%20Digital%20PDFs/RFD77402.pdf
1110 */
1211
12+ #include <linux/bits.h>
13+ #include <linux/completion.h>
1314#include <linux/delay.h>
15+ #include <linux/dev_printk.h>
16+ #include <linux/errno.h>
1417#include <linux/i2c.h>
18+ #include <linux/interrupt.h>
1519#include <linux/iopoll.h>
20+ #include <linux/jiffies.h>
1621#include <linux/module.h>
22+ #include <linux/types.h>
1723
1824#include <linux/iio/iio.h>
1925
2026#define RFD77402_DRV_NAME "rfd77402"
2127
2228#define RFD77402_ICSR 0x00 /* Interrupt Control Status Register */
29+ #define RFD77402_ICSR_CLR_CFG BIT(0)
30+ #define RFD77402_ICSR_CLR_TYPE BIT(1)
2331#define RFD77402_ICSR_INT_MODE BIT(2)
2432#define RFD77402_ICSR_INT_POL BIT(3)
2533#define RFD77402_ICSR_RESULT BIT(4)
2634#define RFD77402_ICSR_M2H_MSG BIT(5)
2735#define RFD77402_ICSR_H2M_MSG BIT(6)
2836#define RFD77402_ICSR_RESET BIT(7)
2937
38+ #define RFD77402_IER 0x02
39+ #define RFD77402_IER_RESULT BIT(0)
40+ #define RFD77402_IER_M2H_MSG BIT(1)
41+ #define RFD77402_IER_H2M_MSG BIT(2)
42+ #define RFD77402_IER_RESET BIT(3)
43+
3044#define RFD77402_CMD_R 0x04
3145#define RFD77402_CMD_SINGLE 0x01
3246#define RFD77402_CMD_STANDBY 0x10
@@ -81,10 +95,14 @@ static const struct {
8195 * struct rfd77402_data - device-specific data for the RFD77402 sensor
8296 * @client: I2C client handle
8397 * @lock: mutex to serialize sensor reads
98+ * @completion: completion used for interrupt-driven measurements
99+ * @irq_en: indicates whether interrupt mode is enabled
84100 */
85101struct rfd77402_data {
86102 struct i2c_client * client ;
87103 struct mutex lock ;
104+ struct completion completion ;
105+ bool irq_en ;
88106};
89107
90108static const struct iio_chan_spec rfd77402_channels [] = {
@@ -95,6 +113,41 @@ static const struct iio_chan_spec rfd77402_channels[] = {
95113 },
96114};
97115
116+ static irqreturn_t rfd77402_interrupt_handler (int irq , void * pdata )
117+ {
118+ struct rfd77402_data * data = pdata ;
119+ int ret ;
120+
121+ ret = i2c_smbus_read_byte_data (data -> client , RFD77402_ICSR );
122+ if (ret < 0 )
123+ return IRQ_NONE ;
124+
125+ /* Check if the interrupt is from our device */
126+ if (!(ret & RFD77402_ICSR_RESULT ))
127+ return IRQ_NONE ;
128+
129+ /* Signal completion of measurement */
130+ complete (& data -> completion );
131+ return IRQ_HANDLED ;
132+ }
133+
134+ static int rfd77402_wait_for_irq (struct rfd77402_data * data )
135+ {
136+ int ret ;
137+
138+ /*
139+ * According to RFD77402 Datasheet v1.8,
140+ * Section 3.1.1 "Single Measure" (Figure: Single Measure Flow Chart),
141+ * the suggested timeout for single measure is 100 ms.
142+ */
143+ ret = wait_for_completion_timeout (& data -> completion ,
144+ msecs_to_jiffies (100 ));
145+ if (ret == 0 )
146+ return - ETIMEDOUT ;
147+
148+ return 0 ;
149+ }
150+
98151static int rfd77402_set_state (struct i2c_client * client , u8 state , u16 check )
99152{
100153 int ret ;
@@ -120,6 +173,11 @@ static int rfd77402_wait_for_result(struct rfd77402_data *data)
120173 struct i2c_client * client = data -> client ;
121174 int val , ret ;
122175
176+ if (data -> irq_en ) {
177+ reinit_completion (& data -> completion );
178+ return rfd77402_wait_for_irq (data );
179+ }
180+
123181 /*
124182 * As per RFD77402 datasheet section '3.1.1 Single Measure', the
125183 * suggested timeout value for single measure is 100ms.
@@ -204,19 +262,47 @@ static const struct iio_info rfd77402_info = {
204262 .read_raw = rfd77402_read_raw ,
205263};
206264
207- static int rfd77402_init (struct i2c_client * client )
265+ static int rfd77402_config_irq (struct i2c_client * client , u8 csr , u8 ier )
208266{
267+ int ret ;
268+
269+ ret = i2c_smbus_write_byte_data (client , RFD77402_ICSR , csr );
270+ if (ret )
271+ return ret ;
272+
273+ return i2c_smbus_write_byte_data (client , RFD77402_IER , ier );
274+ }
275+
276+ static int rfd77402_init (struct rfd77402_data * data )
277+ {
278+ struct i2c_client * client = data -> client ;
209279 int ret , i ;
210280
211281 ret = rfd77402_set_state (client , RFD77402_CMD_STANDBY ,
212282 RFD77402_STATUS_STANDBY );
213283 if (ret < 0 )
214284 return ret ;
215285
216- /* configure INT pad as push-pull, active low */
217- ret = i2c_smbus_write_byte_data (client , RFD77402_ICSR ,
218- RFD77402_ICSR_INT_MODE );
219- if (ret < 0 )
286+ if (data -> irq_en ) {
287+ /*
288+ * Enable interrupt mode:
289+ * - Configure ICSR for auto-clear on read and
290+ * push-pull output
291+ * - Enable "result ready" interrupt in IER
292+ */
293+ ret = rfd77402_config_irq (client ,
294+ RFD77402_ICSR_CLR_CFG |
295+ RFD77402_ICSR_INT_MODE ,
296+ RFD77402_IER_RESULT );
297+ } else {
298+ /*
299+ * Disable all interrupts:
300+ * - Clear ICSR configuration
301+ * - Disable all interrupts in IER
302+ */
303+ ret = rfd77402_config_irq (client , 0 , 0 );
304+ }
305+ if (ret )
220306 return ret ;
221307
222308 /* I2C configuration */
@@ -296,13 +382,29 @@ static int rfd77402_probe(struct i2c_client *client)
296382 if (ret )
297383 return ret ;
298384
385+ init_completion (& data -> completion );
386+
387+ if (client -> irq > 0 ) {
388+ ret = devm_request_threaded_irq (& client -> dev , client -> irq ,
389+ NULL , rfd77402_interrupt_handler ,
390+ IRQF_ONESHOT ,
391+ "rfd77402" , data );
392+ if (ret )
393+ return ret ;
394+
395+ data -> irq_en = true;
396+ dev_dbg (& client -> dev , "Using interrupt mode\n" );
397+ } else {
398+ dev_dbg (& client -> dev , "Using polling mode\n" );
399+ }
400+
299401 indio_dev -> info = & rfd77402_info ;
300402 indio_dev -> channels = rfd77402_channels ;
301403 indio_dev -> num_channels = ARRAY_SIZE (rfd77402_channels );
302404 indio_dev -> name = RFD77402_DRV_NAME ;
303405 indio_dev -> modes = INDIO_DIRECT_MODE ;
304406
305- ret = rfd77402_init (client );
407+ ret = rfd77402_init (data );
306408 if (ret < 0 )
307409 return ret ;
308410
@@ -320,7 +422,10 @@ static int rfd77402_suspend(struct device *dev)
320422
321423static int rfd77402_resume (struct device * dev )
322424{
323- return rfd77402_init (to_i2c_client (dev ));
425+ struct iio_dev * indio_dev = dev_get_drvdata (dev );
426+ struct rfd77402_data * data = iio_priv (indio_dev );
427+
428+ return rfd77402_init (data );
324429}
325430
326431static DEFINE_SIMPLE_DEV_PM_OPS (rfd77402_pm_ops , rfd77402_suspend ,
0 commit comments