coreboot-kgpe-d16/src/device/i2c.c

48 lines
1.1 KiB
C
Raw Normal View History

/*
* This file is part of the coreboot project.
*
* Copyright 2016 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/i2c_simple.h>
device: i2c: Add support for I2C bus operations In order to support doing bus operations on an I2C device that is described in the devicetree there needs to be some linkage of the device and the existing opaque I2C controller bus number. This is provided in a similar fashion to the existing SMBUS operations but modified to fit within the existing I2C infrastructure. Variants of the existing I2C helper functions are provided that will obtain the bus number that corresponds to this device by looking for the SOC-provided I2C bus operation structure to provide a function that will make that translation. For example an SOC using a PCI I2C controller at 0:15.0 could use: soc/intel/.../i2c.c: static int i2c_dev_to_bus(struct device *dev) { if (dev->path.pci.devfn == PCI_DEVFN(0x15, 0)) return 0; return -1; } static struct i2c_bus_operation i2c_bus_ops = { .dev_to_bus = &i2c_dev_to_bus } static struct device_operations i2c_dev_ops = { .ops_i2c_bus = &i2c_bus_ops ... } With an I2C device on that bus at address 0x1a described in the tree: devicetree.cb: device pci 15.0 on # I2C0 chip drivers/i2c/sample device i2c 1a.0 on end end end That driver can then do I2C transactions with the device object without needing to know that the SOC-specific bus number that this I2C device lives on is "0". For example it could read a version value from register address 0 with a byte transaction: drivers/i2c/sample/sample.c: static void i2c_sample_enable(struct device *dev) { uint8_t ver; if (!i2c_dev_readb(dev, 0x00, &ver)) printk(BIOS_INFO, "I2C %s version 0x02x\n", dev_path(dev), ver); } Change-Id: I6c41c8e0d10caabe01cc41da96382074de40e91e Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/15100 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org>
2016-06-08 00:38:14 +02:00
#include <stdint.h>
int i2c_read_field(unsigned bus, uint8_t chip, uint8_t reg, uint8_t *data,
uint8_t mask, uint8_t shift)
{
int ret;
uint8_t buf = 0;
ret = i2c_readb(bus, chip, reg, &buf);
buf &= (mask << shift);
*data = (buf >> shift);
return ret;
}
int i2c_write_field(unsigned bus, uint8_t chip, uint8_t reg, uint8_t data,
uint8_t mask, uint8_t shift)
{
int ret;
uint8_t buf = 0;
ret = i2c_readb(bus, chip, reg, &buf);
buf &= ~(mask << shift);
buf |= (data << shift);
ret |= i2c_writeb(bus, chip, reg, buf);
return ret;
}