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