xref: /linux/drivers/fpga/xilinx-spi.c (revision a41034df538968e726c6aad3e5d8b99799d2d0cd)
1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * Xilinx Spartan6 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  
23  struct xilinx_spi_conf {
24  	struct spi_device *spi;
25  	struct gpio_desc *prog_b;
26  	struct gpio_desc *done;
27  };
28  
29  static enum fpga_mgr_states xilinx_spi_state(struct fpga_manager *mgr)
30  {
31  	struct xilinx_spi_conf *conf = mgr->priv;
32  
33  	if (!gpiod_get_value(conf->done))
34  		return FPGA_MGR_STATE_RESET;
35  
36  	return FPGA_MGR_STATE_UNKNOWN;
37  }
38  
39  static int xilinx_spi_write_init(struct fpga_manager *mgr,
40  				 struct fpga_image_info *info,
41  				 const char *buf, size_t count)
42  {
43  	struct xilinx_spi_conf *conf = mgr->priv;
44  	const size_t prog_latency_7500us = 7500;
45  	const size_t prog_pulse_1us = 1;
46  
47  	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
48  		dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
49  		return -EINVAL;
50  	}
51  
52  	gpiod_set_value(conf->prog_b, 1);
53  
54  	udelay(prog_pulse_1us); /* min is 500 ns */
55  
56  	gpiod_set_value(conf->prog_b, 0);
57  
58  	if (gpiod_get_value(conf->done)) {
59  		dev_err(&mgr->dev, "Unexpected DONE pin state...\n");
60  		return -EIO;
61  	}
62  
63  	/* program latency */
64  	usleep_range(prog_latency_7500us, prog_latency_7500us + 100);
65  	return 0;
66  }
67  
68  static int xilinx_spi_write(struct fpga_manager *mgr, const char *buf,
69  			    size_t count)
70  {
71  	struct xilinx_spi_conf *conf = mgr->priv;
72  	const char *fw_data = buf;
73  	const char *fw_data_end = fw_data + count;
74  
75  	while (fw_data < fw_data_end) {
76  		size_t remaining, stride;
77  		int ret;
78  
79  		remaining = fw_data_end - fw_data;
80  		stride = min_t(size_t, remaining, SZ_4K);
81  
82  		ret = spi_write(conf->spi, fw_data, stride);
83  		if (ret) {
84  			dev_err(&mgr->dev, "SPI error in firmware write: %d\n",
85  				ret);
86  			return ret;
87  		}
88  		fw_data += stride;
89  	}
90  
91  	return 0;
92  }
93  
94  static int xilinx_spi_apply_cclk_cycles(struct xilinx_spi_conf *conf)
95  {
96  	struct spi_device *spi = conf->spi;
97  	const u8 din_data[1] = { 0xff };
98  	int ret;
99  
100  	ret = spi_write(conf->spi, din_data, sizeof(din_data));
101  	if (ret)
102  		dev_err(&spi->dev, "applying CCLK cycles failed: %d\n", ret);
103  
104  	return ret;
105  }
106  
107  static int xilinx_spi_write_complete(struct fpga_manager *mgr,
108  				     struct fpga_image_info *info)
109  {
110  	struct xilinx_spi_conf *conf = mgr->priv;
111  	unsigned long timeout;
112  	int ret;
113  
114  	if (gpiod_get_value(conf->done))
115  		return xilinx_spi_apply_cclk_cycles(conf);
116  
117  	timeout = jiffies + usecs_to_jiffies(info->config_complete_timeout_us);
118  
119  	while (time_before(jiffies, timeout)) {
120  
121  		ret = xilinx_spi_apply_cclk_cycles(conf);
122  		if (ret)
123  			return ret;
124  
125  		if (gpiod_get_value(conf->done))
126  			return xilinx_spi_apply_cclk_cycles(conf);
127  	}
128  
129  	dev_err(&mgr->dev, "Timeout after config data transfer.\n");
130  	return -ETIMEDOUT;
131  }
132  
133  static const struct fpga_manager_ops xilinx_spi_ops = {
134  	.state = xilinx_spi_state,
135  	.write_init = xilinx_spi_write_init,
136  	.write = xilinx_spi_write,
137  	.write_complete = xilinx_spi_write_complete,
138  };
139  
140  static int xilinx_spi_probe(struct spi_device *spi)
141  {
142  	struct xilinx_spi_conf *conf;
143  	struct fpga_manager *mgr;
144  
145  	conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL);
146  	if (!conf)
147  		return -ENOMEM;
148  
149  	conf->spi = spi;
150  
151  	/* PROGRAM_B is active low */
152  	conf->prog_b = devm_gpiod_get(&spi->dev, "prog_b", GPIOD_OUT_LOW);
153  	if (IS_ERR(conf->prog_b)) {
154  		dev_err(&spi->dev, "Failed to get PROGRAM_B gpio: %ld\n",
155  			PTR_ERR(conf->prog_b));
156  		return PTR_ERR(conf->prog_b);
157  	}
158  
159  	conf->done = devm_gpiod_get(&spi->dev, "done", GPIOD_IN);
160  	if (IS_ERR(conf->done)) {
161  		dev_err(&spi->dev, "Failed to get DONE gpio: %ld\n",
162  			PTR_ERR(conf->done));
163  		return PTR_ERR(conf->done);
164  	}
165  
166  	mgr = devm_fpga_mgr_create(&spi->dev,
167  				   "Xilinx Slave Serial FPGA Manager",
168  				   &xilinx_spi_ops, conf);
169  	if (!mgr)
170  		return -ENOMEM;
171  
172  	spi_set_drvdata(spi, mgr);
173  
174  	return fpga_mgr_register(mgr);
175  }
176  
177  static int xilinx_spi_remove(struct spi_device *spi)
178  {
179  	struct fpga_manager *mgr = spi_get_drvdata(spi);
180  
181  	fpga_mgr_unregister(mgr);
182  
183  	return 0;
184  }
185  
186  static const struct of_device_id xlnx_spi_of_match[] = {
187  	{ .compatible = "xlnx,fpga-slave-serial", },
188  	{}
189  };
190  MODULE_DEVICE_TABLE(of, xlnx_spi_of_match);
191  
192  static struct spi_driver xilinx_slave_spi_driver = {
193  	.driver = {
194  		.name = "xlnx-slave-spi",
195  		.of_match_table = of_match_ptr(xlnx_spi_of_match),
196  	},
197  	.probe = xilinx_spi_probe,
198  	.remove = xilinx_spi_remove,
199  };
200  
201  module_spi_driver(xilinx_slave_spi_driver)
202  
203  MODULE_LICENSE("GPL v2");
204  MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
205  MODULE_DESCRIPTION("Load Xilinx FPGA firmware over SPI");
206