1 /* ST Microelectronics ILPS22QS pressure and temperature sensor
2  *
3  * Copyright (c) 2023-2024 STMicroelectronics
4  * Copyright (c) 2023 PHYTEC Messtechnik GmbH
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include "lps2xdf.h"
10 #include "ilps22qs.h"
11 #include <zephyr/logging/log.h>
12 
13 LOG_MODULE_DECLARE(LPS2XDF, CONFIG_SENSOR_LOG_LEVEL);
14 
ilps22qs_mode_set_odr_raw(const struct device * dev,uint8_t odr)15 static inline int ilps22qs_mode_set_odr_raw(const struct device *dev, uint8_t odr)
16 {
17 	const struct lps2xdf_config *const cfg = dev->config;
18 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
19 	ilps22qs_md_t md = { 0 };
20 
21 	md.odr = odr;
22 	md.avg = cfg->avg;
23 	md.lpf = cfg->lpf;
24 	md.fs = cfg->fs;
25 
26 	return ilps22qs_mode_set(ctx, &md);
27 }
28 
ilps22qs_sample_fetch(const struct device * dev,enum sensor_channel chan)29 static int ilps22qs_sample_fetch(const struct device *dev, enum sensor_channel chan)
30 {
31 	struct lps2xdf_data *data = dev->data;
32 	const struct lps2xdf_config *const cfg = dev->config;
33 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
34 	ilps22qs_data_t raw_data;
35 	ilps22qs_md_t md = { 0 };
36 
37 	md.fs = cfg->fs;
38 
39 	if (ilps22qs_data_get(ctx, &md, &raw_data) < 0) {
40 		LOG_DBG("Failed to read sample");
41 		return -EIO;
42 	}
43 
44 	data->sample_press = raw_data.pressure.raw;
45 	data->sample_temp = raw_data.heat.raw;
46 
47 	return 0;
48 }
49 
50 #ifdef CONFIG_LPS2XDF_TRIGGER
51 /**
52  * ilps22qs_config_interrupt - not supported
53  */
ilps22qs_config_interrupt(const struct device * dev)54 static int ilps22qs_config_interrupt(const struct device *dev)
55 {
56 	return -ENOTSUP;
57 }
58 
59 /**
60  * ilps22qs_handle_interrupt - not supported
61  */
ilps22qs_handle_interrupt(const struct device * dev)62 static void ilps22qs_handle_interrupt(const struct device *dev)
63 {
64 }
65 
66 /**
67  * ilps22qs_trigger_set - not supported
68  */
ilps22qs_trigger_set(const struct device * dev,const struct sensor_trigger * trig,sensor_trigger_handler_t handler)69 static int ilps22qs_trigger_set(const struct device *dev,
70 				const struct sensor_trigger *trig,
71 				sensor_trigger_handler_t handler)
72 {
73 	return -ENOTSUP;
74 }
75 #endif /* CONFIG_LPS2XDF_TRIGGER */
76 
77 const struct lps2xdf_chip_api st_ilps22qs_chip_api = {
78 	.mode_set_odr_raw = ilps22qs_mode_set_odr_raw,
79 	.sample_fetch = ilps22qs_sample_fetch,
80 #if CONFIG_LPS2XDF_TRIGGER
81 	.config_interrupt = ilps22qs_config_interrupt,
82 	.handle_interrupt = ilps22qs_handle_interrupt,
83 	.trigger_set = ilps22qs_trigger_set,
84 #endif
85 };
86 
st_ilps22qs_init(const struct device * dev)87 int st_ilps22qs_init(const struct device *dev)
88 {
89 	const struct lps2xdf_config *const cfg = dev->config;
90 	stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
91 	ilps22qs_id_t id;
92 	ilps22qs_stat_t status;
93 	uint8_t tries = 10;
94 	int ret;
95 
96 #if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_ilps22qs, i3c)
97 	if (cfg->i3c.bus != NULL) {
98 		struct lps2xdf_data *data = dev->data;
99 		/*
100 		 * Need to grab the pointer to the I3C device descriptor
101 		 * before we can talk to the sensor.
102 		 */
103 		data->i3c_dev = i3c_device_find(cfg->i3c.bus, &cfg->i3c.dev_id);
104 		if (data->i3c_dev == NULL) {
105 			LOG_ERR("Cannot find I3C device descriptor");
106 			return -ENODEV;
107 		}
108 	}
109 #endif
110 
111 	if (ilps22qs_id_get(ctx, &id) < 0) {
112 		LOG_ERR("%s: Not able to read dev id", dev->name);
113 		return -EIO;
114 	}
115 
116 	if (id.whoami != ILPS22QS_ID) {
117 		LOG_ERR("%s: Invalid chip ID 0x%02x", dev->name, id.whoami);
118 		return -EIO;
119 	}
120 
121 	LOG_DBG("%s: chip id 0x%x", dev->name, id.whoami);
122 
123 	/* Restore default configuration */
124 	if (ilps22qs_init_set(ctx, ILPS22QS_RESET) < 0) {
125 		LOG_ERR("%s: Not able to reset device", dev->name);
126 		return -EIO;
127 	}
128 
129 	do {
130 		if (!--tries) {
131 			LOG_DBG("sw reset timed out");
132 			return -ETIMEDOUT;
133 		}
134 		k_usleep(LPS2XDF_SWRESET_WAIT_TIME_US);
135 
136 		if (ilps22qs_status_get(ctx, &status) < 0) {
137 			return -EIO;
138 		}
139 	} while (status.sw_reset);
140 
141 	/* Set bdu and if_inc recommended for driver usage */
142 	if (ilps22qs_init_set(ctx, ILPS22QS_DRV_RDY) < 0) {
143 		LOG_ERR("%s: Not able to set device to ready state", dev->name);
144 		return -EIO;
145 	}
146 
147 	if (ON_I3C_BUS(cfg)) {
148 		ilps22qs_bus_mode_t bus_mode;
149 
150 		/* Select bus interface */
151 		ilps22qs_bus_mode_get(ctx, &bus_mode);
152 		bus_mode.filter = ILPS22QS_FILTER_AUTO;
153 		bus_mode.interface = ILPS22QS_SEL_BY_HW;
154 		ilps22qs_bus_mode_set(ctx, &bus_mode);
155 	}
156 
157 	/* set sensor default odr */
158 	LOG_DBG("%s: odr: %d", dev->name, cfg->odr);
159 	ret = ilps22qs_mode_set_odr_raw(dev, cfg->odr);
160 	if (ret < 0) {
161 		LOG_ERR("%s: Failed to set odr %d", dev->name, cfg->odr);
162 		return ret;
163 	}
164 
165 #ifdef CONFIG_LPS2XDF_TRIGGER
166 	if (cfg->trig_enabled) {
167 		if (lps2xdf_init_interrupt(dev, DEVICE_VARIANT_ILPS22QS) < 0) {
168 			LOG_ERR("Failed to initialize interrupt.");
169 			return -EIO;
170 		}
171 	}
172 #endif
173 
174 	return 0;
175 }
176