1 /*
2  * Copyright 2024 NXP
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 FXLS8974_BUS_I2C				(1<<0)
19 #define FXLS8974_BUS_SPI				(1<<1)
20 #define FXLS8974_REG_OUTXLSB				0x04
21 #define FXLS8974_REG_OUTTEMP				0x01
22 #define FXLS8974_REG_WHOAMI				0x13
23 #define FXLS8974_REG_CTRLREG1				0x15
24 #define FXLS8974_REG_CTRLREG2				0x16
25 #define FXLS8974_REG_CTRLREG3				0x17
26 #define FXLS8974_REG_CTRLREG4				0x18
27 #define FXLS8974_REG_CTRLREG5				0x19
28 
29 #define WHOAMI_ID_FXLS8964				0x84
30 #define WHOAMI_ID_FXLS8974				0x86
31 
32 #define FXLS8974_CTRLREG1_ACTIVE_MASK			0x01
33 #define FXLS8974_CTRLREG1_RST_MASK			0x80
34 #define FXLS8974_CTRLREG1_FSR_MASK			0x06
35 #define FXLS8974_CTRLREG1_FSR_2G			0x00
36 #define FXLS8974_CTRLREG1_FSR_4G			0x02
37 #define FXLS8974_CTRLREG1_FSR_8G			0x04
38 #define FXLS8974_CTRLREG1_FSR_16G			0x06
39 
40 #define FXLS8974_CTRLREG2_WAKE_PM_MASK			0xC0
41 #define FXLS8974_CTRLREG2_SLEEP_PM_MASK			0x30
42 
43 #define FXLS8974_CTRLREG3_WAKE_ODR_MASK			0xF0
44 #define FXLS8974_CTRLREG3_SLEEP_ODR_MASK		0x0F
45 
46 #define FXLS8974_CTRLREG3_ODR_RATE_3200			0x00
47 #define FXLS8974_CTRLREG3_ODR_RATE_1600			0x01
48 #define FXLS8974_CTRLREG3_ODR_RATE_800			0x02
49 #define FXLS8974_CTRLREG3_ODR_RATE_400			0x03
50 #define FXLS8974_CTRLREG3_ODR_RATE_200			0x04
51 #define FXLS8974_CTRLREG3_ODR_RATE_100			0x05
52 #define FXLS8974_CTRLREG3_ODR_RATE_50			0x06
53 #define FXLS8974_CTRLREG3_ODR_RATE_25			0x07
54 #define FXLS8974_CTRLREG3_ODR_RATE_12_5			0x08
55 #define FXLS8974_CTRLREG3_ODR_RATE_6_25			0x09
56 #define FXLS8974_CTRLREG3_ODR_RATE_3_125		0x0A
57 #define FXLS8974_CTRLREG3_ODR_RATE_1_563		0x0B
58 #define FXLS8974_CTRLREG3_ODR_RATE_0_781		0x0C
59 
60 #define FXLS8974_CTRLREG4_INT_POL_HIGH			0x01
61 
62 #define FXLS8974_INTREG_EN				0x20
63 #define FXLS8974_INT_PIN_SEL_REG			0x21
64 
65 #define FXLS8974_DATA_ACCEL_X_OFFSET			0
66 #define FXLS8974_DATA_ACCEL_Y_OFFSET			FXLS8974_BYTES_PER_CHANNEL_NORMAL
67 #define FXLS8974_DATA_ACCEL_Z_OFFSET			2*FXLS8974_BYTES_PER_CHANNEL_NORMAL
68 #define FXLS8974_DATA_TEMP_OFFSET			3*FXLS8974_BYTES_PER_CHANNEL_NORMAL
69 #define FXLS8974_ZERO_TEMP				25
70 
71 #define FXLS8974_MAX_NUM_CHANNELS			4
72 #define FXLS8974_MAX_ACCEL_CHANNELS			3
73 #define FXLS8974_MAX_TEMP_CHANNELS			1
74 
75 #define FXLS8974_BYTES_PER_CHANNEL_NORMAL		2
76 #define FXLS8974_BYTES_PER_CHANNEL_FAST			1
77 
78 #define FXLS8974_MAX_ACCEL_BYTES			(FXLS8974_MAX_ACCEL_CHANNELS*2)
79 #define FXLS8974_MAX_NUM_BYTES		(FXLS8974_MAX_ACCEL_BYTES + FXLS8974_MAX_TEMP_CHANNELS)
80 
81 #define FXLS8974_DRDY_MASK				0x80
82 
83 enum fxls8974_active {
84 	FXLS8974_ACTIVE_OFF		= 0,
85 	FXLS8974_ACTIVE_ON,
86 };
87 
88 enum fxls8974_wake {
89 	FXLS8974_WAKE			= 0,
90 	FXLS8974_SLEEP,
91 };
92 
93 enum fxls8974_channel {
94 	FXLS8974_CHANNEL_ACCEL_X	= 0,
95 	FXLS8974_CHANNEL_ACCEL_Y,
96 	FXLS8974_CHANNEL_ACCEL_Z,
97 	FXLS8974_CHANNEL_TEMP,
98 };
99 
100 struct fxls8974_io_ops {
101 	int (*read)(const struct device *dev,
102 			uint8_t reg,
103 			void *data,
104 			size_t length);
105 	int (*byte_read)(const struct device *dev,
106 			uint8_t reg,
107 			uint8_t *byte);
108 	int (*byte_write)(const struct device *dev,
109 			uint8_t reg,
110 			uint8_t byte);
111 	int (*reg_field_update)(const struct device *dev,
112 			uint8_t reg,
113 			uint8_t mask,
114 			uint8_t val);
115 };
116 
117 union fxls8974_bus_cfg {
118 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
119 	struct spi_dt_spec spi;
120 #endif
121 
122 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
123 	struct i2c_dt_spec i2c;
124 #endif
125 };
126 
127 struct fxls8974_config {
128 	const union fxls8974_bus_cfg bus_cfg;
129 	const struct fxls8974_io_ops *ops;
130 	struct gpio_dt_spec reset_gpio;
131 	uint8_t range;
132 	uint8_t inst_on_bus;
133 #ifdef CONFIG_FXLS8974_TRIGGER
134 	struct gpio_dt_spec int_gpio;
135 #endif
136 
137 };
138 
139 struct fxls8974_data {
140 	struct k_sem sem;
141 	int16_t raw[FXLS8974_MAX_NUM_CHANNELS];
142 	uint8_t whoami;
143 #ifdef CONFIG_FXLS8974_TRIGGER
144 	const struct device *dev;
145 	struct gpio_callback gpio_cb;
146 	sensor_trigger_handler_t drdy_handler;
147 	const struct sensor_trigger *drdy_trig;
148 #endif
149 #ifdef CONFIG_FXLS8974_TRIGGER_OWN_THREAD
150 	K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_FXLS8974_THREAD_STACK_SIZE);
151 	struct k_thread thread;
152 	struct k_sem trig_sem;
153 #endif
154 #ifdef CONFIG_FXLS8974_TRIGGER_GLOBAL_THREAD
155 	struct k_work work;
156 #endif
157 };
158 
159 int fxls8974_get_active(const struct device *dev, uint8_t *active);
160 int fxls8974_set_active(const struct device *dev, uint8_t active);
161 
162 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
163 int fxls8974_byte_write_spi(const struct device *dev,
164 		uint8_t reg,
165 		uint8_t byte);
166 
167 int fxls8974_byte_read_spi(const struct device *dev,
168 		uint8_t reg,
169 		uint8_t *byte);
170 
171 int fxls8974_reg_field_update_spi(const struct device *dev,
172 		uint8_t reg,
173 		uint8_t mask,
174 		uint8_t val);
175 
176 int fxls8974_read_spi(const struct device *dev,
177 		uint8_t reg,
178 		void *data,
179 		size_t length);
180 #endif
181 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
182 int fxls8974_byte_write_i2c(const struct device *dev,
183 		uint8_t reg,
184 		uint8_t byte);
185 
186 int fxls8974_byte_read_i2c(const struct device *dev,
187 		uint8_t reg,
188 		uint8_t *byte);
189 
190 int fxls8974_reg_field_update_i2c(const struct device *dev,
191 		uint8_t reg,
192 		uint8_t mask,
193 		uint8_t val);
194 
195 int fxls8974_read_i2c(const struct device *dev,
196 		uint8_t reg,
197 		void *data,
198 		size_t length);
199 #endif
200 #if CONFIG_FXLS8974_TRIGGER
201 int fxls8974_trigger_init(const struct device *dev);
202 int fxls8974_trigger_set(const struct device *dev,
203 		const struct sensor_trigger *trig,
204 		sensor_trigger_handler_t handler);
205 #endif
206