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/property.h> 15#include <linux/regmap.h> 16#include <linux/bitfield.h> 17 18#include <linux/iio/iio.h> 19#include <linux/iio/trigger.h> 20#include <linux/iio/events.h> 21#include <linux/iio/trigger_consumer.h> 22#include <linux/iio/triggered_buffer.h> 23#include <linux/iio/buffer.h> 24 25#include <linux/platform_data/st_sensors_pdata.h> 26 27#include "hts221.h" 28 29#define HTS221_REG_DRDY_HL_ADDR 0x22 30#define HTS221_REG_DRDY_HL_MASK BIT(7) 31#define HTS221_REG_DRDY_PP_OD_ADDR 0x22 32#define HTS221_REG_DRDY_PP_OD_MASK BIT(6) 33#define HTS221_REG_DRDY_EN_ADDR 0x22 34#define HTS221_REG_DRDY_EN_MASK BIT(2) 35#define HTS221_REG_STATUS_ADDR 0x27 36#define HTS221_RH_DRDY_MASK BIT(1) 37#define HTS221_TEMP_DRDY_MASK BIT(0) 38 39static int hts221_trig_set_state(struct iio_trigger *trig, bool state) 40{ 41 struct iio_dev *iio_dev = iio_trigger_get_drvdata(trig); 42 struct hts221_hw *hw = iio_priv(iio_dev); 43 44 return regmap_update_bits(hw->regmap, HTS221_REG_DRDY_EN_ADDR, 45 HTS221_REG_DRDY_EN_MASK, 46 FIELD_PREP(HTS221_REG_DRDY_EN_MASK, state)); 47} 48 49static const struct iio_trigger_ops hts221_trigger_ops = { 50 .set_trigger_state = hts221_trig_set_state, 51}; 52 53static irqreturn_t hts221_trigger_handler_thread(int irq, void *private) 54{ 55 struct hts221_hw *hw = private; 56 int err, status; 57 58 err = regmap_read(hw->regmap, HTS221_REG_STATUS_ADDR, &status); 59 if (err < 0) 60 return IRQ_HANDLED; 61 62 /* 63 * H_DA bit (humidity data available) is routed to DRDY line. 64 * Humidity sample is computed after temperature one. 65 * Here we can assume data channels are both available if H_DA bit 66 * is set in status register 67 */ 68 if (!(status & HTS221_RH_DRDY_MASK)) 69 return IRQ_NONE; 70 71 iio_trigger_poll_nested(hw->trig); 72 73 return IRQ_HANDLED; 74} 75 76int hts221_allocate_trigger(struct iio_dev *iio_dev) 77{ 78 struct hts221_hw *hw = iio_priv(iio_dev); 79 struct st_sensors_platform_data *pdata = dev_get_platdata(hw->dev); 80 bool irq_active_low = false, open_drain = false; 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 if (device_property_read_bool(hw->dev, "drive-open-drain") || 110 (pdata && pdata->open_drain)) { 111 irq_type |= IRQF_SHARED; 112 open_drain = true; 113 } 114 115 err = regmap_update_bits(hw->regmap, HTS221_REG_DRDY_PP_OD_ADDR, 116 HTS221_REG_DRDY_PP_OD_MASK, 117 FIELD_PREP(HTS221_REG_DRDY_PP_OD_MASK, 118 open_drain)); 119 if (err < 0) 120 return err; 121 122 err = devm_request_threaded_irq(hw->dev, hw->irq, NULL, 123 hts221_trigger_handler_thread, 124 irq_type | IRQF_ONESHOT, 125 hw->name, hw); 126 if (err) { 127 dev_err(hw->dev, "failed to request trigger irq %d\n", 128 hw->irq); 129 return err; 130 } 131 132 hw->trig = devm_iio_trigger_alloc(hw->dev, "%s-trigger", 133 iio_dev->name); 134 if (!hw->trig) 135 return -ENOMEM; 136 137 iio_trigger_set_drvdata(hw->trig, iio_dev); 138 hw->trig->ops = &hts221_trigger_ops; 139 140 err = devm_iio_trigger_register(hw->dev, hw->trig); 141 142 iio_dev->trig = iio_trigger_get(hw->trig); 143 144 return err; 145} 146 147static int hts221_buffer_preenable(struct iio_dev *iio_dev) 148{ 149 return hts221_set_enable(iio_priv(iio_dev), true); 150} 151 152static int hts221_buffer_postdisable(struct iio_dev *iio_dev) 153{ 154 return hts221_set_enable(iio_priv(iio_dev), false); 155} 156 157static const struct iio_buffer_setup_ops hts221_buffer_ops = { 158 .preenable = hts221_buffer_preenable, 159 .postdisable = hts221_buffer_postdisable, 160}; 161 162static irqreturn_t hts221_buffer_handler_thread(int irq, void *p) 163{ 164 struct iio_poll_func *pf = p; 165 struct iio_dev *iio_dev = pf->indio_dev; 166 struct hts221_hw *hw = iio_priv(iio_dev); 167 struct iio_chan_spec const *ch; 168 int err; 169 170 /* humidity data */ 171 ch = &iio_dev->channels[HTS221_SENSOR_H]; 172 err = regmap_bulk_read(hw->regmap, ch->address, 173 &hw->scan.channels[0], 174 sizeof(hw->scan.channels[0])); 175 if (err < 0) 176 goto out; 177 178 /* temperature data */ 179 ch = &iio_dev->channels[HTS221_SENSOR_T]; 180 err = regmap_bulk_read(hw->regmap, ch->address, 181 &hw->scan.channels[1], 182 sizeof(hw->scan.channels[1])); 183 if (err < 0) 184 goto out; 185 186 iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan, 187 iio_get_time_ns(iio_dev)); 188 189out: 190 iio_trigger_notify_done(hw->trig); 191 192 return IRQ_HANDLED; 193} 194 195int hts221_allocate_buffers(struct iio_dev *iio_dev) 196{ 197 struct hts221_hw *hw = iio_priv(iio_dev); 198 return devm_iio_triggered_buffer_setup(hw->dev, iio_dev, 199 NULL, hts221_buffer_handler_thread, 200 &hts221_buffer_ops); 201} 202 203MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>"); 204MODULE_DESCRIPTION("STMicroelectronics hts221 buffer driver"); 205MODULE_LICENSE("GPL v2"); 206