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