// SPDX-License-Identifier: GPL-2.0-only
/*
 * Altera Passive Serial SPI Driver
 *
 *  Copyright (c) 2017 United Western Technologies, Corporation
 *
 *  Joshua Clayton <stillcompiling@gmail.com>
 *
 * Manage Altera FPGA firmware that is loaded over SPI using the passive
 * serial configuration method.
 * Firmware must be in binary "rbf" format.
 * Works on Arria 10, Cyclone V and Stratix V. Should work on Cyclone series.
 * May work on other Altera FPGAs.
 */

#include <linux/bitrev.h>
#include <linux/delay.h>
#include <linux/fpga/fpga-mgr.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spi/spi.h>
#include <linux/sizes.h>

enum altera_ps_devtype {
	CYCLONE5,
	ARRIA10,
};

struct altera_ps_data {
	enum altera_ps_devtype devtype;
	int status_wait_min_us;
	int status_wait_max_us;
	int t_cfg_us;
	int t_st2ck_us;
};

struct altera_ps_conf {
	struct gpio_desc *config;
	struct gpio_desc *confd;
	struct gpio_desc *status;
	struct spi_device *spi;
	const struct altera_ps_data *data;
	u32 info_flags;
	char mgr_name[64];
};

/*          |   Arria 10  |   Cyclone5  |   Stratix5  |
 * t_CF2ST0 |     [; 600] |     [; 600] |     [; 600] |ns
 * t_CFG    |        [2;] |        [2;] |        [2;] |µs
 * t_STATUS | [268; 3000] | [268; 1506] | [268; 1506] |µs
 * t_CF2ST1 |    [; 3000] |    [; 1506] |    [; 1506] |µs
 * t_CF2CK  |     [3010;] |     [1506;] |     [1506;] |µs
 * t_ST2CK  |       [10;] |        [2;] |        [2;] |µs
 * t_CD2UM  |  [175; 830] |  [175; 437] |  [175; 437] |µs
 */
static struct altera_ps_data c5_data = {
	/* these values for Cyclone5 are compatible with Stratix5 */
	.devtype = CYCLONE5,
	.status_wait_min_us = 268,
	.status_wait_max_us = 1506,
	.t_cfg_us = 2,
	.t_st2ck_us = 2,
};

static struct altera_ps_data a10_data = {
	.devtype = ARRIA10,
	.status_wait_min_us = 268,  /* min(t_STATUS) */
	.status_wait_max_us = 3000, /* max(t_CF2ST1) */
	.t_cfg_us = 2,    /* max { min(t_CFG), max(tCF2ST0) } */
	.t_st2ck_us = 10, /* min(t_ST2CK) */
};

static const struct of_device_id of_ef_match[] = {
	{ .compatible = "altr,fpga-passive-serial", .data = &c5_data },
	{ .compatible = "altr,fpga-arria10-passive-serial", .data = &a10_data },
	{}
};
MODULE_DEVICE_TABLE(of, of_ef_match);

static enum fpga_mgr_states altera_ps_state(struct fpga_manager *mgr)
{
	struct altera_ps_conf *conf = mgr->priv;

	if (gpiod_get_value_cansleep(conf->status))
		return FPGA_MGR_STATE_RESET;

	return FPGA_MGR_STATE_UNKNOWN;
}

static inline void altera_ps_delay(int delay_us)
{
	if (delay_us > 10)
		usleep_range(delay_us, delay_us + 5);
	else
		udelay(delay_us);
}

static int altera_ps_write_init(struct fpga_manager *mgr,
				struct fpga_image_info *info,
				const char *buf, size_t count)
{
	struct altera_ps_conf *conf = mgr->priv;
	int min, max, waits;
	int i;

	conf->info_flags = info->flags;

	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
		dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
		return -EINVAL;
	}

	gpiod_set_value_cansleep(conf->config, 1);

	/* wait min reset pulse time */
	altera_ps_delay(conf->data->t_cfg_us);

	if (!gpiod_get_value_cansleep(conf->status)) {
		dev_err(&mgr->dev, "Status pin failed to show a reset\n");
		return -EIO;
	}

	gpiod_set_value_cansleep(conf->config, 0);

	min = conf->data->status_wait_min_us;
	max = conf->data->status_wait_max_us;
	waits = max / min;
	if (max % min)
		waits++;

	/* wait for max { max(t_STATUS), max(t_CF2ST1) } */
	for (i = 0; i < waits; i++) {
		usleep_range(min, min + 10);
		if (!gpiod_get_value_cansleep(conf->status)) {
			/* wait for min(t_ST2CK)*/
			altera_ps_delay(conf->data->t_st2ck_us);
			return 0;
		}
	}

	dev_err(&mgr->dev, "Status pin not ready.\n");
	return -EIO;
}

