mirror of
https://github.com/smaeul/u-boot.git
synced 2025-10-20 07:38:14 +01:00
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"' I failed to notice that b4 noticed it was based on next and so took that as the base commit and merged that part of next to master. This reverts commit c8ffd1356d42223cbb8c86280a083cc3c93e6426, reversing changes made to 2ee6f3a5f7550de3599faef9704e166e5dcace35. Reported-by: Jonas Karlman <jonas@kwiboo.se> Signed-off-by: Tom Rini <trini@konsulko.com>
151 lines
3.4 KiB
C
151 lines
3.4 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (c) 2015 Google, Inc
|
|
* Written by Simon Glass <sjg@chromium.org>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <dm.h>
|
|
#include <errno.h>
|
|
#include <i2c.h>
|
|
#include <log.h>
|
|
#include <malloc.h>
|
|
#include <asm/global_data.h>
|
|
#include <asm/gpio.h>
|
|
#include <linux/delay.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 = sizeof(struct i2c_arbitrator_priv),
|
|
};
|