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 38static 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 48static const struct iio_trigger_ops hts221_trigger_ops = { 49 .set_trigger_state = hts221_trig_set_state, 50}; 51 52static 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 75int hts221_allocate_trigger(struct iio_dev *iio_dev) 76{ 77 struct hts221_hw *hw = iio_priv(iio_dev); 78 struct st_sensors_platform_data *pdata = dev_get_platdata(hw->dev); 79 bool irq_active_low = false, open_drain = false; 80 unsigned long irq_type; 81 int err; 82 83 irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); 84 85 switch (irq_type) { 86 case IRQF_TRIGGER_HIGH: 87 case IRQF_TRIGGER_RISING: 88 break; 89 case IRQF_TRIGGER_LOW: 90 case IRQF_TRIGGER_FALLING: 91 irq_active_low = true; 92 break; 93 default: 94 dev_info(hw->dev, 95 "mode %lx unsupported, using IRQF_TRIGGER_RISING\n", 96 irq_type); 97 irq_type = IRQF_TRIGGER_RISING; 98 break; 99 } 100 101 err = regmap_update_bits(hw->regmap, HTS221_REG_DRDY_HL_ADDR, 102 HTS221_REG_DRDY_HL_MASK, 103 FIELD_PREP(HTS221_REG_DRDY_HL_MASK, 104 irq_active_low)); 105 if (err < 0) 106 return err; 107 108 if (device_property_read_bool(hw->dev, "drive-open-drain") || 109 (pdata && pdata->open_drain)) { 110 irq_type |= IRQF_SHARED; 111 open_drain = true; 112 } 113 114 err = regmap_update_bits(hw->regmap, HTS221_REG_DRDY_PP_OD_ADDR, 115 HTS221_REG_DRDY_PP_OD_MASK, 116 FIELD_PREP(HTS221_REG_DRDY_PP_OD_MASK, 117 open_drain)); 118 if (err < 0) 119 return err; 120 121 err = devm_request_threaded_irq(hw->dev, hw->irq, NULL, 122 hts221_trigger_handler_thread, 123 irq_type | IRQF_ONESHOT, 124 hw->name, hw); 125 if (err) { 126 dev_err(hw->dev, "failed to request trigger irq %d\n", 127 hw->irq); 128 return err; 129 } 130 131 hw->trig = devm_iio_trigger_alloc(hw->dev, "%s-trigger", 132 iio_dev->name); 133 if (!hw->trig) 134 return -ENOMEM; 135 136 iio_trigger_set_drvdata(hw->trig, iio_dev); 137 hw->trig->ops = &hts221_trigger_ops; 138 hw->trig->dev.parent = hw->dev; 139 iio_dev->trig = iio_trigger_get(hw->trig); 140 141 return devm_iio_trigger_register(hw->dev, hw->trig); 142} 143 144static int hts221_buffer_preenable(struct iio_dev *iio_dev) 145{ 146 return hts221_set_enable(iio_priv(iio_dev), true); 147} 148 149static int hts221_buffer_postdisable(struct iio_dev *iio_dev) 150{ 151 return hts221_set_enable(iio_priv(iio_dev), false); 152} 153 154static const struct iio_buffer_setup_ops hts221_buffer_ops = { 155 .preenable = hts221_buffer_preenable, 156 .postdisable = hts221_buffer_postdisable, 157}; 158 159static irqreturn_t hts221_buffer_handler_thread(int irq, void *p) 160{ 161 struct iio_poll_func *pf = p; 162 struct iio_dev *iio_dev = pf->indio_dev; 163 struct hts221_hw *hw = iio_priv(iio_dev); 164 struct iio_chan_spec const *ch; 165 int err; 166 167 /* humidity data */ 168 ch = &iio_dev->channels[HTS221_SENSOR_H]; 169 err = regmap_bulk_read(hw->regmap, ch->address, 170 &hw->scan.channels[0], 171 sizeof(hw->scan.channels[0])); 172 if (err < 0) 173 goto out; 174 175 /* temperature data */ 176 ch = &iio_dev->channels[HTS221_SENSOR_T]; 177 err = regmap_bulk_read(hw->regmap, ch->address, 178 &hw->scan.channels[1], 179 sizeof(hw->scan.channels[1])); 180 if (err < 0) 181 goto out; 182 183 iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan, 184 iio_get_time_ns(iio_dev)); 185 186out: 187 iio_trigger_notify_done(hw->trig); 188 189 return IRQ_HANDLED; 190} 191 192int hts221_allocate_buffers(struct iio_dev *iio_dev) 193{ 194 struct hts221_hw *hw = iio_priv(iio_dev); 195 return devm_iio_triggered_buffer_setup(hw->dev, iio_dev, 196 NULL, hts221_buffer_handler_thread, 197 &hts221_buffer_ops); 198} 199 200MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>"); 201MODULE_DESCRIPTION("STMicroelectronics hts221 buffer driver"); 202MODULE_LICENSE("GPL v2"); 203