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