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 | |
23 | struct 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 | |
30 | static 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(desc: conf->done); |
36 | |
37 | if (ret < 0) |
38 | dev_err(&mgr->dev, "Error reading DONE (%d)\n" , ret); |
39 | |
40 | return ret; |
41 | } |
42 | |
43 | static 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 | */ |
63 | static 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(m: 1000); |
68 | |
69 | if (conf->init_b) { |
70 | while (time_before(jiffies, timeout)) { |
71 | int ret = gpiod_get_value(desc: 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(min: 100, max: 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 | |
94 | static 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(desc: conf->prog_b, value: 1); |
107 | |
108 | err = wait_for_init_b(mgr, value: 1, alt_udelay: 1); /* min is 500 ns */ |
109 | if (err) { |
110 | gpiod_set_value(desc: conf->prog_b, value: 0); |
111 | return err; |
112 | } |
113 | |
114 | gpiod_set_value(desc: conf->prog_b, value: 0); |
115 | |
116 | err = wait_for_init_b(mgr, value: 0, alt_udelay: 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(min: 7500, max: 7600); |
127 | return 0; |
128 | } |
129 | |
130 | static 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(spi: conf->spi, buf: fw_data, len: 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 | |
156 | static 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(spi: conf->spi, buf: din_data, len: sizeof(din_data)); |
163 | if (ret) |
164 | dev_err(&spi->dev, "applying CCLK cycles failed: %d\n" , ret); |
165 | |
166 | return ret; |
167 | } |
168 | |
169 | static 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(u: 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(desc: 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 | |
216 | static 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 | |
223 | static 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(dev: &spi->dev, size: 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(dev: &spi->dev, con_id: "prog_b" , flags: GPIOD_OUT_LOW); |
236 | if (IS_ERR(ptr: conf->prog_b)) |
237 | return dev_err_probe(dev: &spi->dev, err: PTR_ERR(ptr: conf->prog_b), |
238 | fmt: "Failed to get PROGRAM_B gpio\n" ); |
239 | |
240 | conf->init_b = devm_gpiod_get_optional(dev: &spi->dev, con_id: "init-b" , flags: GPIOD_IN); |
241 | if (IS_ERR(ptr: conf->init_b)) |
242 | return dev_err_probe(dev: &spi->dev, err: PTR_ERR(ptr: conf->init_b), |
243 | fmt: "Failed to get INIT_B gpio\n" ); |
244 | |
245 | conf->done = devm_gpiod_get(dev: &spi->dev, con_id: "done" , flags: GPIOD_IN); |
246 | if (IS_ERR(ptr: conf->done)) |
247 | return dev_err_probe(dev: &spi->dev, err: PTR_ERR(ptr: conf->done), |
248 | fmt: "Failed to get DONE gpio\n" ); |
249 | |
250 | mgr = devm_fpga_mgr_register(parent: &spi->dev, |
251 | name: "Xilinx Slave Serial FPGA Manager" , |
252 | mops: &xilinx_spi_ops, priv: conf); |
253 | return PTR_ERR_OR_ZERO(ptr: mgr); |
254 | } |
255 | |
256 | #ifdef CONFIG_OF |
257 | static const struct of_device_id xlnx_spi_of_match[] = { |
258 | { .compatible = "xlnx,fpga-slave-serial" , }, |
259 | {} |
260 | }; |
261 | MODULE_DEVICE_TABLE(of, xlnx_spi_of_match); |
262 | #endif |
263 | |
264 | static 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 | |
272 | module_spi_driver(xilinx_slave_spi_driver) |
273 | |
274 | MODULE_LICENSE("GPL v2" ); |
275 | MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>" ); |
276 | MODULE_DESCRIPTION("Load Xilinx FPGA firmware over SPI" ); |
277 | |