/** * struct i2c_arbitrator_data - Driver data for I2C arbitrator * * @our_gpio: GPIO descriptor we'll use to claim. * @their_gpio: GPIO descriptor that the other side will use to claim. * @slew_delay_us: microseconds to wait for a GPIO to go high. * @wait_retry_us: we'll attempt another claim after this many microseconds. * @wait_free_us: we'll give up after this many microseconds.
*/
/* * i2c_arbitrator_select - claim the I2C bus * * Use the GPIO-based signalling protocol; return -EBUSY if we fail.
*/ staticint i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
{ conststruct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); unsignedlong stop_retry, stop_time;
/* Start a round of trying to claim the bus */
stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1; do { /* Indicate that we want to claim the bus */
gpiod_set_value(arb->our_gpio, 1);
udelay(arb->slew_delay_us);
/* Wait for the other master to release it */
stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1; while (time_before(jiffies, stop_retry)) { int gpio_val = gpiod_get_value(arb->their_gpio);
if (!gpio_val) { /* We got it, so return */ return 0;
}
usleep_range(50, 200);
}
/* It didn't release, so give up, wait, and try again */
gpiod_set_value(arb->our_gpio, 0);
usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2);
} while (time_before(jiffies, stop_time));
/* Give up, release our claim */
gpiod_set_value(arb->our_gpio, 0);
udelay(arb->slew_delay_us);
dev_err(muxc->dev, "Could not claim bus, timeout\n"); return -EBUSY;
}
/* * i2c_arbitrator_deselect - release the I2C bus * * Release the I2C bus using the GPIO-based signalling protocol.
*/ staticint i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan)
{ conststruct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
/* Release the bus and wait for the other master to notice */
gpiod_set_value(arb->our_gpio, 0);
udelay(arb->slew_delay_us);
/* We only support probing from device tree; no platform_data */ if (!np) {
dev_err(dev, "Cannot find device tree node\n"); return -ENODEV;
} if (dev_get_platdata(dev)) {
dev_err(dev, "Platform data is not supported\n"); return -EINVAL;
}
/* Request GPIOs, our GPIO as unclaimed to begin with */
arb->our_gpio = devm_gpiod_get(dev, "our-claim", GPIOD_OUT_LOW); if (IS_ERR(arb->our_gpio)) {
dev_err(dev, "could not get \"our-claim\" GPIO (%ld)\n",
PTR_ERR(arb->our_gpio)); return PTR_ERR(arb->our_gpio);
}
arb->their_gpio = devm_gpiod_get(dev, "their-claim", GPIOD_IN); if (IS_ERR(arb->their_gpio)) {
dev_err(dev, "could not get \"their-claim\" GPIO (%ld)\n",
PTR_ERR(arb->their_gpio)); return PTR_ERR(arb->their_gpio);
}
/* At the moment we only support a single two master (us + 1 other) */
dummy = devm_gpiod_get_index(dev, "their-claim", 1, GPIOD_IN); if (!IS_ERR(dummy)) {
dev_err(dev, "Only one other master is supported\n"); return -EINVAL;
} elseif (PTR_ERR(dummy) == -EPROBE_DEFER) { return -EPROBE_DEFER;
}
/* Arbitration parameters */ if (of_property_read_u32(np, "slew-delay-us", &arb->slew_delay_us))
arb->slew_delay_us = 10; if (of_property_read_u32(np, "wait-retry-us", &arb->wait_retry_us))
arb->wait_retry_us = 3000; if (of_property_read_u32(np, "wait-free-us", &arb->wait_free_us))
arb->wait_free_us = 50000;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.