File Index
Files and directories
Sign in
FILE

w1-uart.c

File preview with syntax highlighting.

linux-6.19.14/drivers/w1/masters/w1-uart.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * w1-uart - UART 1-Wire bus driver
  4 *
  5 * Uses the UART interface (via Serial Device Bus) to create the 1-Wire
  6 * timing patterns. Implements the following 1-Wire master interface:
  7 *
  8 * - reset_bus: requests baud-rate 9600
  9 *
 10 * - touch_bit: requests baud-rate 115200
 11 *
 12 * Author: Christoph Winklhofer <cj.winklhofer@gmail.com>
 13 */
 14
 15#include <linux/completion.h>
 16#include <linux/delay.h>
 17#include <linux/jiffies.h>
 18#include <linux/module.h>
 19#include <linux/mutex.h>
 20#include <linux/of.h>
 21#include <linux/serdev.h>
 22#include <linux/w1.h>
 23
 24/* UART packet contains start and stop bit */
 25#define W1_UART_BITS_PER_PACKET (BITS_PER_BYTE + 2)
 26
 27/* Timeout to wait for completion of serdev-receive */
 28#define W1_UART_TIMEOUT msecs_to_jiffies(500)
 29
 30/**
 31 * struct w1_uart_config - configuration for 1-Wire operation
 32 * @baudrate: baud-rate returned from serdev
 33 * @delay_us: delay to complete a 1-Wire cycle (in us)
 34 * @tx_byte: byte to generate 1-Wire timing pattern
 35 */
 36struct w1_uart_config {
 37	unsigned int baudrate;
 38	unsigned int delay_us;
 39	u8 tx_byte;
 40};
 41
 42/**
 43 * struct w1_uart_device - 1-Wire UART device structure
 44 * @serdev: serial device
 45 * @bus: w1-bus master
 46 * @cfg_reset: config for 1-Wire reset
 47 * @cfg_touch_0: config for 1-Wire write-0 cycle
 48 * @cfg_touch_1: config for 1-Wire write-1 and read cycle
 49 * @rx_byte_received: completion for serdev receive
 50 * @rx_mutex: mutex to protect rx_err and rx_byte
 51 * @rx_err: indicates an error in serdev-receive
 52 * @rx_byte: result byte from serdev-receive
 53 */
 54struct w1_uart_device {
 55	struct serdev_device *serdev;
 56	struct w1_bus_master bus;
 57
 58	struct w1_uart_config cfg_reset;
 59	struct w1_uart_config cfg_touch_0;
 60	struct w1_uart_config cfg_touch_1;
 61
 62	struct completion rx_byte_received;
 63	/*
 64	 * protect rx_err and rx_byte from concurrent access in
 65	 * w1-callbacks and serdev-receive.
 66	 */
 67	struct mutex rx_mutex;
 68	int rx_err;
 69	u8 rx_byte;
 70};
 71
 72/**
 73 * struct w1_uart_limits - limits for 1-Wire operations
 74 * @baudrate: Requested baud-rate to create 1-Wire timing pattern
 75 * @bit_min_us: minimum time for a bit (in us)
 76 * @bit_max_us: maximum time for a bit (in us)
 77 * @sample_us: timespan to sample 1-Wire response
 78 * @cycle_us: duration of the 1-Wire cycle
 79 */
 80struct w1_uart_limits {
 81	unsigned int baudrate;
 82	unsigned int bit_min_us;
 83	unsigned int bit_max_us;
 84	unsigned int sample_us;
 85	unsigned int cycle_us;
 86};
 87
 88static inline unsigned int baud_to_bit_ns(unsigned int baud)
 89{
 90	return NSEC_PER_SEC / baud;
 91}
 92
 93static inline unsigned int to_ns(unsigned int us)
 94{
 95	return us * NSEC_PER_USEC;
 96}
 97
 98/*
 99 * Set baud-rate, delay and tx-byte to create a 1-Wire pulse and adapt
100 * the tx-byte according to the actual baud-rate.
101 *
102 * Reject when:
103 * - time for a bit outside min/max range
104 * - a 1-Wire response is not detectable for sent byte
105 */
106static int w1_uart_set_config(struct serdev_device *serdev,
107			      const struct w1_uart_limits *limits,
108			      struct w1_uart_config *w1cfg)
109{
110	unsigned int packet_ns;
111	unsigned int bits_low;
112	unsigned int bit_ns;
113	unsigned int low_ns;
114
115	w1cfg->baudrate = serdev_device_set_baudrate(serdev, limits->baudrate);
116	if (w1cfg->baudrate == 0)
117		return -EINVAL;
118
119	/* Compute in nanoseconds for accuracy */
120	bit_ns = baud_to_bit_ns(w1cfg->baudrate);
121	bits_low = to_ns(limits->bit_min_us) / bit_ns;
122	/* start bit is always low */
123	low_ns = bit_ns * (bits_low + 1);
124
125	if (low_ns < to_ns(limits->bit_min_us))
126		return -EINVAL;
127
128	if (low_ns > to_ns(limits->bit_max_us))
129		return -EINVAL;
130
131	/* 1-Wire response detectable for sent byte */
132	if (limits->sample_us > 0 &&
133	    bit_ns * BITS_PER_BYTE < low_ns + to_ns(limits->sample_us))
134		return -EINVAL;
135
136	/* delay: 1-Wire cycle takes longer than the UART packet */
137	packet_ns = bit_ns * W1_UART_BITS_PER_PACKET;
138	w1cfg->delay_us = 0;
139	if (to_ns(limits->cycle_us) > packet_ns)
140		w1cfg->delay_us =
141			(to_ns(limits->cycle_us) - packet_ns) / NSEC_PER_USEC;
142
143	/* byte to create 1-Wire pulse */
144	w1cfg->tx_byte = 0xff << bits_low;
145
146	return 0;
147}
148
149/*
150 * Configuration for reset and presence detect
151 * - bit_min_us is 480us, add margin and use 485us
152 * - limits for sample time 60us-75us, use 65us
153 */
154static int w1_uart_set_config_reset(struct w1_uart_device *w1dev)
155{
156	struct serdev_device *serdev = w1dev->serdev;
157	struct device_node *np = serdev->dev.of_node;
158
159	struct w1_uart_limits limits = { .baudrate = 9600,
160					 .bit_min_us = 485,
161					 .bit_max_us = 640,
162					 .sample_us = 65,
163					 .cycle_us = 960 };
164
165	of_property_read_u32(np, "reset-bps", &limits.baudrate);
166
167	return w1_uart_set_config(serdev, &limits, &w1dev->cfg_reset);
168}
169
170/*
171 * Configuration for write-0 cycle (touch bit 0)
172 * - bit_min_us is 60us, add margin and use 65us
173 * - no sampling required, sample_us = 0
174 */
175static int w1_uart_set_config_touch_0(struct w1_uart_device *w1dev)
176{
177	struct serdev_device *serdev = w1dev->serdev;
178	struct device_node *np = serdev->dev.of_node;
179
180	struct w1_uart_limits limits = { .baudrate = 115200,
181					 .bit_min_us = 65,
182					 .bit_max_us = 120,
183					 .sample_us = 0,
184					 .cycle_us = 70 };
185
186	of_property_read_u32(np, "write-0-bps", &limits.baudrate);
187
188	return w1_uart_set_config(serdev, &limits, &w1dev->cfg_touch_0);
189}
190
191/*
192 * Configuration for write-1 and read cycle (touch bit 1)
193 * - bit_min_us is 5us, add margin and use 6us
194 * - limits for sample time 5us-15us, use 15us
195 */
196static int w1_uart_set_config_touch_1(struct w1_uart_device *w1dev)
197{
198	struct serdev_device *serdev = w1dev->serdev;
199	struct device_node *np = serdev->dev.of_node;
200
201	struct w1_uart_limits limits = { .baudrate = 115200,
202					 .bit_min_us = 6,
203					 .bit_max_us = 15,
204					 .sample_us = 15,
205					 .cycle_us = 70 };
206
207	of_property_read_u32(np, "write-1-bps", &limits.baudrate);
208
209	return w1_uart_set_config(serdev, &limits, &w1dev->cfg_touch_1);
210}
211
212/*
213 * Configure and open the serial device
214 */
215static int w1_uart_serdev_open(struct w1_uart_device *w1dev)
216{
217	struct serdev_device *serdev = w1dev->serdev;
218	struct device *dev = &serdev->dev;
219	int ret;
220
221	ret = devm_serdev_device_open(dev, serdev);
222	if (ret < 0)
223		return ret;
224
225	ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
226	if (ret < 0) {
227		dev_err(dev, "set parity failed\n");
228		return ret;
229	}
230
231	ret = w1_uart_set_config_reset(w1dev);
232	if (ret < 0) {
233		dev_err(dev, "config for reset failed\n");
234		return ret;
235	}
236
237	ret = w1_uart_set_config_touch_0(w1dev);
238	if (ret < 0) {
239		dev_err(dev, "config for touch-0 failed\n");
240		return ret;
241	}
242
243	ret = w1_uart_set_config_touch_1(w1dev);
244	if (ret < 0) {
245		dev_err(dev, "config for touch-1 failed\n");
246		return ret;
247	}
248
249	serdev_device_set_flow_control(serdev, false);
250
251	return 0;
252}
253
254/*
255 * Send one byte (tx_byte) and read one byte (rx_byte) via serdev.
256 */
257static int w1_uart_serdev_tx_rx(struct w1_uart_device *w1dev,
258				const struct w1_uart_config *w1cfg, u8 *rx_byte)
259{
260	struct serdev_device *serdev = w1dev->serdev;
261	int ret;
262
263	serdev_device_write_flush(serdev);
264	serdev_device_set_baudrate(serdev, w1cfg->baudrate);
265
266	/* write and immediately read one byte */
267	reinit_completion(&w1dev->rx_byte_received);
268	ret = serdev_device_write_buf(serdev, &w1cfg->tx_byte, 1);
269	if (ret != 1)
270		return -EIO;
271	ret = wait_for_completion_interruptible_timeout(
272		&w1dev->rx_byte_received, W1_UART_TIMEOUT);
273	if (ret <= 0)
274		return -EIO;
275
276	/* locking could fail when serdev is unexpectedly receiving. */
277	if (!mutex_trylock(&w1dev->rx_mutex))
278		return -EIO;
279
280	ret = w1dev->rx_err;
281	if (ret == 0)
282		*rx_byte = w1dev->rx_byte;
283
284	mutex_unlock(&w1dev->rx_mutex);
285
286	if (w1cfg->delay_us > 0)
287		fsleep(w1cfg->delay_us);
288
289	return ret;
290}
291
292static size_t w1_uart_serdev_receive_buf(struct serdev_device *serdev,
293					  const u8 *buf, size_t count)
294{
295	struct w1_uart_device *w1dev = serdev_device_get_drvdata(serdev);
296
297	mutex_lock(&w1dev->rx_mutex);
298
299	/* sent a single byte and receive one single byte */
300	if (count == 1) {
301		w1dev->rx_byte = buf[0];
302		w1dev->rx_err = 0;
303	} else {
304		w1dev->rx_err = -EIO;
305	}
306
307	mutex_unlock(&w1dev->rx_mutex);
308	complete(&w1dev->rx_byte_received);
309
310	return count;
311}
312
313static const struct serdev_device_ops w1_uart_serdev_ops = {
314	.receive_buf = w1_uart_serdev_receive_buf,
315	.write_wakeup = serdev_device_write_wakeup,
316};
317
318/*
319 * 1-wire reset and presence detect: A present slave will manipulate
320 * the received byte by pulling the 1-Wire low.
321 */
322static u8 w1_uart_reset_bus(void *data)
323{
324	struct w1_uart_device *w1dev = data;
325	const struct w1_uart_config *w1cfg = &w1dev->cfg_reset;
326	int ret;
327	u8 val;
328
329	ret = w1_uart_serdev_tx_rx(w1dev, w1cfg, &val);
330	if (ret < 0)
331		return -1;
332
333	/* Device present (0) or no device (1) */
334	return val != w1cfg->tx_byte ? 0 : 1;
335}
336
337/*
338 * 1-Wire read and write cycle: Only the read-0 manipulates the
339 * received byte, all others left the line untouched.
340 */
341static u8 w1_uart_touch_bit(void *data, u8 bit)
342{
343	struct w1_uart_device *w1dev = data;
344	const struct w1_uart_config *w1cfg = bit ? &w1dev->cfg_touch_1 :
345						   &w1dev->cfg_touch_0;
346	int ret;
347	u8 val;
348
349	ret = w1_uart_serdev_tx_rx(w1dev, w1cfg, &val);
350
351	/* return inactive bus state on error */
352	if (ret < 0)
353		return 1;
354
355	return val == w1cfg->tx_byte ? 1 : 0;
356}
357
358static int w1_uart_probe(struct serdev_device *serdev)
359{
360	struct device *dev = &serdev->dev;
361	struct w1_uart_device *w1dev;
362	int ret;
363
364	w1dev = devm_kzalloc(dev, sizeof(*w1dev), GFP_KERNEL);
365	if (!w1dev)
366		return -ENOMEM;
367	w1dev->bus.data = w1dev;
368	w1dev->bus.reset_bus = w1_uart_reset_bus;
369	w1dev->bus.touch_bit = w1_uart_touch_bit;
370	w1dev->serdev = serdev;
371
372	init_completion(&w1dev->rx_byte_received);
373	mutex_init(&w1dev->rx_mutex);
374
375	serdev_device_set_drvdata(serdev, w1dev);
376	serdev_device_set_client_ops(serdev, &w1_uart_serdev_ops);
377	ret = w1_uart_serdev_open(w1dev);
378	if (ret < 0)
379		return ret;
380
381	return w1_add_master_device(&w1dev->bus);
382}
383
384static void w1_uart_remove(struct serdev_device *serdev)
385{
386	struct w1_uart_device *w1dev = serdev_device_get_drvdata(serdev);
387
388	/*
389	 * Waits until w1-uart callbacks are finished, serdev is closed
390	 * and its device data released automatically by devres (waits
391	 * until serdev-receive is finished).
392	 */
393	w1_remove_master_device(&w1dev->bus);
394}
395
396static const struct of_device_id w1_uart_of_match[] = {
397	{ .compatible = "w1-uart" },
398	{},
399};
400MODULE_DEVICE_TABLE(of, w1_uart_of_match);
401
402static struct serdev_device_driver w1_uart_driver = {
403	.driver	= {
404		.name		= "w1-uart",
405		.of_match_table = w1_uart_of_match,
406	},
407	.probe	= w1_uart_probe,
408	.remove	= w1_uart_remove,
409};
410
411module_serdev_device_driver(w1_uart_driver);
412
413MODULE_DESCRIPTION("UART w1 bus driver");
414MODULE_AUTHOR("Christoph Winklhofer <cj.winklhofer@gmail.com>");
415MODULE_LICENSE("GPL");
~/ Read-only file preview.