1 /*
2 * Copyright (c) 2023 Hudson C. Dalpra
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT zephyr_w1_gpio
8
9 /**
10 * @brief 1-Wire Bus Master driver using Zephyr GPIO interface.
11 *
12 * This file contains the implementation of the 1-Wire Bus Master driver using
13 * the Zephyr GPIO interface. The driver is based on GPIO bit-banging and
14 * follows the timing specifications for 1-Wire communication.
15 *
16 * The driver supports both standard speed and overdrive speed modes.
17 *
18 * This driver is heavily based on the w1_zephyr_serial.c driver and the
19 * technical documentation from Maxim Integrated.
20 *
21 * - w1_zephyr_serial.c: drivers/w1/w1_zephyr_serial.c
22 * - Maxim Integrated 1-Wire Communication Through Software:
23 * https://www.analog.com/en/technical-articles/1wire-communication-through-software.html
24 */
25
26 #include <zephyr/drivers/gpio.h>
27 #include <zephyr/drivers/w1.h>
28 #include <zephyr/device.h>
29 #include <zephyr/kernel.h>
30
31 #include <zephyr/logging/log.h>
32 LOG_MODULE_REGISTER(w1_gpio, CONFIG_W1_LOG_LEVEL);
33
34 /*
35 * The time critical sections are used to ensure that the timing
36 * between communication operations is correct.
37 */
38 #if defined(CONFIG_W1_ZEPHYR_GPIO_TIME_CRITICAL)
39 #define W1_GPIO_ENTER_CRITICAL() irq_lock()
40 #define W1_GPIO_EXIT_CRITICAL(key) irq_unlock(key)
41 #define W1_GPIO_WAIT_US(us) k_busy_wait(us)
42 #else
43 #define W1_GPIO_ENTER_CRITICAL() 0u
44 #define W1_GPIO_EXIT_CRITICAL(key) (void)key
45 #define W1_GPIO_WAIT_US(us) k_usleep(us)
46 #endif
47
48 /*
49 * Standard timing between communication operations:
50 */
51 #define W1_GPIO_TIMING_STD_A 6u
52 #define W1_GPIO_TIMING_STD_B 64u
53 #define W1_GPIO_TIMING_STD_C 60u
54 #define W1_GPIO_TIMING_STD_D 10u
55 #define W1_GPIO_TIMING_STD_E 9u
56 #define W1_GPIO_TIMING_STD_F 55u
57 #define W1_GPIO_TIMING_STD_G 0u
58 #define W1_GPIO_TIMING_STD_H 480u
59 #define W1_GPIO_TIMING_STD_I 70u
60 #define W1_GPIO_TIMING_STD_J 410u
61
62 /*
63 * Overdrive timing between communication operations:
64 *
65 * Not completely correct since the overdrive communication requires
66 * delays of 2.5us, 7.5us and 8.5us.
67 * The delays are approximated by flooring the values.
68 */
69 #define W1_GPIO_TIMING_OD_A 1u
70 #define W1_GPIO_TIMING_OD_B 7u
71 #define W1_GPIO_TIMING_OD_C 7u
72 #define W1_GPIO_TIMING_OD_D 2u
73 #define W1_GPIO_TIMING_OD_E 1u
74 #define W1_GPIO_TIMING_OD_F 7u
75 #define W1_GPIO_TIMING_OD_G 2u
76 #define W1_GPIO_TIMING_OD_H 70u
77 #define W1_GPIO_TIMING_OD_I 8u
78 #define W1_GPIO_TIMING_OD_J 40u
79
80 struct w1_gpio_timing {
81 uint16_t a;
82 uint16_t b;
83 uint16_t c;
84 uint16_t d;
85 uint16_t e;
86 uint16_t f;
87 uint16_t g;
88 uint16_t h;
89 uint16_t i;
90 uint16_t j;
91 };
92
93 struct w1_gpio_config {
94 /** w1 master config, common to all drivers */
95 struct w1_master_config master_config;
96 /** GPIO device used for 1-Wire communication */
97 const struct gpio_dt_spec spec;
98 };
99
100 struct w1_gpio_data {
101 /** w1 master data, common to all drivers */
102 struct w1_master_data master_data;
103 /** timing parameters for 1-Wire communication */
104 const struct w1_gpio_timing *timing;
105 /** overdrive speed mode active */
106 bool overdrive_active;
107 };
108
109 static const struct w1_gpio_timing std = {
110 .a = W1_GPIO_TIMING_STD_A,
111 .b = W1_GPIO_TIMING_STD_B,
112 .c = W1_GPIO_TIMING_STD_C,
113 .d = W1_GPIO_TIMING_STD_D,
114 .e = W1_GPIO_TIMING_STD_E,
115 .f = W1_GPIO_TIMING_STD_F,
116 .g = W1_GPIO_TIMING_STD_G,
117 .h = W1_GPIO_TIMING_STD_H,
118 .i = W1_GPIO_TIMING_STD_I,
119 .j = W1_GPIO_TIMING_STD_J,
120 };
121
122 static const struct w1_gpio_timing od = {
123 .a = W1_GPIO_TIMING_OD_A,
124 .b = W1_GPIO_TIMING_OD_B,
125 .c = W1_GPIO_TIMING_OD_C,
126 .d = W1_GPIO_TIMING_OD_D,
127 .e = W1_GPIO_TIMING_OD_E,
128 .f = W1_GPIO_TIMING_OD_F,
129 .g = W1_GPIO_TIMING_OD_G,
130 .h = W1_GPIO_TIMING_OD_H,
131 .i = W1_GPIO_TIMING_OD_I,
132 .j = W1_GPIO_TIMING_OD_J,
133 };
134
w1_gpio_reset_bus(const struct device * dev)135 static int w1_gpio_reset_bus(const struct device *dev)
136 {
137 const struct w1_gpio_config *cfg = dev->config;
138 const struct w1_gpio_data *data = dev->data;
139
140 const struct gpio_dt_spec *spec = &cfg->spec;
141 const struct w1_gpio_timing *timing = data->timing;
142
143 int ret = 0;
144 unsigned int key = W1_GPIO_ENTER_CRITICAL();
145
146 W1_GPIO_WAIT_US(timing->g);
147 ret = gpio_pin_set_dt(spec, 0);
148 if (ret < 0) {
149 goto out;
150 }
151
152 W1_GPIO_WAIT_US(timing->h);
153 ret = gpio_pin_set_dt(spec, 1);
154 if (ret < 0) {
155 goto out;
156 }
157
158 W1_GPIO_WAIT_US(timing->i);
159 ret = gpio_pin_get_dt(spec);
160 if (ret < 0) {
161 goto out;
162 }
163 ret ^= 0x01;
164
165 W1_GPIO_WAIT_US(timing->j);
166 out:
167 W1_GPIO_EXIT_CRITICAL(key);
168 return ret;
169 }
170
w1_gpio_read_bit(const struct device * dev)171 static int w1_gpio_read_bit(const struct device *dev)
172 {
173 const struct w1_gpio_config *cfg = dev->config;
174 const struct w1_gpio_data *data = dev->data;
175
176 const struct gpio_dt_spec *spec = &cfg->spec;
177 const struct w1_gpio_timing *timing = data->timing;
178
179 int ret = 0;
180 unsigned int key = W1_GPIO_ENTER_CRITICAL();
181
182 ret = gpio_pin_set_dt(spec, 0);
183 if (ret < 0) {
184 goto out;
185 }
186
187 W1_GPIO_WAIT_US(timing->a);
188 ret = gpio_pin_set_dt(spec, 1);
189 if (ret < 0) {
190 goto out;
191 }
192
193 W1_GPIO_WAIT_US(timing->e);
194 ret = gpio_pin_get_dt(spec);
195 if (ret < 0) {
196 goto out;
197 }
198 ret &= 0x01;
199
200 W1_GPIO_WAIT_US(timing->f);
201 out:
202 W1_GPIO_EXIT_CRITICAL(key);
203 return ret;
204 }
205
w1_gpio_write_bit(const struct device * dev,const bool bit)206 static int w1_gpio_write_bit(const struct device *dev, const bool bit)
207 {
208 const struct w1_gpio_config *cfg = dev->config;
209 const struct w1_gpio_data *data = dev->data;
210
211 const struct gpio_dt_spec *spec = &cfg->spec;
212 const struct w1_gpio_timing *timing = data->timing;
213
214 int ret = 0;
215 unsigned int key = W1_GPIO_ENTER_CRITICAL();
216
217 ret = gpio_pin_set_dt(spec, 0);
218 if (ret < 0) {
219 goto out;
220 }
221
222 W1_GPIO_WAIT_US(bit ? timing->a : timing->c);
223 ret = gpio_pin_set_dt(spec, 1);
224 if (ret < 0) {
225 goto out;
226 }
227
228 W1_GPIO_WAIT_US(bit ? timing->b : timing->d);
229 out:
230 W1_GPIO_EXIT_CRITICAL(key);
231 return ret;
232 }
233
w1_gpio_read_byte(const struct device * dev)234 static int w1_gpio_read_byte(const struct device *dev)
235 {
236 int ret = 0;
237 int byte = 0x00;
238
239 for (int i = 0; i < 8; i++) {
240 ret = w1_gpio_read_bit(dev);
241 if (ret < 0) {
242 return ret;
243 }
244
245 byte >>= 1;
246 if (ret) {
247 byte |= 0x80;
248 }
249 }
250
251 return byte;
252 }
253
w1_gpio_write_byte(const struct device * dev,const uint8_t byte)254 static int w1_gpio_write_byte(const struct device *dev, const uint8_t byte)
255 {
256 int ret = 0;
257 uint8_t write = byte;
258
259 for (int i = 0; i < 8; i++) {
260 ret = w1_gpio_write_bit(dev, write & 0x01);
261 if (ret < 0) {
262 return ret;
263 }
264 write >>= 1;
265 }
266
267 return ret;
268 }
269
w1_gpio_configure(const struct device * dev,enum w1_settings_type type,uint32_t value)270 static int w1_gpio_configure(const struct device *dev, enum w1_settings_type type, uint32_t value)
271 {
272 struct w1_gpio_data *data = dev->data;
273
274 switch (type) {
275 case W1_SETTING_SPEED:
276 data->overdrive_active = (value != 0);
277 data->timing = data->overdrive_active ? &od : &std;
278 return 0;
279 default:
280 return -ENOTSUP;
281 }
282 }
283
w1_gpio_init(const struct device * dev)284 static int w1_gpio_init(const struct device *dev)
285 {
286 const struct w1_gpio_config *cfg = dev->config;
287 const struct gpio_dt_spec *spec = &cfg->spec;
288 struct w1_gpio_data *data = dev->data;
289
290 if (gpio_is_ready_dt(spec)) {
291 int ret = gpio_pin_configure_dt(spec, GPIO_OUTPUT_INACTIVE | GPIO_OPEN_DRAIN |
292 GPIO_PULL_UP);
293 if (ret < 0) {
294 LOG_ERR("Failed to configure GPIO port %s pin %d", spec->port->name,
295 spec->pin);
296 return ret;
297 }
298 } else {
299 LOG_ERR("GPIO port %s is not ready", spec->port->name);
300 return -ENODEV;
301 }
302
303 data->timing = &std;
304 data->overdrive_active = false;
305
306 LOG_DBG("w1-gpio initialized, with %d slave devices", cfg->master_config.slave_count);
307 return 0;
308 }
309
310 static const struct w1_driver_api w1_gpio_driver_api = {
311 .reset_bus = w1_gpio_reset_bus,
312 .read_bit = w1_gpio_read_bit,
313 .write_bit = w1_gpio_write_bit,
314 .read_byte = w1_gpio_read_byte,
315 .write_byte = w1_gpio_write_byte,
316 .configure = w1_gpio_configure,
317 };
318
319 #define W1_ZEPHYR_GPIO_INIT(inst) \
320 static const struct w1_gpio_config w1_gpio_cfg_##inst = { \
321 .master_config.slave_count = W1_INST_SLAVE_COUNT(inst), \
322 .spec = GPIO_DT_SPEC_INST_GET(inst, gpios)}; \
323 static struct w1_gpio_data w1_gpio_data_##inst = {}; \
324 DEVICE_DT_INST_DEFINE(inst, &w1_gpio_init, NULL, &w1_gpio_data_##inst, \
325 &w1_gpio_cfg_##inst, POST_KERNEL, CONFIG_W1_INIT_PRIORITY, \
326 &w1_gpio_driver_api);
327
328 DT_INST_FOREACH_STATUS_OKAY(W1_ZEPHYR_GPIO_INIT)
329