1 /*
2  * Copyright (c) 2022 Thomas Stranger
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT zephyr_w1_serial
8 
9 /**
10  * @brief 1-Wire Bus Master driver using Zephyr serial interface.
11  *
12  * This driver implements the 1-Wire interface using an uart.
13  * The driver uses a uart peripheral with a baudrate of 115.2 kBd to send
14  * and receive data bits and a baurade of 9.6 kBd for slave reset and
15  * presence detection as suggested for normal speed operating mode in:
16  * https://www.maximintegrated.com/en/design/technical-documents/tutorials/2/214.html
17  * For overdrive speed communication baudrates of 1 MBd and 115.2 kBd
18  * are used, respectively.
19  */
20 
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <zephyr/drivers/uart.h>
24 #include <zephyr/drivers/w1.h>
25 #include <zephyr/logging/log.h>
26 #include <zephyr/sys/__assert.h>
27 
28 LOG_MODULE_REGISTER(w1_serial, CONFIG_W1_LOG_LEVEL);
29 
30 #define W1_SERIAL_READ_REQ_BYTE   0xFF
31 #define W1_SERIAL_BIT_1           0xFF
32 #define W1_SERIAL_BIT_0           0x00
33 
34 /* Standard speed signal parameters:
35  * RST: t_RSTL=520us; t_slot=1041us
36  * DATA: t_low1=8.68us; t_low0=78.1us; t_slot=86.8us
37  */
38 #define W1_SERIAL_STD_RESET_BYTE   0xF0
39 #define W1_SERIAL_STD_RESET_BAUD   9600u
40 #define W1_SERIAL_STD_DATA_BAUD    115200u
41 
42 /*
43  * Overdrive speed signal parameters:
44  * RST: t_RSTL=52.1us; t_slot=86.8us
45  * DATA: t_low1=1.0us; t_low0=9.0us; t_slot=10.0us
46  */
47 #define W1_SERIAL_OD_RESET_BYTE    0xE0
48 #define W1_SERIAL_OD_RESET_BAUD    115200u
49 #define W1_SERIAL_OD_DATA_BAUD     1000000u
50 
51 struct w1_serial_config {
52 	/** w1 master config, common to all drivers */
53 	struct w1_master_config master_config;
54 	/** UART device used for 1-Wire communication */
55 	const struct device *uart_dev;
56 };
57 
58 struct w1_serial_data {
59 	/** w1 master data, common to all drivers */
60 	struct w1_master_data master_data;
61 	struct uart_config uart_cfg;
62 	bool overdrive_active;
63 };
64 
65 /*
66  * Concurrently transmits and receives one 1-Wire bit
67  * by sending and receiving one uart byte
68  */
serial_tx_rx(const struct device * dev,const uint8_t * tx_data,uint8_t * rx_data,size_t len,uint32_t timeout)69 static int serial_tx_rx(const struct device *dev, const uint8_t *tx_data,
70 			uint8_t *rx_data, size_t len, uint32_t timeout)
71 {
72 	const struct w1_serial_config *cfg = dev->config;
73 	uint64_t end;
74 	uint8_t dummy;
75 	int ret = 0;
76 
77 	__ASSERT_NO_MSG(tx_data != NULL);
78 	__ASSERT_NO_MSG(rx_data != NULL);
79 
80 	for (int i = 0; i < len; ++i) {
81 		while (uart_poll_in(cfg->uart_dev, &dummy) == 0) {
82 			/* poll in any buffered data */
83 		}
84 
85 		uart_poll_out(cfg->uart_dev, tx_data[i]);
86 		end = sys_clock_timeout_end_calc(K_USEC(timeout));
87 
88 		do {
89 			ret = uart_poll_in(cfg->uart_dev, &rx_data[i]);
90 		} while (ret != 0 && end > k_uptime_ticks());
91 	}
92 
93 	return ret;
94 }
95 
96 /* Concurretly tranmits and receives one 1-Wire byte */
serial_tx_rx_byte(const struct device * dev,uint8_t tx_byte,uint8_t * rx_byte)97 static int serial_tx_rx_byte(const struct device *dev, uint8_t tx_byte,
98 			     uint8_t *rx_byte)
99 {
100 	__ASSERT_NO_MSG(rx_byte != NULL);
101 	uint8_t byte_representation[8];
102 
103 	for (int i = 0; i < 8; ++i) {
104 		/*
105 		 * Transmitting 0xFF the uart start bit pulls the line low to
106 		 * indicate either write Bit 1, or read low time.
107 		 * Write Bit 0 is represented as 0x00
108 		 */
109 		byte_representation[i] =
110 			((tx_byte & (1 << i)) != 0) ? W1_SERIAL_BIT_1 : W1_SERIAL_BIT_0;
111 	}
112 
113 	if (serial_tx_rx(dev, &byte_representation[0], &byte_representation[0],
114 			 8, CONFIG_W1_ZEPHYR_SERIAL_BIT_TIMEOUT) < 0) {
115 		return -EIO;
116 	}
117 
118 	*rx_byte = 0;
119 	for (int i = 0; i < 8; ++i) {
120 		/*
121 		 * rx-byte different from 0xFF indicates that a slave has
122 		 * pulled line low to transmit a 0 bit, otherwise a 1 bit.
123 		 */
124 		*rx_byte |= (uint8_t)(byte_representation[i] == 0xFF) << i;
125 	}
126 
127 	return 0;
128 }
129 
w1_serial_reset_bus(const struct device * dev)130 static int w1_serial_reset_bus(const struct device *dev)
131 {
132 	const struct w1_serial_config *cfg = dev->config;
133 	struct w1_serial_data *data = dev->data;
134 	uint8_t reset_byte = data->overdrive_active ?
135 			     W1_SERIAL_OD_RESET_BYTE : W1_SERIAL_STD_RESET_BYTE;
136 	/* reset uses 115200/9600=12 slower baudrate,
137 	 * adjust timeout accordingly, also valid for overdrive speed.
138 	 */
139 	const uint32_t reset_timeout = CONFIG_W1_ZEPHYR_SERIAL_BIT_TIMEOUT * 12;
140 
141 	data->uart_cfg.baudrate = data->overdrive_active ?
142 			W1_SERIAL_OD_RESET_BAUD : W1_SERIAL_STD_RESET_BAUD;
143 	if (uart_configure(cfg->uart_dev, &data->uart_cfg) != 0) {
144 		LOG_ERR("Failed set baud rate for reset pulse");
145 		return -EIO;
146 	}
147 
148 	if (serial_tx_rx(dev, &reset_byte, &reset_byte, 1, reset_timeout) < 0) {
149 		LOG_ERR("tx_rx_error reset_present");
150 		return -EIO;
151 	}
152 
153 	data->uart_cfg.baudrate = data->overdrive_active ?
154 			W1_SERIAL_OD_DATA_BAUD : W1_SERIAL_STD_DATA_BAUD;
155 	if (uart_configure(cfg->uart_dev, &data->uart_cfg) != 0) {
156 		LOG_ERR("Failed set baud rate for data transfer");
157 		return -EIO;
158 	}
159 
160 	/* At least 1 device is present on bus, if reset_byte is different
161 	 * from 0xF0. But Bus probably shorted if reset_byte is 0x00.
162 	 */
163 	return (reset_byte != W1_SERIAL_STD_RESET_BYTE) && (reset_byte != 0x00);
164 }
165 
w1_serial_read_bit(const struct device * dev)166 static int w1_serial_read_bit(const struct device *dev)
167 {
168 	uint8_t tx_bit = W1_SERIAL_READ_REQ_BYTE;
169 	uint8_t rx_bit;
170 
171 	if (serial_tx_rx(dev, &tx_bit, &rx_bit, 1,
172 			 CONFIG_W1_ZEPHYR_SERIAL_BIT_TIMEOUT) != 0) {
173 		return -EIO;
174 	};
175 
176 	return rx_bit == W1_SERIAL_READ_REQ_BYTE;
177 }
178 
w1_serial_write_bit(const struct device * dev,const bool bit)179 static int w1_serial_write_bit(const struct device *dev, const bool bit)
180 {
181 	uint8_t tx_bit;
182 	uint8_t rx_bit;
183 
184 	tx_bit = bit ? W1_SERIAL_BIT_1 : W1_SERIAL_BIT_0;
185 	if (serial_tx_rx(dev, &tx_bit, &rx_bit, 1,
186 			 CONFIG_W1_ZEPHYR_SERIAL_BIT_TIMEOUT) != 0) {
187 		return -EIO;
188 	}
189 	return 0;
190 }
191 
w1_serial_read_byte(const struct device * dev)192 static int w1_serial_read_byte(const struct device *dev)
193 {
194 	uint8_t tx_byte = 0xFF;
195 	uint8_t rx_byte;
196 
197 	if (serial_tx_rx_byte(dev, tx_byte, &rx_byte) != 0) {
198 		return -EIO;
199 	}
200 
201 	return rx_byte;
202 }
203 
w1_serial_write_byte(const struct device * dev,const uint8_t byte)204 static int w1_serial_write_byte(const struct device *dev, const uint8_t byte)
205 {
206 	uint8_t rx_byte;
207 
208 	return serial_tx_rx_byte(dev, byte, &rx_byte);
209 }
210 
w1_serial_configure(const struct device * dev,enum w1_settings_type type,uint32_t value)211 static int w1_serial_configure(const struct device *dev,
212 			       enum w1_settings_type type, uint32_t value)
213 {
214 	const struct w1_serial_config *cfg = dev->config;
215 	struct w1_serial_data *data = dev->data;
216 	int ret = 0;
217 	bool temp;
218 
219 	switch (type) {
220 	case W1_SETTING_SPEED:
221 		temp = (bool)value;
222 		if (temp == data->overdrive_active) {
223 			break;
224 		}
225 
226 		data->overdrive_active = temp;
227 		data->uart_cfg.baudrate = data->overdrive_active ?
228 				W1_SERIAL_OD_DATA_BAUD : W1_SERIAL_STD_DATA_BAUD;
229 		if (uart_configure(cfg->uart_dev, &data->uart_cfg) != 0) {
230 			LOG_ERR("Failed set baud rate for data transfer");
231 			ret = -EIO;
232 		}
233 		break;
234 	default:
235 		ret = -ENOTSUP;
236 	}
237 	return ret;
238 }
239 
w1_serial_init(const struct device * dev)240 static int w1_serial_init(const struct device *dev)
241 {
242 	const struct w1_serial_config *cfg = dev->config;
243 	struct w1_serial_data *data = dev->data;
244 
245 	if (!device_is_ready(cfg->uart_dev)) {
246 		LOG_ERR("Serial device not ready");
247 		return -ENODEV;
248 	}
249 
250 	data->uart_cfg.baudrate = W1_SERIAL_STD_DATA_BAUD;
251 	data->uart_cfg.parity = UART_CFG_PARITY_NONE;
252 	data->uart_cfg.data_bits = UART_CFG_DATA_BITS_8;
253 	data->uart_cfg.stop_bits = UART_CFG_STOP_BITS_1;
254 	data->uart_cfg.flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
255 
256 	if (uart_configure(cfg->uart_dev, &data->uart_cfg) != 0) {
257 		LOG_ERR("Failed to configure UART");
258 		return -EINVAL;
259 	}
260 
261 	data->overdrive_active = false;
262 
263 	LOG_DBG("w1-serial initialized, with %d slave devices",
264 		cfg->master_config.slave_count);
265 	return 0;
266 }
267 
268 static const struct w1_driver_api w1_serial_driver_api = {
269 	.reset_bus = w1_serial_reset_bus,
270 	.read_bit = w1_serial_read_bit,
271 	.write_bit = w1_serial_write_bit,
272 	.read_byte = w1_serial_read_byte,
273 	.write_byte = w1_serial_write_byte,
274 	.configure = w1_serial_configure,
275 };
276 
277 #define W1_ZEPHYR_SERIAL_INIT(inst)					   \
278 static const struct w1_serial_config w1_serial_cfg_##inst = {		   \
279 	.uart_dev = DEVICE_DT_GET(DT_INST_BUS(inst)),			   \
280 	.master_config.slave_count = W1_INST_SLAVE_COUNT(inst)		   \
281 };									   \
282 static struct w1_serial_data w1_serial_data_##inst = {};		   \
283 DEVICE_DT_INST_DEFINE(inst, &w1_serial_init, NULL, &w1_serial_data_##inst, \
284 		      &w1_serial_cfg_##inst, POST_KERNEL,		   \
285 		      CONFIG_W1_INIT_PRIORITY, &w1_serial_driver_api);	   \
286 
287 DT_INST_FOREACH_STATUS_OKAY(W1_ZEPHYR_SERIAL_INIT)
288