Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: pressure: driver for Honeywell HSC/SSC series

Adds driver for digital Honeywell TruStability HSC and SSC series
pressure and temperature sensors.
Communication is one way. The sensor only requires 4 bytes worth of
clock pulses on both i2c and spi in order to push the data out.
The i2c address is hardcoded and depends on the part number.
There is no additional GPIO control.
code is now based on iio/togreg

Datasheet:
https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/trustability-hsc-series/documents/sps-siot-trustability-hsc-series-high-accuracy-board-mount-pressure-sensors-50099148-a-en-ciid-151133.pdf [HSC]
Datasheet:
https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/trustability-ssc-series/documents/sps-siot-trustability-ssc-series-standard-accuracy-board-mount-pressure-sensors-50099533-a-en-ciid-151134.pdf [SSC]

Signed-off-by: Petre Rodan <petre.rodan@subdimension.ro>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20231207164634.11998-2-petre.rodan@subdimension.ro
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Petre Rodan and committed by
Jonathan Cameron
6362d965 5fc0a980

+730
+7
MAINTAINERS
··· 9709 9709 F: mm/hmm* 9710 9710 F: tools/testing/selftests/mm/*hmm* 9711 9711 9712 + HONEYWELL HSC030PA PRESSURE SENSOR SERIES IIO DRIVER 9713 + M: Petre Rodan <petre.rodan@subdimension.ro> 9714 + L: linux-iio@vger.kernel.org 9715 + S: Maintained 9716 + F: Documentation/devicetree/bindings/iio/pressure/honeywell,hsc030pa.yaml 9717 + F: drivers/iio/pressure/hsc030pa* 9718 + 9712 9719 HONEYWELL MPRLS0025PA PRESSURE SENSOR SERIES IIO DRIVER 9713 9720 M: Andreas Klinger <ak@it-klinger.de> 9714 9721 L: linux-iio@vger.kernel.org
+22
drivers/iio/pressure/Kconfig
··· 109 109 To compile this driver as a module, choose M here: the module 110 110 will be called hp03. 111 111 112 + config HSC030PA 113 + tristate "Honeywell HSC/SSC TruStability pressure sensor series" 114 + depends on (I2C || SPI_MASTER) 115 + select HSC030PA_I2C if I2C 116 + select HSC030PA_SPI if SPI_MASTER 117 + help 118 + Say Y here to build support for the Honeywell TruStability 119 + HSC and SSC pressure and temperature sensor series. 120 + 121 + To compile this driver as a module, choose M here: the module 122 + will be called hsc030pa. 123 + 124 + config HSC030PA_I2C 125 + tristate 126 + depends on HSC030PA 127 + depends on I2C 128 + 129 + config HSC030PA_SPI 130 + tristate 131 + depends on HSC030PA 132 + depends on SPI_MASTER 133 + 112 134 config ICP10100 113 135 tristate "InvenSense ICP-101xx pressure and temperature sensor" 114 136 depends on I2C
+3
drivers/iio/pressure/Makefile
··· 15 15 obj-$(CONFIG_IIO_CROS_EC_BARO) += cros_ec_baro.o 16 16 obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o 17 17 obj-$(CONFIG_HP03) += hp03.o 18 + obj-$(CONFIG_HSC030PA) += hsc030pa.o 19 + obj-$(CONFIG_HSC030PA_I2C) += hsc030pa_i2c.o 20 + obj-$(CONFIG_HSC030PA_SPI) += hsc030pa_spi.o 18 21 obj-$(CONFIG_ICP10100) += icp10100.o 19 22 obj-$(CONFIG_MPL115) += mpl115.o 20 23 obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o
+494
drivers/iio/pressure/hsc030pa.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Honeywell TruStability HSC Series pressure/temperature sensor 4 + * 5 + * Copyright (c) 2023 Petre Rodan <petre.rodan@subdimension.ro> 6 + * 7 + * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/trustability-hsc-series/documents/sps-siot-trustability-hsc-series-high-accuracy-board-mount-pressure-sensors-50099148-a-en-ciid-151133.pdf 8 + */ 9 + 10 + #include <linux/array_size.h> 11 + #include <linux/bitfield.h> 12 + #include <linux/bits.h> 13 + #include <linux/cleanup.h> 14 + #include <linux/init.h> 15 + #include <linux/math64.h> 16 + #include <linux/mod_devicetable.h> 17 + #include <linux/module.h> 18 + #include <linux/printk.h> 19 + #include <linux/property.h> 20 + #include <linux/regulator/consumer.h> 21 + #include <linux/string.h> 22 + #include <linux/types.h> 23 + #include <linux/units.h> 24 + 25 + #include <linux/iio/iio.h> 26 + #include <linux/iio/sysfs.h> 27 + 28 + #include <asm/unaligned.h> 29 + 30 + #include "hsc030pa.h" 31 + 32 + /* 33 + * HSC_PRESSURE_TRIPLET_LEN - length for the string that defines the 34 + * pressure range, measurement unit and type as per the part nomenclature. 35 + * Consult honeywell,pressure-triplet in the bindings file for details. 36 + */ 37 + #define HSC_PRESSURE_TRIPLET_LEN 6 38 + #define HSC_STATUS_MASK GENMASK(7, 6) 39 + #define HSC_TEMPERATURE_MASK GENMASK(15, 5) 40 + #define HSC_PRESSURE_MASK GENMASK(29, 16) 41 + 42 + struct hsc_func_spec { 43 + u32 output_min; 44 + u32 output_max; 45 + }; 46 + 47 + /* 48 + * function A: 10% - 90% of 2^14 49 + * function B: 5% - 95% of 2^14 50 + * function C: 5% - 85% of 2^14 51 + * function F: 4% - 94% of 2^14 52 + */ 53 + static const struct hsc_func_spec hsc_func_spec[] = { 54 + [HSC_FUNCTION_A] = { .output_min = 1638, .output_max = 14746 }, 55 + [HSC_FUNCTION_B] = { .output_min = 819, .output_max = 15565 }, 56 + [HSC_FUNCTION_C] = { .output_min = 819, .output_max = 13926 }, 57 + [HSC_FUNCTION_F] = { .output_min = 655, .output_max = 15401 }, 58 + }; 59 + 60 + enum hsc_variants { 61 + HSC001BA = 0x00, HSC1_6BA = 0x01, HSC2_5BA = 0x02, HSC004BA = 0x03, 62 + HSC006BA = 0x04, HSC010BA = 0x05, HSC1_6MD = 0x06, HSC2_5MD = 0x07, 63 + HSC004MD = 0x08, HSC006MD = 0x09, HSC010MD = 0x0a, HSC016MD = 0x0b, 64 + HSC025MD = 0x0c, HSC040MD = 0x0d, HSC060MD = 0x0e, HSC100MD = 0x0f, 65 + HSC160MD = 0x10, HSC250MD = 0x11, HSC400MD = 0x12, HSC600MD = 0x13, 66 + HSC001BD = 0x14, HSC1_6BD = 0x15, HSC2_5BD = 0x16, HSC004BD = 0x17, 67 + HSC2_5MG = 0x18, HSC004MG = 0x19, HSC006MG = 0x1a, HSC010MG = 0x1b, 68 + HSC016MG = 0x1c, HSC025MG = 0x1d, HSC040MG = 0x1e, HSC060MG = 0x1f, 69 + HSC100MG = 0x20, HSC160MG = 0x21, HSC250MG = 0x22, HSC400MG = 0x23, 70 + HSC600MG = 0x24, HSC001BG = 0x25, HSC1_6BG = 0x26, HSC2_5BG = 0x27, 71 + HSC004BG = 0x28, HSC006BG = 0x29, HSC010BG = 0x2a, HSC100KA = 0x2b, 72 + HSC160KA = 0x2c, HSC250KA = 0x2d, HSC400KA = 0x2e, HSC600KA = 0x2f, 73 + HSC001GA = 0x30, HSC160LD = 0x31, HSC250LD = 0x32, HSC400LD = 0x33, 74 + HSC600LD = 0x34, HSC001KD = 0x35, HSC1_6KD = 0x36, HSC2_5KD = 0x37, 75 + HSC004KD = 0x38, HSC006KD = 0x39, HSC010KD = 0x3a, HSC016KD = 0x3b, 76 + HSC025KD = 0x3c, HSC040KD = 0x3d, HSC060KD = 0x3e, HSC100KD = 0x3f, 77 + HSC160KD = 0x40, HSC250KD = 0x41, HSC400KD = 0x42, HSC250LG = 0x43, 78 + HSC400LG = 0x44, HSC600LG = 0x45, HSC001KG = 0x46, HSC1_6KG = 0x47, 79 + HSC2_5KG = 0x48, HSC004KG = 0x49, HSC006KG = 0x4a, HSC010KG = 0x4b, 80 + HSC016KG = 0x4c, HSC025KG = 0x4d, HSC040KG = 0x4e, HSC060KG = 0x4f, 81 + HSC100KG = 0x50, HSC160KG = 0x51, HSC250KG = 0x52, HSC400KG = 0x53, 82 + HSC600KG = 0x54, HSC001GG = 0x55, HSC015PA = 0x56, HSC030PA = 0x57, 83 + HSC060PA = 0x58, HSC100PA = 0x59, HSC150PA = 0x5a, HSC0_5ND = 0x5b, 84 + HSC001ND = 0x5c, HSC002ND = 0x5d, HSC004ND = 0x5e, HSC005ND = 0x5f, 85 + HSC010ND = 0x60, HSC020ND = 0x61, HSC030ND = 0x62, HSC001PD = 0x63, 86 + HSC005PD = 0x64, HSC015PD = 0x65, HSC030PD = 0x66, HSC060PD = 0x67, 87 + HSC001NG = 0x68, HSC002NG = 0x69, HSC004NG = 0x6a, HSC005NG = 0x6b, 88 + HSC010NG = 0x6c, HSC020NG = 0x6d, HSC030NG = 0x6e, HSC001PG = 0x6f, 89 + HSC005PG = 0x70, HSC015PG = 0x71, HSC030PG = 0x72, HSC060PG = 0x73, 90 + HSC100PG = 0x74, HSC150PG = 0x75, HSC_VARIANTS_MAX 91 + }; 92 + 93 + static const char * const hsc_triplet_variants[HSC_VARIANTS_MAX] = { 94 + [HSC001BA] = "001BA", [HSC1_6BA] = "1.6BA", [HSC2_5BA] = "2.5BA", 95 + [HSC004BA] = "004BA", [HSC006BA] = "006BA", [HSC010BA] = "010BA", 96 + [HSC1_6MD] = "1.6MD", [HSC2_5MD] = "2.5MD", [HSC004MD] = "004MD", 97 + [HSC006MD] = "006MD", [HSC010MD] = "010MD", [HSC016MD] = "016MD", 98 + [HSC025MD] = "025MD", [HSC040MD] = "040MD", [HSC060MD] = "060MD", 99 + [HSC100MD] = "100MD", [HSC160MD] = "160MD", [HSC250MD] = "250MD", 100 + [HSC400MD] = "400MD", [HSC600MD] = "600MD", [HSC001BD] = "001BD", 101 + [HSC1_6BD] = "1.6BD", [HSC2_5BD] = "2.5BD", [HSC004BD] = "004BD", 102 + [HSC2_5MG] = "2.5MG", [HSC004MG] = "004MG", [HSC006MG] = "006MG", 103 + [HSC010MG] = "010MG", [HSC016MG] = "016MG", [HSC025MG] = "025MG", 104 + [HSC040MG] = "040MG", [HSC060MG] = "060MG", [HSC100MG] = "100MG", 105 + [HSC160MG] = "160MG", [HSC250MG] = "250MG", [HSC400MG] = "400MG", 106 + [HSC600MG] = "600MG", [HSC001BG] = "001BG", [HSC1_6BG] = "1.6BG", 107 + [HSC2_5BG] = "2.5BG", [HSC004BG] = "004BG", [HSC006BG] = "006BG", 108 + [HSC010BG] = "010BG", [HSC100KA] = "100KA", [HSC160KA] = "160KA", 109 + [HSC250KA] = "250KA", [HSC400KA] = "400KA", [HSC600KA] = "600KA", 110 + [HSC001GA] = "001GA", [HSC160LD] = "160LD", [HSC250LD] = "250LD", 111 + [HSC400LD] = "400LD", [HSC600LD] = "600LD", [HSC001KD] = "001KD", 112 + [HSC1_6KD] = "1.6KD", [HSC2_5KD] = "2.5KD", [HSC004KD] = "004KD", 113 + [HSC006KD] = "006KD", [HSC010KD] = "010KD", [HSC016KD] = "016KD", 114 + [HSC025KD] = "025KD", [HSC040KD] = "040KD", [HSC060KD] = "060KD", 115 + [HSC100KD] = "100KD", [HSC160KD] = "160KD", [HSC250KD] = "250KD", 116 + [HSC400KD] = "400KD", [HSC250LG] = "250LG", [HSC400LG] = "400LG", 117 + [HSC600LG] = "600LG", [HSC001KG] = "001KG", [HSC1_6KG] = "1.6KG", 118 + [HSC2_5KG] = "2.5KG", [HSC004KG] = "004KG", [HSC006KG] = "006KG", 119 + [HSC010KG] = "010KG", [HSC016KG] = "016KG", [HSC025KG] = "025KG", 120 + [HSC040KG] = "040KG", [HSC060KG] = "060KG", [HSC100KG] = "100KG", 121 + [HSC160KG] = "160KG", [HSC250KG] = "250KG", [HSC400KG] = "400KG", 122 + [HSC600KG] = "600KG", [HSC001GG] = "001GG", [HSC015PA] = "015PA", 123 + [HSC030PA] = "030PA", [HSC060PA] = "060PA", [HSC100PA] = "100PA", 124 + [HSC150PA] = "150PA", [HSC0_5ND] = "0.5ND", [HSC001ND] = "001ND", 125 + [HSC002ND] = "002ND", [HSC004ND] = "004ND", [HSC005ND] = "005ND", 126 + [HSC010ND] = "010ND", [HSC020ND] = "020ND", [HSC030ND] = "030ND", 127 + [HSC001PD] = "001PD", [HSC005PD] = "005PD", [HSC015PD] = "015PD", 128 + [HSC030PD] = "030PD", [HSC060PD] = "060PD", [HSC001NG] = "001NG", 129 + [HSC002NG] = "002NG", [HSC004NG] = "004NG", [HSC005NG] = "005NG", 130 + [HSC010NG] = "010NG", [HSC020NG] = "020NG", [HSC030NG] = "030NG", 131 + [HSC001PG] = "001PG", [HSC005PG] = "005PG", [HSC015PG] = "015PG", 132 + [HSC030PG] = "030PG", [HSC060PG] = "060PG", [HSC100PG] = "100PG", 133 + [HSC150PG] = "150PG", 134 + }; 135 + 136 + /** 137 + * struct hsc_range_config - list of pressure ranges based on nomenclature 138 + * @pmin: lowest pressure that can be measured 139 + * @pmax: highest pressure that can be measured 140 + */ 141 + struct hsc_range_config { 142 + const s32 pmin; 143 + const s32 pmax; 144 + }; 145 + 146 + /* All min max limits have been converted to pascals */ 147 + static const struct hsc_range_config hsc_range_config[HSC_VARIANTS_MAX] = { 148 + [HSC001BA] = { .pmin = 0, .pmax = 100000 }, 149 + [HSC1_6BA] = { .pmin = 0, .pmax = 160000 }, 150 + [HSC2_5BA] = { .pmin = 0, .pmax = 250000 }, 151 + [HSC004BA] = { .pmin = 0, .pmax = 400000 }, 152 + [HSC006BA] = { .pmin = 0, .pmax = 600000 }, 153 + [HSC010BA] = { .pmin = 0, .pmax = 1000000 }, 154 + [HSC1_6MD] = { .pmin = -160, .pmax = 160 }, 155 + [HSC2_5MD] = { .pmin = -250, .pmax = 250 }, 156 + [HSC004MD] = { .pmin = -400, .pmax = 400 }, 157 + [HSC006MD] = { .pmin = -600, .pmax = 600 }, 158 + [HSC010MD] = { .pmin = -1000, .pmax = 1000 }, 159 + [HSC016MD] = { .pmin = -1600, .pmax = 1600 }, 160 + [HSC025MD] = { .pmin = -2500, .pmax = 2500 }, 161 + [HSC040MD] = { .pmin = -4000, .pmax = 4000 }, 162 + [HSC060MD] = { .pmin = -6000, .pmax = 6000 }, 163 + [HSC100MD] = { .pmin = -10000, .pmax = 10000 }, 164 + [HSC160MD] = { .pmin = -16000, .pmax = 16000 }, 165 + [HSC250MD] = { .pmin = -25000, .pmax = 25000 }, 166 + [HSC400MD] = { .pmin = -40000, .pmax = 40000 }, 167 + [HSC600MD] = { .pmin = -60000, .pmax = 60000 }, 168 + [HSC001BD] = { .pmin = -100000, .pmax = 100000 }, 169 + [HSC1_6BD] = { .pmin = -160000, .pmax = 160000 }, 170 + [HSC2_5BD] = { .pmin = -250000, .pmax = 250000 }, 171 + [HSC004BD] = { .pmin = -400000, .pmax = 400000 }, 172 + [HSC2_5MG] = { .pmin = 0, .pmax = 250 }, 173 + [HSC004MG] = { .pmin = 0, .pmax = 400 }, 174 + [HSC006MG] = { .pmin = 0, .pmax = 600 }, 175 + [HSC010MG] = { .pmin = 0, .pmax = 1000 }, 176 + [HSC016MG] = { .pmin = 0, .pmax = 1600 }, 177 + [HSC025MG] = { .pmin = 0, .pmax = 2500 }, 178 + [HSC040MG] = { .pmin = 0, .pmax = 4000 }, 179 + [HSC060MG] = { .pmin = 0, .pmax = 6000 }, 180 + [HSC100MG] = { .pmin = 0, .pmax = 10000 }, 181 + [HSC160MG] = { .pmin = 0, .pmax = 16000 }, 182 + [HSC250MG] = { .pmin = 0, .pmax = 25000 }, 183 + [HSC400MG] = { .pmin = 0, .pmax = 40000 }, 184 + [HSC600MG] = { .pmin = 0, .pmax = 60000 }, 185 + [HSC001BG] = { .pmin = 0, .pmax = 100000 }, 186 + [HSC1_6BG] = { .pmin = 0, .pmax = 160000 }, 187 + [HSC2_5BG] = { .pmin = 0, .pmax = 250000 }, 188 + [HSC004BG] = { .pmin = 0, .pmax = 400000 }, 189 + [HSC006BG] = { .pmin = 0, .pmax = 600000 }, 190 + [HSC010BG] = { .pmin = 0, .pmax = 1000000 }, 191 + [HSC100KA] = { .pmin = 0, .pmax = 100000 }, 192 + [HSC160KA] = { .pmin = 0, .pmax = 160000 }, 193 + [HSC250KA] = { .pmin = 0, .pmax = 250000 }, 194 + [HSC400KA] = { .pmin = 0, .pmax = 400000 }, 195 + [HSC600KA] = { .pmin = 0, .pmax = 600000 }, 196 + [HSC001GA] = { .pmin = 0, .pmax = 1000000 }, 197 + [HSC160LD] = { .pmin = -160, .pmax = 160 }, 198 + [HSC250LD] = { .pmin = -250, .pmax = 250 }, 199 + [HSC400LD] = { .pmin = -400, .pmax = 400 }, 200 + [HSC600LD] = { .pmin = -600, .pmax = 600 }, 201 + [HSC001KD] = { .pmin = -1000, .pmax = 1000 }, 202 + [HSC1_6KD] = { .pmin = -1600, .pmax = 1600 }, 203 + [HSC2_5KD] = { .pmin = -2500, .pmax = 2500 }, 204 + [HSC004KD] = { .pmin = -4000, .pmax = 4000 }, 205 + [HSC006KD] = { .pmin = -6000, .pmax = 6000 }, 206 + [HSC010KD] = { .pmin = -10000, .pmax = 10000 }, 207 + [HSC016KD] = { .pmin = -16000, .pmax = 16000 }, 208 + [HSC025KD] = { .pmin = -25000, .pmax = 25000 }, 209 + [HSC040KD] = { .pmin = -40000, .pmax = 40000 }, 210 + [HSC060KD] = { .pmin = -60000, .pmax = 60000 }, 211 + [HSC100KD] = { .pmin = -100000, .pmax = 100000 }, 212 + [HSC160KD] = { .pmin = -160000, .pmax = 160000 }, 213 + [HSC250KD] = { .pmin = -250000, .pmax = 250000 }, 214 + [HSC400KD] = { .pmin = -400000, .pmax = 400000 }, 215 + [HSC250LG] = { .pmin = 0, .pmax = 250 }, 216 + [HSC400LG] = { .pmin = 0, .pmax = 400 }, 217 + [HSC600LG] = { .pmin = 0, .pmax = 600 }, 218 + [HSC001KG] = { .pmin = 0, .pmax = 1000 }, 219 + [HSC1_6KG] = { .pmin = 0, .pmax = 1600 }, 220 + [HSC2_5KG] = { .pmin = 0, .pmax = 2500 }, 221 + [HSC004KG] = { .pmin = 0, .pmax = 4000 }, 222 + [HSC006KG] = { .pmin = 0, .pmax = 6000 }, 223 + [HSC010KG] = { .pmin = 0, .pmax = 10000 }, 224 + [HSC016KG] = { .pmin = 0, .pmax = 16000 }, 225 + [HSC025KG] = { .pmin = 0, .pmax = 25000 }, 226 + [HSC040KG] = { .pmin = 0, .pmax = 40000 }, 227 + [HSC060KG] = { .pmin = 0, .pmax = 60000 }, 228 + [HSC100KG] = { .pmin = 0, .pmax = 100000 }, 229 + [HSC160KG] = { .pmin = 0, .pmax = 160000 }, 230 + [HSC250KG] = { .pmin = 0, .pmax = 250000 }, 231 + [HSC400KG] = { .pmin = 0, .pmax = 400000 }, 232 + [HSC600KG] = { .pmin = 0, .pmax = 600000 }, 233 + [HSC001GG] = { .pmin = 0, .pmax = 1000000 }, 234 + [HSC015PA] = { .pmin = 0, .pmax = 103421 }, 235 + [HSC030PA] = { .pmin = 0, .pmax = 206843 }, 236 + [HSC060PA] = { .pmin = 0, .pmax = 413685 }, 237 + [HSC100PA] = { .pmin = 0, .pmax = 689476 }, 238 + [HSC150PA] = { .pmin = 0, .pmax = 1034214 }, 239 + [HSC0_5ND] = { .pmin = -125, .pmax = 125 }, 240 + [HSC001ND] = { .pmin = -249, .pmax = 249 }, 241 + [HSC002ND] = { .pmin = -498, .pmax = 498 }, 242 + [HSC004ND] = { .pmin = -996, .pmax = 996 }, 243 + [HSC005ND] = { .pmin = -1245, .pmax = 1245 }, 244 + [HSC010ND] = { .pmin = -2491, .pmax = 2491 }, 245 + [HSC020ND] = { .pmin = -4982, .pmax = 4982 }, 246 + [HSC030ND] = { .pmin = -7473, .pmax = 7473 }, 247 + [HSC001PD] = { .pmin = -6895, .pmax = 6895 }, 248 + [HSC005PD] = { .pmin = -34474, .pmax = 34474 }, 249 + [HSC015PD] = { .pmin = -103421, .pmax = 103421 }, 250 + [HSC030PD] = { .pmin = -206843, .pmax = 206843 }, 251 + [HSC060PD] = { .pmin = -413685, .pmax = 413685 }, 252 + [HSC001NG] = { .pmin = 0, .pmax = 249 }, 253 + [HSC002NG] = { .pmin = 0, .pmax = 498 }, 254 + [HSC004NG] = { .pmin = 0, .pmax = 996 }, 255 + [HSC005NG] = { .pmin = 0, .pmax = 1245 }, 256 + [HSC010NG] = { .pmin = 0, .pmax = 2491 }, 257 + [HSC020NG] = { .pmin = 0, .pmax = 4982 }, 258 + [HSC030NG] = { .pmin = 0, .pmax = 7473 }, 259 + [HSC001PG] = { .pmin = 0, .pmax = 6895 }, 260 + [HSC005PG] = { .pmin = 0, .pmax = 34474 }, 261 + [HSC015PG] = { .pmin = 0, .pmax = 103421 }, 262 + [HSC030PG] = { .pmin = 0, .pmax = 206843 }, 263 + [HSC060PG] = { .pmin = 0, .pmax = 413685 }, 264 + [HSC100PG] = { .pmin = 0, .pmax = 689476 }, 265 + [HSC150PG] = { .pmin = 0, .pmax = 1034214 }, 266 + }; 267 + 268 + /** 269 + * hsc_measurement_is_valid() - validate last conversion via status bits 270 + * @data: structure containing instantiated sensor data 271 + * Return: true only if both status bits are zero 272 + * 273 + * the two MSB from the first transfered byte contain a status code 274 + * 00 - normal operation, valid data 275 + * 01 - device in factory programming mode 276 + * 10 - stale data 277 + * 11 - diagnostic condition 278 + */ 279 + static bool hsc_measurement_is_valid(struct hsc_data *data) 280 + { 281 + return !(data->buffer[0] & HSC_STATUS_MASK); 282 + } 283 + 284 + static int hsc_get_measurement(struct hsc_data *data) 285 + { 286 + const struct hsc_chip_data *chip = data->chip; 287 + int ret; 288 + 289 + ret = data->recv_cb(data); 290 + if (ret < 0) 291 + return ret; 292 + 293 + data->is_valid = chip->valid(data); 294 + if (!data->is_valid) 295 + return -EAGAIN; 296 + 297 + return 0; 298 + } 299 + 300 + /* 301 + * IIO ABI expects 302 + * value = (conv + offset) * scale 303 + * 304 + * datasheet provides the following formula for determining the temperature 305 + * temp[C] = conv * a + b 306 + * where a = 200/2047; b = -50 307 + * 308 + * temp[C] = (conv + (b/a)) * a * (1000) 309 + * => 310 + * scale = a * 1000 = .097703957 * 1000 = 97.703957 311 + * offset = b/a = -50 / .097703957 = -50000000 / 97704 312 + * 313 + * based on the datasheet 314 + * pressure = (conv - Omin) * Q + Pmin = 315 + * ((conv - Omin) + Pmin/Q) * Q 316 + * => 317 + * scale = Q = (Pmax - Pmin) / (Omax - Omin) 318 + * offset = Pmin/Q - Omin = Pmin * (Omax - Omin) / (Pmax - Pmin) - Omin 319 + */ 320 + static int hsc_read_raw(struct iio_dev *indio_dev, 321 + struct iio_chan_spec const *channel, int *val, 322 + int *val2, long mask) 323 + { 324 + struct hsc_data *data = iio_priv(indio_dev); 325 + int ret; 326 + u32 recvd; 327 + 328 + switch (mask) { 329 + case IIO_CHAN_INFO_RAW: 330 + ret = hsc_get_measurement(data); 331 + if (ret) 332 + return ret; 333 + 334 + recvd = get_unaligned_be32(data->buffer); 335 + switch (channel->type) { 336 + case IIO_PRESSURE: 337 + *val = FIELD_GET(HSC_PRESSURE_MASK, recvd); 338 + return IIO_VAL_INT; 339 + case IIO_TEMP: 340 + *val = FIELD_GET(HSC_TEMPERATURE_MASK, recvd); 341 + return IIO_VAL_INT; 342 + default: 343 + return -EINVAL; 344 + } 345 + 346 + case IIO_CHAN_INFO_SCALE: 347 + switch (channel->type) { 348 + case IIO_TEMP: 349 + *val = 97; 350 + *val2 = 703957; 351 + return IIO_VAL_INT_PLUS_MICRO; 352 + case IIO_PRESSURE: 353 + *val = data->p_scale; 354 + *val2 = data->p_scale_dec; 355 + return IIO_VAL_INT_PLUS_NANO; 356 + default: 357 + return -EINVAL; 358 + } 359 + 360 + case IIO_CHAN_INFO_OFFSET: 361 + switch (channel->type) { 362 + case IIO_TEMP: 363 + *val = -50000000; 364 + *val2 = 97704; 365 + return IIO_VAL_FRACTIONAL; 366 + case IIO_PRESSURE: 367 + *val = data->p_offset; 368 + *val2 = data->p_offset_dec; 369 + return IIO_VAL_INT_PLUS_MICRO; 370 + default: 371 + return -EINVAL; 372 + } 373 + 374 + default: 375 + return -EINVAL; 376 + } 377 + } 378 + 379 + static const struct iio_chan_spec hsc_channels[] = { 380 + { 381 + .type = IIO_PRESSURE, 382 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 383 + BIT(IIO_CHAN_INFO_SCALE) | 384 + BIT(IIO_CHAN_INFO_OFFSET), 385 + }, 386 + { 387 + .type = IIO_TEMP, 388 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 389 + BIT(IIO_CHAN_INFO_SCALE) | 390 + BIT(IIO_CHAN_INFO_OFFSET), 391 + }, 392 + }; 393 + 394 + static const struct iio_info hsc_info = { 395 + .read_raw = hsc_read_raw, 396 + }; 397 + 398 + static const struct hsc_chip_data hsc_chip = { 399 + .valid = hsc_measurement_is_valid, 400 + .channels = hsc_channels, 401 + .num_channels = ARRAY_SIZE(hsc_channels), 402 + }; 403 + 404 + int hsc_common_probe(struct device *dev, hsc_recv_fn recv) 405 + { 406 + struct hsc_data *hsc; 407 + struct iio_dev *indio_dev; 408 + const char *triplet; 409 + u64 tmp; 410 + int ret; 411 + 412 + indio_dev = devm_iio_device_alloc(dev, sizeof(*hsc)); 413 + if (!indio_dev) 414 + return -ENOMEM; 415 + 416 + hsc = iio_priv(indio_dev); 417 + 418 + hsc->chip = &hsc_chip; 419 + hsc->recv_cb = recv; 420 + hsc->dev = dev; 421 + 422 + ret = device_property_read_u32(dev, "honeywell,transfer-function", 423 + &hsc->function); 424 + if (ret) 425 + return dev_err_probe(dev, ret, 426 + "honeywell,transfer-function could not be read\n"); 427 + if (hsc->function > HSC_FUNCTION_F) 428 + return dev_err_probe(dev, -EINVAL, 429 + "honeywell,transfer-function %d invalid\n", 430 + hsc->function); 431 + 432 + ret = device_property_read_string(dev, "honeywell,pressure-triplet", 433 + &triplet); 434 + if (ret) 435 + return dev_err_probe(dev, ret, 436 + "honeywell,pressure-triplet could not be read\n"); 437 + 438 + if (str_has_prefix(triplet, "NA")) { 439 + ret = device_property_read_u32(dev, "honeywell,pmin-pascal", 440 + &hsc->pmin); 441 + if (ret) 442 + return dev_err_probe(dev, ret, 443 + "honeywell,pmin-pascal could not be read\n"); 444 + 445 + ret = device_property_read_u32(dev, "honeywell,pmax-pascal", 446 + &hsc->pmax); 447 + if (ret) 448 + return dev_err_probe(dev, ret, 449 + "honeywell,pmax-pascal could not be read\n"); 450 + } else { 451 + ret = device_property_match_property_string(dev, 452 + "honeywell,pressure-triplet", 453 + hsc_triplet_variants, 454 + HSC_VARIANTS_MAX); 455 + if (ret < 0) 456 + return dev_err_probe(dev, -EINVAL, 457 + "honeywell,pressure-triplet is invalid\n"); 458 + 459 + hsc->pmin = hsc_range_config[ret].pmin; 460 + hsc->pmax = hsc_range_config[ret].pmax; 461 + } 462 + 463 + if (hsc->pmin >= hsc->pmax) 464 + return dev_err_probe(dev, -EINVAL, 465 + "pressure limits are invalid\n"); 466 + 467 + ret = devm_regulator_get_enable(dev, "vdd"); 468 + if (ret) 469 + return dev_err_probe(dev, ret, "can't get vdd supply\n"); 470 + 471 + hsc->outmin = hsc_func_spec[hsc->function].output_min; 472 + hsc->outmax = hsc_func_spec[hsc->function].output_max; 473 + 474 + tmp = div_s64(((s64)(hsc->pmax - hsc->pmin)) * MICRO, 475 + hsc->outmax - hsc->outmin); 476 + hsc->p_scale = div_s64_rem(tmp, NANO, &hsc->p_scale_dec); 477 + tmp = div_s64(((s64)hsc->pmin * (s64)(hsc->outmax - hsc->outmin)) * MICRO, 478 + hsc->pmax - hsc->pmin); 479 + tmp -= (s64)hsc->outmin * MICRO; 480 + hsc->p_offset = div_s64_rem(tmp, MICRO, &hsc->p_offset_dec); 481 + 482 + indio_dev->name = "hsc030pa"; 483 + indio_dev->modes = INDIO_DIRECT_MODE; 484 + indio_dev->info = &hsc_info; 485 + indio_dev->channels = hsc->chip->channels; 486 + indio_dev->num_channels = hsc->chip->num_channels; 487 + 488 + return devm_iio_device_register(dev, indio_dev); 489 + } 490 + EXPORT_SYMBOL_NS(hsc_common_probe, IIO_HONEYWELL_HSC030PA); 491 + 492 + MODULE_AUTHOR("Petre Rodan <petre.rodan@subdimension.ro>"); 493 + MODULE_DESCRIPTION("Honeywell HSC and SSC pressure sensor core driver"); 494 + MODULE_LICENSE("GPL");
+74
drivers/iio/pressure/hsc030pa.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Honeywell TruStability HSC Series pressure/temperature sensor 4 + * 5 + * Copyright (c) 2023 Petre Rodan <petre.rodan@subdimension.ro> 6 + */ 7 + 8 + #ifndef _HSC030PA_H 9 + #define _HSC030PA_H 10 + 11 + #include <linux/types.h> 12 + 13 + #define HSC_REG_MEASUREMENT_RD_SIZE 4 14 + 15 + struct device; 16 + 17 + struct iio_chan_spec; 18 + struct iio_dev; 19 + 20 + struct hsc_data; 21 + struct hsc_chip_data; 22 + 23 + typedef int (*hsc_recv_fn)(struct hsc_data *); 24 + 25 + /** 26 + * struct hsc_data 27 + * @dev: current device structure 28 + * @chip: structure containing chip's channel properties 29 + * @recv_cb: function that implements the chip reads 30 + * @is_valid: true if last transfer has been validated 31 + * @pmin: minimum measurable pressure limit 32 + * @pmax: maximum measurable pressure limit 33 + * @outmin: minimum raw pressure in counts (based on transfer function) 34 + * @outmax: maximum raw pressure in counts (based on transfer function) 35 + * @function: transfer function 36 + * @p_scale: pressure scale 37 + * @p_scale_dec: pressure scale, decimal places 38 + * @p_offset: pressure offset 39 + * @p_offset_dec: pressure offset, decimal places 40 + * @buffer: raw conversion data 41 + */ 42 + struct hsc_data { 43 + struct device *dev; 44 + const struct hsc_chip_data *chip; 45 + hsc_recv_fn recv_cb; 46 + bool is_valid; 47 + s32 pmin; 48 + s32 pmax; 49 + u32 outmin; 50 + u32 outmax; 51 + u32 function; 52 + s64 p_scale; 53 + s32 p_scale_dec; 54 + s64 p_offset; 55 + s32 p_offset_dec; 56 + u8 buffer[HSC_REG_MEASUREMENT_RD_SIZE] __aligned(IIO_DMA_MINALIGN); 57 + }; 58 + 59 + struct hsc_chip_data { 60 + bool (*valid)(struct hsc_data *data); 61 + const struct iio_chan_spec *channels; 62 + u8 num_channels; 63 + }; 64 + 65 + enum hsc_func_id { 66 + HSC_FUNCTION_A, 67 + HSC_FUNCTION_B, 68 + HSC_FUNCTION_C, 69 + HSC_FUNCTION_F, 70 + }; 71 + 72 + int hsc_common_probe(struct device *dev, hsc_recv_fn recv); 73 + 74 + #endif
+69
drivers/iio/pressure/hsc030pa_i2c.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Honeywell TruStability HSC Series pressure/temperature sensor 4 + * 5 + * Copyright (c) 2023 Petre Rodan <petre.rodan@subdimension.ro> 6 + * 7 + * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/trustability-hsc-series/documents/sps-siot-trustability-hsc-series-high-accuracy-board-mount-pressure-sensors-50099148-a-en-ciid-151133.pdf [hsc] 8 + * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/common/documents/sps-siot-i2c-comms-digital-output-pressure-sensors-tn-008201-3-en-ciid-45841.pdf [i2c related] 9 + */ 10 + 11 + #include <linux/errno.h> 12 + #include <linux/i2c.h> 13 + #include <linux/mod_devicetable.h> 14 + #include <linux/module.h> 15 + 16 + #include <linux/iio/iio.h> 17 + 18 + #include "hsc030pa.h" 19 + 20 + static int hsc_i2c_recv(struct hsc_data *data) 21 + { 22 + struct i2c_client *client = to_i2c_client(data->dev); 23 + struct i2c_msg msg; 24 + int ret; 25 + 26 + msg.addr = client->addr; 27 + msg.flags = client->flags | I2C_M_RD; 28 + msg.len = HSC_REG_MEASUREMENT_RD_SIZE; 29 + msg.buf = data->buffer; 30 + 31 + ret = i2c_transfer(client->adapter, &msg, 1); 32 + 33 + return (ret == 2) ? 0 : ret; 34 + } 35 + 36 + static int hsc_i2c_probe(struct i2c_client *client) 37 + { 38 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 39 + return -EOPNOTSUPP; 40 + 41 + return hsc_common_probe(&client->dev, hsc_i2c_recv); 42 + } 43 + 44 + static const struct of_device_id hsc_i2c_match[] = { 45 + { .compatible = "honeywell,hsc030pa" }, 46 + {} 47 + }; 48 + MODULE_DEVICE_TABLE(of, hsc_i2c_match); 49 + 50 + static const struct i2c_device_id hsc_i2c_id[] = { 51 + { "hsc030pa" }, 52 + {} 53 + }; 54 + MODULE_DEVICE_TABLE(i2c, hsc_i2c_id); 55 + 56 + static struct i2c_driver hsc_i2c_driver = { 57 + .driver = { 58 + .name = "hsc030pa", 59 + .of_match_table = hsc_i2c_match, 60 + }, 61 + .probe = hsc_i2c_probe, 62 + .id_table = hsc_i2c_id, 63 + }; 64 + module_i2c_driver(hsc_i2c_driver); 65 + 66 + MODULE_AUTHOR("Petre Rodan <petre.rodan@subdimension.ro>"); 67 + MODULE_DESCRIPTION("Honeywell HSC and SSC pressure sensor i2c driver"); 68 + MODULE_LICENSE("GPL"); 69 + MODULE_IMPORT_NS(IIO_HONEYWELL_HSC030PA);
+61
drivers/iio/pressure/hsc030pa_spi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Honeywell TruStability HSC Series pressure/temperature sensor 4 + * 5 + * Copyright (c) 2023 Petre Rodan <petre.rodan@subdimension.ro> 6 + * 7 + * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/trustability-hsc-series/documents/sps-siot-trustability-hsc-series-high-accuracy-board-mount-pressure-sensors-50099148-a-en-ciid-151133.pdf 8 + */ 9 + 10 + #include <linux/mod_devicetable.h> 11 + #include <linux/module.h> 12 + #include <linux/spi/spi.h> 13 + #include <linux/stddef.h> 14 + 15 + #include <linux/iio/iio.h> 16 + 17 + #include "hsc030pa.h" 18 + 19 + static int hsc_spi_recv(struct hsc_data *data) 20 + { 21 + struct spi_device *spi = to_spi_device(data->dev); 22 + struct spi_transfer xfer = { 23 + .tx_buf = NULL, 24 + .rx_buf = data->buffer, 25 + .len = HSC_REG_MEASUREMENT_RD_SIZE, 26 + }; 27 + 28 + return spi_sync_transfer(spi, &xfer, 1); 29 + } 30 + 31 + static int hsc_spi_probe(struct spi_device *spi) 32 + { 33 + return hsc_common_probe(&spi->dev, hsc_spi_recv); 34 + } 35 + 36 + static const struct of_device_id hsc_spi_match[] = { 37 + { .compatible = "honeywell,hsc030pa" }, 38 + {} 39 + }; 40 + MODULE_DEVICE_TABLE(of, hsc_spi_match); 41 + 42 + static const struct spi_device_id hsc_spi_id[] = { 43 + { "hsc030pa" }, 44 + {} 45 + }; 46 + MODULE_DEVICE_TABLE(spi, hsc_spi_id); 47 + 48 + static struct spi_driver hsc_spi_driver = { 49 + .driver = { 50 + .name = "hsc030pa", 51 + .of_match_table = hsc_spi_match, 52 + }, 53 + .probe = hsc_spi_probe, 54 + .id_table = hsc_spi_id, 55 + }; 56 + module_spi_driver(hsc_spi_driver); 57 + 58 + MODULE_AUTHOR("Petre Rodan <petre.rodan@subdimension.ro>"); 59 + MODULE_DESCRIPTION("Honeywell HSC and SSC pressure sensor spi driver"); 60 + MODULE_LICENSE("GPL"); 61 + MODULE_IMPORT_NS(IIO_HONEYWELL_HSC030PA);