1 /*
2  * Copyright (c) 2017, NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT maxim_max30101
8 
9 #include <zephyr/logging/log.h>
10 
11 #include "max30101.h"
12 
13 LOG_MODULE_REGISTER(MAX30101, CONFIG_SENSOR_LOG_LEVEL);
14 
max30101_sample_fetch(const struct device * dev,enum sensor_channel chan)15 static int max30101_sample_fetch(const struct device *dev,
16 				 enum sensor_channel chan)
17 {
18 	struct max30101_data *data = dev->data;
19 	const struct max30101_config *config = dev->config;
20 	uint8_t buffer[MAX30101_MAX_BYTES_PER_SAMPLE];
21 	uint32_t fifo_data;
22 	int fifo_chan;
23 	int num_bytes;
24 	int i;
25 
26 	/* Read all the active channels for one sample */
27 	num_bytes = data->num_channels * MAX30101_BYTES_PER_CHANNEL;
28 	if (i2c_burst_read_dt(&config->i2c, MAX30101_REG_FIFO_DATA, buffer,
29 			      num_bytes)) {
30 		LOG_ERR("Could not fetch sample");
31 		return -EIO;
32 	}
33 
34 	fifo_chan = 0;
35 	for (i = 0; i < num_bytes; i += 3) {
36 		/* Each channel is 18-bits */
37 		fifo_data = (buffer[i] << 16) | (buffer[i + 1] << 8) |
38 			    (buffer[i + 2]);
39 		fifo_data &= MAX30101_FIFO_DATA_MASK;
40 
41 		/* Save the raw data */
42 		data->raw[fifo_chan++] = fifo_data;
43 	}
44 
45 	return 0;
46 }
47 
max30101_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)48 static int max30101_channel_get(const struct device *dev,
49 				enum sensor_channel chan,
50 				struct sensor_value *val)
51 {
52 	struct max30101_data *data = dev->data;
53 	enum max30101_led_channel led_chan;
54 	int fifo_chan;
55 
56 	switch (chan) {
57 	case SENSOR_CHAN_RED:
58 		led_chan = MAX30101_LED_CHANNEL_RED;
59 		break;
60 
61 	case SENSOR_CHAN_IR:
62 		led_chan = MAX30101_LED_CHANNEL_IR;
63 		break;
64 
65 	case SENSOR_CHAN_GREEN:
66 		led_chan = MAX30101_LED_CHANNEL_GREEN;
67 		break;
68 
69 	default:
70 		LOG_ERR("Unsupported sensor channel");
71 		return -ENOTSUP;
72 	}
73 
74 	/* Check if the led channel is active by looking up the associated fifo
75 	 * channel. If the fifo channel isn't valid, then the led channel
76 	 * isn't active.
77 	 */
78 	fifo_chan = data->map[led_chan];
79 	if (fifo_chan >= MAX30101_MAX_NUM_CHANNELS) {
80 		LOG_ERR("Inactive sensor channel");
81 		return -ENOTSUP;
82 	}
83 
84 	/* TODO: Scale the raw data to standard units */
85 	val->val1 = data->raw[fifo_chan];
86 	val->val2 = 0;
87 
88 	return 0;
89 }
90 
91 static const struct sensor_driver_api max30101_driver_api = {
92 	.sample_fetch = max30101_sample_fetch,
93 	.channel_get = max30101_channel_get,
94 };
95 
max30101_init(const struct device * dev)96 static int max30101_init(const struct device *dev)
97 {
98 	const struct max30101_config *config = dev->config;
99 	struct max30101_data *data = dev->data;
100 	uint8_t part_id;
101 	uint8_t mode_cfg;
102 	uint32_t led_chan;
103 	int fifo_chan;
104 
105 	if (!device_is_ready(config->i2c.bus)) {
106 		LOG_ERR("Bus device is not ready");
107 		return -ENODEV;
108 	}
109 
110 	/* Check the part id to make sure this is MAX30101 */
111 	if (i2c_reg_read_byte_dt(&config->i2c, MAX30101_REG_PART_ID,
112 				 &part_id)) {
113 		LOG_ERR("Could not get Part ID");
114 		return -EIO;
115 	}
116 	if (part_id != MAX30101_PART_ID) {
117 		LOG_ERR("Got Part ID 0x%02x, expected 0x%02x",
118 			    part_id, MAX30101_PART_ID);
119 		return -EIO;
120 	}
121 
122 	/* Reset the sensor */
123 	if (i2c_reg_write_byte_dt(&config->i2c, MAX30101_REG_MODE_CFG,
124 				  MAX30101_MODE_CFG_RESET_MASK)) {
125 		return -EIO;
126 	}
127 
128 	/* Wait for reset to be cleared */
129 	do {
130 		if (i2c_reg_read_byte_dt(&config->i2c, MAX30101_REG_MODE_CFG,
131 					 &mode_cfg)) {
132 			LOG_ERR("Could read mode cfg after reset");
133 			return -EIO;
134 		}
135 	} while (mode_cfg & MAX30101_MODE_CFG_RESET_MASK);
136 
137 	/* Write the FIFO configuration register */
138 	if (i2c_reg_write_byte_dt(&config->i2c, MAX30101_REG_FIFO_CFG,
139 				  config->fifo)) {
140 		return -EIO;
141 	}
142 
143 	/* Write the mode configuration register */
144 	if (i2c_reg_write_byte_dt(&config->i2c, MAX30101_REG_MODE_CFG,
145 				  config->mode)) {
146 		return -EIO;
147 	}
148 
149 	/* Write the SpO2 configuration register */
150 	if (i2c_reg_write_byte_dt(&config->i2c, MAX30101_REG_SPO2_CFG,
151 				  config->spo2)) {
152 		return -EIO;
153 	}
154 
155 	/* Write the LED pulse amplitude registers */
156 	if (i2c_reg_write_byte_dt(&config->i2c, MAX30101_REG_LED1_PA,
157 				  config->led_pa[0])) {
158 		return -EIO;
159 	}
160 	if (i2c_reg_write_byte_dt(&config->i2c, MAX30101_REG_LED2_PA,
161 				  config->led_pa[1])) {
162 		return -EIO;
163 	}
164 	if (i2c_reg_write_byte_dt(&config->i2c, MAX30101_REG_LED3_PA,
165 				  config->led_pa[2])) {
166 		return -EIO;
167 	}
168 
169 #ifdef CONFIG_MAX30101_MULTI_LED_MODE
170 	uint8_t multi_led[2];
171 
172 	/* Write the multi-LED mode control registers */
173 	multi_led[0] = (config->slot[1] << 4) | (config->slot[0]);
174 	multi_led[1] = (config->slot[3] << 4) | (config->slot[2]);
175 
176 	if (i2c_reg_write_byte_dt(&config->i2c, MAX30101_REG_MULTI_LED,
177 				  multi_led[0])) {
178 		return -EIO;
179 	}
180 	if (i2c_reg_write_byte_dt(&config->i2c, MAX30101_REG_MULTI_LED + 1,
181 				  multi_led[1])) {
182 		return -EIO;
183 	}
184 #endif
185 
186 	/* Initialize the channel map and active channel count */
187 	data->num_channels = 0U;
188 	for (led_chan = 0U; led_chan < MAX30101_MAX_NUM_CHANNELS; led_chan++) {
189 		data->map[led_chan] = MAX30101_MAX_NUM_CHANNELS;
190 	}
191 
192 	/* Count the number of active channels and build a map that translates
193 	 * the LED channel number (red/ir/green) to the fifo channel number.
194 	 */
195 	for (fifo_chan = 0; fifo_chan < MAX30101_MAX_NUM_CHANNELS;
196 	     fifo_chan++) {
197 		led_chan = (config->slot[fifo_chan] & MAX30101_SLOT_LED_MASK)-1;
198 		if (led_chan < MAX30101_MAX_NUM_CHANNELS) {
199 			data->map[led_chan] = fifo_chan;
200 			data->num_channels++;
201 		}
202 	}
203 
204 	return 0;
205 }
206 
207 static struct max30101_config max30101_config = {
208 	.i2c = I2C_DT_SPEC_INST_GET(0),
209 	.fifo = (CONFIG_MAX30101_SMP_AVE << MAX30101_FIFO_CFG_SMP_AVE_SHIFT) |
210 #ifdef CONFIG_MAX30101_FIFO_ROLLOVER_EN
211 		MAX30101_FIFO_CFG_ROLLOVER_EN_MASK |
212 #endif
213 		(CONFIG_MAX30101_FIFO_A_FULL <<
214 		 MAX30101_FIFO_CFG_FIFO_FULL_SHIFT),
215 
216 #if defined(CONFIG_MAX30101_HEART_RATE_MODE)
217 	.mode = MAX30101_MODE_HEART_RATE,
218 	.slot[0] = MAX30101_SLOT_RED_LED1_PA,
219 	.slot[1] = MAX30101_SLOT_DISABLED,
220 	.slot[2] = MAX30101_SLOT_DISABLED,
221 	.slot[3] = MAX30101_SLOT_DISABLED,
222 #elif defined(CONFIG_MAX30101_SPO2_MODE)
223 	.mode = MAX30101_MODE_SPO2,
224 	.slot[0] = MAX30101_SLOT_RED_LED1_PA,
225 	.slot[1] = MAX30101_SLOT_IR_LED2_PA,
226 	.slot[2] = MAX30101_SLOT_DISABLED,
227 	.slot[3] = MAX30101_SLOT_DISABLED,
228 #else
229 	.mode = MAX30101_MODE_MULTI_LED,
230 	.slot[0] = CONFIG_MAX30101_SLOT1,
231 	.slot[1] = CONFIG_MAX30101_SLOT2,
232 	.slot[2] = CONFIG_MAX30101_SLOT3,
233 	.slot[3] = CONFIG_MAX30101_SLOT4,
234 #endif
235 
236 	.spo2 = (CONFIG_MAX30101_ADC_RGE << MAX30101_SPO2_ADC_RGE_SHIFT) |
237 		(CONFIG_MAX30101_SR << MAX30101_SPO2_SR_SHIFT) |
238 		(MAX30101_PW_18BITS << MAX30101_SPO2_PW_SHIFT),
239 
240 	.led_pa[0] = CONFIG_MAX30101_LED1_PA,
241 	.led_pa[1] = CONFIG_MAX30101_LED2_PA,
242 	.led_pa[2] = CONFIG_MAX30101_LED3_PA,
243 };
244 
245 static struct max30101_data max30101_data;
246 
247 SENSOR_DEVICE_DT_INST_DEFINE(0, max30101_init, NULL,
248 		    &max30101_data, &max30101_config,
249 		    POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
250 		    &max30101_driver_api);
251