123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /*
- * Copyright (c) 2015 Google, Inc
- * Written by Simon Glass <sjg@chromium.org>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
- #include <common.h>
- #include <dm.h>
- #include <errno.h>
- #include <i2c.h>
- #include <asm/gpio.h>
- DECLARE_GLOBAL_DATA_PTR;
- struct i2c_arbitrator_priv {
- struct gpio_desc ap_claim;
- struct gpio_desc ec_claim;
- uint slew_delay_us;
- uint wait_retry_ms;
- uint wait_free_ms;
- };
- int i2c_arbitrator_deselect(struct udevice *mux, struct udevice *bus,
- uint channel)
- {
- struct i2c_arbitrator_priv *priv = dev_get_priv(mux);
- int ret;
- debug("%s: %s\n", __func__, mux->name);
- ret = dm_gpio_set_value(&priv->ap_claim, 0);
- udelay(priv->slew_delay_us);
- return ret;
- }
- int i2c_arbitrator_select(struct udevice *mux, struct udevice *bus,
- uint channel)
- {
- struct i2c_arbitrator_priv *priv = dev_get_priv(mux);
- unsigned start;
- int ret;
- debug("%s: %s\n", __func__, mux->name);
- /* Start a round of trying to claim the bus */
- start = get_timer(0);
- do {
- unsigned start_retry;
- int waiting = 0;
- /* Indicate that we want to claim the bus */
- ret = dm_gpio_set_value(&priv->ap_claim, 1);
- if (ret)
- goto err;
- udelay(priv->slew_delay_us);
- /* Wait for the EC to release it */
- start_retry = get_timer(0);
- while (get_timer(start_retry) < priv->wait_retry_ms) {
- ret = dm_gpio_get_value(&priv->ec_claim);
- if (ret < 0) {
- goto err;
- } else if (!ret) {
- /* We got it, so return */
- return 0;
- }
- if (!waiting)
- waiting = 1;
- }
- /* It didn't release, so give up, wait, and try again */
- ret = dm_gpio_set_value(&priv->ap_claim, 0);
- if (ret)
- goto err;
- mdelay(priv->wait_retry_ms);
- } while (get_timer(start) < priv->wait_free_ms);
- /* Give up, release our claim */
- printf("I2C: Could not claim bus, timeout %lu\n", get_timer(start));
- ret = -ETIMEDOUT;
- ret = 0;
- err:
- return ret;
- }
- static int i2c_arbitrator_probe(struct udevice *dev)
- {
- struct i2c_arbitrator_priv *priv = dev_get_priv(dev);
- const void *blob = gd->fdt_blob;
- int node = dev_of_offset(dev);
- int ret;
- debug("%s: %s\n", __func__, dev->name);
- priv->slew_delay_us = fdtdec_get_int(blob, node, "slew-delay-us", 0);
- priv->wait_retry_ms = fdtdec_get_int(blob, node, "wait-retry-us", 0) /
- 1000;
- priv->wait_free_ms = fdtdec_get_int(blob, node, "wait-free-us", 0) /
- 1000;
- ret = gpio_request_by_name(dev, "our-claim-gpio", 0, &priv->ap_claim,
- GPIOD_IS_OUT);
- if (ret)
- goto err;
- ret = gpio_request_by_name(dev, "their-claim-gpios", 0, &priv->ec_claim,
- GPIOD_IS_IN);
- if (ret)
- goto err_ec_gpio;
- return 0;
- err_ec_gpio:
- dm_gpio_free(dev, &priv->ap_claim);
- err:
- debug("%s: ret=%d\n", __func__, ret);
- return ret;
- }
- static int i2c_arbitrator_remove(struct udevice *dev)
- {
- struct i2c_arbitrator_priv *priv = dev_get_priv(dev);
- dm_gpio_free(dev, &priv->ap_claim);
- dm_gpio_free(dev, &priv->ec_claim);
- return 0;
- }
- static const struct i2c_mux_ops i2c_arbitrator_ops = {
- .select = i2c_arbitrator_select,
- .deselect = i2c_arbitrator_deselect,
- };
- static const struct udevice_id i2c_arbitrator_ids[] = {
- { .compatible = "i2c-arb-gpio-challenge" },
- { }
- };
- U_BOOT_DRIVER(i2c_arbitrator) = {
- .name = "i2c_arbitrator",
- .id = UCLASS_I2C_MUX,
- .of_match = i2c_arbitrator_ids,
- .probe = i2c_arbitrator_probe,
- .remove = i2c_arbitrator_remove,
- .ops = &i2c_arbitrator_ops,
- .priv_auto_alloc_size = sizeof(struct i2c_arbitrator_priv),
- };
|