1 // SPDX-License-Identifier: GPL-2.0-only
3 * Xilinx Spartan6 Slave Serial SPI Driver
5 * Copyright (C) 2017 DENX Software Engineering
7 * Anatolij Gustschin <agust@denx.de>
9 * Manage Xilinx FPGA firmware that is loaded over SPI using
10 * the slave serial configuration interface.
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>
20 #include <linux/spi/spi.h>
21 #include <linux/sizes.h>
23 struct xilinx_spi_conf
{
24 struct spi_device
*spi
;
25 struct gpio_desc
*prog_b
;
26 struct gpio_desc
*done
;
29 static enum fpga_mgr_states
xilinx_spi_state(struct fpga_manager
*mgr
)
31 struct xilinx_spi_conf
*conf
= mgr
->priv
;
33 if (!gpiod_get_value(conf
->done
))
34 return FPGA_MGR_STATE_RESET
;
36 return FPGA_MGR_STATE_UNKNOWN
;
39 static int xilinx_spi_write_init(struct fpga_manager
*mgr
,
40 struct fpga_image_info
*info
,
41 const char *buf
, size_t count
)
43 struct xilinx_spi_conf
*conf
= mgr
->priv
;
44 const size_t prog_latency_7500us
= 7500;
45 const size_t prog_pulse_1us
= 1;
47 if (info
->flags
& FPGA_MGR_PARTIAL_RECONFIG
) {
48 dev_err(&mgr
->dev
, "Partial reconfiguration not supported.\n");
52 gpiod_set_value(conf
->prog_b
, 1);
54 udelay(prog_pulse_1us
); /* min is 500 ns */
56 gpiod_set_value(conf
->prog_b
, 0);
58 if (gpiod_get_value(conf
->done
)) {
59 dev_err(&mgr
->dev
, "Unexpected DONE pin state...\n");
64 usleep_range(prog_latency_7500us
, prog_latency_7500us
+ 100);
68 static int xilinx_spi_write(struct fpga_manager
*mgr
, const char *buf
,
71 struct xilinx_spi_conf
*conf
= mgr
->priv
;
72 const char *fw_data
= buf
;
73 const char *fw_data_end
= fw_data
+ count
;
75 while (fw_data
< fw_data_end
) {
76 size_t remaining
, stride
;
79 remaining
= fw_data_end
- fw_data
;
80 stride
= min_t(size_t, remaining
, SZ_4K
);
82 ret
= spi_write(conf
->spi
, fw_data
, stride
);
84 dev_err(&mgr
->dev
, "SPI error in firmware write: %d\n",
94 static int xilinx_spi_apply_cclk_cycles(struct xilinx_spi_conf
*conf
)
96 struct spi_device
*spi
= conf
->spi
;
97 const u8 din_data
[1] = { 0xff };
100 ret
= spi_write(conf
->spi
, din_data
, sizeof(din_data
));
102 dev_err(&spi
->dev
, "applying CCLK cycles failed: %d\n", ret
);
107 static int xilinx_spi_write_complete(struct fpga_manager
*mgr
,
108 struct fpga_image_info
*info
)
110 struct xilinx_spi_conf
*conf
= mgr
->priv
;
111 unsigned long timeout
;
114 if (gpiod_get_value(conf
->done
))
115 return xilinx_spi_apply_cclk_cycles(conf
);
117 timeout
= jiffies
+ usecs_to_jiffies(info
->config_complete_timeout_us
);
119 while (time_before(jiffies
, timeout
)) {
121 ret
= xilinx_spi_apply_cclk_cycles(conf
);
125 if (gpiod_get_value(conf
->done
))
126 return xilinx_spi_apply_cclk_cycles(conf
);
129 dev_err(&mgr
->dev
, "Timeout after config data transfer.\n");
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
,
140 static int xilinx_spi_probe(struct spi_device
*spi
)
142 struct xilinx_spi_conf
*conf
;
143 struct fpga_manager
*mgr
;
145 conf
= devm_kzalloc(&spi
->dev
, sizeof(*conf
), GFP_KERNEL
);
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
);
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
);
166 mgr
= devm_fpga_mgr_create(&spi
->dev
,
167 "Xilinx Slave Serial FPGA Manager",
168 &xilinx_spi_ops
, conf
);
172 spi_set_drvdata(spi
, mgr
);
174 return fpga_mgr_register(mgr
);
177 static int xilinx_spi_remove(struct spi_device
*spi
)
179 struct fpga_manager
*mgr
= spi_get_drvdata(spi
);
181 fpga_mgr_unregister(mgr
);
186 static const struct of_device_id xlnx_spi_of_match
[] = {
187 { .compatible
= "xlnx,fpga-slave-serial", },
190 MODULE_DEVICE_TABLE(of
, xlnx_spi_of_match
);
192 static struct spi_driver xilinx_slave_spi_driver
= {
194 .name
= "xlnx-slave-spi",
195 .of_match_table
= of_match_ptr(xlnx_spi_of_match
),
197 .probe
= xilinx_spi_probe
,
198 .remove
= xilinx_spi_remove
,
201 module_spi_driver(xilinx_slave_spi_driver
)
203 MODULE_LICENSE("GPL v2");
204 MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
205 MODULE_DESCRIPTION("Load Xilinx FPGA firmware over SPI");