/*
 * I2C Driver for Atmel ATSHA204 over I2C
 *
 * Copyright (C) 2014 Josh Datko, Cryptotronix, jbd@cryptotronix.com
 *		 2016 Tomas Hlavacek, CZ.NIC, tmshlvck@gmail.com
 *		 2017 Marek Behún, CZ.NIC, kabel@kernel.org
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <common.h>
#include <dm.h>
#include <i2c.h>
#include <errno.h>
#include <atsha204a-i2c.h>
#include <log.h>
#include <asm/global_data.h>
#include <linux/delay.h>
#include <linux/bitrev.h>
#include <u-boot/crc.h>

#define ATSHA204A_TWHI_US		2500
#define ATSHA204A_TRANSACTION_TIMEOUT	100000
#define ATSHA204A_TRANSACTION_RETRY	5
#define ATSHA204A_EXECTIME		5000

DECLARE_GLOBAL_DATA_PTR;

static inline u16 atsha204a_crc16(const u8 *buffer, size_t len)
{
	return bitrev16(crc16(0, buffer, len));
}

static int atsha204a_ping_bus(struct udevice *dev)
{
	struct udevice *bus = dev_get_parent(dev);
	struct i2c_msg msg;
	int speed;
	int res;
	u8 val = 0;

	speed = dm_i2c_get_bus_speed(bus);
	if (speed != I2C_SPEED_STANDARD_RATE) {
		int rv;

		rv = dm_i2c_set_bus_speed(bus, I2C_SPEED_STANDARD_RATE);
		if (rv)
			debug("Couldn't change the I2C bus speed\n");
	}

	/*
	 * The I2C drivers don't support sending messages when NAK is received.
	 * This chip requires wake up low signal on SDA for >= 60us.
	 * To achieve this, we slow the bus to 100kHz and send an empty
	 * message to address 0. This will hold the SDA line low for the
	 * required time to wake up the chip.
	 */
	msg.addr = 0;
	msg.flags = I2C_M_STOP;
	msg.len = sizeof(val);
	msg.buf = &val;

	res = dm_i2c_xfer(dev, &msg, 1);

	if (speed != I2C_SPEED_STANDARD_RATE) {
		int rv;

		rv = dm_i2c_set_bus_speed(bus, speed);
		if (rv)
			debug("Couldn't restore the I2C bus speed\n");
	}

	return res;
}

static int atsha204a_send(struct udevice *dev, const u8 *buf, u8 len)
{
	fdt_addr_t *priv = dev_get_priv(dev);
	struct i2c_msg msg;

	msg.addr = *priv;
	msg.flags = I2C_M_STOP;
	msg.len = len;
	msg.buf = (u8 *) buf;

	return dm_i2c_xfer(dev, &msg, 1);
}

static int atsha204a_recv(struct udevice *dev, u8 *buf, u8 len)
{
	fdt_addr_t *priv = dev_get_priv(dev);
	struct i2c_msg msg;

	msg.addr = *priv;
	msg.flags = I2C_M_RD | I2C_M_STOP;
	msg.len = len;
	msg.buf = (u8 *) buf;

	return dm_i2c_xfer(dev, &msg, 1);
}

static int atsha204a_recv_resp(struct udevice *dev,
			       struct atsha204a_resp *resp)
{
	int res;
	u16 resp_crc, computed_crc;
	u8 *p = (u8 *) resp;

	res = atsha204a_recv(dev, p, 4);
	if (res)
		return res;

	if (resp->length > 4) {
		if (resp->length > sizeof(*resp))
			return -EMSGSIZE;

		res = atsha204a_recv(dev, p + 4, resp->length - 4);
		if (res)
			return res;
	}

	resp_crc = (u16) p[resp->length - 2]
		   | (((u16) p[resp->length - 1]) << 8);
	computed_crc = atsha204a_crc16(p, resp->length - 2);

	if (resp_crc != computed_crc) {
		debug("Invalid checksum in ATSHA204A response\n");
		return -EBADMSG;
	}

	return 0;
}

int atsha204a_wakeup(struct udevice *dev)
{
	struct atsha204a_resp resp;
	int res;

	debug("Waking up ATSHA204A\n");

	/*
	 * The device ignores any levels or transitions on the SCL pin
	 * when the device is idle, asleep or during waking up.
	 * Don't check for error when waking up the device.
	 */
	atsha204a_ping_bus(dev);

	udelay(ATSHA204A_TWHI_US);

	res = atsha204a_recv_resp(dev, &resp);
	if (res) {
		debug("failed on receiving response, ending\n");
		return res;
	}

	if (resp.code != ATSHA204A_STATUS_AFTER_WAKE) {
		debug("failed (response code = %02x), ending\n", resp.code);
		return -EBADMSG;
	}

	debug("success\n");
	return 0;
}

