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