root/drivers/iio/humidity/hts221_buffer.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hts221_trig_set_state
  2. hts221_trigger_handler_thread
  3. hts221_allocate_trigger
  4. hts221_buffer_preenable
  5. hts221_buffer_postdisable
  6. hts221_buffer_handler_thread
  7. hts221_allocate_buffers

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * STMicroelectronics hts221 sensor driver
   4  *
   5  * Copyright 2016 STMicroelectronics Inc.
   6  *
   7  * Lorenzo Bianconi <lorenzo.bianconi@st.com>
   8  */
   9 #include <linux/kernel.h>
  10 #include <linux/module.h>
  11 #include <linux/device.h>
  12 #include <linux/interrupt.h>
  13 #include <linux/irqreturn.h>
  14 #include <linux/regmap.h>
  15 #include <linux/bitfield.h>
  16 
  17 #include <linux/iio/iio.h>
  18 #include <linux/iio/trigger.h>
  19 #include <linux/iio/events.h>
  20 #include <linux/iio/trigger_consumer.h>
  21 #include <linux/iio/triggered_buffer.h>
  22 #include <linux/iio/buffer.h>
  23 
  24 #include <linux/platform_data/st_sensors_pdata.h>
  25 
  26 #include "hts221.h"
  27 
  28 #define HTS221_REG_DRDY_HL_ADDR         0x22
  29 #define HTS221_REG_DRDY_HL_MASK         BIT(7)
  30 #define HTS221_REG_DRDY_PP_OD_ADDR      0x22
  31 #define HTS221_REG_DRDY_PP_OD_MASK      BIT(6)
  32 #define HTS221_REG_DRDY_EN_ADDR         0x22
  33 #define HTS221_REG_DRDY_EN_MASK         BIT(2)
  34 #define HTS221_REG_STATUS_ADDR          0x27
  35 #define HTS221_RH_DRDY_MASK             BIT(1)
  36 #define HTS221_TEMP_DRDY_MASK           BIT(0)
  37 
  38 static int hts221_trig_set_state(struct iio_trigger *trig, bool state)
  39 {
  40         struct iio_dev *iio_dev = iio_trigger_get_drvdata(trig);
  41         struct hts221_hw *hw = iio_priv(iio_dev);
  42 
  43         return regmap_update_bits(hw->regmap, HTS221_REG_DRDY_EN_ADDR,
  44                                   HTS221_REG_DRDY_EN_MASK,
  45                                   FIELD_PREP(HTS221_REG_DRDY_EN_MASK, state));
  46 }
  47 
  48 static const struct iio_trigger_ops hts221_trigger_ops = {
  49         .set_trigger_state = hts221_trig_set_state,
  50 };
  51 
  52 static irqreturn_t hts221_trigger_handler_thread(int irq, void *private)
  53 {
  54         struct hts221_hw *hw = private;
  55         int err, status;
  56 
  57         err = regmap_read(hw->regmap, HTS221_REG_STATUS_ADDR, &status);
  58         if (err < 0)
  59                 return IRQ_HANDLED;
  60 
  61         /*
  62          * H_DA bit (humidity data available) is routed to DRDY line.
  63          * Humidity sample is computed after temperature one.
  64          * Here we can assume data channels are both available if H_DA bit
  65          * is set in status register
  66          */
  67         if (!(status & HTS221_RH_DRDY_MASK))
  68                 return IRQ_NONE;
  69 
  70         iio_trigger_poll_chained(hw->trig);
  71 
  72         return IRQ_HANDLED;
  73 }
  74 
  75 int hts221_allocate_trigger(struct hts221_hw *hw)
  76 {
  77         struct iio_dev *iio_dev = iio_priv_to_dev(hw);
  78         bool irq_active_low = false, open_drain = false;
  79         struct device_node *np = hw->dev->of_node;
  80         struct st_sensors_platform_data *pdata;
  81         unsigned long irq_type;
  82         int err;
  83 
  84         irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
  85 
  86         switch (irq_type) {
  87         case IRQF_TRIGGER_HIGH:
  88         case IRQF_TRIGGER_RISING:
  89                 break;
  90         case IRQF_TRIGGER_LOW:
  91         case IRQF_TRIGGER_FALLING:
  92                 irq_active_low = true;
  93                 break;
  94         default:
  95                 dev_info(hw->dev,
  96                          "mode %lx unsupported, using IRQF_TRIGGER_RISING\n",
  97                          irq_type);
  98                 irq_type = IRQF_TRIGGER_RISING;
  99                 break;
 100         }
 101 
 102         err = regmap_update_bits(hw->regmap, HTS221_REG_DRDY_HL_ADDR,
 103                                  HTS221_REG_DRDY_HL_MASK,
 104                                  FIELD_PREP(HTS221_REG_DRDY_HL_MASK,
 105                                             irq_active_low));
 106         if (err < 0)
 107                 return err;
 108 
 109         pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
 110         if ((np && of_property_read_bool(np, "drive-open-drain")) ||
 111             (pdata && pdata->open_drain)) {
 112                 irq_type |= IRQF_SHARED;
 113                 open_drain = true;
 114         }
 115 
 116         err = regmap_update_bits(hw->regmap, HTS221_REG_DRDY_PP_OD_ADDR,
 117                                  HTS221_REG_DRDY_PP_OD_MASK,
 118                                  FIELD_PREP(HTS221_REG_DRDY_PP_OD_MASK,
 119                                             open_drain));
 120         if (err < 0)
 121                 return err;
 122 
 123         err = devm_request_threaded_irq(hw->dev, hw->irq, NULL,
 124                                         hts221_trigger_handler_thread,
 125                                         irq_type | IRQF_ONESHOT,
 126                                         hw->name, hw);
 127         if (err) {
 128                 dev_err(hw->dev, "failed to request trigger irq %d\n",
 129                         hw->irq);
 130                 return err;
 131         }
 132 
 133         hw->trig = devm_iio_trigger_alloc(hw->dev, "%s-trigger",
 134                                           iio_dev->name);
 135         if (!hw->trig)
 136                 return -ENOMEM;
 137 
 138         iio_trigger_set_drvdata(hw->trig, iio_dev);
 139         hw->trig->ops = &hts221_trigger_ops;
 140         hw->trig->dev.parent = hw->dev;
 141         iio_dev->trig = iio_trigger_get(hw->trig);
 142 
 143         return devm_iio_trigger_register(hw->dev, hw->trig);
 144 }
 145 
 146 static int hts221_buffer_preenable(struct iio_dev *iio_dev)
 147 {
 148         return hts221_set_enable(iio_priv(iio_dev), true);
 149 }
 150 
 151 static int hts221_buffer_postdisable(struct iio_dev *iio_dev)
 152 {
 153         return hts221_set_enable(iio_priv(iio_dev), false);
 154 }
 155 
 156 static const struct iio_buffer_setup_ops hts221_buffer_ops = {
 157         .preenable = hts221_buffer_preenable,
 158         .postenable = iio_triggered_buffer_postenable,
 159         .predisable = iio_triggered_buffer_predisable,
 160         .postdisable = hts221_buffer_postdisable,
 161 };
 162 
 163 static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
 164 {
 165         u8 buffer[ALIGN(2 * HTS221_DATA_SIZE, sizeof(s64)) + sizeof(s64)];
 166         struct iio_poll_func *pf = p;
 167         struct iio_dev *iio_dev = pf->indio_dev;
 168         struct hts221_hw *hw = iio_priv(iio_dev);
 169         struct iio_chan_spec const *ch;
 170         int err;
 171 
 172         /* humidity data */
 173         ch = &iio_dev->channels[HTS221_SENSOR_H];
 174         err = regmap_bulk_read(hw->regmap, ch->address,
 175                                buffer, HTS221_DATA_SIZE);
 176         if (err < 0)
 177                 goto out;
 178 
 179         /* temperature data */
 180         ch = &iio_dev->channels[HTS221_SENSOR_T];
 181         err = regmap_bulk_read(hw->regmap, ch->address,
 182                                buffer + HTS221_DATA_SIZE, HTS221_DATA_SIZE);
 183         if (err < 0)
 184                 goto out;
 185 
 186         iio_push_to_buffers_with_timestamp(iio_dev, buffer,
 187                                            iio_get_time_ns(iio_dev));
 188 
 189 out:
 190         iio_trigger_notify_done(hw->trig);
 191 
 192         return IRQ_HANDLED;
 193 }
 194 
 195 int hts221_allocate_buffers(struct hts221_hw *hw)
 196 {
 197         return devm_iio_triggered_buffer_setup(hw->dev, iio_priv_to_dev(hw),
 198                                         NULL, hts221_buffer_handler_thread,
 199                                         &hts221_buffer_ops);
 200 }
 201 
 202 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
 203 MODULE_DESCRIPTION("STMicroelectronics hts221 buffer driver");
 204 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */