brintos

brintos / linux-shallow public Read only

0
0
Text · 15.2 KiB · a3b9356 Raw
553 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * STMicroelectronics st_lsm6dsx sensor driver4 *5 * Copyright 2016 STMicroelectronics Inc.6 *7 * Lorenzo Bianconi <lorenzo.bianconi@st.com>8 * Denis Ciocca <denis.ciocca@st.com>9 */10 11#ifndef ST_LSM6DSX_H12#define ST_LSM6DSX_H13 14#include <linux/device.h>15#include <linux/iio/iio.h>16#include <linux/regulator/consumer.h>17 18#define ST_LSM6DS3_DEV_NAME	"lsm6ds3"19#define ST_LSM6DS3H_DEV_NAME	"lsm6ds3h"20#define ST_LSM6DSL_DEV_NAME	"lsm6dsl"21#define ST_LSM6DSM_DEV_NAME	"lsm6dsm"22#define ST_ISM330DLC_DEV_NAME	"ism330dlc"23#define ST_LSM6DSO_DEV_NAME	"lsm6dso"24#define ST_ASM330LHH_DEV_NAME	"asm330lhh"25#define ST_LSM6DSOX_DEV_NAME	"lsm6dsox"26#define ST_LSM6DSR_DEV_NAME	"lsm6dsr"27#define ST_LSM6DS3TRC_DEV_NAME	"lsm6ds3tr-c"28#define ST_ISM330DHCX_DEV_NAME	"ism330dhcx"29#define ST_LSM9DS1_DEV_NAME	"lsm9ds1-imu"30#define ST_LSM6DS0_DEV_NAME	"lsm6ds0"31#define ST_LSM6DSRX_DEV_NAME	"lsm6dsrx"32#define ST_LSM6DST_DEV_NAME	"lsm6dst"33#define ST_LSM6DSOP_DEV_NAME	"lsm6dsop"34#define ST_ASM330LHHX_DEV_NAME	"asm330lhhx"35#define ST_LSM6DSTX_DEV_NAME	"lsm6dstx"36#define ST_LSM6DSV_DEV_NAME	"lsm6dsv"37#define ST_LSM6DSV16X_DEV_NAME	"lsm6dsv16x"38#define ST_LSM6DSO16IS_DEV_NAME	"lsm6dso16is"39#define ST_ISM330IS_DEV_NAME	"ism330is"40#define ST_ASM330LHB_DEV_NAME	"asm330lhb"41#define ST_ASM330LHHXG1_DEV_NAME	"asm330lhhxg1"42 43enum st_lsm6dsx_hw_id {44	ST_LSM6DS3_ID = 1,45	ST_LSM6DS3H_ID,46	ST_LSM6DSL_ID,47	ST_LSM6DSM_ID,48	ST_ISM330DLC_ID,49	ST_LSM6DSO_ID,50	ST_ASM330LHH_ID,51	ST_LSM6DSOX_ID,52	ST_LSM6DSR_ID,53	ST_LSM6DS3TRC_ID,54	ST_ISM330DHCX_ID,55	ST_LSM9DS1_ID,56	ST_LSM6DS0_ID,57	ST_LSM6DSRX_ID,58	ST_LSM6DST_ID,59	ST_LSM6DSOP_ID,60	ST_ASM330LHHX_ID,61	ST_LSM6DSTX_ID,62	ST_LSM6DSV_ID,63	ST_LSM6DSV16X_ID,64	ST_LSM6DSO16IS_ID,65	ST_ISM330IS_ID,66	ST_ASM330LHB_ID,67	ST_ASM330LHHXG1_ID,68	ST_LSM6DSX_MAX_ID,69};70 71#define ST_LSM6DSX_BUFF_SIZE		51272#define ST_LSM6DSX_CHAN_SIZE		273#define ST_LSM6DSX_SAMPLE_SIZE		674#define ST_LSM6DSX_TAG_SIZE		175#define ST_LSM6DSX_TAGGED_SAMPLE_SIZE	(ST_LSM6DSX_SAMPLE_SIZE + \76					 ST_LSM6DSX_TAG_SIZE)77#define ST_LSM6DSX_MAX_WORD_LEN		((32 / ST_LSM6DSX_SAMPLE_SIZE) * \78					 ST_LSM6DSX_SAMPLE_SIZE)79#define ST_LSM6DSX_MAX_TAGGED_WORD_LEN	((32 / ST_LSM6DSX_TAGGED_SAMPLE_SIZE) \80					 * ST_LSM6DSX_TAGGED_SAMPLE_SIZE)81#define ST_LSM6DSX_SHIFT_VAL(val, mask)	(((val) << __ffs(mask)) & (mask))82 83#define ST_LSM6DSX_CHANNEL_ACC(chan_type, addr, mod, scan_idx)		\84{									\85	.type = chan_type,						\86	.address = addr,						\87	.modified = 1,							\88	.channel2 = mod,						\89	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\90	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\91	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),	\92	.scan_index = scan_idx,						\93	.scan_type = {							\94		.sign = 's',						\95		.realbits = 16,						\96		.storagebits = 16,					\97		.endianness = IIO_LE,					\98	},								\99	.event_spec = &st_lsm6dsx_event,				\100	.ext_info = st_lsm6dsx_ext_info,				\101	.num_event_specs = 1,						\102}103 104#define ST_LSM6DSX_CHANNEL(chan_type, addr, mod, scan_idx)		\105{									\106	.type = chan_type,						\107	.address = addr,						\108	.modified = 1,							\109	.channel2 = mod,						\110	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\111	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\112	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),	\113	.scan_index = scan_idx,						\114	.scan_type = {							\115		.sign = 's',						\116		.realbits = 16,						\117		.storagebits = 16,					\118		.endianness = IIO_LE,					\119	},								\120	.ext_info = st_lsm6dsx_ext_info,				\121}122 123struct st_lsm6dsx_reg {124	u8 addr;125	u8 mask;126};127 128struct st_lsm6dsx_sensor;129struct st_lsm6dsx_hw;130 131struct st_lsm6dsx_odr {132	u32 milli_hz;133	u8 val;134};135 136#define ST_LSM6DSX_ODR_LIST_SIZE	8137struct st_lsm6dsx_odr_table_entry {138	struct st_lsm6dsx_reg reg;139 140	struct st_lsm6dsx_odr odr_avl[ST_LSM6DSX_ODR_LIST_SIZE];141	int odr_len;142};143 144struct st_lsm6dsx_samples_to_discard {145	struct {146		u32 milli_hz;147		u16 samples;148	} val[ST_LSM6DSX_ODR_LIST_SIZE];149};150 151struct st_lsm6dsx_fs {152	u32 gain;153	u8 val;154};155 156#define ST_LSM6DSX_FS_LIST_SIZE		4157struct st_lsm6dsx_fs_table_entry {158	struct st_lsm6dsx_reg reg;159 160	struct st_lsm6dsx_fs fs_avl[ST_LSM6DSX_FS_LIST_SIZE];161	int fs_len;162};163 164/**165 * struct st_lsm6dsx_fifo_ops - ST IMU FIFO settings166 * @update_fifo: Update FIFO configuration callback.167 * @read_fifo: Read FIFO callback.168 * @fifo_th: FIFO threshold register info (addr + mask).169 * @fifo_diff: FIFO diff status register info (addr + mask).170 * @max_size: Sensor max fifo length in FIFO words.171 * @th_wl: FIFO threshold word length.172 */173struct st_lsm6dsx_fifo_ops {174	int (*update_fifo)(struct st_lsm6dsx_sensor *sensor, bool enable);175	int (*read_fifo)(struct st_lsm6dsx_hw *hw);176	struct {177		u8 addr;178		u16 mask;179	} fifo_th;180	struct {181		u8 addr;182		u16 mask;183	} fifo_diff;184	u16 max_size;185	u8 th_wl;186};187 188/**189 * struct st_lsm6dsx_hw_ts_settings - ST IMU hw timer settings190 * @timer_en: Hw timer enable register info (addr + mask).191 * @hr_timer: Hw timer resolution register info (addr + mask).192 * @fifo_en: Hw timer FIFO enable register info (addr + mask).193 * @decimator: Hw timer FIFO decimator register info (addr + mask).194 * @freq_fine: Difference in % of ODR with respect to the typical.195 */196struct st_lsm6dsx_hw_ts_settings {197	struct st_lsm6dsx_reg timer_en;198	struct st_lsm6dsx_reg hr_timer;199	struct st_lsm6dsx_reg fifo_en;200	struct st_lsm6dsx_reg decimator;201	u8 freq_fine;202};203 204/**205 * struct st_lsm6dsx_shub_settings - ST IMU hw i2c controller settings206 * @page_mux: register page mux info (addr + mask).207 * @master_en: master config register info (addr + mask).208 * @pullup_en: i2c controller pull-up register info (addr + mask).209 * @aux_sens: aux sensor register info (addr + mask).210 * @wr_once: write_once register info (addr + mask).211 * @emb_func:  embedded function register info (addr + mask).212 * @num_ext_dev: max number of slave devices.213 * @shub_out: sensor hub first output register info.214 * @slv0_addr: slave0 address in secondary page.215 * @dw_slv0_addr: slave0 write register address in secondary page.216 * @batch_en: Enable/disable FIFO batching.217 * @pause: controller pause value.218 */219struct st_lsm6dsx_shub_settings {220	struct st_lsm6dsx_reg page_mux;221	struct {222		bool sec_page;223		u8 addr;224		u8 mask;225	} master_en;226	struct {227		bool sec_page;228		u8 addr;229		u8 mask;230	} pullup_en;231	struct st_lsm6dsx_reg aux_sens;232	struct st_lsm6dsx_reg wr_once;233	struct st_lsm6dsx_reg emb_func;234	u8 num_ext_dev;235	struct {236		bool sec_page;237		u8 addr;238	} shub_out;239	u8 slv0_addr;240	u8 dw_slv0_addr;241	u8 batch_en;242	u8 pause;243};244 245struct st_lsm6dsx_event_settings {246	struct st_lsm6dsx_reg enable_reg;247	struct st_lsm6dsx_reg wakeup_reg;248	u8 wakeup_src_reg;249	u8 wakeup_src_status_mask;250	u8 wakeup_src_z_mask;251	u8 wakeup_src_y_mask;252	u8 wakeup_src_x_mask;253};254 255enum st_lsm6dsx_ext_sensor_id {256	ST_LSM6DSX_ID_MAGN,257};258 259/**260 * struct st_lsm6dsx_ext_dev_settings - i2c controller slave settings261 * @i2c_addr: I2c slave address list.262 * @wai: Wai address info.263 * @id: external sensor id.264 * @odr_table: Output data rate of the sensor [Hz].265 * @fs_table: Configured sensor sensitivity table depending on full scale.266 * @temp_comp: Temperature compensation register info (addr + mask).267 * @pwr_table: Power on register info (addr + mask).268 * @off_canc: Offset cancellation register info (addr + mask).269 * @bdu: Block data update register info (addr + mask).270 * @out: Output register info.271 */272struct st_lsm6dsx_ext_dev_settings {273	u8 i2c_addr[2];274	struct {275		u8 addr;276		u8 val;277	} wai;278	enum st_lsm6dsx_ext_sensor_id id;279	struct st_lsm6dsx_odr_table_entry odr_table;280	struct st_lsm6dsx_fs_table_entry fs_table;281	struct st_lsm6dsx_reg temp_comp;282	struct {283		struct st_lsm6dsx_reg reg;284		u8 off_val;285		u8 on_val;286	} pwr_table;287	struct st_lsm6dsx_reg off_canc;288	struct st_lsm6dsx_reg bdu;289	struct {290		u8 addr;291		u8 len;292	} out;293};294 295/**296 * struct st_lsm6dsx_settings - ST IMU sensor settings297 * @reset: register address for reset.298 * @boot: register address for boot.299 * @bdu: register address for Block Data Update.300 * @id: List of hw id/device name supported by the driver configuration.301 * @channels: IIO channels supported by the device.302 * @irq_config: interrupts related registers.303 * @drdy_mask: register info for data-ready mask (addr + mask).304 * @odr_table: Hw sensors odr table (Hz + val).305 * @samples_to_discard: Number of samples to discard for filters settling time.306 * @fs_table: Hw sensors gain table (gain + val).307 * @decimator: List of decimator register info (addr + mask).308 * @batch: List of FIFO batching register info (addr + mask).309 * @fifo_ops: Sensor hw FIFO parameters.310 * @ts_settings: Hw timer related settings.311 * @shub_settings: i2c controller related settings.312 */313struct st_lsm6dsx_settings {314	struct st_lsm6dsx_reg reset;315	struct st_lsm6dsx_reg boot;316	struct st_lsm6dsx_reg bdu;317	struct {318		enum st_lsm6dsx_hw_id hw_id;319		const char *name;320		u8 wai;321	} id[ST_LSM6DSX_MAX_ID];322	struct {323		const struct iio_chan_spec *chan;324		int len;325	} channels[2];326	struct {327		struct st_lsm6dsx_reg irq1;328		struct st_lsm6dsx_reg irq2;329		struct st_lsm6dsx_reg irq1_func;330		struct st_lsm6dsx_reg irq2_func;331		struct st_lsm6dsx_reg lir;332		struct st_lsm6dsx_reg clear_on_read;333		struct st_lsm6dsx_reg hla;334		struct st_lsm6dsx_reg od;335	} irq_config;336	struct st_lsm6dsx_reg drdy_mask;337	struct st_lsm6dsx_odr_table_entry odr_table[2];338	struct st_lsm6dsx_samples_to_discard samples_to_discard[2];339	struct st_lsm6dsx_fs_table_entry fs_table[2];340	struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID];341	struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID];342	struct st_lsm6dsx_fifo_ops fifo_ops;343	struct st_lsm6dsx_hw_ts_settings ts_settings;344	struct st_lsm6dsx_shub_settings shub_settings;345	struct st_lsm6dsx_event_settings event_settings;346};347 348enum st_lsm6dsx_sensor_id {349	ST_LSM6DSX_ID_GYRO,350	ST_LSM6DSX_ID_ACC,351	ST_LSM6DSX_ID_EXT0,352	ST_LSM6DSX_ID_EXT1,353	ST_LSM6DSX_ID_EXT2,354	ST_LSM6DSX_ID_MAX,355};356 357enum st_lsm6dsx_fifo_mode {358	ST_LSM6DSX_FIFO_BYPASS = 0x0,359	ST_LSM6DSX_FIFO_CONT = 0x6,360};361 362/**363 * struct st_lsm6dsx_sensor - ST IMU sensor instance364 * @name: Sensor name.365 * @id: Sensor identifier.366 * @hw: Pointer to instance of struct st_lsm6dsx_hw.367 * @gain: Configured sensor sensitivity.368 * @odr: Output data rate of the sensor [Hz].369 * @samples_to_discard: Number of samples to discard for filters settling time.370 * @watermark: Sensor watermark level.371 * @decimator: Sensor decimation factor.372 * @sip: Number of samples in a given pattern.373 * @ts_ref: Sensor timestamp reference for hw one.374 * @ext_info: Sensor settings if it is connected to i2c controller375 */376struct st_lsm6dsx_sensor {377	char name[32];378	enum st_lsm6dsx_sensor_id id;379	struct st_lsm6dsx_hw *hw;380 381	u32 gain;382	u32 odr;383 384	u16 samples_to_discard;385	u16 watermark;386	u8 decimator;387	u8 sip;388	s64 ts_ref;389 390	struct {391		const struct st_lsm6dsx_ext_dev_settings *settings;392		u32 slv_odr;393		u8 addr;394	} ext_info;395};396 397/**398 * struct st_lsm6dsx_hw - ST IMU MEMS hw instance399 * @dev: Pointer to instance of struct device (I2C or SPI).400 * @regmap: Register map of the device.401 * @irq: Device interrupt line (I2C or SPI).402 * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO.403 * @conf_lock: Mutex to prevent concurrent FIFO configuration update.404 * @page_lock: Mutex to prevent concurrent memory page configuration.405 * @suspend_mask: Suspended sensor bitmask.406 * @enable_mask: Enabled sensor bitmask.407 * @fifo_mask: Enabled hw FIFO bitmask.408 * @ts_gain: Hw timestamp rate after internal calibration.409 * @ts_sip: Total number of timestamp samples in a given pattern.410 * @sip: Total number of samples (acc/gyro/ts) in a given pattern.411 * @buff: Device read buffer.412 * @irq_routing: pointer to interrupt routing configuration.413 * @event_threshold: wakeup event threshold.414 * @enable_event: enabled event bitmask.415 * @iio_devs: Pointers to acc/gyro iio_dev instances.416 * @settings: Pointer to the specific sensor settings in use.417 * @orientation: sensor chip orientation relative to main hardware.418 * @scan: Temporary buffers used to align data before iio_push_to_buffers()419 */420struct st_lsm6dsx_hw {421	struct device *dev;422	struct regmap *regmap;423	int irq;424 425	struct mutex fifo_lock;426	struct mutex conf_lock;427	struct mutex page_lock;428 429	u8 suspend_mask;430	u8 enable_mask;431	u8 fifo_mask;432	s64 ts_gain;433	u8 ts_sip;434	u8 sip;435 436	const struct st_lsm6dsx_reg *irq_routing;437	u8 event_threshold;438	u8 enable_event;439 440	u8 *buff;441 442	struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX];443 444	const struct st_lsm6dsx_settings *settings;445 446	struct iio_mount_matrix orientation;447	/* Ensure natural alignment of buffer elements */448	struct {449		__le16 channels[3];450		s64 ts __aligned(8);451	} scan[ST_LSM6DSX_ID_MAX];452};453 454static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = {455	.type = IIO_EV_TYPE_THRESH,456	.dir = IIO_EV_DIR_EITHER,457	.mask_separate = BIT(IIO_EV_INFO_VALUE) |458			 BIT(IIO_EV_INFO_ENABLE)459};460 461static __maybe_unused const unsigned long st_lsm6dsx_available_scan_masks[] = {462	0x7, 0x0,463};464 465extern const struct dev_pm_ops st_lsm6dsx_pm_ops;466 467int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,468		     struct regmap *regmap);469int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,470				 bool enable);471int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw);472int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val);473int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor,474				u16 watermark);475int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable);476int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw);477int st_lsm6dsx_resume_fifo(struct st_lsm6dsx_hw *hw);478int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw);479int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw);480int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val);481int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name);482int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable);483int st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int len);484int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable);485 486static inline int487st_lsm6dsx_update_bits_locked(struct st_lsm6dsx_hw *hw, unsigned int addr,488			      unsigned int mask, unsigned int val)489{490	int err;491 492	mutex_lock(&hw->page_lock);493	err = regmap_update_bits(hw->regmap, addr, mask, val);494	mutex_unlock(&hw->page_lock);495 496	return err;497}498 499static inline int500st_lsm6dsx_read_locked(struct st_lsm6dsx_hw *hw, unsigned int addr,501		       void *val, unsigned int len)502{503	int err;504 505	mutex_lock(&hw->page_lock);506	err = regmap_bulk_read(hw->regmap, addr, val, len);507	mutex_unlock(&hw->page_lock);508 509	return err;510}511 512static inline int513st_lsm6dsx_write_locked(struct st_lsm6dsx_hw *hw, unsigned int addr,514			unsigned int val)515{516	int err;517 518	mutex_lock(&hw->page_lock);519	err = regmap_write(hw->regmap, addr, val);520	mutex_unlock(&hw->page_lock);521 522	return err;523}524 525static inline const struct iio_mount_matrix *526st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev,527			    const struct iio_chan_spec *chan)528{529	struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);530	struct st_lsm6dsx_hw *hw = sensor->hw;531 532	return &hw->orientation;533}534 535static inline int536st_lsm6dsx_device_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable)537{538	if (sensor->id == ST_LSM6DSX_ID_EXT0 ||539	    sensor->id == ST_LSM6DSX_ID_EXT1 ||540	    sensor->id == ST_LSM6DSX_ID_EXT2)541		return st_lsm6dsx_shub_set_enable(sensor, enable);542 543	return st_lsm6dsx_sensor_set_enable(sensor, enable);544}545 546static const547struct iio_chan_spec_ext_info __maybe_unused st_lsm6dsx_ext_info[] = {548	IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix),549	{ }550};551 552#endif /* ST_LSM6DSX_H */553