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