From 5b7c4cabbb65f5c469464da6c5f614cbd7f730f2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 21 Feb 2023 18:24:12 -0800 Subject: Merge tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next Pull networking updates from Jakub Kicinski: "Core: - Add dedicated kmem_cache for typical/small skb->head, avoid having to access struct page at kfree time, and improve memory use. - Introduce sysctl to set default RPS configuration for new netdevs. - Define Netlink protocol specification format which can be used to describe messages used by each family and auto-generate parsers. Add tools for generating kernel data structures and uAPI headers. - Expose all net/core sysctls inside netns. - Remove 4s sleep in netpoll if carrier is instantly detected on boot. - Add configurable limit of MDB entries per port, and port-vlan. - Continue populating drop reasons throughout the stack. - Retire a handful of legacy Qdiscs and classifiers. Protocols: - Support IPv4 big TCP (TSO frames larger than 64kB). - Add IP_LOCAL_PORT_RANGE socket option, to control local port range on socket by socket basis. - Track and report in procfs number of MPTCP sockets used. - Support mixing IPv4 and IPv6 flows in the in-kernel MPTCP path manager. - IPv6: don't check net.ipv6.route.max_size and rely on garbage collection to free memory (similarly to IPv4). - Support Penultimate Segment Pop (PSP) flavor in SRv6 (RFC8986). - ICMP: add per-rate limit counters. - Add support for user scanning requests in ieee802154. - Remove static WEP support. - Support minimal Wi-Fi 7 Extremely High Throughput (EHT) rate reporting. - WiFi 7 EHT channel puncturing support (client & AP). BPF: - Add a rbtree data structure following the "next-gen data structure" precedent set by recently added linked list, that is, by using kfunc + kptr instead of adding a new BPF map type. - Expose XDP hints via kfuncs with initial support for RX hash and timestamp metadata. - Add BPF_F_NO_TUNNEL_KEY extension to bpf_skb_set_tunnel_key to better support decap on GRE tunnel devices not operating in collect metadata. - Improve x86 JIT's codegen for PROBE_MEM runtime error checks. - Remove the need for trace_printk_lock for bpf_trace_printk and bpf_trace_vprintk helpers. - Extend libbpf's bpf_tracing.h support for tracing arguments of kprobes/uprobes and syscall as a special case. - Significantly reduce the search time for module symbols by livepatch and BPF. - Enable cpumasks to be used as kptrs, which is useful for tracing programs tracking which tasks end up running on which CPUs in different time intervals. - Add support for BPF trampoline on s390x and riscv64. - Add capability to export the XDP features supported by the NIC. - Add __bpf_kfunc tag for marking kernel functions as kfuncs. - Add cgroup.memory=nobpf kernel parameter option to disable BPF memory accounting for container environments. Netfilter: - Remove the CLUSTERIP target. It has been marked as obsolete for years, and we still have WARN splats wrt races of the out-of-band /proc interface installed by this target. - Add 'destroy' commands to nf_tables. They are identical to the existing 'delete' commands, but do not return an error if the referenced object (set, chain, rule...) did not exist. Driver API: - Improve cpumask_local_spread() locality to help NICs set the right IRQ affinity on AMD platforms. - Separate C22 and C45 MDIO bus transactions more clearly. - Introduce new DCB table to control DSCP rewrite on egress. - Support configuration of Physical Layer Collision Avoidance (PLCA) Reconciliation Sublayer (RS) (802.3cg-2019). Modern version of shared medium Ethernet. - Support for MAC Merge layer (IEEE 802.3-2018 clause 99). Allowing preemption of low priority frames by high priority frames. - Add support for controlling MACSec offload using netlink SET. - Rework devlink instance refcounts to allow registration and de-registration under the instance lock. Split the code into multiple files, drop some of the unnecessarily granular locks and factor out common parts of netlink operation handling. - Add TX frame aggregation parameters (for USB drivers). - Add a new attr TCA_EXT_WARN_MSG to report TC (offload) warning messages with notifications for debug. - Allow offloading of UDP NEW connections via act_ct. - Add support for per action HW stats in TC. - Support hardware miss to TC action (continue processing in SW from a specific point in the action chain). - Warn if old Wireless Extension user space interface is used with modern cfg80211/mac80211 drivers. Do not support Wireless Extensions for Wi-Fi 7 devices at all. Everyone should switch to using nl80211 interface instead. - Improve the CAN bit timing configuration. Use extack to return error messages directly to user space, update the SJW handling, including the definition of a new default value that will benefit CAN-FD controllers, by increasing their oscillator tolerance. New hardware / drivers: - Ethernet: - nVidia BlueField-3 support (control traffic driver) - Ethernet support for imx93 SoCs - Motorcomm yt8531 gigabit Ethernet PHY - onsemi NCN26000 10BASE-T1S PHY (with support for PLCA) - Microchip LAN8841 PHY (incl. cable diagnostics and PTP) - Amlogic gxl MDIO mux - WiFi: - RealTek RTL8188EU (rtl8xxxu) - Qualcomm Wi-Fi 7 devices (ath12k) - CAN: - Renesas R-Car V4H Drivers: - Bluetooth: - Set Per Platform Antenna Gain (PPAG) for Intel controllers. - Ethernet NICs: - Intel (1G, igc): - support TSN / Qbv / packet scheduling features of i226 model - Intel (100G, ice): - use GNSS subsystem instead of TTY - multi-buffer XDP support - extend support for GPIO pins to E823 devices - nVidia/Mellanox: - update the shared buffer configuration on PFC commands - implement PTP adjphase function for HW offset control - TC support for Geneve and GRE with VF tunnel offload - more efficient crypto key management method - multi-port eswitch support - Netronome/Corigine: - add DCB IEEE support - support IPsec offloading for NFP3800 - Freescale/NXP (enetc): - support XDP_REDIRECT for XDP non-linear buffers - improve reconfig, avoid link flap and waiting for idle - support MAC Merge layer - Other NICs: - sfc/ef100: add basic devlink support for ef100 - ionic: rx_push mode operation (writing descriptors via MMIO) - bnxt: use the auxiliary bus abstraction for RDMA - r8169: disable ASPM and reset bus in case of tx timeout - cpsw: support QSGMII mode for J721e CPSW9G - cpts: support pulse-per-second output - ngbe: add an mdio bus driver - usbnet: optimize usbnet_bh() by avoiding unnecessary queuing - r8152: handle devices with FW with NCM support - amd-xgbe: support 10Mbps, 2.5GbE speeds and rx-adaptation - virtio-net: support multi buffer XDP - virtio/vsock: replace virtio_vsock_pkt with sk_buff - tsnep: XDP support - Ethernet high-speed switches: - nVidia/Mellanox (mlxsw): - add support for latency TLV (in FW control messages) - Microchip (sparx5): - separate explicit and implicit traffic forwarding rules, make the implicit rules always active - add support for egress DSCP rewrite - IS0 VCAP support (Ingress Classification) - IS2 VCAP filters (protos, L3 addrs, L4 ports, flags, ToS etc.) - ES2 VCAP support (Egress Access Control) - support for Per-Stream Filtering and Policing (802.1Q, 8.6.5.1) - Ethernet embedded switches: - Marvell (mv88e6xxx): - add MAB (port auth) offload support - enable PTP receive for mv88e6390 - NXP (ocelot): - support MAC Merge layer - support for the the vsc7512 internal copper phys - Microchip: - lan9303: convert to PHYLINK - lan966x: support TC flower filter statistics - lan937x: PTP support for KSZ9563/KSZ8563 and LAN937x - lan937x: support Credit Based Shaper configuration - ksz9477: support Energy Efficient Ethernet - other: - qca8k: convert to regmap read/write API, use bulk operations - rswitch: Improve TX timestamp accuracy - Intel WiFi (iwlwifi): - EHT (Wi-Fi 7) rate reporting - STEP equalizer support: transfer some STEP (connection to radio on platforms with integrated wifi) related parameters from the BIOS to the firmware. - Qualcomm 802.11ax WiFi (ath11k): - IPQ5018 support - Fine Timing Measurement (FTM) responder role support - channel 177 support - MediaTek WiFi (mt76): - per-PHY LED support - mt7996: EHT (Wi-Fi 7) support - Wireless Ethernet Dispatch (WED) reset support - switch to using page pool allocator - RealTek WiFi (rtw89): - support new version of Bluetooth co-existance - Mobile: - rmnet: support TX aggregation" * tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1872 commits) page_pool: add a comment explaining the fragment counter usage net: ethtool: fix __ethtool_dev_mm_supported() implementation ethtool: pse-pd: Fix double word in comments xsk: add linux/vmalloc.h to xsk.c sefltests: netdevsim: wait for devlink instance after netns removal selftest: fib_tests: Always cleanup before exit net/mlx5e: Align IPsec ASO result memory to be as required by hardware net/mlx5e: TC, Set CT miss to the specific ct action instance net/mlx5e: Rename CHAIN_TO_REG to MAPPED_OBJ_TO_REG net/mlx5: Refactor tc miss handling to a single function net/mlx5: Kconfig: Make tc offload depend on tc skb extension net/sched: flower: Support hardware miss to tc action net/sched: flower: Move filter handle initialization earlier net/sched: cls_api: Support hardware miss to tc action net/sched: Rename user cookie and act cookie sfc: fix builds without CONFIG_RTC_LIB sfc: clean up some inconsistent indentings net/mlx4_en: Introduce flexible array to silence overflow warning net: lan966x: Fix possible deadlock inside PTP net/ulp: Remove redundant ->clone() test in inet_clone_ulp(). ... --- drivers/iio/pressure/st_pressure_core.c | 798 ++++++++++++++++++++++++++++++++ 1 file changed, 798 insertions(+) create mode 100644 drivers/iio/pressure/st_pressure_core.c (limited to 'drivers/iio/pressure/st_pressure_core.c') diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c new file mode 100644 index 000000000..80176e308 --- /dev/null +++ b/drivers/iio/pressure/st_pressure_core.c @@ -0,0 +1,798 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * STMicroelectronics pressures driver + * + * Copyright 2013 STMicroelectronics Inc. + * + * Denis Ciocca + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "st_pressure.h" + +/* + * About determining pressure scaling factors + * ------------------------------------------ + * + * Datasheets specify typical pressure sensitivity so that pressure is computed + * according to the following equation : + * pressure[mBar] = raw / sensitivity + * where : + * raw the 24 bits long raw sampled pressure + * sensitivity a scaling factor specified by the datasheet in LSB/mBar + * + * IIO ABI expects pressure to be expressed as kPascal, hence pressure should be + * computed according to : + * pressure[kPascal] = pressure[mBar] / 10 + * = raw / (sensitivity * 10) (1) + * + * Finally, st_press_read_raw() returns pressure scaling factor as an + * IIO_VAL_INT_PLUS_NANO with a zero integral part and "gain" as decimal part. + * Therefore, from (1), "gain" becomes : + * gain = 10^9 / (sensitivity * 10) + * = 10^8 / sensitivity + * + * About determining temperature scaling factors and offsets + * --------------------------------------------------------- + * + * Datasheets specify typical temperature sensitivity and offset so that + * temperature is computed according to the following equation : + * temp[Celsius] = offset[Celsius] + (raw / sensitivity) + * where : + * raw the 16 bits long raw sampled temperature + * offset a constant specified by the datasheet in degree Celsius + * (sometimes zero) + * sensitivity a scaling factor specified by the datasheet in LSB/Celsius + * + * IIO ABI expects temperature to be expressed as milli degree Celsius such as + * user space should compute temperature according to : + * temp[mCelsius] = temp[Celsius] * 10^3 + * = (offset[Celsius] + (raw / sensitivity)) * 10^3 + * = ((offset[Celsius] * sensitivity) + raw) * + * (10^3 / sensitivity) (2) + * + * IIO ABI expects user space to apply offset and scaling factors to raw samples + * according to : + * temp[mCelsius] = (OFFSET + raw) * SCALE + * where : + * OFFSET an arbitrary constant exposed by device + * SCALE an arbitrary scaling factor exposed by device + * + * Matching OFFSET and SCALE with members of (2) gives : + * OFFSET = offset[Celsius] * sensitivity (3) + * SCALE = 10^3 / sensitivity (4) + * + * st_press_read_raw() returns temperature scaling factor as an + * IIO_VAL_FRACTIONAL with a 10^3 numerator and "gain2" as denominator. + * Therefore, from (3), "gain2" becomes : + * gain2 = sensitivity + * + * When declared within channel, i.e. for a non zero specified offset, + * st_press_read_raw() will return the latter as an IIO_VAL_FRACTIONAL such as : + * numerator = OFFSET * 10^3 + * denominator = 10^3 + * giving from (4): + * numerator = offset[Celsius] * 10^3 * sensitivity + * = offset[mCelsius] * gain2 + */ + +#define MCELSIUS_PER_CELSIUS 1000 + +/* Default pressure sensitivity */ +#define ST_PRESS_LSB_PER_MBAR 4096UL +#define ST_PRESS_KPASCAL_NANO_SCALE (100000000UL / \ + ST_PRESS_LSB_PER_MBAR) + +/* Default temperature sensitivity */ +#define ST_PRESS_LSB_PER_CELSIUS 480UL +#define ST_PRESS_MILLI_CELSIUS_OFFSET 42500UL + +/* FULLSCALE */ +#define ST_PRESS_FS_AVL_1100MB 1100 +#define ST_PRESS_FS_AVL_1260MB 1260 + +#define ST_PRESS_1_OUT_XL_ADDR 0x28 +#define ST_TEMP_1_OUT_L_ADDR 0x2b + +/* LPS001WP pressure resolution */ +#define ST_PRESS_LPS001WP_LSB_PER_MBAR 16UL +/* LPS001WP temperature resolution */ +#define ST_PRESS_LPS001WP_LSB_PER_CELSIUS 64UL +/* LPS001WP pressure gain */ +#define ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN \ + (100000000UL / ST_PRESS_LPS001WP_LSB_PER_MBAR) +/* LPS001WP pressure and temp L addresses */ +#define ST_PRESS_LPS001WP_OUT_L_ADDR 0x28 +#define ST_TEMP_LPS001WP_OUT_L_ADDR 0x2a + +/* LPS25H pressure and temp L addresses */ +#define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 +#define ST_TEMP_LPS25H_OUT_L_ADDR 0x2b + +/* LPS22HB temperature sensitivity */ +#define ST_PRESS_LPS22HB_LSB_PER_CELSIUS 100UL + +static const struct iio_chan_spec st_press_1_channels[] = { + { + .type = IIO_PRESSURE, + .address = ST_PRESS_1_OUT_XL_ADDR, + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, + { + .type = IIO_TEMP, + .address = ST_TEMP_1_OUT_L_ADDR, + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, + IIO_CHAN_SOFT_TIMESTAMP(2) +}; + +static const struct iio_chan_spec st_press_lps001wp_channels[] = { + { + .type = IIO_PRESSURE, + .address = ST_PRESS_LPS001WP_OUT_L_ADDR, + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + }, + { + .type = IIO_TEMP, + .address = ST_TEMP_LPS001WP_OUT_L_ADDR, + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + }, + IIO_CHAN_SOFT_TIMESTAMP(2) +}; + +static const struct iio_chan_spec st_press_lps22hb_channels[] = { + { + .type = IIO_PRESSURE, + .address = ST_PRESS_1_OUT_XL_ADDR, + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, + { + .type = IIO_TEMP, + .address = ST_TEMP_1_OUT_L_ADDR, + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, + IIO_CHAN_SOFT_TIMESTAMP(2) +}; + +static const struct st_sensor_settings st_press_sensors_settings[] = { + { + /* + * CUSTOM VALUES FOR LPS331AP SENSOR + * See LPS331AP datasheet: + * http://www2.st.com/resource/en/datasheet/lps331ap.pdf + */ + .wai = 0xbb, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LPS331AP_PRESS_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_press_1_channels, + .num_ch = ARRAY_SIZE(st_press_1_channels), + .odr = { + .addr = 0x20, + .mask = 0x70, + .odr_avl = { + { .hz = 1, .value = 0x01 }, + { .hz = 7, .value = 0x05 }, + { .hz = 13, .value = 0x06 }, + { .hz = 25, .value = 0x07 }, + }, + }, + .pw = { + .addr = 0x20, + .mask = 0x80, + .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .fs = { + .addr = 0x23, + .mask = 0x30, + .fs_avl = { + /* + * Pressure and temperature sensitivity values + * as defined in table 3 of LPS331AP datasheet. + */ + [0] = { + .num = ST_PRESS_FS_AVL_1260MB, + .gain = ST_PRESS_KPASCAL_NANO_SCALE, + .gain2 = ST_PRESS_LSB_PER_CELSIUS, + }, + }, + }, + .bdu = { + .addr = 0x20, + .mask = 0x04, + }, + .drdy_irq = { + .int1 = { + .addr = 0x22, + .mask = 0x04, + .addr_od = 0x22, + .mask_od = 0x40, + }, + .int2 = { + .addr = 0x22, + .mask = 0x20, + .addr_od = 0x22, + .mask_od = 0x40, + }, + .addr_ihl = 0x22, + .mask_ihl = 0x80, + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = 0x03, + }, + }, + .sim = { + .addr = 0x20, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, + { + /* + * CUSTOM VALUES FOR LPS001WP SENSOR + */ + .wai = 0xba, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LPS001WP_PRESS_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_press_lps001wp_channels, + .num_ch = ARRAY_SIZE(st_press_lps001wp_channels), + .odr = { + .addr = 0x20, + .mask = 0x30, + .odr_avl = { + { .hz = 1, .value = 0x01 }, + { .hz = 7, .value = 0x02 }, + { .hz = 13, .value = 0x03 }, + }, + }, + .pw = { + .addr = 0x20, + .mask = 0x40, + .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .fs = { + .fs_avl = { + /* + * Pressure and temperature resolution values + * as defined in table 3 of LPS001WP datasheet. + */ + [0] = { + .num = ST_PRESS_FS_AVL_1100MB, + .gain = ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN, + .gain2 = ST_PRESS_LPS001WP_LSB_PER_CELSIUS, + }, + }, + }, + .bdu = { + .addr = 0x20, + .mask = 0x04, + }, + .sim = { + .addr = 0x20, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, + { + /* + * CUSTOM VALUES FOR LPS25H SENSOR + * See LPS25H datasheet: + * http://www2.st.com/resource/en/datasheet/lps25h.pdf + */ + .wai = 0xbd, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LPS25H_PRESS_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_press_1_channels, + .num_ch = ARRAY_SIZE(st_press_1_channels), + .odr = { + .addr = 0x20, + .mask = 0x70, + .odr_avl = { + { .hz = 1, .value = 0x01 }, + { .hz = 7, .value = 0x02 }, + { .hz = 13, .value = 0x03 }, + { .hz = 25, .value = 0x04 }, + }, + }, + .pw = { + .addr = 0x20, + .mask = 0x80, + .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .fs = { + .fs_avl = { + /* + * Pressure and temperature sensitivity values + * as defined in table 3 of LPS25H datasheet. + */ + [0] = { + .num = ST_PRESS_FS_AVL_1260MB, + .gain = ST_PRESS_KPASCAL_NANO_SCALE, + .gain2 = ST_PRESS_LSB_PER_CELSIUS, + }, + }, + }, + .bdu = { + .addr = 0x20, + .mask = 0x04, + }, + .drdy_irq = { + .int1 = { + .addr = 0x23, + .mask = 0x01, + .addr_od = 0x22, + .mask_od = 0x40, + }, + .addr_ihl = 0x22, + .mask_ihl = 0x80, + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = 0x03, + }, + }, + .sim = { + .addr = 0x20, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, + { + /* + * CUSTOM VALUES FOR LPS22HB SENSOR + * See LPS22HB datasheet: + * http://www2.st.com/resource/en/datasheet/lps22hb.pdf + */ + .wai = 0xb1, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LPS22HB_PRESS_DEV_NAME, + [1] = LPS33HW_PRESS_DEV_NAME, + [2] = LPS35HW_PRESS_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_press_lps22hb_channels, + .num_ch = ARRAY_SIZE(st_press_lps22hb_channels), + .odr = { + .addr = 0x10, + .mask = 0x70, + .odr_avl = { + { .hz = 1, .value = 0x01 }, + { .hz = 10, .value = 0x02 }, + { .hz = 25, .value = 0x03 }, + { .hz = 50, .value = 0x04 }, + { .hz = 75, .value = 0x05 }, + }, + }, + .pw = { + .addr = 0x10, + .mask = 0x70, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .fs = { + .fs_avl = { + /* + * Pressure and temperature sensitivity values + * as defined in table 3 of LPS22HB datasheet. + */ + [0] = { + .num = ST_PRESS_FS_AVL_1260MB, + .gain = ST_PRESS_KPASCAL_NANO_SCALE, + .gain2 = ST_PRESS_LPS22HB_LSB_PER_CELSIUS, + }, + }, + }, + .bdu = { + .addr = 0x10, + .mask = 0x02, + }, + .drdy_irq = { + .int1 = { + .addr = 0x12, + .mask = 0x04, + .addr_od = 0x12, + .mask_od = 0x40, + }, + .addr_ihl = 0x12, + .mask_ihl = 0x80, + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = 0x03, + }, + }, + .sim = { + .addr = 0x10, + .value = BIT(0), + }, + .multi_read_bit = false, + .bootime = 2, + }, + { + /* + * CUSTOM VALUES FOR LPS22HH SENSOR + * See LPS22HH datasheet: + * http://www2.st.com/resource/en/datasheet/lps22hh.pdf + */ + .wai = 0xb3, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LPS22HH_PRESS_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_press_lps22hb_channels, + .num_ch = ARRAY_SIZE(st_press_lps22hb_channels), + .odr = { + .addr = 0x10, + .mask = 0x70, + .odr_avl = { + { .hz = 1, .value = 0x01 }, + { .hz = 10, .value = 0x02 }, + { .hz = 25, .value = 0x03 }, + { .hz = 50, .value = 0x04 }, + { .hz = 75, .value = 0x05 }, + { .hz = 100, .value = 0x06 }, + { .hz = 200, .value = 0x07 }, + }, + }, + .pw = { + .addr = 0x10, + .mask = 0x70, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .fs = { + .fs_avl = { + /* + * Pressure and temperature sensitivity values + * as defined in table 3 of LPS22HH datasheet. + */ + [0] = { + .num = ST_PRESS_FS_AVL_1260MB, + .gain = ST_PRESS_KPASCAL_NANO_SCALE, + .gain2 = ST_PRESS_LPS22HB_LSB_PER_CELSIUS, + }, + }, + }, + .bdu = { + .addr = 0x10, + .mask = BIT(1), + }, + .drdy_irq = { + .int1 = { + .addr = 0x12, + .mask = BIT(2), + .addr_od = 0x11, + .mask_od = BIT(5), + }, + .addr_ihl = 0x11, + .mask_ihl = BIT(6), + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = 0x03, + }, + }, + .sim = { + .addr = 0x10, + .value = BIT(0), + }, + .multi_read_bit = false, + .bootime = 2, + }, + { + /* + * CUSTOM VALUES FOR LPS22DF SENSOR + * See LPS22DF datasheet: + * http://www.st.com/resource/en/datasheet/lps22df.pdf + */ + .wai = 0xb4, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LPS22DF_PRESS_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_press_lps22hb_channels, + .num_ch = ARRAY_SIZE(st_press_lps22hb_channels), + .odr = { + .addr = 0x10, + .mask = 0x78, + .odr_avl = { + { .hz = 1, .value = 0x01 }, + { .hz = 4, .value = 0x02 }, + { .hz = 10, .value = 0x03 }, + { .hz = 25, .value = 0x04 }, + { .hz = 50, .value = 0x05 }, + { .hz = 75, .value = 0x06 }, + { .hz = 100, .value = 0x07 }, + { .hz = 200, .value = 0x08 }, + }, + }, + .pw = { + .addr = 0x10, + .mask = 0x78, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .fs = { + .fs_avl = { + /* + * Pressure and temperature sensitivity values + * as defined in table 2 of LPS22DF datasheet. + */ + [0] = { + .num = ST_PRESS_FS_AVL_1260MB, + .gain = ST_PRESS_KPASCAL_NANO_SCALE, + .gain2 = ST_PRESS_LPS22HB_LSB_PER_CELSIUS, + }, + }, + }, + .bdu = { + .addr = 0x11, + .mask = BIT(3), + }, + .drdy_irq = { + .int1 = { + .addr = 0x13, + .mask = BIT(5), + .addr_od = 0x12, + .mask_od = BIT(1), + }, + .addr_ihl = 0x12, + .mask_ihl = BIT(3), + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = 0x03, + }, + }, + .sim = { + .addr = 0x0E, + .value = BIT(5), + }, + .multi_read_bit = false, + .bootime = 2, + }, +}; + +static int st_press_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *ch, + int val, + int val2, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + + return st_sensors_set_odr(indio_dev, val); + default: + return -EINVAL; + } +} + +static int st_press_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *ch, int *val, + int *val2, long mask) +{ + int err; + struct st_sensor_data *press_data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + err = st_sensors_read_info_raw(indio_dev, ch, val); + if (err < 0) + goto read_error; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (ch->type) { + case IIO_PRESSURE: + *val = 0; + *val2 = press_data->current_fullscale->gain; + return IIO_VAL_INT_PLUS_NANO; + case IIO_TEMP: + *val = MCELSIUS_PER_CELSIUS; + *val2 = press_data->current_fullscale->gain2; + return IIO_VAL_FRACTIONAL; + default: + err = -EINVAL; + goto read_error; + } + + case IIO_CHAN_INFO_OFFSET: + switch (ch->type) { + case IIO_TEMP: + *val = ST_PRESS_MILLI_CELSIUS_OFFSET * + press_data->current_fullscale->gain2; + *val2 = MCELSIUS_PER_CELSIUS; + break; + default: + err = -EINVAL; + goto read_error; + } + + return IIO_VAL_FRACTIONAL; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = press_data->odr; + return IIO_VAL_INT; + default: + return -EINVAL; + } + +read_error: + return err; +} + +static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL(); + +static struct attribute *st_press_attributes[] = { + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group st_press_attribute_group = { + .attrs = st_press_attributes, +}; + +static const struct iio_info press_info = { + .attrs = &st_press_attribute_group, + .read_raw = &st_press_read_raw, + .write_raw = &st_press_write_raw, + .debugfs_reg_access = &st_sensors_debugfs_reg_access, +}; + +#ifdef CONFIG_IIO_TRIGGER +static const struct iio_trigger_ops st_press_trigger_ops = { + .set_trigger_state = ST_PRESS_TRIGGER_SET_STATE, + .validate_device = st_sensors_validate_device, +}; +#define ST_PRESS_TRIGGER_OPS (&st_press_trigger_ops) +#else +#define ST_PRESS_TRIGGER_OPS NULL +#endif + +/* + * st_press_get_settings() - get sensor settings from device name + * @name: device name buffer reference. + * + * Return: valid reference on success, NULL otherwise. + */ +const struct st_sensor_settings *st_press_get_settings(const char *name) +{ + int index = st_sensors_get_settings_index(name, + st_press_sensors_settings, + ARRAY_SIZE(st_press_sensors_settings)); + if (index < 0) + return NULL; + + return &st_press_sensors_settings[index]; +} +EXPORT_SYMBOL_NS(st_press_get_settings, IIO_ST_SENSORS); + +int st_press_common_probe(struct iio_dev *indio_dev) +{ + struct st_sensor_data *press_data = iio_priv(indio_dev); + struct device *parent = indio_dev->dev.parent; + struct st_sensors_platform_data *pdata = dev_get_platdata(parent); + int err; + + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &press_info; + + err = st_sensors_verify_id(indio_dev); + if (err < 0) + return err; + + /* + * Skip timestamping channel while declaring available channels to + * common st_sensor layer. Look at st_sensors_get_buffer_element() to + * see how timestamps are explicitly pushed as last samples block + * element. + */ + press_data->num_data_channels = press_data->sensor_settings->num_ch - 1; + indio_dev->channels = press_data->sensor_settings->ch; + indio_dev->num_channels = press_data->sensor_settings->num_ch; + + press_data->current_fullscale = &press_data->sensor_settings->fs.fs_avl[0]; + + press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz; + + /* Some devices don't support a data ready pin. */ + if (!pdata && (press_data->sensor_settings->drdy_irq.int1.addr || + press_data->sensor_settings->drdy_irq.int2.addr)) + pdata = (struct st_sensors_platform_data *)&default_press_pdata; + + err = st_sensors_init_sensor(indio_dev, pdata); + if (err < 0) + return err; + + err = st_press_allocate_ring(indio_dev); + if (err < 0) + return err; + + if (press_data->irq > 0) { + err = st_sensors_allocate_trigger(indio_dev, + ST_PRESS_TRIGGER_OPS); + if (err < 0) + return err; + } + + return devm_iio_device_register(parent, indio_dev); +} +EXPORT_SYMBOL_NS(st_press_common_probe, IIO_ST_SENSORS); + +MODULE_AUTHOR("Denis Ciocca "); +MODULE_DESCRIPTION("STMicroelectronics pressures driver"); +MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_ST_SENSORS); -- cgit v1.2.3