int atsha204a_idle(struct udevice *dev)
{
	int res;
	u8 req = ATSHA204A_FUNC_IDLE;

	res = atsha204a_send(dev, &req, 1);
	if (res)
		debug("Failed putting ATSHA204A idle\n");
	return res;
}

int atsha204a_sleep(struct udevice *dev)
{
	int res;
	u8 req = ATSHA204A_FUNC_SLEEP;

	res = atsha204a_send(dev, &req, 1);
	if (res)
		debug("Failed putting ATSHA204A to sleep\n");
	return res;
}

static int atsha204a_transaction(struct udevice *dev, struct atsha204a_req *req,
				struct atsha204a_resp *resp)
{
	int res, timeout = ATSHA204A_TRANSACTION_TIMEOUT;

	res = atsha204a_send(dev, (u8 *) req, req->length + 1);
	if (res) {
		debug("ATSHA204A transaction send failed\n");
		return -EBUSY;
	}

	do {
		udelay(ATSHA204A_EXECTIME);
		res = atsha204a_recv_resp(dev, resp);
		if (!res || res == -EMSGSIZE || res == -EBADMSG)
			break;

		debug("ATSHA204A transaction polling for response "
		      "(timeout = %d)\n", timeout);

		timeout -= ATSHA204A_EXECTIME;
	} while (timeout > 0);

	if (timeout <= 0) {
		debug("ATSHA204A transaction timed out\n");
		return -ETIMEDOUT;
	}

	return res;
}

static void atsha204a_req_crc32(struct atsha204a_req *req)
{
	u8 *p = (u8 *) req;
	u16 computed_crc;
	u16 *crc_ptr = (u16 *) &p[req->length - 1];

	/* The buffer to crc16 starts at byte 1, not 0 */
	computed_crc = atsha204a_crc16(p + 1, req->length - 2);

	*crc_ptr = cpu_to_le16(computed_crc);
}

int atsha204a_read(struct udevice *dev, enum atsha204a_zone zone, bool read32,
		  u16 addr, u8 *buffer)
{
	int res, retry = ATSHA204A_TRANSACTION_RETRY;
	struct atsha204a_req req;
	struct atsha204a_resp resp;

	req.function = ATSHA204A_FUNC_COMMAND;
	req.length = 7;
	req.command = ATSHA204A_CMD_READ;

	req.param1 = (u8) zone;
	if (read32)
		req.param1 |= 0x80;

	req.param2 = cpu_to_le16(addr);

	atsha204a_req_crc32(&req);

	do {
		res = atsha204a_transaction(dev, &req, &resp);
		if (!res)
			break;

		debug("ATSHA204A read retry (%d)\n", retry);
		retry--;
		atsha204a_wakeup(dev);
	} while (retry >= 0);

	if (res) {
		debug("ATSHA204A read failed\n");
		return res;
	}

	if (resp.length != (read32 ? 32 : 4) + 3) {
		debug("ATSHA204A read bad response length (%d)\n",
		      resp.length);
		return -EBADMSG;
	}

	memcpy(buffer, ((u8 *) &resp) + 1, read32 ? 32 : 4);

	return 0;
}

int atsha204a_get_random(struct udevice *dev, u8 *buffer, size_t max)
{
	int res;
	struct atsha204a_req req;
	struct atsha204a_resp resp;

	req.function = ATSHA204A_FUNC_COMMAND;
	req.length = 7;
	req.command = ATSHA204A_CMD_RANDOM;

	req.param1 = 1;
	req.param2 = 0;

	/* We do not have to compute the checksum dynamically */
	req.data[0] = 0x27;
	req.data[1] = 0x47;

	res = atsha204a_transaction(dev, &req, &resp);
	if (res) {
		debug("ATSHA204A random transaction failed\n");
		return res;
	}

	memcpy(buffer, ((u8 *) &resp) + 1, max >= 32 ? 32 : max);
	return 0;
}

static int atsha204a_of_to_plat(struct udevice *dev)
{
	fdt_addr_t *priv = dev_get_priv(dev);
	fdt_addr_t addr;

	addr = dev_read_addr(dev);
	if (addr == FDT_ADDR_T_NONE) {
		debug("Can't get ATSHA204A I2C base address\n");
		return -ENXIO;
	}

	*priv = addr;
	return 0;
}

static const struct udevice_id atsha204a_ids[] = {
	{ .compatible = "atmel,atsha204" },
	{ .compatible = "atmel,atsha204a" },
	{ }
};

U_BOOT_DRIVER(atsha204) = {
	.name			= "atsha204",
	.id			= UCLASS_MISC,
	.of_match		= atsha204a_ids,
	.of_to_plat	= atsha204a_of_to_plat,
	.priv_auto	= sizeof(fdt_addr_t),
};
