xref: /openbmc/u-boot/drivers/w1/w1-gpio.c (revision 592cd5de)
1*73aea285SMaxime Ripard /* SPDX-License-Identifier:	GPL-2.0+
2*73aea285SMaxime Ripard  *
3*73aea285SMaxime Ripard  * Copyright (c) 2015 Free Electrons
4*73aea285SMaxime Ripard  * Copyright (c) 2015 NextThing Co
5*73aea285SMaxime Ripard  *
6*73aea285SMaxime Ripard  * Maxime Ripard <maxime.ripard@free-electrons.com>
7*73aea285SMaxime Ripard  *
8*73aea285SMaxime Ripard  */
9*73aea285SMaxime Ripard 
10*73aea285SMaxime Ripard #include <common.h>
11*73aea285SMaxime Ripard #include <dm.h>
12*73aea285SMaxime Ripard #include <w1.h>
13*73aea285SMaxime Ripard 
14*73aea285SMaxime Ripard #include <asm/gpio.h>
15*73aea285SMaxime Ripard 
16*73aea285SMaxime Ripard #define W1_TIMING_A	6
17*73aea285SMaxime Ripard #define W1_TIMING_B	64
18*73aea285SMaxime Ripard #define W1_TIMING_C	60
19*73aea285SMaxime Ripard #define W1_TIMING_D	10
20*73aea285SMaxime Ripard #define W1_TIMING_E	9
21*73aea285SMaxime Ripard #define W1_TIMING_F	55
22*73aea285SMaxime Ripard #define W1_TIMING_G	0
23*73aea285SMaxime Ripard #define W1_TIMING_H	480
24*73aea285SMaxime Ripard #define W1_TIMING_I	70
25*73aea285SMaxime Ripard #define W1_TIMING_J	410
26*73aea285SMaxime Ripard 
27*73aea285SMaxime Ripard struct w1_gpio_pdata {
28*73aea285SMaxime Ripard 	struct gpio_desc	gpio;
29*73aea285SMaxime Ripard 	u64			search_id;
30*73aea285SMaxime Ripard };
31*73aea285SMaxime Ripard 
w1_gpio_read_bit(struct udevice * dev)32*73aea285SMaxime Ripard static bool w1_gpio_read_bit(struct udevice *dev)
33*73aea285SMaxime Ripard {
34*73aea285SMaxime Ripard 	struct w1_gpio_pdata *pdata = dev_get_platdata(dev);
35*73aea285SMaxime Ripard 	int val;
36*73aea285SMaxime Ripard 
37*73aea285SMaxime Ripard 	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT);
38*73aea285SMaxime Ripard 	udelay(W1_TIMING_A);
39*73aea285SMaxime Ripard 
40*73aea285SMaxime Ripard 	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_IN);
41*73aea285SMaxime Ripard 	udelay(W1_TIMING_E);
42*73aea285SMaxime Ripard 
43*73aea285SMaxime Ripard 	val = dm_gpio_get_value(&pdata->gpio);
44*73aea285SMaxime Ripard 	if (val < 0)
45*73aea285SMaxime Ripard 		debug("error in retrieving GPIO value");
46*73aea285SMaxime Ripard 	udelay(W1_TIMING_F);
47*73aea285SMaxime Ripard 
48*73aea285SMaxime Ripard 	return val;
49*73aea285SMaxime Ripard }
50*73aea285SMaxime Ripard 
w1_gpio_read_byte(struct udevice * dev)51*73aea285SMaxime Ripard static u8 w1_gpio_read_byte(struct udevice *dev)
52*73aea285SMaxime Ripard {
53*73aea285SMaxime Ripard 	int i;
54*73aea285SMaxime Ripard 	u8 ret = 0;
55*73aea285SMaxime Ripard 
56*73aea285SMaxime Ripard 	for (i = 0; i < 8; ++i)
57*73aea285SMaxime Ripard 		ret |= (w1_gpio_read_bit(dev) ? 1 : 0) << i;
58*73aea285SMaxime Ripard 
59*73aea285SMaxime Ripard 	return ret;
60*73aea285SMaxime Ripard }
61*73aea285SMaxime Ripard 
w1_gpio_write_bit(struct udevice * dev,bool bit)62*73aea285SMaxime Ripard static void w1_gpio_write_bit(struct udevice *dev, bool bit)
63*73aea285SMaxime Ripard {
64*73aea285SMaxime Ripard 	struct w1_gpio_pdata *pdata = dev_get_platdata(dev);
65*73aea285SMaxime Ripard 
66*73aea285SMaxime Ripard 	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT);
67*73aea285SMaxime Ripard 
68*73aea285SMaxime Ripard 	bit ? udelay(W1_TIMING_A) : udelay(W1_TIMING_C);
69*73aea285SMaxime Ripard 
70*73aea285SMaxime Ripard 	dm_gpio_set_value(&pdata->gpio, 1);
71*73aea285SMaxime Ripard 
72*73aea285SMaxime Ripard 	bit ? udelay(W1_TIMING_B) : udelay(W1_TIMING_D);
73*73aea285SMaxime Ripard }
74*73aea285SMaxime Ripard 
w1_gpio_write_byte(struct udevice * dev,u8 byte)75*73aea285SMaxime Ripard static void w1_gpio_write_byte(struct udevice *dev, u8 byte)
76*73aea285SMaxime Ripard {
77*73aea285SMaxime Ripard 	int i;
78*73aea285SMaxime Ripard 
79*73aea285SMaxime Ripard 	for (i = 0; i < 8; ++i)
80*73aea285SMaxime Ripard 		w1_gpio_write_bit(dev, (byte >> i) & 0x1);
81*73aea285SMaxime Ripard }
82*73aea285SMaxime Ripard 
w1_gpio_reset(struct udevice * dev)83*73aea285SMaxime Ripard static bool w1_gpio_reset(struct udevice *dev)
84*73aea285SMaxime Ripard {
85*73aea285SMaxime Ripard 	struct w1_gpio_pdata *pdata = dev_get_platdata(dev);
86*73aea285SMaxime Ripard 	int val;
87*73aea285SMaxime Ripard 
88*73aea285SMaxime Ripard 	/* initiate the reset pulse. first we must pull the bus to low */
89*73aea285SMaxime Ripard 	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
90*73aea285SMaxime Ripard 	udelay(W1_TIMING_G);
91*73aea285SMaxime Ripard 
92*73aea285SMaxime Ripard 	dm_gpio_set_value(&pdata->gpio, 0);
93*73aea285SMaxime Ripard 	/* wait for the specified time with the bus kept low */
94*73aea285SMaxime Ripard 	udelay(W1_TIMING_H);
95*73aea285SMaxime Ripard 
96*73aea285SMaxime Ripard 	/* now we must read the presence pulse */
97*73aea285SMaxime Ripard 	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_IN);
98*73aea285SMaxime Ripard 	udelay(W1_TIMING_I);
99*73aea285SMaxime Ripard 
100*73aea285SMaxime Ripard 	val = dm_gpio_get_value(&pdata->gpio);
101*73aea285SMaxime Ripard 	if (val < 0)
102*73aea285SMaxime Ripard 		debug("error in retrieving GPIO value");
103*73aea285SMaxime Ripard 
104*73aea285SMaxime Ripard 	/* if nobody pulled the bus down , it means nobody is on the bus */
105*73aea285SMaxime Ripard 	if (val != 0)
106*73aea285SMaxime Ripard 		return 1;
107*73aea285SMaxime Ripard 	/* we have the bus pulled down, let's wait for the specified presence time */
108*73aea285SMaxime Ripard 	udelay(W1_TIMING_J);
109*73aea285SMaxime Ripard 
110*73aea285SMaxime Ripard 	/* read again, the other end should leave the bus free */
111*73aea285SMaxime Ripard 	val = dm_gpio_get_value(&pdata->gpio);
112*73aea285SMaxime Ripard 	if (val < 0)
113*73aea285SMaxime Ripard 		debug("error in retrieving GPIO value");
114*73aea285SMaxime Ripard 
115*73aea285SMaxime Ripard 	/* bus is not going up again, so we have an error */
116*73aea285SMaxime Ripard 	if (val != 1)
117*73aea285SMaxime Ripard 		return 1;
118*73aea285SMaxime Ripard 
119*73aea285SMaxime Ripard 	/* all good, presence detected */
120*73aea285SMaxime Ripard 	return 0;
121*73aea285SMaxime Ripard }
122*73aea285SMaxime Ripard 
w1_gpio_triplet(struct udevice * dev,bool bdir)123*73aea285SMaxime Ripard static u8 w1_gpio_triplet(struct udevice *dev, bool bdir)
124*73aea285SMaxime Ripard {
125*73aea285SMaxime Ripard 	u8 id_bit   = w1_gpio_read_bit(dev);
126*73aea285SMaxime Ripard 	u8 comp_bit = w1_gpio_read_bit(dev);
127*73aea285SMaxime Ripard 	u8 retval;
128*73aea285SMaxime Ripard 
129*73aea285SMaxime Ripard 	if (id_bit && comp_bit)
130*73aea285SMaxime Ripard 		return 0x03;  /* error */
131*73aea285SMaxime Ripard 
132*73aea285SMaxime Ripard 	if (!id_bit && !comp_bit) {
133*73aea285SMaxime Ripard 		/* Both bits are valid, take the direction given */
134*73aea285SMaxime Ripard 		retval = bdir ? 0x04 : 0;
135*73aea285SMaxime Ripard 	} else {
136*73aea285SMaxime Ripard 		/* Only one bit is valid, take that direction */
137*73aea285SMaxime Ripard 		bdir = id_bit;
138*73aea285SMaxime Ripard 		retval = id_bit ? 0x05 : 0x02;
139*73aea285SMaxime Ripard 	}
140*73aea285SMaxime Ripard 
141*73aea285SMaxime Ripard 	w1_gpio_write_bit(dev, bdir);
142*73aea285SMaxime Ripard 	return retval;
143*73aea285SMaxime Ripard }
144*73aea285SMaxime Ripard 
145*73aea285SMaxime Ripard static const struct w1_ops w1_gpio_ops = {
146*73aea285SMaxime Ripard 	.read_byte	= w1_gpio_read_byte,
147*73aea285SMaxime Ripard 	.reset		= w1_gpio_reset,
148*73aea285SMaxime Ripard 	.triplet	= w1_gpio_triplet,
149*73aea285SMaxime Ripard 	.write_byte	= w1_gpio_write_byte,
150*73aea285SMaxime Ripard };
151*73aea285SMaxime Ripard 
w1_gpio_ofdata_to_platdata(struct udevice * dev)152*73aea285SMaxime Ripard static int w1_gpio_ofdata_to_platdata(struct udevice *dev)
153*73aea285SMaxime Ripard {
154*73aea285SMaxime Ripard 	struct w1_gpio_pdata *pdata = dev_get_platdata(dev);
155*73aea285SMaxime Ripard 	int ret;
156*73aea285SMaxime Ripard 
157*73aea285SMaxime Ripard 	ret = gpio_request_by_name(dev, "gpios", 0, &pdata->gpio, 0);
158*73aea285SMaxime Ripard 	if (ret < 0)
159*73aea285SMaxime Ripard 		printf("Error claiming GPIO %d\n", ret);
160*73aea285SMaxime Ripard 
161*73aea285SMaxime Ripard 	return ret;
162*73aea285SMaxime Ripard };
163*73aea285SMaxime Ripard 
164*73aea285SMaxime Ripard static const struct udevice_id w1_gpio_id[] = {
165*73aea285SMaxime Ripard 	{ "w1-gpio", 0 },
166*73aea285SMaxime Ripard 	{ },
167*73aea285SMaxime Ripard };
168*73aea285SMaxime Ripard 
169*73aea285SMaxime Ripard U_BOOT_DRIVER(w1_gpio_drv) = {
170*73aea285SMaxime Ripard 	.id				= UCLASS_W1,
171*73aea285SMaxime Ripard 	.name				= "w1_gpio_drv",
172*73aea285SMaxime Ripard 	.of_match			= w1_gpio_id,
173*73aea285SMaxime Ripard 	.ofdata_to_platdata		= w1_gpio_ofdata_to_platdata,
174*73aea285SMaxime Ripard 	.ops				= &w1_gpio_ops,
175*73aea285SMaxime Ripard 	.platdata_auto_alloc_size	= sizeof(struct w1_gpio_pdata),
176*73aea285SMaxime Ripard };
177