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