/*
 * This file is part of the coreboot project.
 *
 * 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 <stdlib.h>
#include <stdint.h>
#include <console/console.h>
#include <device/smbus.h>
#include <device/i2c_bus.h>

struct bus *i2c_link(struct device *const dev)
{
	if (!dev || !dev->bus)
		return NULL;

	struct bus *link = dev->bus;
	while (link) {
		struct device *const parent = link->dev;

		if (parent && parent->ops &&
		    (parent->ops->ops_i2c_bus || parent->ops->ops_smbus_bus))
			break;

		if (parent && parent->bus)
			link = parent->bus;
		else
			link = NULL;
	}

	if (!link) {
		printk(BIOS_ALERT, "%s Cannot find I2C or SMBus bus operations",
		       dev_path(dev));
	}

	return link;
}

int i2c_readb(struct device *const dev)
{
	struct device *const busdev = i2c_busdev(dev);
	if (!busdev)
		return -1;

	if (busdev->ops->ops_i2c_bus) {
		uint8_t val;
		const struct i2c_msg msg = {
			.flags	= I2C_M_RD,
			.slave	= dev->path.i2c.device,
			.buf	= &val,
			.len	= sizeof(val),
		};

		const int ret = busdev->ops->ops_i2c_bus->
			transfer(busdev, &msg, 1);
		if (ret)
			return ret;
		else
			return val;
	} else if (busdev->ops->ops_smbus_bus->recv_byte) {
		return busdev->ops->ops_smbus_bus->recv_byte(dev);
	} else {
		printk(BIOS_ERR, "%s Missing ops_smbus_bus->recv_byte",
		       dev_path(busdev));
		return -1;
	}
}

int i2c_writeb(struct device *const dev, uint8_t val)
{
	struct device *const busdev = i2c_busdev(dev);
	if (!busdev)
		return -1;

	if (busdev->ops->ops_i2c_bus) {
		const struct i2c_msg msg = {
			.flags	= 0,
			.slave	= dev->path.i2c.device,
			.buf	= &val,
			.len	= sizeof(val),
		};
		return busdev->ops->ops_i2c_bus->transfer(busdev, &msg, 1);
	} else if (busdev->ops->ops_smbus_bus->send_byte) {
		return busdev->ops->ops_smbus_bus->send_byte(dev, val);
	} else {
		printk(BIOS_ERR, "%s Missing ops_smbus_bus->send_byte",
		       dev_path(busdev));
		return -1;
	}
}

int i2c_readb_at(struct device *const dev, uint8_t off)
{
	struct device *const busdev = i2c_busdev(dev);
	if (!busdev)
		return -1;

	if (busdev->ops->ops_i2c_bus) {
		uint8_t val;
		const struct i2c_msg msg[] = {
			{
				.flags	= 0,
				.slave	= dev->path.i2c.device,
				.buf	= &off,
				.len	= sizeof(off),
			},
			{
				.flags	= I2C_M_RD,
				.slave	= dev->path.i2c.device,
				.buf	= &val,
				.len	= sizeof(val),
			},
		};

		const int ret = busdev->ops->ops_i2c_bus->
			transfer(busdev, msg, ARRAY_SIZE(msg));
		if (ret)
			return ret;
		else
			return val;
	} else if (busdev->ops->ops_smbus_bus->read_byte) {
		return busdev->ops->ops_smbus_bus->read_byte(dev, off);
	} else {
		printk(BIOS_ERR, "%s Missing ops_smbus_bus->read_byte",
		       dev_path(busdev));
		return -1;
	}
}

int i2c_writeb_at(struct device *const dev,
		  const uint8_t off, const uint8_t val)
{
	struct device *const busdev = i2c_busdev(dev);
	if (!busdev)
		return -1;

	if (busdev->ops->ops_i2c_bus) {
		uint8_t buf[] = { off, val };
		const struct i2c_msg msg = {
			.flags	= 0,
			.slave	= dev->path.i2c.device,
			.buf	= buf,
			.len	= sizeof(buf),
		};
		return busdev->ops->ops_i2c_bus->transfer(busdev, &msg, 1);
	} else if (busdev->ops->ops_smbus_bus->write_byte) {
		return busdev->ops->ops_smbus_bus->write_byte(dev, off, val);
	} else {
		printk(BIOS_ERR, "%s Missing ops_smbus_bus->write_byte",
		       dev_path(busdev));
		return -1;
	}
}
