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