1 /*
2  * Copyright (c) 2024 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_SENSOR_MMC56X3_MMC56X3_H_
8 #define ZEPHYR_DRIVERS_SENSOR_MMC56X3_MMC56X3_H_
9 
10 #include <zephyr/types.h>
11 #include <zephyr/device.h>
12 #include <zephyr/devicetree.h>
13 #include <zephyr/drivers/i2c.h>
14 #include <zephyr/drivers/sensor.h>
15 #include <zephyr/rtio/rtio.h>
16 #include <zephyr/drivers/sensor/mmc56x3.h>
17 
18 #define DT_DRV_COMPAT memsic_mmc56x3
19 
20 #define MMC56X3_BUS_I2C DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
21 
22 union mmc56x3_bus {
23 	struct i2c_dt_spec i2c;
24 };
25 
26 typedef int (*mmc56x3_bus_check_fn)(const union mmc56x3_bus *bus);
27 typedef int (*mmc56x3_reg_read_fn)(const union mmc56x3_bus *bus, uint8_t start, uint8_t *buf,
28 				   int size);
29 typedef int (*mmc56x3_reg_write_fn)(const union mmc56x3_bus *bus, uint8_t reg, uint8_t val);
30 typedef int (*mmc56x3_raw_read_fn)(const union mmc56x3_bus *bus, uint8_t *buf, size_t size);
31 typedef int (*mmc56x3_raw_write_fn)(const union mmc56x3_bus *bus, uint8_t *buf, size_t size);
32 
33 struct mmc56x3_bus_io {
34 	mmc56x3_bus_check_fn check;
35 	mmc56x3_reg_read_fn read;
36 	mmc56x3_reg_write_fn write;
37 	mmc56x3_raw_read_fn raw_read;
38 	mmc56x3_raw_write_fn raw_write;
39 };
40 
41 extern const struct mmc56x3_bus_io mmc56x3_bus_io_i2c;
42 
43 #define MMC56X3_REG_TEMP            0x09
44 #define MMC56X3_CHIP_ID             0x10
45 #define MMC56X3_REG_STATUS          0x18
46 #define MMC56X3_REG_INTERNAL_ODR    0x1a
47 #define MMC56X3_REG_INTERNAL_CTRL_0 0x1b
48 #define MMC56X3_REG_INTERNAL_CTRL_1 0x1c
49 #define MMC56X3_REG_INTERNAL_CTRL_2 0x1d
50 #define MMC56X3_REG_ID              0x39
51 
52 #define MMC56X3_CMD_RESET              0x10
53 #define MMC56X3_CMD_SET                0x08
54 #define MMC56X3_CMD_SW_RESET           0x80
55 #define MMC56X3_CMD_TAKE_MEAS_M        0x01
56 #define MMC56X3_CMD_TAKE_MEAS_T        0x02
57 #define MMC56X3_CMD_AUTO_SELF_RESET_EN 0x20
58 #define MMC56X3_CMD_CMM_FREQ_EN        0x80
59 #define MMC56X3_CMD_CMM_EN             0x10
60 #define MMC56X3_CMD_HPOWER             0x80
61 
62 #define MMC56X3_STATUS_MEAS_M_DONE 0x80
63 #define MMC56X3_STATUS_MEAS_T_DONE 0x40
64 
65 #define MMC56X3_REG_MAGN_X_OUT_0     0x00
66 /* Range is -30 to 30, sensitivity of raw 20-bit reading is
67  * 16384 = 1 Gauss. To convert raw reading to
68  * Q5.26 with range -32 to 32,
69  * reading * (1/16384) * pow(2, 31)/32
70  * = reading * 4096
71  */
72 #define MMC56X3_MAGN_CONV_Q5_26_20B  4096
73 /* 1/16384 */
74 #define MMC56X3_MAGN_GAUSS_RES       0.000061035
75 /* To convert reading to Q7.24 with range -128, 128,
76  * (BASE + reading * RES) * pow(2, 31)/128
77  * = BASE * pow(2, 31)/128 + reading * RES * pow(2, 31)/128
78  * CONV_BASE = BASE * pow(2, 31)/128
79  * CONV_RES = RES * pow(2, 31)/128
80  * = CONV_BASE + reading * CONV_RES
81  */
82 #define MMC56X3_TEMP_BASE            -75
83 #define MMC56X3_TEMP_RES             0.8
84 #define MMC56X3_TEMP_CONV_Q7_24_BASE -1258291200
85 #define MMC56X3_TEMP_CONV_Q7_24_RES  13421773
86 
87 #define MMC56X3_MAGN_SHIFT 5
88 #define MMC56X3_TEMP_SHIFT 7
89 
90 #ifdef __cplusplus
91 extern "C" {
92 #endif
93 
94 struct mmc56x3_config {
95 	uint16_t magn_odr;
96 	bool bw0;
97 	bool bw1;
98 	bool auto_sr;
99 };
100 
101 struct mmc56x3_data {
102 	struct mmc56x3_config config;
103 
104 	uint8_t ctrl0_cache;
105 	uint8_t ctrl1_cache;
106 	uint8_t ctrl2_cache;
107 
108 	uint32_t temp;
109 	int32_t magn_x;
110 	int32_t magn_y;
111 	int32_t magn_z;
112 };
113 
114 struct mmc56x3_dev_config {
115 	union mmc56x3_bus bus;
116 	const struct mmc56x3_bus_io *bus_io;
117 };
118 
119 struct mmc56x3_decoder_header {
120 	uint64_t timestamp;
121 } __attribute__((__packed__));
122 
123 struct mmc56x3_encoded_data {
124 	struct mmc56x3_decoder_header header;
125 	struct {
126 		/** Set if `temp` has data */
127 		uint8_t has_temp: 1;
128 		/** Set if `magn_x` has data */
129 		uint8_t has_magn_x: 1;
130 		/** Set if `magn_y` has data */
131 		uint8_t has_magn_y: 1;
132 		/** Set if `magn_z` has data */
133 		uint8_t has_magn_z: 1;
134 	} __attribute__((__packed__));
135 	struct mmc56x3_data data;
136 };
137 
138 int mmc56x3_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder);
139 
140 void mmc56x3_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe);
141 
142 int mmc56x3_sample_fetch(const struct device *dev, enum sensor_channel chan);
143 
144 int mmc56x3_sample_fetch_helper(const struct device *dev, enum sensor_channel chan,
145 				struct mmc56x3_data *data);
146 
147 #ifdef __cplusplus
148 }
149 #endif
150 
151 #endif /* ZEPHYR_DRIVERS_SENSOR_MMC56X3_MMC56X3_H_ */
152