blob: c3ea68b18f4f545a40c775d4d02b03c26e2d2d76 [file] [log] [blame]
Mario Tesic6a86652018-04-24 11:49:14 +02001/*
2 * STMicroelectronics st_asm330lhh sensor driver
3 *
4 * Copyright 2018 STMicroelectronics Inc.
5 *
6 * Lorenzo Bianconi <lorenzo.bianconi@st.com>
7 *
8 * Licensed under the GPL-2.
9 */
10
11#ifndef ST_ASM330LHH_H
12#define ST_ASM330LHH_H
13
14#include <linux/device.h>
15#include <linux/iio/iio.h>
Puneet yatnala80857e72018-03-07 17:30:49 +053016#include <linux/input.h>
17#include <linux/ktime.h>
18#include <linux/slab.h>
Mario Tesic6a86652018-04-24 11:49:14 +020019
20#define ST_ASM330LHH_REVISION "2.0.1"
Mario Tesi98ce0b82019-11-25 15:30:12 +010021#define ST_ASM330LHH_PATCH "2"
Mario Tesic6a86652018-04-24 11:49:14 +020022
23#define ST_ASM330LHH_VERSION "v" \
24 ST_ASM330LHH_REVISION \
25 "-" \
26 ST_ASM330LHH_PATCH
27
28#define ST_ASM330LHH_DEV_NAME "asm330lhh"
29
30#define ST_ASM330LHH_SAMPLE_SIZE 6
31#define ST_ASM330LHH_TS_SAMPLE_SIZE 4
32#define ST_ASM330LHH_TAG_SIZE 1
33#define ST_ASM330LHH_FIFO_SAMPLE_SIZE (ST_ASM330LHH_SAMPLE_SIZE + \
34 ST_ASM330LHH_TAG_SIZE)
35#define ST_ASM330LHH_MAX_FIFO_DEPTH 416
36
37#define ST_ASM330LHH_REG_FIFO_BATCH_ADDR 0x09
38#define ST_ASM330LHH_REG_FIFO_CTRL4_ADDR 0x0a
39#define ST_ASM330LHH_REG_STATUS_ADDR 0x1e
40#define ST_ASM330LHH_REG_STATUS_TDA BIT(2)
41#define ST_ASM330LHH_REG_OUT_TEMP_L_ADDR 0x20
42#define ST_ASM330LHH_REG_OUT_TEMP_H_ADDR 0x21
43
44#define ST_ASM330LHH_MAX_ODR 416
45
mario tesi547c2f52020-03-18 13:36:32 +010046/* Timestamp Tick 25us/LSB */
47#define ST_ASM330LHH_TS_DELTA_NS 25000ULL
48
Mario Tesic6a86652018-04-24 11:49:14 +020049/* Define Custom events for FIFO flush */
50#define CUSTOM_IIO_EV_DIR_FIFO_EMPTY (IIO_EV_DIR_NONE + 1)
51#define CUSTOM_IIO_EV_DIR_FIFO_DATA (IIO_EV_DIR_NONE + 2)
52#define CUSTOM_IIO_EV_TYPE_FIFO_FLUSH (IIO_EV_TYPE_CHANGE + 1)
53
54#define ST_ASM330LHH_CHANNEL(chan_type, addr, mod, ch2, scan_idx, \
55 rb, sb, sg) \
56{ \
57 .type = chan_type, \
58 .address = addr, \
59 .modified = mod, \
60 .channel2 = ch2, \
61 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
62 BIT(IIO_CHAN_INFO_SCALE), \
63 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
64 .scan_index = scan_idx, \
65 .scan_type = { \
66 .sign = sg, \
67 .realbits = rb, \
68 .storagebits = sb, \
69 .endianness = IIO_LE, \
70 }, \
71}
72
73static const struct iio_event_spec st_asm330lhh_flush_event = {
74 .type = CUSTOM_IIO_EV_TYPE_FIFO_FLUSH,
75 .dir = IIO_EV_DIR_EITHER,
76};
77
78#define ST_ASM330LHH_FLUSH_CHANNEL(dtype) \
79{ \
80 .type = dtype, \
81 .modified = 0, \
82 .scan_index = -1, \
83 .indexed = -1, \
84 .event_spec = &st_asm330lhh_flush_event, \
85 .num_event_specs = 1, \
86}
87
mario tesi547c2f52020-03-18 13:36:32 +010088#define ST_ASM330LHH_RX_MAX_LENGTH 64
89#define ST_ASM330LHH_TX_MAX_LENGTH 16
Mario Tesic6a86652018-04-24 11:49:14 +020090
Puneet yatnala80857e72018-03-07 17:30:49 +053091#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
92#define ASM_MAXSAMPLE 4000
93#define G_MAX 23920640
94struct asm_sample {
95 int xyz[3];
96 unsigned int tsec;
97 unsigned long long tnsec;
98};
99#endif
100
Mario Tesic6a86652018-04-24 11:49:14 +0200101struct st_asm330lhh_transfer_buffer {
102 u8 rx_buf[ST_ASM330LHH_RX_MAX_LENGTH];
103 u8 tx_buf[ST_ASM330LHH_TX_MAX_LENGTH] ____cacheline_aligned;
104};
105
106struct st_asm330lhh_transfer_function {
107 int (*read)(struct device *dev, u8 addr, int len, u8 *data);
108 int (*write)(struct device *dev, u8 addr, int len, u8 *data);
109};
110
111struct st_asm330lhh_reg {
112 u8 addr;
113 u8 mask;
114};
115
116struct st_asm330lhh_odr {
117 u16 hz;
118 u8 val;
119};
120
121#define ST_ASM330LHH_ODR_LIST_SIZE 7
122struct st_asm330lhh_odr_table_entry {
123 struct st_asm330lhh_reg reg;
124 struct st_asm330lhh_odr odr_avl[ST_ASM330LHH_ODR_LIST_SIZE];
125};
126
127struct st_asm330lhh_fs {
128 u32 gain;
129 u8 val;
130};
131
132#define ST_ASM330LHH_FS_ACC_LIST_SIZE 4
133#define ST_ASM330LHH_FS_GYRO_LIST_SIZE 6
134#define ST_ASM330LHH_FS_TEMP_LIST_SIZE 1
135#define ST_ASM330LHH_FS_LIST_SIZE 6
136struct st_asm330lhh_fs_table_entry {
137 u32 size;
138 struct st_asm330lhh_reg reg;
139 struct st_asm330lhh_fs fs_avl[ST_ASM330LHH_FS_LIST_SIZE];
140};
141
142enum st_asm330lhh_sensor_id {
143 ST_ASM330LHH_ID_ACC,
144 ST_ASM330LHH_ID_GYRO,
145 ST_ASM330LHH_ID_TEMP,
146 ST_ASM330LHH_ID_MAX,
147};
148
149enum st_asm330lhh_fifo_mode {
150 ST_ASM330LHH_FIFO_BYPASS = 0x0,
151 ST_ASM330LHH_FIFO_CONT = 0x6,
152};
153
154enum {
155 ST_ASM330LHH_HW_FLUSH,
156 ST_ASM330LHH_HW_OPERATIONAL,
157};
158
159/**
160 * struct st_asm330lhh_sensor - ST IMU sensor instance
161 * @id: Sensor identifier.
162 * @hw: Pointer to instance of struct st_asm330lhh_hw.
163 * @gain: Configured sensor sensitivity.
164 * @odr: Output data rate of the sensor [Hz].
165 * @watermark: Sensor watermark level.
166 * @batch_mask: Sensor mask for FIFO batching register
167 */
168struct st_asm330lhh_sensor {
169 enum st_asm330lhh_sensor_id id;
170 struct st_asm330lhh_hw *hw;
171
172 u32 gain;
173 u16 odr;
174 u32 offset;
175
176 __le16 old_data;
177
178 u8 std_samples;
179 u8 std_level;
180
181 u16 watermark;
182 u8 batch_mask;
183 u8 batch_addr;
Puneet Yatnal08c625e2020-03-30 10:40:46 +0530184 struct mutex sensor_buff;
Puneet yatnala80857e72018-03-07 17:30:49 +0530185#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
186 bool read_boot_sample;
187 int bufsample_cnt;
188 bool buffer_asm_samples;
189 struct kmem_cache *asm_cachepool;
190 struct asm_sample *asm_samplist[ASM_MAXSAMPLE];
191 ktime_t timestamp;
192 int max_buffer_time;
193 struct input_dev *buf_dev;
194 int report_evt_cnt;
195#endif
Mario Tesic6a86652018-04-24 11:49:14 +0200196};
197
198/**
199 * struct st_asm330lhh_hw - ST IMU MEMS hw instance
200 * @dev: Pointer to instance of struct device (I2C or SPI).
201 * @irq: Device interrupt line (I2C or SPI).
202 * @lock: Mutex to protect read and write operations.
203 * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO.
mario tesi547c2f52020-03-18 13:36:32 +0100204 * @page_lock: Mutex to prevent concurrent memory page configuration.
Mario Tesic6a86652018-04-24 11:49:14 +0200205 * @fifo_mode: FIFO operating mode supported by the device.
206 * @state: hw operational state.
207 * @enable_mask: Enabled sensor bitmask.
208 * @ts_offset: Hw timestamp offset.
209 * @hw_ts: Latest hw timestamp from the sensor.
210 * @ts: Latest timestamp from irq handler.
211 * @delta_ts: Delta time between two consecutive interrupts.
mario tesi547c2f52020-03-18 13:36:32 +0100212 * @ts_delta_ns: Calibrate delta time tick.
213 * @hw_ts: Latest hw timestamp from the sensor.
214 * @val_ts_old: Hold hw timestamp for timer rollover.
215 * @hw_ts_high: Save MSB hw timestamp.
216 * @tsample: Timestamp for each sensor sample.
217 * @delta_ts: Delta time between two consecutive interrupts.
218 * @ts: Latest timestamp from irq handler.
Mario Tesic6a86652018-04-24 11:49:14 +0200219 * @iio_devs: Pointers to acc/gyro iio_dev instances.
220 * @tf: Transfer function structure used by I/O operations.
221 * @tb: Transfer buffers used by SPI I/O operations.
222 */
223struct st_asm330lhh_hw {
224 struct device *dev;
225 int irq;
226
227 struct mutex lock;
228 struct mutex fifo_lock;
mario tesi547c2f52020-03-18 13:36:32 +0100229 struct mutex page_lock;
Mario Tesic6a86652018-04-24 11:49:14 +0200230
231 enum st_asm330lhh_fifo_mode fifo_mode;
232 unsigned long state;
233 u8 enable_mask;
234
235 s64 ts_offset;
mario tesi547c2f52020-03-18 13:36:32 +0100236 u64 ts_delta_ns;
Mario Tesic6a86652018-04-24 11:49:14 +0200237 s64 hw_ts;
mario tesi547c2f52020-03-18 13:36:32 +0100238 u32 val_ts_old;
239 u32 hw_ts_high;
240 s64 tsample;
Mario Tesic6a86652018-04-24 11:49:14 +0200241 s64 delta_ts;
242 s64 ts;
Mario Tesic6a86652018-04-24 11:49:14 +0200243 struct iio_dev *iio_devs[ST_ASM330LHH_ID_MAX];
244
245 const struct st_asm330lhh_transfer_function *tf;
246 struct st_asm330lhh_transfer_buffer tb;
Puneet Yatnal26fb3692020-01-22 13:29:03 +0530247 int enable_gpio;
Puneet Yatnal08e34f82020-03-26 13:48:33 +0530248 bool asm330_hrtimer;
Puneet Yatnalef8d7652020-03-19 09:57:34 +0530249 struct hrtimer st_asm330lhh_hrtimer;
Mario Tesic6a86652018-04-24 11:49:14 +0200250};
251
252extern const struct dev_pm_ops st_asm330lhh_pm_ops;
253
mario tesi547c2f52020-03-18 13:36:32 +0100254static inline int st_asm330lhh_read_atomic(struct st_asm330lhh_hw *hw, u8 addr,
255 int len, u8 *data)
256{
257 int err;
258
259 mutex_lock(&hw->page_lock);
260 err = hw->tf->read(hw->dev, addr, len, data);
261 mutex_unlock(&hw->page_lock);
262
263 return err;
264}
265
266static inline s64 st_asm330lhh_get_time_ns(void)
267{
268 struct timespec ts;
269
270 get_monotonic_boottime(&ts);
271 return timespec_to_ns(&ts);
272}
273
Mario Tesic6a86652018-04-24 11:49:14 +0200274int st_asm330lhh_probe(struct device *dev, int irq,
275 const struct st_asm330lhh_transfer_function *tf_ops);
276int st_asm330lhh_sensor_set_enable(struct st_asm330lhh_sensor *sensor,
277 bool enable);
278int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw);
279int st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw, u8 addr, u8 mask,
280 u8 val);
281int st_asm330lhh_get_odr_val(enum st_asm330lhh_sensor_id id, u16 odr, u8 *val);
282ssize_t st_asm330lhh_flush_fifo(struct device *dev,
283 struct device_attribute *attr,
284 const char *buf, size_t size);
285ssize_t st_asm330lhh_get_max_watermark(struct device *dev,
286 struct device_attribute *attr, char *buf);
287ssize_t st_asm330lhh_get_watermark(struct device *dev,
288 struct device_attribute *attr, char *buf);
289ssize_t st_asm330lhh_set_watermark(struct device *dev,
290 struct device_attribute *attr,
291 const char *buf, size_t size);
292int st_asm330lhh_set_fifo_mode(struct st_asm330lhh_hw *hw,
293 enum st_asm330lhh_fifo_mode fifo_mode);
294int st_asm330lhh_suspend_fifo(struct st_asm330lhh_hw *hw);
Puneet yatnala80857e72018-03-07 17:30:49 +0530295int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
296 u16 watermark);
297int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable);
298int asm330_check_acc_gyro_early_buff_enable_flag(
299 struct st_asm330lhh_sensor *sensor);
Puneet Yatnalef8d7652020-03-19 09:57:34 +0530300void st_asm330lhh_set_cpu_idle_state(bool value);
301void st_asm330lhh_hrtimer_reset(struct st_asm330lhh_hw *hw, s64 irq_delta_ts);
Mario Tesic6a86652018-04-24 11:49:14 +0200302#endif /* ST_ASM330LHH_H */