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"); 169