static void rev_buf(char *buf, size_t len)
{
	u32 *fw32 = (u32 *)buf;
	size_t extra_bytes = (len & 0x03);
	const u32 *fw_end = (u32 *)(buf + len - extra_bytes);

	/* set buffer to lsb first */
	while (fw32 < fw_end) {
		*fw32 = bitrev8x4(*fw32);
		fw32++;
	}

	if (extra_bytes) {
		buf = (char *)fw_end;
		while (extra_bytes) {
			*buf = bitrev8(*buf);
			buf++;
			extra_bytes--;
		}
	}
}

static int altera_ps_write(struct fpga_manager *mgr, const char *buf,
			   size_t count)
{
	struct altera_ps_conf *conf = mgr->priv;
	const char *fw_data = buf;
	const char *fw_data_end = fw_data + count;

	while (fw_data < fw_data_end) {
		int ret;
		size_t stride = min_t(size_t, fw_data_end - fw_data, SZ_4K);

		if (!(conf->info_flags & FPGA_MGR_BITSTREAM_LSB_FIRST))
			rev_buf((char *)fw_data, stride);

		ret = spi_write(conf->spi, fw_data, stride);
		if (ret) {
			dev_err(&mgr->dev, "spi error in firmware write: %d\n",
				ret);
			return ret;
		}
		fw_data += stride;
	}

	return 0;
}

static int altera_ps_write_complete(struct fpga_manager *mgr,
				    struct fpga_image_info *info)
{
	struct altera_ps_conf *conf = mgr->priv;
	static const char dummy[] = {0};
	int ret;

	if (gpiod_get_value_cansleep(conf->status)) {
		dev_err(&mgr->dev, "Error during configuration.\n");
		return -EIO;
	}

	if (conf->confd) {
		if (!gpiod_get_raw_value_cansleep(conf->confd)) {
			dev_err(&mgr->dev, "CONF_DONE is inactive!\n");
			return -EIO;
		}
	}

	/*
	 * After CONF_DONE goes high, send two additional falling edges on DCLK
	 * to begin initialization and enter user mode
	 */
	ret = spi_write(conf->spi, dummy, 1);
	if (ret) {
		dev_err(&mgr->dev, "spi error during end sequence: %d\n", ret);
		return ret;
	}

	return 0;
}

static const struct fpga_manager_ops altera_ps_ops = {
	.state = altera_ps_state,
	.write_init = altera_ps_write_init,
	.write = altera_ps_write,
	.write_complete = altera_ps_write_complete,
};

static int altera_ps_probe(struct spi_device *spi)
{
	struct altera_ps_conf *conf;
	struct fpga_manager *mgr;

	conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL);
	if (!conf)
		return -ENOMEM;

	conf->data = spi_get_device_match_data(spi);
	conf->spi = spi;
	conf->config = devm_gpiod_get(&spi->dev, "nconfig", GPIOD_OUT_LOW);
	if (IS_ERR(conf->config)) {
		dev_err(&spi->dev, "Failed to get config gpio: %ld\n",
			PTR_ERR(conf->config));
		return PTR_ERR(conf->config);
	}

	conf->status = devm_gpiod_get(&spi->dev, "nstat", GPIOD_IN);
	if (IS_ERR(conf->status)) {
		dev_err(&spi->dev, "Failed to get status gpio: %ld\n",
			PTR_ERR(conf->status));
		return PTR_ERR(conf->status);
	}

	conf->confd = devm_gpiod_get_optional(&spi->dev, "confd", GPIOD_IN);
	if (IS_ERR(conf->confd)) {
		dev_err(&spi->dev, "Failed to get confd gpio: %ld\n",
			PTR_ERR(conf->confd));
		return PTR_ERR(conf->confd);
	} else if (!conf->confd) {
		dev_warn(&spi->dev, "Not using confd gpio");
	}

	/* Register manager with unique name */
	snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s",
		 dev_driver_string(&spi->dev), dev_name(&spi->dev));

	mgr = devm_fpga_mgr_register(&spi->dev, conf->mgr_name,
				     &altera_ps_ops, conf);
	return PTR_ERR_OR_ZERO(mgr);
}

static const struct spi_device_id altera_ps_spi_ids[] = {
	{ "cyclone-ps-spi", (uintptr_t)&c5_data },
	{ "fpga-passive-serial", (uintptr_t)&c5_data },
	{ "fpga-arria10-passive-serial", (uintptr_t)&a10_data },
	{}
};
MODULE_DEVICE_TABLE(spi, altera_ps_spi_ids);

static struct spi_driver altera_ps_driver = {
	.driver = {
		.name = "altera-ps-spi",
		.owner = THIS_MODULE,
		.of_match_table = of_ef_match,
	},
	.id_table = altera_ps_spi_ids,
	.probe = altera_ps_probe,
};

module_spi_driver(altera_ps_driver)

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Joshua Clayton <stillcompiling@gmail.com>");
MODULE_DESCRIPTION("Module to load Altera FPGA firmware over SPI");
