07600c5022d94f6725cb246b8d806de718a2d123
[oweals/u-boot.git] / drivers / i2c / muxes / i2c-arb-gpio-challenge.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <i2c.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <asm/gpio.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 struct i2c_arbitrator_priv {
18         struct gpio_desc ap_claim;
19         struct gpio_desc ec_claim;
20         uint slew_delay_us;
21         uint wait_retry_ms;
22         uint wait_free_ms;
23 };
24
25 int i2c_arbitrator_deselect(struct udevice *mux, struct udevice *bus,
26                             uint channel)
27 {
28         struct i2c_arbitrator_priv *priv = dev_get_priv(mux);
29         int ret;
30
31         debug("%s: %s\n", __func__, mux->name);
32         ret = dm_gpio_set_value(&priv->ap_claim, 0);
33         udelay(priv->slew_delay_us);
34
35         return ret;
36 }
37
38 int i2c_arbitrator_select(struct udevice *mux, struct udevice *bus,
39                           uint channel)
40 {
41         struct i2c_arbitrator_priv *priv = dev_get_priv(mux);
42         unsigned start;
43         int ret;
44
45         debug("%s: %s\n", __func__, mux->name);
46         /* Start a round of trying to claim the bus */
47         start = get_timer(0);
48         do {
49                 unsigned start_retry;
50                 int waiting = 0;
51
52                 /* Indicate that we want to claim the bus */
53                 ret = dm_gpio_set_value(&priv->ap_claim, 1);
54                 if (ret)
55                         goto err;
56                 udelay(priv->slew_delay_us);
57
58                 /* Wait for the EC to release it */
59                 start_retry = get_timer(0);
60                 while (get_timer(start_retry) < priv->wait_retry_ms) {
61                         ret = dm_gpio_get_value(&priv->ec_claim);
62                         if (ret < 0) {
63                                 goto err;
64                         } else if (!ret) {
65                                 /* We got it, so return */
66                                 return 0;
67                         }
68
69                         if (!waiting)
70                                 waiting = 1;
71                 }
72
73                 /* It didn't release, so give up, wait, and try again */
74                 ret = dm_gpio_set_value(&priv->ap_claim, 0);
75                 if (ret)
76                         goto err;
77
78                 mdelay(priv->wait_retry_ms);
79         } while (get_timer(start) < priv->wait_free_ms);
80
81         /* Give up, release our claim */
82         printf("I2C: Could not claim bus, timeout %lu\n", get_timer(start));
83         ret = -ETIMEDOUT;
84         ret = 0;
85 err:
86         return ret;
87 }
88
89 static int i2c_arbitrator_probe(struct udevice *dev)
90 {
91         struct i2c_arbitrator_priv *priv = dev_get_priv(dev);
92         const void *blob = gd->fdt_blob;
93         int node = dev_of_offset(dev);
94         int ret;
95
96         debug("%s: %s\n", __func__, dev->name);
97         priv->slew_delay_us = fdtdec_get_int(blob, node, "slew-delay-us", 0);
98         priv->wait_retry_ms = fdtdec_get_int(blob, node, "wait-retry-us", 0) /
99                 1000;
100         priv->wait_free_ms = fdtdec_get_int(blob, node, "wait-free-us", 0) /
101                 1000;
102         ret = gpio_request_by_name(dev, "our-claim-gpio", 0, &priv->ap_claim,
103                                    GPIOD_IS_OUT);
104         if (ret)
105                 goto err;
106         ret = gpio_request_by_name(dev, "their-claim-gpios", 0, &priv->ec_claim,
107                                    GPIOD_IS_IN);
108         if (ret)
109                 goto err_ec_gpio;
110
111         return 0;
112
113 err_ec_gpio:
114         dm_gpio_free(dev, &priv->ap_claim);
115 err:
116         debug("%s: ret=%d\n", __func__, ret);
117         return ret;
118 }
119
120 static int i2c_arbitrator_remove(struct udevice *dev)
121 {
122         struct i2c_arbitrator_priv *priv = dev_get_priv(dev);
123
124         dm_gpio_free(dev, &priv->ap_claim);
125         dm_gpio_free(dev, &priv->ec_claim);
126
127         return 0;
128 }
129
130 static const struct i2c_mux_ops i2c_arbitrator_ops = {
131         .select         = i2c_arbitrator_select,
132         .deselect       = i2c_arbitrator_deselect,
133 };
134
135 static const struct udevice_id i2c_arbitrator_ids[] = {
136         { .compatible = "i2c-arb-gpio-challenge" },
137         { }
138 };
139
140 U_BOOT_DRIVER(i2c_arbitrator) = {
141         .name = "i2c_arbitrator",
142         .id = UCLASS_I2C_MUX,
143         .of_match = i2c_arbitrator_ids,
144         .probe = i2c_arbitrator_probe,
145         .remove = i2c_arbitrator_remove,
146         .ops = &i2c_arbitrator_ops,
147         .priv_auto_alloc_size = sizeof(struct i2c_arbitrator_priv),
148 };