Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fpga: xilinx-spi: extract a common driver core

Factor out the gpio handshaking (using PROGRAM_B, INIT_B and DONE)
protocol in xilinx-core so that it can be reused for another driver.
This commit does not change anything functionally to xilinx-spi.

xilinx-core expects drivers to provide a write(const char* buf,
size_t count) function that performs the actual write to the device,
as well as a struct device* for resource management.

Signed-off-by: Charles Perry <charles.perry@savoirfairelinux.com>
Acked-by: Xu Yilun <yilun.xu@intel.com>
Link: https://lore.kernel.org/r/20240321220447.3260065-2-charles.perry@savoirfairelinux.com
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>

authored by

Charles Perry and committed by
Xu Yilun
a52e3a9d 1da11f82

+260 -209
+4
drivers/fpga/Kconfig
··· 64 64 help 65 65 FPGA manager driver support for the Intel Stratix10 SoC. 66 66 67 + config FPGA_MGR_XILINX_CORE 68 + tristate 69 + 67 70 config FPGA_MGR_XILINX_SPI 68 71 tristate "Xilinx Configuration over Slave Serial (SPI)" 69 72 depends on SPI 73 + select FPGA_MGR_XILINX_CORE 70 74 help 71 75 FPGA manager driver support for Xilinx FPGA configuration 72 76 over slave serial interface.
+1
drivers/fpga/Makefile
··· 15 15 obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o 16 16 obj-$(CONFIG_FPGA_MGR_STRATIX10_SOC) += stratix10-soc.o 17 17 obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o 18 + obj-$(CONFIG_FPGA_MGR_XILINX_CORE) += xilinx-core.o 18 19 obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o 19 20 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o 20 21 obj-$(CONFIG_FPGA_MGR_ZYNQMP_FPGA) += zynqmp-fpga.o
+213
drivers/fpga/xilinx-core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Common parts of the Xilinx Spartan6 and 7 Series FPGA manager drivers. 4 + * 5 + * Copyright (C) 2017 DENX Software Engineering 6 + * 7 + * Anatolij Gustschin <agust@denx.de> 8 + */ 9 + 10 + #include "xilinx-core.h" 11 + 12 + #include <linux/delay.h> 13 + #include <linux/fpga/fpga-mgr.h> 14 + #include <linux/gpio/consumer.h> 15 + #include <linux/of.h> 16 + 17 + static int get_done_gpio(struct fpga_manager *mgr) 18 + { 19 + struct xilinx_fpga_core *core = mgr->priv; 20 + int ret; 21 + 22 + ret = gpiod_get_value(core->done); 23 + if (ret < 0) 24 + dev_err(&mgr->dev, "Error reading DONE (%d)\n", ret); 25 + 26 + return ret; 27 + } 28 + 29 + static enum fpga_mgr_states xilinx_core_state(struct fpga_manager *mgr) 30 + { 31 + if (!get_done_gpio(mgr)) 32 + return FPGA_MGR_STATE_RESET; 33 + 34 + return FPGA_MGR_STATE_UNKNOWN; 35 + } 36 + 37 + /** 38 + * wait_for_init_b - wait for the INIT_B pin to have a given state, or wait 39 + * a given delay if the pin is unavailable 40 + * 41 + * @mgr: The FPGA manager object 42 + * @value: Value INIT_B to wait for (1 = asserted = low) 43 + * @alt_udelay: Delay to wait if the INIT_B GPIO is not available 44 + * 45 + * Returns 0 when the INIT_B GPIO reached the given state or -ETIMEDOUT if 46 + * too much time passed waiting for that. If no INIT_B GPIO is available 47 + * then always return 0. 48 + */ 49 + static int wait_for_init_b(struct fpga_manager *mgr, int value, 50 + unsigned long alt_udelay) 51 + { 52 + struct xilinx_fpga_core *core = mgr->priv; 53 + unsigned long timeout = jiffies + msecs_to_jiffies(1000); 54 + 55 + if (core->init_b) { 56 + while (time_before(jiffies, timeout)) { 57 + int ret = gpiod_get_value(core->init_b); 58 + 59 + if (ret == value) 60 + return 0; 61 + 62 + if (ret < 0) { 63 + dev_err(&mgr->dev, 64 + "Error reading INIT_B (%d)\n", ret); 65 + return ret; 66 + } 67 + 68 + usleep_range(100, 400); 69 + } 70 + 71 + dev_err(&mgr->dev, "Timeout waiting for INIT_B to %s\n", 72 + value ? "assert" : "deassert"); 73 + return -ETIMEDOUT; 74 + } 75 + 76 + udelay(alt_udelay); 77 + 78 + return 0; 79 + } 80 + 81 + static int xilinx_core_write_init(struct fpga_manager *mgr, 82 + struct fpga_image_info *info, const char *buf, 83 + size_t count) 84 + { 85 + struct xilinx_fpga_core *core = mgr->priv; 86 + int err; 87 + 88 + if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) { 89 + dev_err(&mgr->dev, "Partial reconfiguration not supported\n"); 90 + return -EINVAL; 91 + } 92 + 93 + gpiod_set_value(core->prog_b, 1); 94 + 95 + err = wait_for_init_b(mgr, 1, 1); /* min is 500 ns */ 96 + if (err) { 97 + gpiod_set_value(core->prog_b, 0); 98 + return err; 99 + } 100 + 101 + gpiod_set_value(core->prog_b, 0); 102 + 103 + err = wait_for_init_b(mgr, 0, 0); 104 + if (err) 105 + return err; 106 + 107 + if (get_done_gpio(mgr)) { 108 + dev_err(&mgr->dev, "Unexpected DONE pin state...\n"); 109 + return -EIO; 110 + } 111 + 112 + /* program latency */ 113 + usleep_range(7500, 7600); 114 + return 0; 115 + } 116 + 117 + static int xilinx_core_write(struct fpga_manager *mgr, const char *buf, 118 + size_t count) 119 + { 120 + struct xilinx_fpga_core *core = mgr->priv; 121 + 122 + return core->write(core, buf, count); 123 + } 124 + 125 + static int xilinx_core_write_complete(struct fpga_manager *mgr, 126 + struct fpga_image_info *info) 127 + { 128 + struct xilinx_fpga_core *core = mgr->priv; 129 + unsigned long timeout = 130 + jiffies + usecs_to_jiffies(info->config_complete_timeout_us); 131 + bool expired = false; 132 + int done; 133 + int ret; 134 + const char padding[1] = { 0xff }; 135 + 136 + /* 137 + * This loop is carefully written such that if the driver is 138 + * scheduled out for more than 'timeout', we still check for DONE 139 + * before giving up and we apply 8 extra CCLK cycles in all cases. 140 + */ 141 + while (!expired) { 142 + expired = time_after(jiffies, timeout); 143 + 144 + done = get_done_gpio(mgr); 145 + if (done < 0) 146 + return done; 147 + 148 + ret = core->write(core, padding, sizeof(padding)); 149 + if (ret) 150 + return ret; 151 + 152 + if (done) 153 + return 0; 154 + } 155 + 156 + if (core->init_b) { 157 + ret = gpiod_get_value(core->init_b); 158 + 159 + if (ret < 0) { 160 + dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret); 161 + return ret; 162 + } 163 + 164 + dev_err(&mgr->dev, 165 + ret ? "CRC error or invalid device\n" : 166 + "Missing sync word or incomplete bitstream\n"); 167 + } else { 168 + dev_err(&mgr->dev, "Timeout after config data transfer\n"); 169 + } 170 + 171 + return -ETIMEDOUT; 172 + } 173 + 174 + static const struct fpga_manager_ops xilinx_core_ops = { 175 + .state = xilinx_core_state, 176 + .write_init = xilinx_core_write_init, 177 + .write = xilinx_core_write, 178 + .write_complete = xilinx_core_write_complete, 179 + }; 180 + 181 + int xilinx_core_probe(struct xilinx_fpga_core *core) 182 + { 183 + struct fpga_manager *mgr; 184 + 185 + if (!core || !core->dev || !core->write) 186 + return -EINVAL; 187 + 188 + /* PROGRAM_B is active low */ 189 + core->prog_b = devm_gpiod_get(core->dev, "prog_b", GPIOD_OUT_LOW); 190 + if (IS_ERR(core->prog_b)) 191 + return dev_err_probe(core->dev, PTR_ERR(core->prog_b), 192 + "Failed to get PROGRAM_B gpio\n"); 193 + 194 + core->init_b = devm_gpiod_get_optional(core->dev, "init-b", GPIOD_IN); 195 + if (IS_ERR(core->init_b)) 196 + return dev_err_probe(core->dev, PTR_ERR(core->init_b), 197 + "Failed to get INIT_B gpio\n"); 198 + 199 + core->done = devm_gpiod_get(core->dev, "done", GPIOD_IN); 200 + if (IS_ERR(core->done)) 201 + return dev_err_probe(core->dev, PTR_ERR(core->done), 202 + "Failed to get DONE gpio\n"); 203 + 204 + mgr = devm_fpga_mgr_register(core->dev, 205 + "Xilinx Slave Serial FPGA Manager", 206 + &xilinx_core_ops, core); 207 + return PTR_ERR_OR_ZERO(mgr); 208 + } 209 + EXPORT_SYMBOL_GPL(xilinx_core_probe); 210 + 211 + MODULE_LICENSE("GPL"); 212 + MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>"); 213 + MODULE_DESCRIPTION("Xilinx 7 Series FPGA manager core");
+27
drivers/fpga/xilinx-core.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __XILINX_CORE_H 4 + #define __XILINX_CORE_H 5 + 6 + #include <linux/device.h> 7 + 8 + /** 9 + * struct xilinx_fpga_core - interface between the driver and the core manager 10 + * of Xilinx 7 Series FPGA manager 11 + * @dev: device node 12 + * @write: write callback of the driver 13 + */ 14 + struct xilinx_fpga_core { 15 + /* public: */ 16 + struct device *dev; 17 + int (*write)(struct xilinx_fpga_core *core, const char *buf, 18 + size_t count); 19 + /* private: handled by xilinx-core */ 20 + struct gpio_desc *prog_b; 21 + struct gpio_desc *init_b; 22 + struct gpio_desc *done; 23 + }; 24 + 25 + int xilinx_core_probe(struct xilinx_fpga_core *core); 26 + 27 + #endif /* __XILINX_CORE_H */
+15 -209
drivers/fpga/xilinx-spi.c
··· 10 10 * the slave serial configuration interface. 11 11 */ 12 12 13 - #include <linux/delay.h> 14 - #include <linux/device.h> 15 - #include <linux/fpga/fpga-mgr.h> 16 - #include <linux/gpio/consumer.h> 13 + #include "xilinx-core.h" 14 + 17 15 #include <linux/module.h> 18 16 #include <linux/mod_devicetable.h> 19 17 #include <linux/of.h> 20 18 #include <linux/spi/spi.h> 21 - #include <linux/sizes.h> 22 19 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(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(1000); 68 - 69 - if (conf->init_b) { 70 - while (time_before(jiffies, timeout)) { 71 - int ret = gpiod_get_value(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(100, 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(conf->prog_b, 1); 107 - 108 - err = wait_for_init_b(mgr, 1, 1); /* min is 500 ns */ 109 - if (err) { 110 - gpiod_set_value(conf->prog_b, 0); 111 - return err; 112 - } 113 - 114 - gpiod_set_value(conf->prog_b, 0); 115 - 116 - err = wait_for_init_b(mgr, 0, 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(7500, 7600); 127 - return 0; 128 - } 129 - 130 - static int xilinx_spi_write(struct fpga_manager *mgr, const char *buf, 20 + static int xilinx_spi_write(struct xilinx_fpga_core *core, const char *buf, 131 21 size_t count) 132 22 { 133 - struct xilinx_spi_conf *conf = mgr->priv; 23 + struct spi_device *spi = to_spi_device(core->dev); 134 24 const char *fw_data = buf; 135 25 const char *fw_data_end = fw_data + count; 136 26 ··· 31 141 remaining = fw_data_end - fw_data; 32 142 stride = min_t(size_t, remaining, SZ_4K); 33 143 34 - ret = spi_write(conf->spi, fw_data, stride); 144 + ret = spi_write(spi, fw_data, stride); 35 145 if (ret) { 36 - dev_err(&mgr->dev, "SPI error in firmware write: %d\n", 146 + dev_err(core->dev, "SPI error in firmware write: %d\n", 37 147 ret); 38 148 return ret; 39 149 } ··· 43 153 return 0; 44 154 } 45 155 46 - static int xilinx_spi_apply_cclk_cycles(struct xilinx_spi_conf *conf) 47 - { 48 - struct spi_device *spi = conf->spi; 49 - const u8 din_data[1] = { 0xff }; 50 - int ret; 51 - 52 - ret = spi_write(conf->spi, din_data, sizeof(din_data)); 53 - if (ret) 54 - dev_err(&spi->dev, "applying CCLK cycles failed: %d\n", ret); 55 - 56 - return ret; 57 - } 58 - 59 - static int xilinx_spi_write_complete(struct fpga_manager *mgr, 60 - struct fpga_image_info *info) 61 - { 62 - struct xilinx_spi_conf *conf = mgr->priv; 63 - unsigned long timeout = jiffies + usecs_to_jiffies(info->config_complete_timeout_us); 64 - bool expired = false; 65 - int done; 66 - int ret; 67 - 68 - /* 69 - * This loop is carefully written such that if the driver is 70 - * scheduled out for more than 'timeout', we still check for DONE 71 - * before giving up and we apply 8 extra CCLK cycles in all cases. 72 - */ 73 - while (!expired) { 74 - expired = time_after(jiffies, timeout); 75 - 76 - done = get_done_gpio(mgr); 77 - if (done < 0) 78 - return done; 79 - 80 - ret = xilinx_spi_apply_cclk_cycles(conf); 81 - if (ret) 82 - return ret; 83 - 84 - if (done) 85 - return 0; 86 - } 87 - 88 - if (conf->init_b) { 89 - ret = gpiod_get_value(conf->init_b); 90 - 91 - if (ret < 0) { 92 - dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret); 93 - return ret; 94 - } 95 - 96 - dev_err(&mgr->dev, 97 - ret ? "CRC error or invalid device\n" 98 - : "Missing sync word or incomplete bitstream\n"); 99 - } else { 100 - dev_err(&mgr->dev, "Timeout after config data transfer\n"); 101 - } 102 - 103 - return -ETIMEDOUT; 104 - } 105 - 106 - static const struct fpga_manager_ops xilinx_spi_ops = { 107 - .state = xilinx_spi_state, 108 - .write_init = xilinx_spi_write_init, 109 - .write = xilinx_spi_write, 110 - .write_complete = xilinx_spi_write_complete, 111 - }; 112 - 113 156 static int xilinx_spi_probe(struct spi_device *spi) 114 157 { 115 - struct xilinx_spi_conf *conf; 116 - struct fpga_manager *mgr; 158 + struct xilinx_fpga_core *core; 117 159 118 - conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); 119 - if (!conf) 160 + core = devm_kzalloc(&spi->dev, sizeof(*core), GFP_KERNEL); 161 + if (!core) 120 162 return -ENOMEM; 121 163 122 - conf->spi = spi; 164 + core->dev = &spi->dev; 165 + core->write = xilinx_spi_write; 123 166 124 - /* PROGRAM_B is active low */ 125 - conf->prog_b = devm_gpiod_get(&spi->dev, "prog_b", GPIOD_OUT_LOW); 126 - if (IS_ERR(conf->prog_b)) 127 - return dev_err_probe(&spi->dev, PTR_ERR(conf->prog_b), 128 - "Failed to get PROGRAM_B gpio\n"); 129 - 130 - conf->init_b = devm_gpiod_get_optional(&spi->dev, "init-b", GPIOD_IN); 131 - if (IS_ERR(conf->init_b)) 132 - return dev_err_probe(&spi->dev, PTR_ERR(conf->init_b), 133 - "Failed to get INIT_B gpio\n"); 134 - 135 - conf->done = devm_gpiod_get(&spi->dev, "done", GPIOD_IN); 136 - if (IS_ERR(conf->done)) 137 - return dev_err_probe(&spi->dev, PTR_ERR(conf->done), 138 - "Failed to get DONE gpio\n"); 139 - 140 - mgr = devm_fpga_mgr_register(&spi->dev, 141 - "Xilinx Slave Serial FPGA Manager", 142 - &xilinx_spi_ops, conf); 143 - return PTR_ERR_OR_ZERO(mgr); 167 + return xilinx_core_probe(core); 144 168 } 145 169 146 170 #ifdef CONFIG_OF 147 171 static const struct of_device_id xlnx_spi_of_match[] = { 148 - { .compatible = "xlnx,fpga-slave-serial", }, 172 + { 173 + .compatible = "xlnx,fpga-slave-serial", 174 + }, 149 175 {} 150 176 }; 151 177 MODULE_DEVICE_TABLE(of, xlnx_spi_of_match);