cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xilinx-spi.c (6593B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Xilinx Spartan6 and 7 Series Slave Serial SPI Driver
      4 *
      5 * Copyright (C) 2017 DENX Software Engineering
      6 *
      7 * Anatolij Gustschin <agust@denx.de>
      8 *
      9 * Manage Xilinx FPGA firmware that is loaded over SPI using
     10 * the slave serial configuration interface.
     11 */
     12
     13#include <linux/delay.h>
     14#include <linux/device.h>
     15#include <linux/fpga/fpga-mgr.h>
     16#include <linux/gpio/consumer.h>
     17#include <linux/module.h>
     18#include <linux/mod_devicetable.h>
     19#include <linux/of.h>
     20#include <linux/spi/spi.h>
     21#include <linux/sizes.h>
     22
     23struct xilinx_spi_conf {
     24	struct spi_device *spi;
     25	struct gpio_desc *prog_b;
     26	struct gpio_desc *init_b;
     27	struct gpio_desc *done;
     28};
     29
     30static int get_done_gpio(struct fpga_manager *mgr)
     31{
     32	struct xilinx_spi_conf *conf = mgr->priv;
     33	int ret;
     34
     35	ret = gpiod_get_value(conf->done);
     36
     37	if (ret < 0)
     38		dev_err(&mgr->dev, "Error reading DONE (%d)\n", ret);
     39
     40	return ret;
     41}
     42
     43static enum fpga_mgr_states xilinx_spi_state(struct fpga_manager *mgr)
     44{
     45	if (!get_done_gpio(mgr))
     46		return FPGA_MGR_STATE_RESET;
     47
     48	return FPGA_MGR_STATE_UNKNOWN;
     49}
     50
     51/**
     52 * wait_for_init_b - wait for the INIT_B pin to have a given state, or wait
     53 * a given delay if the pin is unavailable
     54 *
     55 * @mgr:        The FPGA manager object
     56 * @value:      Value INIT_B to wait for (1 = asserted = low)
     57 * @alt_udelay: Delay to wait if the INIT_B GPIO is not available
     58 *
     59 * Returns 0 when the INIT_B GPIO reached the given state or -ETIMEDOUT if
     60 * too much time passed waiting for that. If no INIT_B GPIO is available
     61 * then always return 0.
     62 */
     63static int wait_for_init_b(struct fpga_manager *mgr, int value,
     64			   unsigned long alt_udelay)
     65{
     66	struct xilinx_spi_conf *conf = mgr->priv;
     67	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
     68
     69	if (conf->init_b) {
     70		while (time_before(jiffies, timeout)) {
     71			int ret = gpiod_get_value(conf->init_b);
     72
     73			if (ret == value)
     74				return 0;
     75
     76			if (ret < 0) {
     77				dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret);
     78				return ret;
     79			}
     80
     81			usleep_range(100, 400);
     82		}
     83
     84		dev_err(&mgr->dev, "Timeout waiting for INIT_B to %s\n",
     85			value ? "assert" : "deassert");
     86		return -ETIMEDOUT;
     87	}
     88
     89	udelay(alt_udelay);
     90
     91	return 0;
     92}
     93
     94static int xilinx_spi_write_init(struct fpga_manager *mgr,
     95				 struct fpga_image_info *info,
     96				 const char *buf, size_t count)
     97{
     98	struct xilinx_spi_conf *conf = mgr->priv;
     99	int err;
    100
    101	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
    102		dev_err(&mgr->dev, "Partial reconfiguration not supported\n");
    103		return -EINVAL;
    104	}
    105
    106	gpiod_set_value(conf->prog_b, 1);
    107
    108	err = wait_for_init_b(mgr, 1, 1); /* min is 500 ns */
    109	if (err) {
    110		gpiod_set_value(conf->prog_b, 0);
    111		return err;
    112	}
    113
    114	gpiod_set_value(conf->prog_b, 0);
    115
    116	err = wait_for_init_b(mgr, 0, 0);
    117	if (err)
    118		return err;
    119
    120	if (get_done_gpio(mgr)) {
    121		dev_err(&mgr->dev, "Unexpected DONE pin state...\n");
    122		return -EIO;
    123	}
    124
    125	/* program latency */
    126	usleep_range(7500, 7600);
    127	return 0;
    128}
    129
    130static int xilinx_spi_write(struct fpga_manager *mgr, const char *buf,
    131			    size_t count)
    132{
    133	struct xilinx_spi_conf *conf = mgr->priv;
    134	const char *fw_data = buf;
    135	const char *fw_data_end = fw_data + count;
    136
    137	while (fw_data < fw_data_end) {
    138		size_t remaining, stride;
    139		int ret;
    140
    141		remaining = fw_data_end - fw_data;
    142		stride = min_t(size_t, remaining, SZ_4K);
    143
    144		ret = spi_write(conf->spi, fw_data, stride);
    145		if (ret) {
    146			dev_err(&mgr->dev, "SPI error in firmware write: %d\n",
    147				ret);
    148			return ret;
    149		}
    150		fw_data += stride;
    151	}
    152
    153	return 0;
    154}
    155
    156static int xilinx_spi_apply_cclk_cycles(struct xilinx_spi_conf *conf)
    157{
    158	struct spi_device *spi = conf->spi;
    159	const u8 din_data[1] = { 0xff };
    160	int ret;
    161
    162	ret = spi_write(conf->spi, din_data, sizeof(din_data));
    163	if (ret)
    164		dev_err(&spi->dev, "applying CCLK cycles failed: %d\n", ret);
    165
    166	return ret;
    167}
    168
    169static int xilinx_spi_write_complete(struct fpga_manager *mgr,
    170				     struct fpga_image_info *info)
    171{
    172	struct xilinx_spi_conf *conf = mgr->priv;
    173	unsigned long timeout = jiffies + usecs_to_jiffies(info->config_complete_timeout_us);
    174	bool expired = false;
    175	int done;
    176	int ret;
    177
    178	/*
    179	 * This loop is carefully written such that if the driver is
    180	 * scheduled out for more than 'timeout', we still check for DONE
    181	 * before giving up and we apply 8 extra CCLK cycles in all cases.
    182	 */
    183	while (!expired) {
    184		expired = time_after(jiffies, timeout);
    185
    186		done = get_done_gpio(mgr);
    187		if (done < 0)
    188			return done;
    189
    190		ret = xilinx_spi_apply_cclk_cycles(conf);
    191		if (ret)
    192			return ret;
    193
    194		if (done)
    195			return 0;
    196	}
    197
    198	if (conf->init_b) {
    199		ret = gpiod_get_value(conf->init_b);
    200
    201		if (ret < 0) {
    202			dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret);
    203			return ret;
    204		}
    205
    206		dev_err(&mgr->dev,
    207			ret ? "CRC error or invalid device\n"
    208			: "Missing sync word or incomplete bitstream\n");
    209	} else {
    210		dev_err(&mgr->dev, "Timeout after config data transfer\n");
    211	}
    212
    213	return -ETIMEDOUT;
    214}
    215
    216static const struct fpga_manager_ops xilinx_spi_ops = {
    217	.state = xilinx_spi_state,
    218	.write_init = xilinx_spi_write_init,
    219	.write = xilinx_spi_write,
    220	.write_complete = xilinx_spi_write_complete,
    221};
    222
    223static int xilinx_spi_probe(struct spi_device *spi)
    224{
    225	struct xilinx_spi_conf *conf;
    226	struct fpga_manager *mgr;
    227
    228	conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL);
    229	if (!conf)
    230		return -ENOMEM;
    231
    232	conf->spi = spi;
    233
    234	/* PROGRAM_B is active low */
    235	conf->prog_b = devm_gpiod_get(&spi->dev, "prog_b", GPIOD_OUT_LOW);
    236	if (IS_ERR(conf->prog_b))
    237		return dev_err_probe(&spi->dev, PTR_ERR(conf->prog_b),
    238				     "Failed to get PROGRAM_B gpio\n");
    239
    240	conf->init_b = devm_gpiod_get_optional(&spi->dev, "init-b", GPIOD_IN);
    241	if (IS_ERR(conf->init_b))
    242		return dev_err_probe(&spi->dev, PTR_ERR(conf->init_b),
    243				     "Failed to get INIT_B gpio\n");
    244
    245	conf->done = devm_gpiod_get(&spi->dev, "done", GPIOD_IN);
    246	if (IS_ERR(conf->done))
    247		return dev_err_probe(&spi->dev, PTR_ERR(conf->done),
    248				     "Failed to get DONE gpio\n");
    249
    250	mgr = devm_fpga_mgr_register(&spi->dev,
    251				     "Xilinx Slave Serial FPGA Manager",
    252				     &xilinx_spi_ops, conf);
    253	return PTR_ERR_OR_ZERO(mgr);
    254}
    255
    256#ifdef CONFIG_OF
    257static const struct of_device_id xlnx_spi_of_match[] = {
    258	{ .compatible = "xlnx,fpga-slave-serial", },
    259	{}
    260};
    261MODULE_DEVICE_TABLE(of, xlnx_spi_of_match);
    262#endif
    263
    264static struct spi_driver xilinx_slave_spi_driver = {
    265	.driver = {
    266		.name = "xlnx-slave-spi",
    267		.of_match_table = of_match_ptr(xlnx_spi_of_match),
    268	},
    269	.probe = xilinx_spi_probe,
    270};
    271
    272module_spi_driver(xilinx_slave_spi_driver)
    273
    274MODULE_LICENSE("GPL v2");
    275MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
    276MODULE_DESCRIPTION("Load Xilinx FPGA firmware over SPI");