xref: /openbmc/linux/drivers/w1/w1_io.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
3a8018766SEvgeniy Polyakov  * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
41da177e4SLinus Torvalds  */
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds #include <asm/io.h>
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds #include <linux/delay.h>
91da177e4SLinus Torvalds #include <linux/moduleparam.h>
10339f0723SAndrew Morton #include <linux/module.h>
111da177e4SLinus Torvalds 
12de0d6dbdSAndrew F. Davis #include "w1_internal.h"
131da177e4SLinus Torvalds 
14a9fb1c7bSAdrian Bunk static int w1_delay_parm = 1;
151da177e4SLinus Torvalds module_param_named(delay_coef, w1_delay_parm, int, 0);
161da177e4SLinus Torvalds 
178f1e1251SMarkus Franke static int w1_disable_irqs = 0;
188f1e1251SMarkus Franke module_param_named(disable_irqs, w1_disable_irqs, int, 0);
198f1e1251SMarkus Franke 
201da177e4SLinus Torvalds static u8 w1_crc8_table[] = {
211da177e4SLinus Torvalds 	0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
221da177e4SLinus Torvalds 	157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
231da177e4SLinus Torvalds 	35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
241da177e4SLinus Torvalds 	190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
251da177e4SLinus Torvalds 	70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
261da177e4SLinus Torvalds 	219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
271da177e4SLinus Torvalds 	101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
281da177e4SLinus Torvalds 	248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
291da177e4SLinus Torvalds 	140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
301da177e4SLinus Torvalds 	17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
311da177e4SLinus Torvalds 	175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
321da177e4SLinus Torvalds 	50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
331da177e4SLinus Torvalds 	202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
341da177e4SLinus Torvalds 	87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
351da177e4SLinus Torvalds 	233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
361da177e4SLinus Torvalds 	116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
371da177e4SLinus Torvalds };
381da177e4SLinus Torvalds 
w1_delay(unsigned long tm)3970d484bfSEvgeniy Polyakov static void w1_delay(unsigned long tm)
401da177e4SLinus Torvalds {
411da177e4SLinus Torvalds 	udelay(tm * w1_delay_parm);
421da177e4SLinus Torvalds }
431da177e4SLinus Torvalds 
44be57ce26SEvgeniy Polyakov static void w1_write_bit(struct w1_master *dev, int bit);
45be57ce26SEvgeniy Polyakov static u8 w1_read_bit(struct w1_master *dev);
46be57ce26SEvgeniy Polyakov 
47be57ce26SEvgeniy Polyakov /**
48b3be177aSDavid Fries  * w1_touch_bit() - Generates a write-0 or write-1 cycle and samples the level.
49b3be177aSDavid Fries  * @dev:	the master device
50b3be177aSDavid Fries  * @bit:	0 - write a 0, 1 - write a 0 read the level
51be57ce26SEvgeniy Polyakov  */
w1_touch_bit(struct w1_master * dev,int bit)52eb8470dbSJan Kandziora u8 w1_touch_bit(struct w1_master *dev, int bit)
531da177e4SLinus Torvalds {
541da177e4SLinus Torvalds 	if (dev->bus_master->touch_bit)
551da177e4SLinus Torvalds 		return dev->bus_master->touch_bit(dev->bus_master->data, bit);
56be57ce26SEvgeniy Polyakov 	else if (bit)
571da177e4SLinus Torvalds 		return w1_read_bit(dev);
58be57ce26SEvgeniy Polyakov 	else {
59be57ce26SEvgeniy Polyakov 		w1_write_bit(dev, 0);
6023c36c1aSDaniel Mack 		return 0;
61be57ce26SEvgeniy Polyakov 	}
621da177e4SLinus Torvalds }
63eb8470dbSJan Kandziora EXPORT_SYMBOL_GPL(w1_touch_bit);
641da177e4SLinus Torvalds 
65be57ce26SEvgeniy Polyakov /**
66b3be177aSDavid Fries  * w1_write_bit() - Generates a write-0 or write-1 cycle.
67b3be177aSDavid Fries  * @dev:	the master device
68b3be177aSDavid Fries  * @bit:	bit to write
69b3be177aSDavid Fries  *
70be57ce26SEvgeniy Polyakov  * Only call if dev->bus_master->touch_bit is NULL
71be57ce26SEvgeniy Polyakov  */
w1_write_bit(struct w1_master * dev,int bit)72be57ce26SEvgeniy Polyakov static void w1_write_bit(struct w1_master *dev, int bit)
731da177e4SLinus Torvalds {
748f1e1251SMarkus Franke 	unsigned long flags = 0;
758f1e1251SMarkus Franke 
768f1e1251SMarkus Franke 	if(w1_disable_irqs) local_irq_save(flags);
778f1e1251SMarkus Franke 
781da177e4SLinus Torvalds 	if (bit) {
791da177e4SLinus Torvalds 		dev->bus_master->write_bit(dev->bus_master->data, 0);
801da177e4SLinus Torvalds 		w1_delay(6);
811da177e4SLinus Torvalds 		dev->bus_master->write_bit(dev->bus_master->data, 1);
821da177e4SLinus Torvalds 		w1_delay(64);
831da177e4SLinus Torvalds 	} else {
841da177e4SLinus Torvalds 		dev->bus_master->write_bit(dev->bus_master->data, 0);
851da177e4SLinus Torvalds 		w1_delay(60);
861da177e4SLinus Torvalds 		dev->bus_master->write_bit(dev->bus_master->data, 1);
871da177e4SLinus Torvalds 		w1_delay(10);
881da177e4SLinus Torvalds 	}
898f1e1251SMarkus Franke 
908f1e1251SMarkus Franke 	if(w1_disable_irqs) local_irq_restore(flags);
911da177e4SLinus Torvalds }
921da177e4SLinus Torvalds 
93be57ce26SEvgeniy Polyakov /**
94b3be177aSDavid Fries  * w1_pre_write() - pre-write operations
95b3be177aSDavid Fries  * @dev:	the master device
96b3be177aSDavid Fries  *
976a158c0dSDavid Fries  * Pre-write operation, currently only supporting strong pullups.
986a158c0dSDavid Fries  * Program the hardware for a strong pullup, if one has been requested and
996a158c0dSDavid Fries  * the hardware supports it.
1006a158c0dSDavid Fries  */
w1_pre_write(struct w1_master * dev)1016a158c0dSDavid Fries static void w1_pre_write(struct w1_master *dev)
1026a158c0dSDavid Fries {
1036a158c0dSDavid Fries 	if (dev->pullup_duration &&
1046a158c0dSDavid Fries 		dev->enable_pullup && dev->bus_master->set_pullup) {
1056a158c0dSDavid Fries 		dev->bus_master->set_pullup(dev->bus_master->data,
1066a158c0dSDavid Fries 			dev->pullup_duration);
1076a158c0dSDavid Fries 	}
1086a158c0dSDavid Fries }
1096a158c0dSDavid Fries 
1106a158c0dSDavid Fries /**
111b3be177aSDavid Fries  * w1_post_write() - post-write options
112b3be177aSDavid Fries  * @dev:	the master device
113b3be177aSDavid Fries  *
1146a158c0dSDavid Fries  * Post-write operation, currently only supporting strong pullups.
1156a158c0dSDavid Fries  * If a strong pullup was requested, clear it if the hardware supports
1166a158c0dSDavid Fries  * them, or execute the delay otherwise, in either case clear the request.
1176a158c0dSDavid Fries  */
w1_post_write(struct w1_master * dev)1186a158c0dSDavid Fries static void w1_post_write(struct w1_master *dev)
1196a158c0dSDavid Fries {
1206a158c0dSDavid Fries 	if (dev->pullup_duration) {
1216a158c0dSDavid Fries 		if (dev->enable_pullup && dev->bus_master->set_pullup)
1226a158c0dSDavid Fries 			dev->bus_master->set_pullup(dev->bus_master->data, 0);
1236a158c0dSDavid Fries 		else
1246a158c0dSDavid Fries 			msleep(dev->pullup_duration);
1256a158c0dSDavid Fries 		dev->pullup_duration = 0;
1266a158c0dSDavid Fries 	}
1276a158c0dSDavid Fries }
1286a158c0dSDavid Fries 
1296a158c0dSDavid Fries /**
130b3be177aSDavid Fries  * w1_write_8() - Writes 8 bits.
131b3be177aSDavid Fries  * @dev:	the master device
132b3be177aSDavid Fries  * @byte:	the byte to write
133be57ce26SEvgeniy Polyakov  */
w1_write_8(struct w1_master * dev,u8 byte)1341da177e4SLinus Torvalds void w1_write_8(struct w1_master *dev, u8 byte)
1351da177e4SLinus Torvalds {
1361da177e4SLinus Torvalds 	int i;
1371da177e4SLinus Torvalds 
1386a158c0dSDavid Fries 	if (dev->bus_master->write_byte) {
1396a158c0dSDavid Fries 		w1_pre_write(dev);
1401da177e4SLinus Torvalds 		dev->bus_master->write_byte(dev->bus_master->data, byte);
1416a158c0dSDavid Fries 	}
1421da177e4SLinus Torvalds 	else
1436a158c0dSDavid Fries 		for (i = 0; i < 8; ++i) {
1446a158c0dSDavid Fries 			if (i == 7)
1456a158c0dSDavid Fries 				w1_pre_write(dev);
146be57ce26SEvgeniy Polyakov 			w1_touch_bit(dev, (byte >> i) & 0x1);
1471da177e4SLinus Torvalds 		}
1486a158c0dSDavid Fries 	w1_post_write(dev);
1496a158c0dSDavid Fries }
150339f0723SAndrew Morton EXPORT_SYMBOL_GPL(w1_write_8);
1511da177e4SLinus Torvalds 
152be57ce26SEvgeniy Polyakov 
153be57ce26SEvgeniy Polyakov /**
154b3be177aSDavid Fries  * w1_read_bit() - Generates a write-1 cycle and samples the level.
155b3be177aSDavid Fries  * @dev:	the master device
156b3be177aSDavid Fries  *
157be57ce26SEvgeniy Polyakov  * Only call if dev->bus_master->touch_bit is NULL
158be57ce26SEvgeniy Polyakov  */
w1_read_bit(struct w1_master * dev)159be57ce26SEvgeniy Polyakov static u8 w1_read_bit(struct w1_master *dev)
1601da177e4SLinus Torvalds {
1611da177e4SLinus Torvalds 	int result;
1628f1e1251SMarkus Franke 	unsigned long flags = 0;
1631da177e4SLinus Torvalds 
1643fd306c8SJan Weitzel 	/* sample timing is critical here */
1653fd306c8SJan Weitzel 	local_irq_save(flags);
1661da177e4SLinus Torvalds 	dev->bus_master->write_bit(dev->bus_master->data, 0);
1671da177e4SLinus Torvalds 	w1_delay(6);
1681da177e4SLinus Torvalds 	dev->bus_master->write_bit(dev->bus_master->data, 1);
1691da177e4SLinus Torvalds 	w1_delay(9);
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds 	result = dev->bus_master->read_bit(dev->bus_master->data);
1723fd306c8SJan Weitzel 	local_irq_restore(flags);
1733fd306c8SJan Weitzel 
1741da177e4SLinus Torvalds 	w1_delay(55);
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds 	return result & 0x1;
1771da177e4SLinus Torvalds }
1781da177e4SLinus Torvalds 
179be57ce26SEvgeniy Polyakov /**
180b3be177aSDavid Fries  * w1_triplet() - * Does a triplet - used for searching ROM addresses.
181b3be177aSDavid Fries  * @dev:	the master device
182b3be177aSDavid Fries  * @bdir:	the bit to write if both id_bit and comp_bit are 0
183b3be177aSDavid Fries  *
1846b729861SEvgeniy Polyakov  * Return bits:
1856b729861SEvgeniy Polyakov  *  bit 0 = id_bit
1866b729861SEvgeniy Polyakov  *  bit 1 = comp_bit
1876b729861SEvgeniy Polyakov  *  bit 2 = dir_taken
1889167b942SMauro Carvalho Chehab  *
1896b729861SEvgeniy Polyakov  * If both bits 0 & 1 are set, the search should be restarted.
1906b729861SEvgeniy Polyakov  *
191b3be177aSDavid Fries  * Return:        bit fields - see above
1926b729861SEvgeniy Polyakov  */
w1_triplet(struct w1_master * dev,int bdir)1936b729861SEvgeniy Polyakov u8 w1_triplet(struct w1_master *dev, int bdir)
1946b729861SEvgeniy Polyakov {
1956b729861SEvgeniy Polyakov 	if (dev->bus_master->triplet)
19623c36c1aSDaniel Mack 		return dev->bus_master->triplet(dev->bus_master->data, bdir);
1976b729861SEvgeniy Polyakov 	else {
1986b729861SEvgeniy Polyakov 		u8 id_bit   = w1_touch_bit(dev, 1);
1996b729861SEvgeniy Polyakov 		u8 comp_bit = w1_touch_bit(dev, 1);
2006b729861SEvgeniy Polyakov 		u8 retval;
2016b729861SEvgeniy Polyakov 
2026b729861SEvgeniy Polyakov 		if (id_bit && comp_bit)
20323c36c1aSDaniel Mack 			return 0x03;  /* error */
2046b729861SEvgeniy Polyakov 
2056b729861SEvgeniy Polyakov 		if (!id_bit && !comp_bit) {
2066b729861SEvgeniy Polyakov 			/* Both bits are valid, take the direction given */
2076b729861SEvgeniy Polyakov 			retval = bdir ? 0x04 : 0;
2086b729861SEvgeniy Polyakov 		} else {
2096b729861SEvgeniy Polyakov 			/* Only one bit is valid, take that direction */
2106b729861SEvgeniy Polyakov 			bdir = id_bit;
2116b729861SEvgeniy Polyakov 			retval = id_bit ? 0x05 : 0x02;
2126b729861SEvgeniy Polyakov 		}
2136b729861SEvgeniy Polyakov 
2146b729861SEvgeniy Polyakov 		if (dev->bus_master->touch_bit)
2156b729861SEvgeniy Polyakov 			w1_touch_bit(dev, bdir);
2166b729861SEvgeniy Polyakov 		else
2176b729861SEvgeniy Polyakov 			w1_write_bit(dev, bdir);
21823c36c1aSDaniel Mack 		return retval;
2196b729861SEvgeniy Polyakov 	}
2206b729861SEvgeniy Polyakov }
221dd6478d6SMaciej S. Szmigiero EXPORT_SYMBOL_GPL(w1_triplet);
2226b729861SEvgeniy Polyakov 
2236b729861SEvgeniy Polyakov /**
224b3be177aSDavid Fries  * w1_read_8() - Reads 8 bits.
225b3be177aSDavid Fries  * @dev:	the master device
226be57ce26SEvgeniy Polyakov  *
227b3be177aSDavid Fries  * Return:        the byte read
228be57ce26SEvgeniy Polyakov  */
w1_read_8(struct w1_master * dev)22934e453d4SMadhusudhan Chikkature u8 w1_read_8(struct w1_master *dev)
2301da177e4SLinus Torvalds {
2311da177e4SLinus Torvalds 	int i;
2321da177e4SLinus Torvalds 	u8 res = 0;
2331da177e4SLinus Torvalds 
2341da177e4SLinus Torvalds 	if (dev->bus_master->read_byte)
2351da177e4SLinus Torvalds 		res = dev->bus_master->read_byte(dev->bus_master->data);
2361da177e4SLinus Torvalds 	else
2371da177e4SLinus Torvalds 		for (i = 0; i < 8; ++i)
238be57ce26SEvgeniy Polyakov 			res |= (w1_touch_bit(dev,1) << i);
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds 	return res;
2411da177e4SLinus Torvalds }
24234e453d4SMadhusudhan Chikkature EXPORT_SYMBOL_GPL(w1_read_8);
2431da177e4SLinus Torvalds 
244be57ce26SEvgeniy Polyakov /**
245b3be177aSDavid Fries  * w1_write_block() - Writes a series of bytes.
246b3be177aSDavid Fries  * @dev:	the master device
247b3be177aSDavid Fries  * @buf:	pointer to the data to write
248b3be177aSDavid Fries  * @len:	the number of bytes to write
249be57ce26SEvgeniy Polyakov  */
w1_write_block(struct w1_master * dev,const u8 * buf,int len)250be57ce26SEvgeniy Polyakov void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
2511da177e4SLinus Torvalds {
2521da177e4SLinus Torvalds 	int i;
2531da177e4SLinus Torvalds 
2546a158c0dSDavid Fries 	if (dev->bus_master->write_block) {
2556a158c0dSDavid Fries 		w1_pre_write(dev);
2561da177e4SLinus Torvalds 		dev->bus_master->write_block(dev->bus_master->data, buf, len);
2576a158c0dSDavid Fries 	}
2581da177e4SLinus Torvalds 	else
2591da177e4SLinus Torvalds 		for (i = 0; i < len; ++i)
2606a158c0dSDavid Fries 			w1_write_8(dev, buf[i]); /* calls w1_pre_write */
2616a158c0dSDavid Fries 	w1_post_write(dev);
2621da177e4SLinus Torvalds }
263339f0723SAndrew Morton EXPORT_SYMBOL_GPL(w1_write_block);
2641da177e4SLinus Torvalds 
265be57ce26SEvgeniy Polyakov /**
266b3be177aSDavid Fries  * w1_touch_block() - Touches a series of bytes.
267b3be177aSDavid Fries  * @dev:	the master device
268b3be177aSDavid Fries  * @buf:	pointer to the data to write
269b3be177aSDavid Fries  * @len:	the number of bytes to write
2709be62e0bSEvgeniy Polyakov  */
w1_touch_block(struct w1_master * dev,u8 * buf,int len)2719be62e0bSEvgeniy Polyakov void w1_touch_block(struct w1_master *dev, u8 *buf, int len)
2729be62e0bSEvgeniy Polyakov {
2739be62e0bSEvgeniy Polyakov 	int i, j;
2749be62e0bSEvgeniy Polyakov 	u8 tmp;
2759be62e0bSEvgeniy Polyakov 
2769be62e0bSEvgeniy Polyakov 	for (i = 0; i < len; ++i) {
2779be62e0bSEvgeniy Polyakov 		tmp = 0;
2789be62e0bSEvgeniy Polyakov 		for (j = 0; j < 8; ++j) {
2799be62e0bSEvgeniy Polyakov 			if (j == 7)
2809be62e0bSEvgeniy Polyakov 				w1_pre_write(dev);
2819be62e0bSEvgeniy Polyakov 			tmp |= w1_touch_bit(dev, (buf[i] >> j) & 0x1) << j;
2829be62e0bSEvgeniy Polyakov 		}
2839be62e0bSEvgeniy Polyakov 
2849be62e0bSEvgeniy Polyakov 		buf[i] = tmp;
2859be62e0bSEvgeniy Polyakov 	}
2869be62e0bSEvgeniy Polyakov }
2879be62e0bSEvgeniy Polyakov EXPORT_SYMBOL_GPL(w1_touch_block);
2889be62e0bSEvgeniy Polyakov 
2899be62e0bSEvgeniy Polyakov /**
290b3be177aSDavid Fries  * w1_read_block() - Reads a series of bytes.
291b3be177aSDavid Fries  * @dev:	the master device
292b3be177aSDavid Fries  * @buf:	pointer to the buffer to fill
293b3be177aSDavid Fries  * @len:	the number of bytes to read
294b3be177aSDavid Fries  * Return:	the number of bytes read
295be57ce26SEvgeniy Polyakov  */
w1_read_block(struct w1_master * dev,u8 * buf,int len)2961da177e4SLinus Torvalds u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
2971da177e4SLinus Torvalds {
2981da177e4SLinus Torvalds 	int i;
2991da177e4SLinus Torvalds 	u8 ret;
3001da177e4SLinus Torvalds 
3011da177e4SLinus Torvalds 	if (dev->bus_master->read_block)
3021da177e4SLinus Torvalds 		ret = dev->bus_master->read_block(dev->bus_master->data, buf, len);
3031da177e4SLinus Torvalds 	else {
3041da177e4SLinus Torvalds 		for (i = 0; i < len; ++i)
3051da177e4SLinus Torvalds 			buf[i] = w1_read_8(dev);
3061da177e4SLinus Torvalds 		ret = len;
3071da177e4SLinus Torvalds 	}
3081da177e4SLinus Torvalds 
3091da177e4SLinus Torvalds 	return ret;
3101da177e4SLinus Torvalds }
311339f0723SAndrew Morton EXPORT_SYMBOL_GPL(w1_read_block);
3121da177e4SLinus Torvalds 
313be57ce26SEvgeniy Polyakov /**
314b3be177aSDavid Fries  * w1_reset_bus() - Issues a reset bus sequence.
315b3be177aSDavid Fries  * @dev:	the master device
316b3be177aSDavid Fries  * Return:	0=Device present, 1=No device present or error
317be57ce26SEvgeniy Polyakov  */
w1_reset_bus(struct w1_master * dev)3181da177e4SLinus Torvalds int w1_reset_bus(struct w1_master *dev)
3191da177e4SLinus Torvalds {
320be57ce26SEvgeniy Polyakov 	int result;
3218f1e1251SMarkus Franke 	unsigned long flags = 0;
3228f1e1251SMarkus Franke 
3238f1e1251SMarkus Franke 	if(w1_disable_irqs) local_irq_save(flags);
3241da177e4SLinus Torvalds 
3251da177e4SLinus Torvalds 	if (dev->bus_master->reset_bus)
3261da177e4SLinus Torvalds 		result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
3271da177e4SLinus Torvalds 	else {
3281da177e4SLinus Torvalds 		dev->bus_master->write_bit(dev->bus_master->data, 0);
3298e3dae2bSDavid Fries 		/* minimum 480, max ? us
3308e3dae2bSDavid Fries 		 * be nice and sleep, except 18b20 spec lists 960us maximum,
3318e3dae2bSDavid Fries 		 * so until we can sleep with microsecond accuracy, spin.
3328e3dae2bSDavid Fries 		 * Feel free to come up with some other way to give up the
3338e3dae2bSDavid Fries 		 * cpu for such a short amount of time AND get it back in
3348e3dae2bSDavid Fries 		 * the maximum amount of time.
3358e3dae2bSDavid Fries 		 */
3368f1e1251SMarkus Franke 		w1_delay(500);
3371da177e4SLinus Torvalds 		dev->bus_master->write_bit(dev->bus_master->data, 1);
3381da177e4SLinus Torvalds 		w1_delay(70);
3391da177e4SLinus Torvalds 
3401da177e4SLinus Torvalds 		result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
3410db71fecSGeert Uytterhoeven 		/* minimum 70 (above) + 430 = 500 us
3428e3dae2bSDavid Fries 		 * There aren't any timing requirements between a reset and
3438e3dae2bSDavid Fries 		 * the following transactions.  Sleeping is safe here.
3448e3dae2bSDavid Fries 		 */
3458f1e1251SMarkus Franke 		/* w1_delay(430); min required time */
3468e3dae2bSDavid Fries 		msleep(1);
3471da177e4SLinus Torvalds 	}
3481da177e4SLinus Torvalds 
3498f1e1251SMarkus Franke 	if(w1_disable_irqs) local_irq_restore(flags);
3508f1e1251SMarkus Franke 
3511da177e4SLinus Torvalds 	return result;
3521da177e4SLinus Torvalds }
353339f0723SAndrew Morton EXPORT_SYMBOL_GPL(w1_reset_bus);
3541da177e4SLinus Torvalds 
w1_calc_crc8(u8 * data,int len)3551da177e4SLinus Torvalds u8 w1_calc_crc8(u8 * data, int len)
3561da177e4SLinus Torvalds {
3571da177e4SLinus Torvalds 	u8 crc = 0;
3581da177e4SLinus Torvalds 
3591da177e4SLinus Torvalds 	while (len--)
3601da177e4SLinus Torvalds 		crc = w1_crc8_table[crc ^ *data++];
3611da177e4SLinus Torvalds 
3621da177e4SLinus Torvalds 	return crc;
3631da177e4SLinus Torvalds }
364339f0723SAndrew Morton EXPORT_SYMBOL_GPL(w1_calc_crc8);
3651da177e4SLinus Torvalds 
w1_search_devices(struct w1_master * dev,u8 search_type,w1_slave_found_callback cb)36612003375SEvgeniy Polyakov void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
3671da177e4SLinus Torvalds {
3681da177e4SLinus Torvalds 	dev->attempts++;
3691da177e4SLinus Torvalds 	if (dev->bus_master->search)
370c30c9b15SDavid Fries 		dev->bus_master->search(dev->bus_master->data, dev,
371c30c9b15SDavid Fries 			search_type, cb);
3721da177e4SLinus Torvalds 	else
37312003375SEvgeniy Polyakov 		w1_search(dev, search_type, cb);
3741da177e4SLinus Torvalds }
3751da177e4SLinus Torvalds 
376ea7d8f65SEvgeniy Polyakov /**
377b3be177aSDavid Fries  * w1_reset_select_slave() - reset and select a slave
378b3be177aSDavid Fries  * @sl:		the slave to select
379b3be177aSDavid Fries  *
380ea7d8f65SEvgeniy Polyakov  * Resets the bus and then selects the slave by sending either a skip rom
381b3be177aSDavid Fries  * or a rom match.  A skip rom is issued if there is only one device
382b3be177aSDavid Fries  * registered on the bus.
383ea7d8f65SEvgeniy Polyakov  * The w1 master lock must be held.
384ea7d8f65SEvgeniy Polyakov  *
385b3be177aSDavid Fries  * Return:	0=success, anything else=error
386ea7d8f65SEvgeniy Polyakov  */
w1_reset_select_slave(struct w1_slave * sl)387ea7d8f65SEvgeniy Polyakov int w1_reset_select_slave(struct w1_slave *sl)
388ea7d8f65SEvgeniy Polyakov {
389ea7d8f65SEvgeniy Polyakov 	if (w1_reset_bus(sl->master))
390ea7d8f65SEvgeniy Polyakov 		return -1;
391ea7d8f65SEvgeniy Polyakov 
392ea7d8f65SEvgeniy Polyakov 	if (sl->master->slave_count == 1)
393ea7d8f65SEvgeniy Polyakov 		w1_write_8(sl->master, W1_SKIP_ROM);
394ea7d8f65SEvgeniy Polyakov 	else {
395ea7d8f65SEvgeniy Polyakov 		u8 match[9] = {W1_MATCH_ROM, };
396f00a1892SEvgeniy Polyakov 		u64 rn = le64_to_cpu(*((u64*)&sl->reg_num));
397f00a1892SEvgeniy Polyakov 
398f00a1892SEvgeniy Polyakov 		memcpy(&match[1], &rn, 8);
399ea7d8f65SEvgeniy Polyakov 		w1_write_block(sl->master, match, 9);
400ea7d8f65SEvgeniy Polyakov 	}
401ea7d8f65SEvgeniy Polyakov 	return 0;
402ea7d8f65SEvgeniy Polyakov }
403339f0723SAndrew Morton EXPORT_SYMBOL_GPL(w1_reset_select_slave);
4046a158c0dSDavid Fries 
4056a158c0dSDavid Fries /**
406b3be177aSDavid Fries  * w1_reset_resume_command() - resume instead of another match ROM
407b3be177aSDavid Fries  * @dev:	the master device
408b3be177aSDavid Fries  *
40967dfd54cSJean-François Dagenais  * When the workflow with a slave amongst many requires several
41067dfd54cSJean-François Dagenais  * successive commands a reset between each, this function is similar
41167dfd54cSJean-François Dagenais  * to doing a reset then a match ROM for the last matched ROM. The
41267dfd54cSJean-François Dagenais  * advantage being that the matched ROM step is skipped in favor of the
41367dfd54cSJean-François Dagenais  * resume command. The slave must support the command of course.
41467dfd54cSJean-François Dagenais  *
41567dfd54cSJean-François Dagenais  * If the bus has only one slave, traditionnaly the match ROM is skipped
41667dfd54cSJean-François Dagenais  * and a "SKIP ROM" is done for efficiency. On multi-slave busses, this
41767dfd54cSJean-François Dagenais  * doesn't work of course, but the resume command is the next best thing.
41867dfd54cSJean-François Dagenais  *
41967dfd54cSJean-François Dagenais  * The w1 master lock must be held.
42067dfd54cSJean-François Dagenais  */
w1_reset_resume_command(struct w1_master * dev)42167dfd54cSJean-François Dagenais int w1_reset_resume_command(struct w1_master *dev)
42267dfd54cSJean-François Dagenais {
42367dfd54cSJean-François Dagenais 	if (w1_reset_bus(dev))
42467dfd54cSJean-François Dagenais 		return -1;
42567dfd54cSJean-François Dagenais 
42662909da8SMariusz Bialonczyk 	w1_write_8(dev, dev->slave_count > 1 ? W1_RESUME_CMD : W1_SKIP_ROM);
42767dfd54cSJean-François Dagenais 	return 0;
42867dfd54cSJean-François Dagenais }
42967dfd54cSJean-François Dagenais EXPORT_SYMBOL_GPL(w1_reset_resume_command);
43067dfd54cSJean-François Dagenais 
43167dfd54cSJean-François Dagenais /**
432b3be177aSDavid Fries  * w1_next_pullup() - register for a strong pullup
433b3be177aSDavid Fries  * @dev:	the master device
434b3be177aSDavid Fries  * @delay:	time in milliseconds
435b3be177aSDavid Fries  *
4366a158c0dSDavid Fries  * Put out a strong pull-up of the specified duration after the next write
4376a158c0dSDavid Fries  * operation.  Not all hardware supports strong pullups.  Hardware that
4386a158c0dSDavid Fries  * doesn't support strong pullups will sleep for the given time after the
4396a158c0dSDavid Fries  * write operation without a strong pullup.  This is a one shot request for
4406a158c0dSDavid Fries  * the next write, specifying zero will clear a previous request.
4416a158c0dSDavid Fries  * The w1 master lock must be held.
4426a158c0dSDavid Fries  *
443b3be177aSDavid Fries  * Return:	0=success, anything else=error
4446a158c0dSDavid Fries  */
w1_next_pullup(struct w1_master * dev,int delay)4456a158c0dSDavid Fries void w1_next_pullup(struct w1_master *dev, int delay)
4466a158c0dSDavid Fries {
4476a158c0dSDavid Fries 	dev->pullup_duration = delay;
4486a158c0dSDavid Fries }
4496a158c0dSDavid Fries EXPORT_SYMBOL_GPL(w1_next_pullup);
450