// SPDX-License-Identifier: GPL-2.0 /* * sht15.c - support for the SHT15 Temperature and Humidity Sensor * * Portions Copyright (c) 2010-2012 Savoir-faire Linux Inc. * Jerome Oufella <[email protected]> * Vivien Didelot <[email protected]> * * Copyright (c) 2009 Jonathan Cameron * * Copyright (c) 2007 Wouter Horre * * For further information, see the Documentation/hwmon/sht15.rst file. */ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/module.h> #include <linux/init.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/jiffies.h> #include <linux/err.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/atomic.h> #include <linux/bitrev.h> #include <linux/gpio/consumer.h> #include <linux/of.h> /* Commands */ #define SHT15_MEASURE_TEMP … #define SHT15_MEASURE_RH … #define SHT15_WRITE_STATUS … #define SHT15_READ_STATUS … #define SHT15_SOFT_RESET … /* Min timings */ #define SHT15_TSCKL … #define SHT15_TSCKH … #define SHT15_TSU … #define SHT15_TSRST … /* Status Register Bits */ #define SHT15_STATUS_LOW_RESOLUTION … #define SHT15_STATUS_NO_OTP_RELOAD … #define SHT15_STATUS_HEATER … #define SHT15_STATUS_LOW_BATTERY … /* List of supported chips */ enum sht15_chips { … }; /* Actions the driver may be doing */ enum sht15_state { … }; /** * struct sht15_temppair - elements of voltage dependent temp calc * @vdd: supply voltage in microvolts * @d1: see data sheet */ struct sht15_temppair { … }; /* Table 9 from datasheet - relates temperature calculation to supply voltage */ static const struct sht15_temppair temppoints[] = …; /* Table from CRC datasheet, section 2.4 */ static const u8 sht15_crc8_table[] = …; /** * struct sht15_data - device instance specific data * @sck: clock GPIO line * @data: data GPIO line * @read_work: bh of interrupt handler. * @wait_queue: wait queue for getting values from device. * @val_temp: last temperature value read from device. * @val_humid: last humidity value read from device. * @val_status: last status register value read from device. * @checksum_ok: last value read from the device passed CRC validation. * @checksumming: flag used to enable the data validation with CRC. * @state: state identifying the action the driver is doing. * @measurements_valid: are the current stored measures valid (start condition). * @status_valid: is the current stored status valid (start condition). * @last_measurement: time of last measure. * @last_status: time of last status reading. * @read_lock: mutex to ensure only one read in progress at a time. * @dev: associate device structure. * @hwmon_dev: device associated with hwmon subsystem. * @reg: associated regulator (if specified). * @nb: notifier block to handle notifications of voltage * changes. * @supply_uv: local copy of supply voltage used to allow use of * regulator consumer if available. * @supply_uv_valid: indicates that an updated value has not yet been * obtained from the regulator and so any calculations * based upon it will be invalid. * @update_supply_work: work struct that is used to update the supply_uv. * @interrupt_handled: flag used to indicate a handler has been scheduled. */ struct sht15_data { … }; /** * sht15_crc8() - compute crc8 * @data: sht15 specific data. * @value: sht15 retrieved data. * @len: Length of retrieved data * * This implements section 2 of the CRC datasheet. */ static u8 sht15_crc8(struct sht15_data *data, const u8 *value, int len) { … } /** * sht15_connection_reset() - reset the comms interface * @data: sht15 specific data * * This implements section 3.4 of the data sheet */ static int sht15_connection_reset(struct sht15_data *data) { … } /** * sht15_send_bit() - send an individual bit to the device * @data: device state data * @val: value of bit to be sent */ static inline void sht15_send_bit(struct sht15_data *data, int val) { … } /** * sht15_transmission_start() - specific sequence for new transmission * @data: device state data * * Timings for this are not documented on the data sheet, so very * conservative ones used in implementation. This implements * figure 12 on the data sheet. */ static int sht15_transmission_start(struct sht15_data *data) { … } /** * sht15_send_byte() - send a single byte to the device * @data: device state * @byte: value to be sent */ static void sht15_send_byte(struct sht15_data *data, u8 byte) { … } /** * sht15_wait_for_response() - checks for ack from device * @data: device state */ static int sht15_wait_for_response(struct sht15_data *data) { … } /** * sht15_send_cmd() - Sends a command to the device. * @data: device state * @cmd: command byte to be sent * * On entry, sck is output low, data is output pull high * and the interrupt disabled. */ static int sht15_send_cmd(struct sht15_data *data, u8 cmd) { … } /** * sht15_soft_reset() - send a soft reset command * @data: sht15 specific data. * * As described in section 3.2 of the datasheet. */ static int sht15_soft_reset(struct sht15_data *data) { … } /** * sht15_ack() - send a ack * @data: sht15 specific data. * * Each byte of data is acknowledged by pulling the data line * low for one clock pulse. */ static int sht15_ack(struct sht15_data *data) { … } /** * sht15_end_transmission() - notify device of end of transmission * @data: device state. * * This is basically a NAK (single clock pulse, data high). */ static int sht15_end_transmission(struct sht15_data *data) { … } /** * sht15_read_byte() - Read a byte back from the device * @data: device state. */ static u8 sht15_read_byte(struct sht15_data *data) { … } /** * sht15_send_status() - write the status register byte * @data: sht15 specific data. * @status: the byte to set the status register with. * * As described in figure 14 and table 5 of the datasheet. */ static int sht15_send_status(struct sht15_data *data, u8 status) { … } /** * sht15_update_status() - get updated status register from device if too old * @data: device instance specific data. * * As described in figure 15 and table 5 of the datasheet. */ static int sht15_update_status(struct sht15_data *data) { … } /** * sht15_measurement() - get a new value from device * @data: device instance specific data * @command: command sent to request value * @timeout_msecs: timeout after which comms are assumed * to have failed are reset. */ static int sht15_measurement(struct sht15_data *data, int command, int timeout_msecs) { … } /** * sht15_update_measurements() - get updated measures from device if too old * @data: device state */ static int sht15_update_measurements(struct sht15_data *data) { … } /** * sht15_calc_temp() - convert the raw reading to a temperature * @data: device state * * As per section 4.3 of the data sheet. */ static inline int sht15_calc_temp(struct sht15_data *data) { … } /** * sht15_calc_humid() - using last temperature convert raw to humid * @data: device state * * This is the temperature compensated version as per section 4.2 of * the data sheet. * * The sensor is assumed to be V3, which is compatible with V4. * Humidity conversion coefficients are shown in table 7 of the datasheet. */ static inline int sht15_calc_humid(struct sht15_data *data) { … } /** * sht15_status_show() - show status information in sysfs * @dev: device. * @attr: device attribute. * @buf: sysfs buffer where information is written to. * * Will be called on read access to temp1_fault, humidity1_fault * and heater_enable sysfs attributes. * Returns number of bytes written into buffer, negative errno on error. */ static ssize_t sht15_status_show(struct device *dev, struct device_attribute *attr, char *buf) { … } /** * sht15_status_store() - change heater state via sysfs * @dev: device. * @attr: device attribute. * @buf: sysfs buffer to read the new heater state from. * @count: length of the data. * * Will be called on write access to heater_enable sysfs attribute. * Returns number of bytes actually decoded, negative errno on error. */ static ssize_t sht15_status_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } /** * sht15_temp_show() - show temperature measurement value in sysfs * @dev: device. * @attr: device attribute. * @buf: sysfs buffer where measurement values are written to. * * Will be called on read access to temp1_input sysfs attribute. * Returns number of bytes written into buffer, negative errno on error. */ static ssize_t sht15_temp_show(struct device *dev, struct device_attribute *attr, char *buf) { … } /** * sht15_humidity_show() - show humidity measurement value in sysfs * @dev: device. * @attr: device attribute. * @buf: sysfs buffer where measurement values are written to. * * Will be called on read access to humidity1_input sysfs attribute. * Returns number of bytes written into buffer, negative errno on error. */ static ssize_t sht15_humidity_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static SENSOR_DEVICE_ATTR_RO(temp1_input, sht15_temp, 0); static SENSOR_DEVICE_ATTR_RO(humidity1_input, sht15_humidity, 0); static SENSOR_DEVICE_ATTR_RO(temp1_fault, sht15_status, SHT15_STATUS_LOW_BATTERY); static SENSOR_DEVICE_ATTR_RO(humidity1_fault, sht15_status, SHT15_STATUS_LOW_BATTERY); static SENSOR_DEVICE_ATTR_RW(heater_enable, sht15_status, SHT15_STATUS_HEATER); static DEVICE_ATTR_RO(name); static struct attribute *sht15_attrs[] = …; static const struct attribute_group sht15_attr_group = …; static irqreturn_t sht15_interrupt_fired(int irq, void *d) { … } static void sht15_bh_read_data(struct work_struct *work_s) { … } static void sht15_update_voltage(struct work_struct *work_s) { … } /** * sht15_invalidate_voltage() - mark supply voltage invalid when notified by reg * @nb: associated notification structure * @event: voltage regulator state change event code * @ignored: function parameter - ignored here * * Note that as the notification code holds the regulator lock, we have * to schedule an update of the supply voltage rather than getting it directly. */ static int sht15_invalidate_voltage(struct notifier_block *nb, unsigned long event, void *ignored) { … } #ifdef CONFIG_OF static const struct of_device_id sht15_dt_match[] = …; MODULE_DEVICE_TABLE(of, sht15_dt_match); #endif static int sht15_probe(struct platform_device *pdev) { … } static void sht15_remove(struct platform_device *pdev) { … } static const struct platform_device_id sht15_device_ids[] = …; MODULE_DEVICE_TABLE(platform, sht15_device_ids); static struct platform_driver sht15_driver = …; module_platform_driver(…) …; MODULE_LICENSE(…) …; MODULE_DESCRIPTION(…) …;