1 /* ST Microelectronics LIS2DUX12 smart accelerometer APIs
2  *
3  * Copyright (c) 2024 STMicroelectronics
4  * Copyright (c) 2023 PHYTEC Messtechnik GmbH
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include "lis2dux12.h"
10 #include "lis2dux12_api.h"
11 #include <zephyr/logging/log.h>
12 
13 LOG_MODULE_DECLARE(LIS2DUX12, CONFIG_SENSOR_LOG_LEVEL);
14 
st_lis2dux12_set_odr_raw(const struct device * dev,uint8_t odr)15 static int32_t st_lis2dux12_set_odr_raw(const struct device *dev, uint8_t odr)
16 {
17 	struct lis2dux12_data *data = dev->data;
18 	const struct lis2dux12_config *cfg = dev->config;
19 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
20 	lis2dux12_md_t mode = {.odr = odr, .fs = data->range};
21 
22 	data->odr = odr;
23 	return lis2dux12_mode_set(ctx, &mode);
24 }
25 
st_lis2dux12_set_range(const struct device * dev,uint8_t range)26 static int32_t st_lis2dux12_set_range(const struct device *dev, uint8_t range)
27 {
28 	int err;
29 	struct lis2dux12_data *data = dev->data;
30 	const struct lis2dux12_config *cfg = dev->config;
31 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
32 	lis2dux12_md_t val = { .odr = data->odr, .fs = range };
33 
34 	err = lis2dux12_mode_set(ctx, &val);
35 	if (err) {
36 		return err;
37 	}
38 
39 	switch (range) {
40 	case LIS2DUX12_DT_FS_2G:
41 		data->gain = lis2dux12_from_fs2g_to_mg(1);
42 		break;
43 	case LIS2DUX12_DT_FS_4G:
44 		data->gain = lis2dux12_from_fs4g_to_mg(1);
45 		break;
46 	case LIS2DUX12_DT_FS_8G:
47 		data->gain = lis2dux12_from_fs8g_to_mg(1);
48 		break;
49 	case LIS2DUX12_DT_FS_16G:
50 		data->gain = lis2dux12_from_fs16g_to_mg(1);
51 		break;
52 	default:
53 		LOG_ERR("range %d not supported.", range);
54 		return -EINVAL;
55 	}
56 
57 	data->range = range;
58 	return 0;
59 }
60 
st_lis2dux12_sample_fetch_accel(const struct device * dev)61 static int32_t st_lis2dux12_sample_fetch_accel(const struct device *dev)
62 {
63 	struct lis2dux12_data *data = dev->data;
64 	const struct lis2dux12_config *cfg = dev->config;
65 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
66 
67 	/* fetch raw data sample */
68 	lis2dux12_md_t mode = {.fs = data->range};
69 	lis2dux12_xl_data_t xzy_data = {0};
70 
71 	if (lis2dux12_xl_data_get(ctx, &mode, &xzy_data) < 0) {
72 		LOG_ERR("Failed to fetch raw data sample");
73 		return -EIO;
74 	}
75 
76 	data->sample_x = xzy_data.raw[0];
77 	data->sample_y = xzy_data.raw[1];
78 	data->sample_z = xzy_data.raw[2];
79 
80 	return 0;
81 }
82 
83 #ifdef CONFIG_LIS2DUX12_ENABLE_TEMP
st_lis2dux12_sample_fetch_temp(const struct device * dev)84 static int32_t st_lis2dux12_sample_fetch_temp(const struct device *dev)
85 {
86 	struct lis2dux12_data *data = dev->data;
87 	const struct lis2dux12_config *cfg = dev->config;
88 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
89 
90 	/* fetch raw data sample */
91 	lis2dux12_outt_data_t temp_data = {0};
92 
93 	if (lis2dux12_outt_data_get(ctx, &temp_data) < 0) {
94 		LOG_ERR("Failed to fetch raw temperature data sample");
95 		return -EIO;
96 	}
97 
98 	data->sample_temp = temp_data.heat.deg_c;
99 
100 	return 0;
101 }
102 #endif
103 
104 #ifdef CONFIG_LIS2DUX12_TRIGGER
st_lis2dux12_handle_interrupt(const struct device * dev)105 static void st_lis2dux12_handle_interrupt(const struct device *dev)
106 {
107 	struct lis2dux12_data *lis2dux12 = dev->data;
108 	const struct lis2dux12_config *cfg = dev->config;
109 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
110 	lis2dux12_all_sources_t sources;
111 	int ret;
112 
113 	lis2dux12_all_sources_get(ctx, &sources);
114 
115 	if (sources.drdy == 0) {
116 		goto exit; /* spurious interrupt */
117 	}
118 
119 	if (lis2dux12->data_ready_handler != NULL) {
120 		lis2dux12->data_ready_handler(dev, lis2dux12->data_ready_trigger);
121 	}
122 
123 exit:
124 	ret = gpio_pin_interrupt_configure_dt(lis2dux12->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE);
125 	if (ret < 0) {
126 		LOG_ERR("%s: Not able to configure pin_int", dev->name);
127 	}
128 }
129 
st_lis2dux12_init_interrupt(const struct device * dev)130 static int32_t st_lis2dux12_init_interrupt(const struct device *dev)
131 {
132 	const struct lis2dux12_config *cfg = dev->config;
133 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
134 	lis2dux12_pin_int_route_t route;
135 	int err;
136 
137 	/* Enable pulsed mode */
138 	err = lis2dux12_data_ready_mode_set(ctx, LIS2DUX12_DRDY_PULSED);
139 	if (err < 0) {
140 		return err;
141 	}
142 
143 	/* route data-ready interrupt on int1 */
144 	err = lis2dux12_pin_int1_route_get(ctx, &route);
145 	if (err < 0) {
146 		return err;
147 	}
148 
149 	route.drdy = 1;
150 
151 	err = lis2dux12_pin_int1_route_set(ctx, &route);
152 	if (err < 0) {
153 		return err;
154 	}
155 
156 	return 0;
157 }
158 #endif
159 
160 const struct lis2dux12_chip_api st_lis2dux12_chip_api = {
161 	.set_odr_raw = st_lis2dux12_set_odr_raw,
162 	.set_range = st_lis2dux12_set_range,
163 	.sample_fetch_accel = st_lis2dux12_sample_fetch_accel,
164 #ifdef CONFIG_LIS2DUX12_ENABLE_TEMP
165 	.sample_fetch_temp = st_lis2dux12_sample_fetch_temp,
166 #endif
167 #ifdef CONFIG_LIS2DUX12_TRIGGER
168 	.handle_interrupt = st_lis2dux12_handle_interrupt,
169 	.init_interrupt = st_lis2dux12_init_interrupt,
170 #endif
171 };
172 
st_lis2dux12_init(const struct device * dev)173 int st_lis2dux12_init(const struct device *dev)
174 {
175 	const struct lis2dux12_config *const cfg = dev->config;
176 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
177 	uint8_t chip_id;
178 	int ret;
179 
180 	lis2dux12_exit_deep_power_down(ctx);
181 	k_busy_wait(25000);
182 
183 	/* check chip ID */
184 	ret = lis2dux12_device_id_get(ctx, &chip_id);
185 	if (ret < 0) {
186 		LOG_ERR("%s: Not able to read dev id", dev->name);
187 		return ret;
188 	}
189 
190 	if (chip_id != LIS2DUX12_ID) {
191 		LOG_ERR("%s: Invalid chip ID 0x%02x", dev->name, chip_id);
192 		return -EINVAL;
193 	}
194 
195 	/* reset device */
196 	ret = lis2dux12_init_set(ctx, LIS2DUX12_RESET);
197 	if (ret < 0) {
198 		return ret;
199 	}
200 
201 	k_busy_wait(100);
202 
203 	LOG_INF("%s: chip id 0x%x", dev->name, chip_id);
204 
205 	/* Set bdu and if_inc recommended for driver usage */
206 	lis2dux12_init_set(ctx, LIS2DUX12_SENSOR_ONLY_ON);
207 
208 	lis2dux12_timestamp_set(ctx, PROPERTY_ENABLE);
209 
210 #ifdef CONFIG_LIS2DUX12_TRIGGER
211 	if (cfg->trig_enabled) {
212 		ret = lis2dux12_trigger_init(dev);
213 		if (ret < 0) {
214 			LOG_ERR("%s: Failed to initialize triggers", dev->name);
215 			return ret;
216 		}
217 	}
218 #endif
219 
220 	/* set sensor default pm and odr */
221 	LOG_DBG("%s: pm: %d, odr: %d", dev->name, cfg->pm, cfg->odr);
222 	ret = st_lis2dux12_set_odr_raw(dev, cfg->odr);
223 	if (ret < 0) {
224 		LOG_ERR("%s: odr init error (12.5 Hz)", dev->name);
225 		return ret;
226 	}
227 
228 	/* set sensor default scale (used to convert sample values) */
229 	LOG_DBG("%s: range is %d", dev->name, cfg->range);
230 	ret = st_lis2dux12_set_range(dev, cfg->range);
231 	if (ret < 0) {
232 		LOG_ERR("%s: range init error %d", dev->name, cfg->range);
233 		return ret;
234 	}
235 
236 	return 0;
237 }
238