1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <device.h>
8 #include <drivers/gpio.h>
9 #include <sys/util.h>
10 #include <kernel.h>
11 #include <drivers/sensor.h>
12
13 #include "bmc150_magn.h"
14
15 #include <logging/log.h>
16 LOG_MODULE_DECLARE(BMC150_MAGN, CONFIG_SENSOR_LOG_LEVEL);
17
setup_drdy(const struct device * dev,bool enable)18 static inline void setup_drdy(const struct device *dev,
19 bool enable)
20 {
21 struct bmc150_magn_data *data = dev->data;
22 const struct bmc150_magn_config *const cfg =
23 dev->config;
24
25 gpio_pin_interrupt_configure(data->gpio_drdy,
26 cfg->gpio_drdy_int_pin,
27 enable
28 ? GPIO_INT_EDGE_TO_ACTIVE
29 : GPIO_INT_DISABLE);
30 }
31
32
bmc150_magn_trigger_set(const struct device * dev,const struct sensor_trigger * trig,sensor_trigger_handler_t handler)33 int bmc150_magn_trigger_set(const struct device *dev,
34 const struct sensor_trigger *trig,
35 sensor_trigger_handler_t handler)
36 {
37 struct bmc150_magn_data *data = dev->data;
38 const struct bmc150_magn_config * const config =
39 dev->config;
40 uint8_t state;
41
42 #if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
43 if (trig->type == SENSOR_TRIG_DATA_READY) {
44 setup_drdy(dev, false);
45
46 state = 0U;
47 if (handler) {
48 state = 1U;
49 }
50
51 data->handler_drdy = handler;
52 data->trigger_drdy = *trig;
53
54 if (i2c_reg_update_byte(data->i2c_master,
55 config->i2c_slave_addr,
56 BMC150_MAGN_REG_INT_DRDY,
57 BMC150_MAGN_MASK_DRDY_EN,
58 state << BMC150_MAGN_SHIFT_DRDY_EN)
59 < 0) {
60 LOG_DBG("failed to set DRDY interrupt");
61 return -EIO;
62 }
63
64 setup_drdy(dev, true);
65 }
66 #endif
67
68 return 0;
69 }
70
bmc150_magn_gpio_drdy_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)71 static void bmc150_magn_gpio_drdy_callback(const struct device *dev,
72 struct gpio_callback *cb,
73 uint32_t pins)
74 {
75 struct bmc150_magn_data *data =
76 CONTAINER_OF(cb, struct bmc150_magn_data, gpio_cb);
77
78 ARG_UNUSED(pins);
79
80 setup_drdy(data->dev, false);
81
82 k_sem_give(&data->sem);
83 }
84
bmc150_magn_thread_main(struct bmc150_magn_data * data)85 static void bmc150_magn_thread_main(struct bmc150_magn_data *data)
86 {
87 const struct bmc150_magn_config *config = data->dev->config;
88 uint8_t reg_val;
89
90 while (1) {
91 k_sem_take(&data->sem, K_FOREVER);
92
93 while (i2c_reg_read_byte(data->i2c_master,
94 config->i2c_slave_addr,
95 BMC150_MAGN_REG_INT_STATUS,
96 ®_val) < 0) {
97 LOG_DBG("failed to clear data ready interrupt");
98 }
99
100 if (data->handler_drdy) {
101 data->handler_drdy(data->dev, &data->trigger_drdy);
102 }
103
104 setup_drdy(data->dev, true);
105 }
106 }
107
bmc150_magn_set_drdy_polarity(const struct device * dev,int state)108 static int bmc150_magn_set_drdy_polarity(const struct device *dev, int state)
109 {
110 struct bmc150_magn_data *data = dev->data;
111 const struct bmc150_magn_config *config = dev->config;
112
113 if (state) {
114 state = 1;
115 }
116
117 return i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr,
118 BMC150_MAGN_REG_INT_DRDY,
119 BMC150_MAGN_MASK_DRDY_DR_POLARITY,
120 state << BMC150_MAGN_SHIFT_DRDY_DR_POLARITY);
121 }
122
bmc150_magn_init_interrupt(const struct device * dev)123 int bmc150_magn_init_interrupt(const struct device *dev)
124 {
125 const struct bmc150_magn_config * const config =
126 dev->config;
127 struct bmc150_magn_data *data = dev->data;
128
129
130 #if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
131 if (bmc150_magn_set_drdy_polarity(dev, 0) < 0) {
132 LOG_DBG("failed to set DR polarity");
133 return -EIO;
134 }
135
136 if (i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr,
137 BMC150_MAGN_REG_INT_DRDY,
138 BMC150_MAGN_MASK_DRDY_EN,
139 0 << BMC150_MAGN_SHIFT_DRDY_EN) < 0) {
140 LOG_DBG("failed to set data ready interrupt enabled bit");
141 return -EIO;
142 }
143 #endif
144
145 data->handler_drdy = NULL;
146
147 k_sem_init(&data->sem, 0, K_SEM_MAX_LIMIT);
148
149 k_thread_create(&data->thread, data->thread_stack,
150 CONFIG_BMC150_MAGN_TRIGGER_THREAD_STACK,
151 (k_thread_entry_t)bmc150_magn_thread_main,
152 data, NULL, NULL,
153 K_PRIO_COOP(10), 0, K_NO_WAIT);
154
155 data->gpio_drdy = device_get_binding(config->gpio_drdy_dev_name);
156 if (!data->gpio_drdy) {
157 LOG_DBG("gpio controller %s not found",
158 config->gpio_drdy_dev_name);
159 return -EINVAL;
160 }
161
162 gpio_pin_configure(data->gpio_drdy, config->gpio_drdy_int_pin,
163 config->gpio_drdy_int_flags
164 | GPIO_INT_EDGE_TO_ACTIVE);
165
166 gpio_init_callback(&data->gpio_cb,
167 bmc150_magn_gpio_drdy_callback,
168 BIT(config->gpio_drdy_int_pin));
169
170 if (gpio_add_callback(data->gpio_drdy, &data->gpio_cb) < 0) {
171 LOG_DBG("failed to set gpio callback");
172 return -EIO;
173 }
174
175 data->dev = dev;
176
177 return 0;
178 }
179