/* SPDX-License-Identifier:	GPL-2.0+
 *
 * Copyright (c) 2015 Free Electrons
 * Copyright (c) 2015 NextThing Co
 *
 * Maxime Ripard <maxime.ripard@free-electrons.com>
 *
 */

#include <common.h>
#include <dm.h>
#include <w1.h>

#include <asm/gpio.h>

#define W1_TIMING_A	6
#define W1_TIMING_B	64
#define W1_TIMING_C	60
#define W1_TIMING_D	10
#define W1_TIMING_E	9
#define W1_TIMING_F	55
#define W1_TIMING_G	0
#define W1_TIMING_H	480
#define W1_TIMING_I	70
#define W1_TIMING_J	410

struct w1_gpio_pdata {
	struct gpio_desc	gpio;
	u64			search_id;
};

static bool w1_gpio_read_bit(struct udevice *dev)
{
	struct w1_gpio_pdata *pdata = dev_get_platdata(dev);
	int val;

	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT);
	udelay(W1_TIMING_A);

	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_IN);
	udelay(W1_TIMING_E);

	val = dm_gpio_get_value(&pdata->gpio);
	if (val < 0)
		debug("error in retrieving GPIO value");
	udelay(W1_TIMING_F);

	return val;
}

static u8 w1_gpio_read_byte(struct udevice *dev)
{
	int i;
	u8 ret = 0;

	for (i = 0; i < 8; ++i)
		ret |= (w1_gpio_read_bit(dev) ? 1 : 0) << i;

	return ret;
}

static void w1_gpio_write_bit(struct udevice *dev, bool bit)
{
	struct w1_gpio_pdata *pdata = dev_get_platdata(dev);

	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT);

	bit ? udelay(W1_TIMING_A) : udelay(W1_TIMING_C);

	dm_gpio_set_value(&pdata->gpio, 1);

	bit ? udelay(W1_TIMING_B) : udelay(W1_TIMING_D);
}

static void w1_gpio_write_byte(struct udevice *dev, u8 byte)
{
	int i;

	for (i = 0; i < 8; ++i)
		w1_gpio_write_bit(dev, (byte >> i) & 0x1);
}

static bool w1_gpio_reset(struct udevice *dev)
{
	struct w1_gpio_pdata *pdata = dev_get_platdata(dev);
	int val;

	/* initiate the reset pulse. first we must pull the bus to low */
	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
	udelay(W1_TIMING_G);

	dm_gpio_set_value(&pdata->gpio, 0);
	/* wait for the specified time with the bus kept low */
	udelay(W1_TIMING_H);

	/* now we must read the presence pulse */
	dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_IN);
	udelay(W1_TIMING_I);

	val = dm_gpio_get_value(&pdata->gpio);
	if (val < 0)
		debug("error in retrieving GPIO value");

	/* if nobody pulled the bus down , it means nobody is on the bus */
	if (val != 0)
		return 1;
	/* we have the bus pulled down, let's wait for the specified presence time */
	udelay(W1_TIMING_J);

	/* read again, the other end should leave the bus free */
	val = dm_gpio_get_value(&pdata->gpio);
	if (val < 0)
		debug("error in retrieving GPIO value");

	/* bus is not going up again, so we have an error */
	if (val != 1)
		return 1;

	/* all good, presence detected */
	return 0;
}

static u8 w1_gpio_triplet(struct udevice *dev, bool bdir)
{
	u8 id_bit   = w1_gpio_read_bit(dev);
	u8 comp_bit = w1_gpio_read_bit(dev);
	u8 retval;

	if (id_bit && comp_bit)
		return 0x03;  /* error */

	if (!id_bit && !comp_bit) {
		/* Both bits are valid, take the direction given */
		retval = bdir ? 0x04 : 0;
	} else {
		/* Only one bit is valid, take that direction */
		bdir = id_bit;
		retval = id_bit ? 0x05 : 0x02;
	}

	w1_gpio_write_bit(dev, bdir);
	return retval;
}

static const struct w1_ops w1_gpio_ops = {
	.read_byte	= w1_gpio_read_byte,
	.reset		= w1_gpio_reset,
	.triplet	= w1_gpio_triplet,
	.write_byte	= w1_gpio_write_byte,
};

static int w1_gpio_ofdata_to_platdata(struct udevice *dev)
{
	struct w1_gpio_pdata *pdata = dev_get_platdata(dev);
	int ret;

	ret = gpio_request_by_name(dev, "gpios", 0, &pdata->gpio, 0);
	if (ret < 0)
		printf("Error claiming GPIO %d\n", ret);

	return ret;
};

static const struct udevice_id w1_gpio_id[] = {
	{ "w1-gpio", 0 },
	{ },
};

U_BOOT_DRIVER(w1_gpio_drv) = {
	.id				= UCLASS_W1,
	.name				= "w1_gpio_drv",
	.of_match			= w1_gpio_id,
	.ofdata_to_platdata		= w1_gpio_ofdata_to_platdata,
	.ops				= &w1_gpio_ops,
	.platdata_auto_alloc_size	= sizeof(struct w1_gpio_pdata),
};
