blob: 8c04aecb72c0b3eb415d68f5817d1922cdf61a2e [file] [log] [blame]
/*
* Copyright 2013 Google Inc. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*/
#include <assert.h>
#include "base/list.h"
#include "base/time.h"
#include "base/xalloc.h"
#include "drivers/board/daisy/i2c_arb.h"
#include "drivers/bus/i2c/i2c.h"
#include "drivers/gpio/gpio.h"
static void i2c_release_bus(GpioOps *request)
{
gpio_set(request, 1);
}
static int i2c_claim_bus(GpioOps *request, GpioOps *grant)
{
// Request the bus.
if (gpio_set(request, 0) < 0)
return 1;
// Wait for the EC to give it to us.
int timeout = 2000 * 100; // 2s.
while (timeout--) {
int value = gpio_get(grant);
if (value < 0) {
i2c_release_bus(request);
return 1;
}
if (value == 1)
return 0;
udelay(10);
}
// Time out, recind our request.
i2c_release_bus(request);
return 1;
}
static int i2c_arb_transfer(struct I2cOps *me, I2cSeg *segments, int seg_count)
{
assert(me);
SnowI2cArb *arb = container_of(me, SnowI2cArb, ops);
if (!arb->ready) {
i2c_release_bus(arb->request);
arb->ready = 1;
}
if (i2c_claim_bus(arb->request, arb->grant))
return 1;
int res = arb->bus->transfer(arb->bus, segments, seg_count);
i2c_release_bus(arb->request);
return res;
}
SnowI2cArb *new_snow_i2c_arb(I2cOps *bus, GpioOps *request, GpioOps *grant)
{
SnowI2cArb *arb = xzalloc(sizeof(*arb));
arb->ops.transfer = &i2c_arb_transfer;
arb->bus = bus;
arb->request = request;
arb->grant = grant;
return arb;
}