/* Copyright 2013-2015 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define _GNU_SOURCE         /* for aspritnf */
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdint.h>
#include <dirent.h>
#include <sys/param.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <ccan/list/list.h>

#include "opal-prd.h"
#include "module.h"
#include "i2c.h"

struct i2c_bus {
	uint32_t		chip_id;
	uint8_t			engine;
	uint8_t			port;
	const char		*devpath;
	int			fd;
	struct list_node	link;
};

static struct list_head bus_list = LIST_HEAD_INIT(bus_list);

static int i2c_get_dev(uint32_t chip, uint8_t eng, uint8_t port, uint16_t dev)
{
	struct i2c_bus *b, *bus = NULL;

	list_for_each(&bus_list, b, link) {
		if (b->chip_id == chip && b->engine == eng && b->port == port) {
			bus = b;
			break;
		}
	}
	if (!bus) {
		pr_log(LOG_WARNING, "I2C: Bus %08x/%d/%d not found",
				chip, eng, port);
		return -1;
	}
	if (bus->fd < 0) {
		bus->fd = open(bus->devpath, O_RDWR);
		if (bus->fd < 0) {
			pr_log(LOG_ERR, "I2C: Failed to open %s: %m",
				bus->devpath);
			return -1;
		}
	}

	/* XXX We could use the I2C_SLAVE ioctl to check if the device
	 * is currently in use by a kernel driver...
	 */

	return bus->fd;
}

int i2c_read(uint32_t chip_id, uint8_t engine, uint8_t port,
	     uint16_t device, uint32_t offset_size, uint32_t offset,
	     uint32_t length, void* data)
{
	struct i2c_rdwr_ioctl_data ioargs;
	struct i2c_msg	msgs[2];
	uint8_t obuf[4];
	int fd, i, midx = 0;

	if (offset_size > 4) {
		pr_log(LOG_ERR, "I2C: Invalid write offset_size %d",
				offset_size);
		return -1;
	}
	fd = i2c_get_dev(chip_id, engine, port, device);
	if (fd == -1)
		return -1;

	/* If we have an offset, build a message for it */
	if (offset_size) {
		/* The offset has a variable size so let's handle this properly
		 * as it has to be laid out in memory MSB first
		 */
		for (i = 0; i < offset_size; i++)
			obuf[i] = offset >> (8 * (offset_size - i - 1));
		msgs[0].addr = device;
		msgs[0].flags = 0;
		msgs[0].buf = obuf;
		msgs[0].len = offset_size;
		midx = 1;
	}

	/* Build the message for the data portion */
	msgs[midx].addr = device;
	msgs[midx].flags = I2C_M_RD;
	msgs[midx].buf = data;
	msgs[midx].len = length;
	midx++;

	ioargs.msgs = msgs;
	ioargs.nmsgs = midx;
	if (ioctl(fd, I2C_RDWR, &ioargs) < 0) {
		pr_log(LOG_ERR, "I2C: Read error: %m");
		return -1;
	}
	pr_debug("I2C: Read from %08x:%d:%d@%02x+0x%x %d bytes ok",
	       chip_id, engine, port, device, offset_size ? offset : 0, length);

	return 0;
}

int i2c_write(uint32_t chip_id, uint8_t engine, uint8_t port,
	      uint16_t device, uint32_t offset_size, uint32_t offset,
	      uint32_t length, void* data)
{
	struct i2c_rdwr_ioctl_data ioargs;
	struct i2c_msg msg;
	int fd, size, i, rc;
	uint8_t *buf;

	if (offset_size > 4) {
		pr_log(LOG_ERR, "I2C: Invalid write offset_size %d",
				offset_size);
		return -1;
	}
	fd = i2c_get_dev(chip_id, engine, port, device);
	if (fd == -1)
		return -1;

	/* Not all kernel driver versions support breaking up a write into
	 * two components (offset, data), so we coalesce them first and
	 * issue a single write. The offset is laid out in BE format.
	 */
	size = offset_size + length;
	buf = malloc(size);
	if (!buf) {
		pr_log(LOG_ERR, "I2C: Out of memory");
		return -1;
	}

	/* The offset has a variable size so let's handle this properly
	 * as it has to be laid out in memory MSB first
	 */
	for (i = 0; i < offset_size; i++)
		buf[i] = offset >> (8 * (offset_size - i - 1));

	/* Copy the remaining data */
	memcpy(buf + offset_size, data, length);

	/* Build the message */
	msg.addr = device;
	msg.flags = 0;
	msg.buf = buf;
	msg.len = size;
	ioargs.msgs = &msg;
	ioargs.nmsgs = 1;
	rc = ioctl(fd, I2C_RDWR, &ioargs);
	free(buf);
	if (rc < 0) {
		pr_log(LOG_ERR, "I2C: Write error: %m");
		return -1;
	}

	return 0;
}

static void i2c_add_bus(uint32_t chip, uint32_t engine, uint32_t port,
			const char *devname)
{
	struct i2c_bus *b = malloc(sizeof(struct i2c_bus));
	char *dn;

	if (asprintf(&dn, "/dev/%s", devname) < 0) {
		pr_log(LOG_ERR, "I2C: Error creating devpath for %s: %m",
			devname);
		free(b);
		return;
	}

	memset(b, 0, sizeof(*b));
	b->chip_id = chip;
	b->engine = engine;
	b->port = port;
	b->devpath = dn;
	b->fd = -1;
	list_add(&bus_list, &b->link);
}

void i2c_init(void)
{
#define SYSFS	"/sys"	/* XXX Find it ? */
	DIR *devsdir;
	struct dirent *devent;
	char dpath[PATH_MAX];
	char busname[256];
	char *s;
	FILE *f;
	unsigned int chip, engine, port;

	/* Ensure i2c-dev is loaded */
	insert_module("i2c-dev");

	/* Get directory of i2c char devs in sysfs */
	devsdir = opendir(SYSFS "/class/i2c-dev");
	if (!devsdir) {
		pr_log(LOG_ERR, "I2C: Error opening "
					SYSFS "/class/i2c-dev: %m");
		return;
	}
	while ((devent = readdir(devsdir)) != NULL) {
		if (!strcmp(devent->d_name, "."))
			continue;
		if (!strcmp(devent->d_name, ".."))
			continue;

		/* Get bus name */
		sprintf(dpath, SYSFS "/class/i2c-dev/%s/name", devent->d_name);
		f = fopen(dpath, "r");
		if (!f) {
			pr_log(LOG_NOTICE, "I2C: Can't open %s: %m, skipping.",
					dpath);
			continue;
		}
		s = fgets(busname, sizeof(busname), f);
		fclose(f);
		if (!s) {
			pr_log(LOG_NOTICE, "Failed to read %s, skipping.",
					dpath);
			continue;
		}

		/* Is this a P8 or Centaur i2c bus ? No -> move on */
		if (strncmp(s, "p8_", 3) == 0)
			sscanf(s, "p8_%x_e%dp%d", &chip, &engine, &port);
		else if (strncmp(s, "cen_", 4) == 0)
			sscanf(s, "cen_%x_e%dp%d", &chip, &engine, &port);
		else
			continue;

		pr_log(LOG_INFO, "I2C: Found Chip: %08x engine %d port %d",
		       chip, engine, port);
		i2c_add_bus(chip, engine, port, devent->d_name);
	}
	closedir(devsdir);
}

