1 /*
2  * Copyright (c) 2016 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/drivers/sensor.h>
8 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
9 #include <zephyr/drivers/spi.h>
10 #endif
11 
12 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
13 #include <zephyr/drivers/i2c.h>
14 #endif
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/kernel.h>
17 
18 #define FXOS8700_BUS_I2C			(1<<0)
19 #define FXOS8700_BUS_SPI			(1<<1)
20 #define FXOS8700_REG_STATUS			0x00
21 #define FXOS8700_REG_OUTXMSB			0x01
22 #define FXOS8700_REG_INT_SOURCE			0x0c
23 #define FXOS8700_REG_WHOAMI			0x0d
24 #define FXOS8700_REG_XYZ_DATA_CFG		0x0e
25 #define FXOS8700_REG_FF_MT_CFG			0x15
26 #define FXOS8700_REG_FF_MT_SRC			0x16
27 #define FXOS8700_REG_FF_MT_THS			0x17
28 #define FXOS8700_REG_FF_MT_COUNT		0x18
29 #define FXOS8700_REG_PULSE_CFG			0x21
30 #define FXOS8700_REG_PULSE_SRC			0x22
31 #define FXOS8700_REG_PULSE_THSX			0x23
32 #define FXOS8700_REG_PULSE_THSY			0x24
33 #define FXOS8700_REG_PULSE_THSZ			0x25
34 #define FXOS8700_REG_PULSE_TMLT			0x26
35 #define FXOS8700_REG_PULSE_LTCY			0x27
36 #define FXOS8700_REG_PULSE_WIND			0x28
37 #define FXOS8700_REG_CTRLREG1			0x2a
38 #define FXOS8700_REG_CTRLREG2			0x2b
39 #define FXOS8700_REG_CTRLREG3			0x2c
40 #define FXOS8700_REG_CTRLREG4			0x2d
41 #define FXOS8700_REG_CTRLREG5			0x2e
42 #define FXOS8700_REG_M_OUTXMSB			0x33
43 #define FXOS8700_REG_TEMP			0x51
44 #define FXOS8700_REG_M_CTRLREG1			0x5b
45 #define FXOS8700_REG_M_CTRLREG2			0x5c
46 #define FXOS8700_REG_M_INT_SRC			0x5e
47 #define FXOS8700_REG_M_VECM_CFG			0x69
48 #define FXOS8700_REG_M_VECM_THS_MSB		0x6a
49 #define FXOS8700_REG_M_VECM_THS_LSB		0x6b
50 
51 /* Devices that are compatible with this driver: */
52 #define WHOAMI_ID_MMA8451			0x1A
53 #define WHOAMI_ID_MMA8652			0x4A
54 #define WHOAMI_ID_MMA8653			0x5A
55 #define WHOAMI_ID_FXOS8700			0xC7
56 
57 #define FXOS8700_DRDY_MASK			(1 << 0)
58 #define FXOS8700_MAG_VECM_INT1_MASK		(1 << 0)
59 #define FXOS8700_VECM_MASK			(1 << 1)
60 #define FXOS8700_MOTION_MASK			(1 << 2)
61 #define FXOS8700_PULSE_MASK			(1 << 3)
62 
63 #define FXOS8700_XYZ_DATA_CFG_FS_MASK		0x03
64 
65 #define FXOS8700_PULSE_SRC_DPE			(1 << 3)
66 
67 #define FXOS8700_CTRLREG1_ACTIVE_MASK		0x01
68 #define FXOS8700_CTRLREG1_DR_MASK		(7 << 3)
69 #define FXOS8700_CTRLREG1_DR_RATE_800		0
70 #define FXOS8700_CTRLREG1_DR_RATE_400		(1 << 3)
71 #define FXOS8700_CTRLREG1_DR_RATE_200		(2 << 3)
72 #define FXOS8700_CTRLREG1_DR_RATE_100		(3 << 3)
73 #define FXOS8700_CTRLREG1_DR_RATE_50		(4 << 3)
74 #define FXOS8700_CTRLREG1_DR_RATE_12_5		(5 << 3)
75 #define FXOS8700_CTRLREG1_DR_RATE_6_25		(6 << 3)
76 #define FXOS8700_CTRLREG1_DR_RATE_1_56		(7 << 3)
77 
78 #define FXOS8700_CTRLREG2_RST_MASK		0x40
79 #define FXOS8700_CTRLREG2_MODS_MASK		0x03
80 
81 #define FXOS8700_FF_MT_CFG_ELE			BIT(7)
82 #define FXOS8700_FF_MT_CFG_OAE			BIT(6)
83 #define FXOS8700_FF_MT_CFG_ZEFE			BIT(5)
84 #define FXOS8700_FF_MT_CFG_YEFE			BIT(4)
85 #define FXOS8700_FF_MT_CFG_XEFE			BIT(3)
86 #define FXOS8700_FF_MT_THS_MASK			0x7f
87 #define FXOS8700_FF_MT_THS_SCALE		(SENSOR_G * 63000LL / 1000000LL)
88 
89 #define FXOS8700_M_CTRLREG1_MODE_MASK		0x03
90 
91 #define FXOS8700_M_CTRLREG2_AUTOINC_MASK	(1 << 5)
92 
93 #define FXOS8700_NUM_ACCEL_CHANNELS		3
94 #define FXOS8700_NUM_MAG_CHANNELS		3
95 #define FXOS8700_NUM_HYBRID_CHANNELS		6
96 #define FXOS8700_MAX_NUM_CHANNELS		6
97 
98 #define FXOS8700_BYTES_PER_CHANNEL_NORMAL	2
99 #define FXOS8700_BYTES_PER_CHANNEL_FAST		1
100 
101 #define FXOS8700_MAX_NUM_BYTES		(FXOS8700_BYTES_PER_CHANNEL_NORMAL * \
102 					 FXOS8700_MAX_NUM_CHANNELS)
103 
104 enum fxos8700_power {
105 	FXOS8700_POWER_STANDBY		= 0,
106 	FXOS8700_POWER_ACTIVE,
107 };
108 
109 enum fxos8700_mode {
110 	FXOS8700_MODE_ACCEL		= 0,
111 	FXOS8700_MODE_MAGN		= 1,
112 	FXOS8700_MODE_HYBRID		= 3,
113 };
114 
115 enum fxos8700_power_mode {
116 	FXOS8700_PM_NORMAL		= 0,
117 	FXOS8700_PM_LOW_NOISE_LOW_POWER,
118 	FXOS8700_PM_HIGH_RESOLUTION,
119 	FXOS8700_PM_LOW_POWER,
120 };
121 
122 enum fxos8700_channel {
123 	FXOS8700_CHANNEL_ACCEL_X	= 0,
124 	FXOS8700_CHANNEL_ACCEL_Y,
125 	FXOS8700_CHANNEL_ACCEL_Z,
126 	FXOS8700_CHANNEL_MAGN_X,
127 	FXOS8700_CHANNEL_MAGN_Y,
128 	FXOS8700_CHANNEL_MAGN_Z,
129 };
130 
131 /* FXOS8700 specific triggers */
132 enum fxos_trigger_type {
133 	FXOS8700_TRIG_M_VECM,
134 };
135 
136 struct fxos8700_io_ops {
137 	int (*read)(const struct device *dev,
138 		    uint8_t reg,
139 		    void *data,
140 		    size_t length);
141 	int (*byte_read)(const struct device *dev,
142 			 uint8_t reg,
143 			 uint8_t *byte);
144 	int (*byte_write)(const struct device *dev,
145 			  uint8_t reg,
146 			  uint8_t byte);
147 	int (*reg_field_update)(const struct device *dev,
148 				uint8_t reg,
149 				uint8_t mask,
150 				uint8_t val);
151 };
152 
153 union fxos8700_bus_cfg {
154 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
155 	struct spi_dt_spec spi;
156 #endif
157 
158 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
159 	struct i2c_dt_spec i2c;
160 #endif
161 };
162 
163 struct fxos8700_config {
164 	const union fxos8700_bus_cfg bus_cfg;
165 	const struct fxos8700_io_ops *ops;
166 #ifdef CONFIG_FXOS8700_TRIGGER
167 	struct gpio_dt_spec int_gpio;
168 #endif
169 	struct gpio_dt_spec reset_gpio;
170 	enum fxos8700_mode mode;
171 	enum fxos8700_power_mode power_mode;
172 	uint8_t range;
173 	uint8_t start_addr;
174 	uint8_t start_channel;
175 	uint8_t num_channels;
176 #ifdef CONFIG_FXOS8700_PULSE
177 	uint8_t pulse_cfg;
178 	uint8_t pulse_ths[3];
179 	uint8_t pulse_tmlt;
180 	uint8_t pulse_ltcy;
181 	uint8_t pulse_wind;
182 #endif
183 #ifdef CONFIG_FXOS8700_MAG_VECM
184 	uint8_t mag_vecm_cfg;
185 	uint8_t mag_vecm_ths[2];
186 #endif
187 	uint8_t inst_on_bus;
188 };
189 
190 struct fxos8700_data {
191 	struct k_sem sem;
192 #ifdef CONFIG_FXOS8700_TRIGGER
193 	const struct device *dev;
194 	struct gpio_callback gpio_cb;
195 	sensor_trigger_handler_t drdy_handler;
196 	const struct sensor_trigger *drdy_trig;
197 #endif
198 #ifdef CONFIG_FXOS8700_PULSE
199 	sensor_trigger_handler_t tap_handler;
200 	const struct sensor_trigger *tap_trig;
201 	sensor_trigger_handler_t double_tap_handler;
202 	const struct sensor_trigger *double_tap_trig;
203 #endif
204 #ifdef CONFIG_FXOS8700_MOTION
205 	sensor_trigger_handler_t motion_handler;
206 	const struct sensor_trigger *motion_trig;
207 #endif
208 #ifdef CONFIG_FXOS8700_MAG_VECM
209 	sensor_trigger_handler_t m_vecm_handler;
210 	const struct sensor_trigger *m_vecm_trig;
211 #endif
212 #ifdef CONFIG_FXOS8700_TRIGGER_OWN_THREAD
213 	K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_FXOS8700_THREAD_STACK_SIZE);
214 	struct k_thread thread;
215 	struct k_sem trig_sem;
216 #endif
217 #ifdef CONFIG_FXOS8700_TRIGGER_GLOBAL_THREAD
218 	struct k_work work;
219 #endif
220 	int16_t raw[FXOS8700_MAX_NUM_CHANNELS];
221 #ifdef CONFIG_FXOS8700_TEMP
222 	int8_t temp;
223 #endif
224 	uint8_t whoami;
225 };
226 
227 int fxos8700_get_power(const struct device *dev, enum fxos8700_power *power);
228 int fxos8700_set_power(const struct device *dev, enum fxos8700_power power);
229 
230 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
231 int fxos8700_byte_write_spi(const struct device *dev,
232 			    uint8_t reg,
233 			    uint8_t byte);
234 
235 int fxos8700_byte_read_spi(const struct device *dev,
236 			   uint8_t reg,
237 			   uint8_t *byte);
238 
239 int fxos8700_reg_field_update_spi(const struct device *dev,
240 				  uint8_t reg,
241 				  uint8_t mask,
242 				  uint8_t val);
243 
244 int fxos8700_read_spi(const struct device *dev,
245 		      uint8_t reg,
246 		      void *data,
247 		      size_t length);
248 #endif
249 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
250 int fxos8700_byte_write_i2c(const struct device *dev,
251 			    uint8_t reg,
252 			    uint8_t byte);
253 
254 int fxos8700_byte_read_i2c(const struct device *dev,
255 			   uint8_t reg,
256 			   uint8_t *byte);
257 
258 int fxos8700_reg_field_update_i2c(const struct device *dev,
259 				  uint8_t reg,
260 				  uint8_t mask,
261 				  uint8_t val);
262 
263 int fxos8700_read_i2c(const struct device *dev,
264 		      uint8_t reg,
265 		      void *data,
266 		      size_t length);
267 #endif
268 #if CONFIG_FXOS8700_TRIGGER
269 int fxos8700_trigger_init(const struct device *dev);
270 int fxos8700_trigger_set(const struct device *dev,
271 			 const struct sensor_trigger *trig,
272 			 sensor_trigger_handler_t handler);
273 #endif
274