2 * Xilinx Spartan6 Slave Serial SPI Driver
4 * Copyright (C) 2017 DENX Software Engineering
6 * Anatolij Gustschin <agust@denx.de>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
12 * Manage Xilinx FPGA firmware that is loaded over SPI using
13 * the slave serial configuration interface.
16 #include <linux/delay.h>
17 #include <linux/device.h>
18 #include <linux/fpga/fpga-mgr.h>
19 #include <linux/gpio/consumer.h>
20 #include <linux/module.h>
21 #include <linux/mod_devicetable.h>
23 #include <linux/spi/spi.h>
24 #include <linux/sizes.h>
26 struct xilinx_spi_conf
{
27 struct spi_device
*spi
;
28 struct gpio_desc
*prog_b
;
29 struct gpio_desc
*done
;
32 static enum fpga_mgr_states
xilinx_spi_state(struct fpga_manager
*mgr
)
34 struct xilinx_spi_conf
*conf
= mgr
->priv
;
36 if (!gpiod_get_value(conf
->done
))
37 return FPGA_MGR_STATE_RESET
;
39 return FPGA_MGR_STATE_UNKNOWN
;
42 static int xilinx_spi_write_init(struct fpga_manager
*mgr
,
43 struct fpga_image_info
*info
,
44 const char *buf
, size_t count
)
46 struct xilinx_spi_conf
*conf
= mgr
->priv
;
47 const size_t prog_latency_7500us
= 7500;
48 const size_t prog_pulse_1us
= 1;
50 if (info
->flags
& FPGA_MGR_PARTIAL_RECONFIG
) {
51 dev_err(&mgr
->dev
, "Partial reconfiguration not supported.\n");
55 gpiod_set_value(conf
->prog_b
, 1);
57 udelay(prog_pulse_1us
); /* min is 500 ns */
59 gpiod_set_value(conf
->prog_b
, 0);
61 if (gpiod_get_value(conf
->done
)) {
62 dev_err(&mgr
->dev
, "Unexpected DONE pin state...\n");
67 usleep_range(prog_latency_7500us
, prog_latency_7500us
+ 100);
71 static int xilinx_spi_write(struct fpga_manager
*mgr
, const char *buf
,
74 struct xilinx_spi_conf
*conf
= mgr
->priv
;
75 const char *fw_data
= buf
;
76 const char *fw_data_end
= fw_data
+ count
;
78 while (fw_data
< fw_data_end
) {
79 size_t remaining
, stride
;
82 remaining
= fw_data_end
- fw_data
;
83 stride
= min_t(size_t, remaining
, SZ_4K
);
85 ret
= spi_write(conf
->spi
, fw_data
, stride
);
87 dev_err(&mgr
->dev
, "SPI error in firmware write: %d\n",
97 static int xilinx_spi_apply_cclk_cycles(struct xilinx_spi_conf
*conf
)
99 struct spi_device
*spi
= conf
->spi
;
100 const u8 din_data
[1] = { 0xff };
103 ret
= spi_write(conf
->spi
, din_data
, sizeof(din_data
));
105 dev_err(&spi
->dev
, "applying CCLK cycles failed: %d\n", ret
);
110 static int xilinx_spi_write_complete(struct fpga_manager
*mgr
,
111 struct fpga_image_info
*info
)
113 struct xilinx_spi_conf
*conf
= mgr
->priv
;
114 unsigned long timeout
;
117 if (gpiod_get_value(conf
->done
))
118 return xilinx_spi_apply_cclk_cycles(conf
);
120 timeout
= jiffies
+ usecs_to_jiffies(info
->config_complete_timeout_us
);
122 while (time_before(jiffies
, timeout
)) {
124 ret
= xilinx_spi_apply_cclk_cycles(conf
);
128 if (gpiod_get_value(conf
->done
))
129 return xilinx_spi_apply_cclk_cycles(conf
);
132 dev_err(&mgr
->dev
, "Timeout after config data transfer.\n");
136 static const struct fpga_manager_ops xilinx_spi_ops
= {
137 .state
= xilinx_spi_state
,
138 .write_init
= xilinx_spi_write_init
,
139 .write
= xilinx_spi_write
,
140 .write_complete
= xilinx_spi_write_complete
,
143 static int xilinx_spi_probe(struct spi_device
*spi
)
145 struct xilinx_spi_conf
*conf
;
146 struct fpga_manager
*mgr
;
149 conf
= devm_kzalloc(&spi
->dev
, sizeof(*conf
), GFP_KERNEL
);
155 /* PROGRAM_B is active low */
156 conf
->prog_b
= devm_gpiod_get(&spi
->dev
, "prog_b", GPIOD_OUT_LOW
);
157 if (IS_ERR(conf
->prog_b
)) {
158 dev_err(&spi
->dev
, "Failed to get PROGRAM_B gpio: %ld\n",
159 PTR_ERR(conf
->prog_b
));
160 return PTR_ERR(conf
->prog_b
);
163 conf
->done
= devm_gpiod_get(&spi
->dev
, "done", GPIOD_IN
);
164 if (IS_ERR(conf
->done
)) {
165 dev_err(&spi
->dev
, "Failed to get DONE gpio: %ld\n",
166 PTR_ERR(conf
->done
));
167 return PTR_ERR(conf
->done
);
170 mgr
= fpga_mgr_create(&spi
->dev
, "Xilinx Slave Serial FPGA Manager",
171 &xilinx_spi_ops
, conf
);
175 spi_set_drvdata(spi
, mgr
);
177 ret
= fpga_mgr_register(mgr
);
184 static int xilinx_spi_remove(struct spi_device
*spi
)
186 struct fpga_manager
*mgr
= spi_get_drvdata(spi
);
188 fpga_mgr_unregister(mgr
);
193 static const struct of_device_id xlnx_spi_of_match
[] = {
194 { .compatible
= "xlnx,fpga-slave-serial", },
197 MODULE_DEVICE_TABLE(of
, xlnx_spi_of_match
);
199 static struct spi_driver xilinx_slave_spi_driver
= {
201 .name
= "xlnx-slave-spi",
202 .of_match_table
= of_match_ptr(xlnx_spi_of_match
),
204 .probe
= xilinx_spi_probe
,
205 .remove
= xilinx_spi_remove
,
208 module_spi_driver(xilinx_slave_spi_driver
)
210 MODULE_LICENSE("GPL v2");
211 MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
212 MODULE_DESCRIPTION("Load Xilinx FPGA firmware over SPI");