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