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