/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2023 Steve Markgraf <steve@steve-m.de>
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 <string.h>
#include <limits.h>
#include <errno.h>
#include <gpiod.h>
#include "programmer.h"
#include "spi.h"
#include "flash.h"

#define CONSUMER "flashrom"

struct linux_gpio_spi {
	struct gpiod_chip *chip;
	struct gpiod_line_bulk bulk;
	struct gpiod_line *cs_line, *sck_line, *mosi_line, *miso_line;
};

static void linux_gpio_spi_bitbang_set_cs(int val, void *spi_data)
{
	struct linux_gpio_spi *data = spi_data;
	if (gpiod_line_set_value(data->cs_line, val) < 0)
		msg_perr("Setting cs line failed\n");
}

static void linux_gpio_spi_bitbang_set_sck(int val, void *spi_data)
{
	struct linux_gpio_spi *data = spi_data;
	if (gpiod_line_set_value(data->sck_line, val) < 0)
		msg_perr("Setting sck line failed\n");
}

static void linux_gpio_spi_bitbang_set_mosi(int val, void *spi_data)
{
	struct linux_gpio_spi *data = spi_data;
	if (gpiod_line_set_value(data->mosi_line, val) < 0)
		msg_perr("Setting sck line failed\n");
}

static int linux_gpio_spi_bitbang_get_miso(void *spi_data)
{
	struct linux_gpio_spi *data = spi_data;
	int r = gpiod_line_get_value(data->miso_line);
	if (r < 0)
		msg_perr("Getting miso line failed\n");
	return r;
}

static const struct bitbang_spi_master bitbang_spi_master_gpiod = {
	.set_cs		= linux_gpio_spi_bitbang_set_cs,
	.set_sck	= linux_gpio_spi_bitbang_set_sck,
	.set_mosi	= linux_gpio_spi_bitbang_set_mosi,
	.get_miso	= linux_gpio_spi_bitbang_get_miso,
};

static int linux_gpio_spi_shutdown(void *spi_data)
{
	struct linux_gpio_spi *data = spi_data;

	if (gpiod_line_bulk_num_lines(&data->bulk) > 0)
		gpiod_line_release_bulk(&data->bulk);

	if (data->chip)
		gpiod_chip_close(data->chip);

	free(data);

	return 0;
}

static int linux_gpio_spi_init(void)
{
	struct linux_gpio_spi *data = NULL;
	struct gpiod_chip *chip = NULL;
	const char *param_str[] = { "cs", "sck", "mosi", "miso", "gpiochip" };
	const bool param_required[] = { true, true, true, true, false };
	unsigned int param_int[ARRAY_SIZE(param_str)];
	unsigned int i;
	int r;

	data = calloc(1, sizeof(*data));
	if (!data) {
		msg_perr("Unable to allocate space for SPI master data\n");
		return 1;
	}

	for (i = 0; i < ARRAY_SIZE(param_str); i++) {
		char *param = extract_programmer_param(param_str[i]);
		char *endptr;
		r = 1;

		if (param) {
			errno = 0;
			param_int[i] = strtoul(param, &endptr, 10);
			r = (*endptr != '\0') || (errno != 0);
			free(param);
		} else {
			param_int[i] = UINT_MAX;
		}

		if ((param_required[i] || param) && r) {
			msg_perr("Missing or invalid required programmer "
				 "parameter %s=<n>\n", param_str[i]);
			goto err_exit;
		}
	}

	char *const dev = extract_programmer_param("dev");
	if (!dev && param_int[4] == UINT_MAX) {
		msg_perr("Either a 'dev' or 'gpiochip' parameter must be specified.\n");
		goto err_exit;
	}
	if (dev && param_int[4] != UINT_MAX) {
		msg_perr("Only one of 'dev' or 'gpiochip' parameters can be specified.\n");
		free(dev);
		goto err_exit;
	}

	if (dev) {
		chip = gpiod_chip_open(dev);
		free(dev);
	} else {
		chip = gpiod_chip_open_by_number(param_int[4]);
	}
	if (!chip) {
		msg_perr("Failed to open gpiochip: %s\n", strerror(errno));
		goto err_exit;
	}

	data->chip = chip;

	if (gpiod_chip_get_lines(chip, param_int, 4, &data->bulk)) {
		msg_perr("Error getting GPIO lines\n");
		goto err_exit;
	}

	data->cs_line = gpiod_line_bulk_get_line(&data->bulk, 0);
	data->sck_line = gpiod_line_bulk_get_line(&data->bulk, 1);
	data->mosi_line = gpiod_line_bulk_get_line(&data->bulk, 2);
	data->miso_line = gpiod_line_bulk_get_line(&data->bulk, 3);

	r = gpiod_line_request_output(data->cs_line, CONSUMER, 1);
	r |= gpiod_line_request_output(data->sck_line, CONSUMER, 1);
	r |= gpiod_line_request_output(data->mosi_line, CONSUMER, 1);
	r |= gpiod_line_request_input(data->miso_line, CONSUMER);

	if (r < 0) {
		msg_perr("Requesting GPIO lines failed\n");
		goto err_exit;
	}

	if (register_shutdown(linux_gpio_spi_shutdown, data))
		goto err_exit;

	/* shutdown function does the cleanup */
	return register_spi_bitbang_master(&bitbang_spi_master_gpiod, data);

err_exit:
	linux_gpio_spi_shutdown(data);
	return 1;
}

const struct programmer_entry programmer_linux_gpio_spi = {
	.name		= "linux_gpio_spi",
	.type		= OTHER,
	.devs.note	= "Device file /dev/gpiochip<n>\n",
	.init		= linux_gpio_spi_init,
};
