1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_SENSOR_LIS3MDL_LIS3MDL_H_
8 #define ZEPHYR_DRIVERS_SENSOR_LIS3MDL_LIS3MDL_H_
9 
10 #include <zephyr/device.h>
11 #include <zephyr/sys/util.h>
12 #include <zephyr/types.h>
13 #include <zephyr/drivers/i2c.h>
14 #include <zephyr/drivers/gpio.h>
15 #include <zephyr/kernel.h>
16 
17 #define LIS3MDL_REG_WHO_AM_I            0x0F
18 #define LIS3MDL_CHIP_ID                 0x3D
19 
20 #define LIS3MDL_REG_CTRL1               0x20
21 #define LIS3MDL_TEMP_EN_MASK            BIT(7)
22 #define LIS3MDL_TEMP_EN_SHIFT           7
23 #define LIS3MDL_OM_MASK                 (BIT(6) | BIT(5))
24 #define LIS3MDL_OM_SHIFT                5
25 #define LIS3MDL_MAG_DO_MASK             (BIT(4) | BIT(3) | BIT(2))
26 #define LIS3MDL_DO_SHIFT                2
27 #define LIS3MDL_FAST_ODR_MASK           BIT(1)
28 #define LIS3MDL_FAST_ODR_SHIFT          1
29 #define LIS3MDL_ST_MASK                 BIT(0)
30 #define LIS3MDL_ST_SHIFT                0
31 
32 #define LIS3MDL_ODR_BITS(om_bits, do_bits, fast_odr)	\
33 	(((om_bits) << LIS3MDL_OM_SHIFT) |		\
34 	 ((do_bits) << LIS3MDL_DO_SHIFT) |		\
35 	 ((fast_odr) << LIS3MDL_FAST_ODR_SHIFT))
36 
37 #define LIS3MDL_REG_CTRL2               0x21
38 #define LIS3MDL_FS_MASK                 (BIT(6) | BIT(5))
39 #define LIS3MDL_FS_SHIFT                5
40 #define LIS3MDL_REBOOT_MASK             BIT(3)
41 #define LIS3MDL_REBOOT_SHIFT            3
42 #define LIS3MDL_SOFT_RST_MASK           BIT(2)
43 #define LIS3MDL_SOFT_RST_SHIFT          2
44 
45 #define LIS3MDL_FS_IDX                  ((CONFIG_LIS3MDL_FS / 4) - 1)
46 
47 /* guard against invalid CONFIG_LIS3MDL_FS values */
48 #if CONFIG_LIS3MDL_FS % 4 != 0 || LIS3MDL_FS_IDX < -1 || LIS3MDL_FS_IDX >= 4
49 #error "Invalid value for CONFIG_LIS3MDL_FS"
50 #endif
51 
52 #define LIS3MDL_REG_CTRL3               0x22
53 #define LIS3MDL_LP_MASK                 BIT(5)
54 #define LIS3MDL_LP_SHIFT                5
55 #define LIS3MDL_SIM_MASK                BIT(2)
56 #define LIS3MDL_SIM_SHIFT               2
57 #define LIS3MDL_MD_MASK                 (BIT(1) | BIT(0))
58 #define LIS3MDL_MD_SHIFT                0
59 
60 #define LIS3MDL_MD_CONTINUOUS           0
61 #define LIS3MDL_MD_SINGLE               1
62 #define LIS3MDL_MD_POWER_DOWN           2
63 #define LIS3MDL_MD_POWER_DOWN_AUTO      3
64 
65 #define LIS3MDL_REG_CTRL4               0x23
66 #define LIS3MDL_OMZ_MASK                (BIT(3) | BIT(2))
67 #define LIS3MDL_OMZ_SHIFT               2
68 #define LIS3MDL_BLE_MASK                BIT(1)
69 #define LIS3MDL_BLE_SHIFT               1
70 
71 #define LIS3MDL_REG_CTRL5               0x24
72 #define LIS3MDL_FAST_READ_MASK          BIT(7)
73 #define LIS3MDL_FAST_READ_SHIFT         7
74 #define LIS3MDL_BDU_MASK                BIT(6)
75 #define LIS3MDL_BDU_SHIFT               6
76 
77 #define LIS3MDL_BDU_EN                  (1 << LIS3MDL_BDU_SHIFT)
78 
79 #define LIS3MDL_REG_SAMPLE_START        0x28
80 
81 #define LIS3MDL_REG_INT_CFG             0x30
82 #define LIS3MDL_INT_X_EN                BIT(7)
83 #define LIS3MDL_INT_Y_EN                BIT(6)
84 #define LIS3MDL_INT_Z_EN                BIT(5)
85 #define LIS3MDL_INT_XYZ_EN              \
86 	(LIS3MDL_INT_X_EN | LIS3MDL_INT_Y_EN | LIS3MDL_INT_Z_EN)
87 
88 static const char * const lis3mdl_odr_strings[] = {
89 	"0.625", "1.25", "2.5", "5", "10", "20",
90 	"40", "80", "155", "300", "560", "1000"
91 };
92 
93 static const uint8_t lis3mdl_odr_bits[] = {
94 	LIS3MDL_ODR_BITS(0, 0, 0), /* 0.625 Hz */
95 	LIS3MDL_ODR_BITS(0, 1, 0), /* 1.25 Hz */
96 	LIS3MDL_ODR_BITS(0, 2, 0), /* 2.5 Hz */
97 	LIS3MDL_ODR_BITS(0, 3, 0), /* 5 Hz */
98 	LIS3MDL_ODR_BITS(0, 4, 0), /* 10 Hz */
99 	LIS3MDL_ODR_BITS(0, 5, 0), /* 20 Hz */
100 	LIS3MDL_ODR_BITS(0, 6, 0), /* 40 Hz */
101 	LIS3MDL_ODR_BITS(0, 7, 0), /* 80 Hz */
102 	LIS3MDL_ODR_BITS(3, 0, 1), /* 155 Hz */
103 	LIS3MDL_ODR_BITS(2, 0, 1), /* 300 Hz */
104 	LIS3MDL_ODR_BITS(1, 0, 1), /* 560 Hz */
105 	LIS3MDL_ODR_BITS(0, 0, 1)  /* 1000 Hz */
106 };
107 
108 static const uint16_t lis3mdl_magn_gain[] = {
109 	6842, 3421, 2281, 1711
110 };
111 
112 struct lis3mdl_data {
113 	int16_t x_sample;
114 	int16_t y_sample;
115 	int16_t z_sample;
116 	int16_t temp_sample;
117 
118 #ifdef CONFIG_LIS3MDL_TRIGGER
119 	const struct device *dev;
120 	struct gpio_callback gpio_cb;
121 
122 	const struct sensor_trigger *data_ready_trigger;
123 	sensor_trigger_handler_t data_ready_handler;
124 
125 #if defined(CONFIG_LIS3MDL_TRIGGER_OWN_THREAD)
126 	K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_LIS3MDL_THREAD_STACK_SIZE);
127 	struct k_sem gpio_sem;
128 	struct k_thread thread;
129 #elif defined(CONFIG_LIS3MDL_TRIGGER_GLOBAL_THREAD)
130 	struct k_work work;
131 #endif
132 
133 #endif /* CONFIG_LIS3MDL_TRIGGER */
134 };
135 
136 struct lis3mdl_config {
137 	struct i2c_dt_spec i2c;
138 #ifdef CONFIG_LIS3MDL_TRIGGER
139 	struct gpio_dt_spec irq_gpio;
140 #endif
141 };
142 
143 #ifdef CONFIG_LIS3MDL_TRIGGER
144 int lis3mdl_trigger_set(const struct device *dev,
145 			const struct sensor_trigger *trig,
146 			sensor_trigger_handler_t handler);
147 
148 int lis3mdl_sample_fetch(const struct device *dev, enum sensor_channel chan);
149 
150 int lis3mdl_init_interrupt(const struct device *dev);
151 #endif
152 
153 #endif /* __SENSOR_LIS3MDL__ */
154