Message ID | 202cdeff42a2de149c471630110a8b2657ccf5ca.1477669745.git.stillcompiling@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Joshua, [auto build test ERROR on linus/master] [also build test ERROR on v4.9-rc2 next-20161028] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] [Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on] [Check https://git-scm.com/docs/git-format-patch for more information] url: https://github.com/0day-ci/linux/commits/Joshua-Clayton/lib-add-bitrev8x4/20161029-012535 config: i386-allmodconfig (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: # save the attached .config to linux build tree make ARCH=i386 All error/warnings (new ones prefixed by >>): In file included from include/linux/delay.h:10:0, from drivers/fpga/cyclone-ps-spi.c:14: drivers/fpga/cyclone-ps-spi.c: In function 'cyclonespi_write': >> drivers/fpga/cyclone-ps-spi.c:89:46: error: 'SZ_4K' undeclared (first use in this function) size_t stride = min(fw_data_end - fw_data, SZ_4K); ^ include/linux/kernel.h:738:2: note: in definition of macro '__min' t2 min2 = (y); \ ^~ >> drivers/fpga/cyclone-ps-spi.c:89:19: note: in expansion of macro 'min' size_t stride = min(fw_data_end - fw_data, SZ_4K); ^~~ drivers/fpga/cyclone-ps-spi.c:89:46: note: each undeclared identifier is reported only once for each function it appears in size_t stride = min(fw_data_end - fw_data, SZ_4K); ^ include/linux/kernel.h:738:2: note: in definition of macro '__min' t2 min2 = (y); \ ^~ >> drivers/fpga/cyclone-ps-spi.c:89:19: note: in expansion of macro 'min' size_t stride = min(fw_data_end - fw_data, SZ_4K); ^~~ vim +/SZ_4K +89 drivers/fpga/cyclone-ps-spi.c 8 * Works on Cyclone V. Should work on cyclone series. 9 * May work on other Altera fpgas. 10 * 11 */ 12 13 #include <linux/bitrev.h> > 14 #include <linux/delay.h> 15 #include <linux/fpga/fpga-mgr.h> 16 #include <linux/gpio/consumer.h> 17 #include <linux/module.h> 18 #include <linux/of_gpio.h> 19 #include <linux/spi/spi.h> 20 21 #define FPGA_RESET_TIME 50 /* time in usecs to trigger FPGA config */ 22 #define FPGA_MIN_DELAY 250 /* min usecs to wait for config status */ 23 24 struct cyclonespi_conf { 25 struct gpio_desc *config; 26 struct gpio_desc *status; 27 struct spi_device *spi; 28 }; 29 30 static const struct of_device_id of_ef_match[] = { 31 { .compatible = "altr,cyclone-ps-spi-fpga-mgr", }, 32 {} 33 }; 34 MODULE_DEVICE_TABLE(of, of_ef_match); 35 36 static enum fpga_mgr_states cyclonespi_state(struct fpga_manager *mgr) 37 { 38 return mgr->state; 39 } 40 41 static int cyclonespi_write_init(struct fpga_manager *mgr, u32 flags, 42 const char *buf, size_t count) 43 { 44 struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv; 45 46 if (flags & FPGA_MGR_PARTIAL_RECONFIG) { 47 dev_err(&mgr->dev, "Partial reconfiguration not supported.\n"); 48 return -EINVAL; 49 } 50 51 gpiod_set_value(conf->config, 0); 52 usleep_range(FPGA_RESET_TIME, FPGA_RESET_TIME + 20); 53 if (gpiod_get_value(conf->status) == 1) { 54 dev_err(&mgr->dev, "Status pin should be low.\n"); 55 return -EIO; 56 } 57 58 gpiod_set_value(conf->config, 1); 59 usleep_range(FPGA_MIN_DELAY, FPGA_MIN_DELAY + 20); 60 if (gpiod_get_value(conf->status) == 0) { 61 dev_err(&mgr->dev, "Status pin not ready.\n"); 62 return -EIO; 63 } 64 65 return 0; 66 } 67 68 static void rev_buf(void *buf, size_t len) 69 { 70 u32 *fw32 = (u32 *)buf; 71 const u32 *fw_end = (u32 *)(buf + len); 72 73 /* set buffer to lsb first */ 74 while (fw32 < fw_end) { 75 *fw32 = bitrev8x4(*fw32); 76 fw32++; 77 } 78 } 79 80 static int cyclonespi_write(struct fpga_manager *mgr, const char *buf, 81 size_t count) 82 { 83 struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv; 84 const char *fw_data = buf; 85 const char *fw_data_end = fw_data + count; 86 87 while (fw_data < fw_data_end) { 88 int ret; > 89 size_t stride = min(fw_data_end - fw_data, SZ_4K); 90 91 rev_buf((void *)fw_data, stride); 92 ret = spi_write(conf->spi, fw_data, stride); --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Joshua, [auto build test ERROR on linus/master] [also build test ERROR on v4.9-rc2 next-20161028] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] [Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on] [Check https://git-scm.com/docs/git-format-patch for more information] url: https://github.com/0day-ci/linux/commits/Joshua-Clayton/lib-add-bitrev8x4/20161029-012535 config: arm64-allmodconfig (attached as .config) compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm64 All error/warnings (new ones prefixed by >>): In file included from drivers/fpga/cyclone-ps-spi.c:13:0: drivers/fpga/cyclone-ps-spi.c: In function 'rev_buf': >> include/linux/bitrev.h:12:21: error: implicit declaration of function '__arch_bitrev8x4' [-Werror=implicit-function-declaration] #define __bitrev8x4 __arch_bitrev8x4 ^ >> include/linux/bitrev.h:101:2: note: in expansion of macro '__bitrev8x4' __bitrev8x4(__x); \ ^~~~~~~~~~~ >> drivers/fpga/cyclone-ps-spi.c:75:11: note: in expansion of macro 'bitrev8x4' *fw32 = bitrev8x4(*fw32); ^~~~~~~~~ In file included from include/linux/delay.h:10:0, from drivers/fpga/cyclone-ps-spi.c:14: drivers/fpga/cyclone-ps-spi.c: In function 'cyclonespi_write': include/linux/kernel.h:739:16: warning: comparison of distinct pointer types lacks a cast (void) (&min1 == &min2); \ ^ include/linux/kernel.h:742:2: note: in expansion of macro '__min' __min(typeof(x), typeof(y), \ ^~~~~ drivers/fpga/cyclone-ps-spi.c:89:19: note: in expansion of macro 'min' size_t stride = min(fw_data_end - fw_data, SZ_4K); ^~~ cc1: some warnings being treated as errors vim +/__arch_bitrev8x4 +12 include/linux/bitrev.h 556d2f05 Yalin Wang 2014-11-03 6 #ifdef CONFIG_HAVE_ARCH_BITREVERSE 556d2f05 Yalin Wang 2014-11-03 7 #include <asm/bitrev.h> 556d2f05 Yalin Wang 2014-11-03 8 556d2f05 Yalin Wang 2014-11-03 9 #define __bitrev32 __arch_bitrev32 556d2f05 Yalin Wang 2014-11-03 10 #define __bitrev16 __arch_bitrev16 556d2f05 Yalin Wang 2014-11-03 11 #define __bitrev8 __arch_bitrev8 69ff2a81 Joshua Clayton 2016-10-28 @12 #define __bitrev8x4 __arch_bitrev8x4 a5cfc1ec Akinobu Mita 2006-12-08 13 556d2f05 Yalin Wang 2014-11-03 14 #else 556d2f05 Yalin Wang 2014-11-03 15 extern u8 const byte_rev_table[256]; 556d2f05 Yalin Wang 2014-11-03 16 static inline u8 __bitrev8(u8 byte) a5cfc1ec Akinobu Mita 2006-12-08 17 { a5cfc1ec Akinobu Mita 2006-12-08 18 return byte_rev_table[byte]; a5cfc1ec Akinobu Mita 2006-12-08 19 } a5cfc1ec Akinobu Mita 2006-12-08 20 556d2f05 Yalin Wang 2014-11-03 21 static inline u16 __bitrev16(u16 x) 556d2f05 Yalin Wang 2014-11-03 22 { 556d2f05 Yalin Wang 2014-11-03 23 return (__bitrev8(x & 0xff) << 8) | __bitrev8(x >> 8); 556d2f05 Yalin Wang 2014-11-03 24 } 556d2f05 Yalin Wang 2014-11-03 25 556d2f05 Yalin Wang 2014-11-03 26 static inline u32 __bitrev32(u32 x) 556d2f05 Yalin Wang 2014-11-03 27 { 556d2f05 Yalin Wang 2014-11-03 28 return (__bitrev16(x & 0xffff) << 16) | __bitrev16(x >> 16); 556d2f05 Yalin Wang 2014-11-03 29 } 556d2f05 Yalin Wang 2014-11-03 30 69ff2a81 Joshua Clayton 2016-10-28 31 static inline u32 __bitrev8x4(u32 x) 69ff2a81 Joshua Clayton 2016-10-28 32 { 69ff2a81 Joshua Clayton 2016-10-28 33 return(__bitrev8(x & 0xff) | 69ff2a81 Joshua Clayton 2016-10-28 34 (__bitrev8((x >> 8) & 0xff) << 8) | 69ff2a81 Joshua Clayton 2016-10-28 35 (__bitrev8((x >> 16) & 0xff) << 16) | 69ff2a81 Joshua Clayton 2016-10-28 36 (__bitrev8((x >> 24) & 0xff) << 24)); 69ff2a81 Joshua Clayton 2016-10-28 37 } 69ff2a81 Joshua Clayton 2016-10-28 38 556d2f05 Yalin Wang 2014-11-03 39 #endif /* CONFIG_HAVE_ARCH_BITREVERSE */ 556d2f05 Yalin Wang 2014-11-03 40 556d2f05 Yalin Wang 2014-11-03 41 #define __constant_bitrev32(x) \ 556d2f05 Yalin Wang 2014-11-03 42 ({ \ 556d2f05 Yalin Wang 2014-11-03 43 u32 __x = x; \ 556d2f05 Yalin Wang 2014-11-03 44 __x = (__x >> 16) | (__x << 16); \ 556d2f05 Yalin Wang 2014-11-03 45 __x = ((__x & (u32)0xFF00FF00UL) >> 8) | ((__x & (u32)0x00FF00FFUL) << 8); \ 556d2f05 Yalin Wang 2014-11-03 46 __x = ((__x & (u32)0xF0F0F0F0UL) >> 4) | ((__x & (u32)0x0F0F0F0FUL) << 4); \ 556d2f05 Yalin Wang 2014-11-03 47 __x = ((__x & (u32)0xCCCCCCCCUL) >> 2) | ((__x & (u32)0x33333333UL) << 2); \ 556d2f05 Yalin Wang 2014-11-03 48 __x = ((__x & (u32)0xAAAAAAAAUL) >> 1) | ((__x & (u32)0x55555555UL) << 1); \ 556d2f05 Yalin Wang 2014-11-03 49 __x; \ 556d2f05 Yalin Wang 2014-11-03 50 }) 556d2f05 Yalin Wang 2014-11-03 51 556d2f05 Yalin Wang 2014-11-03 52 #define __constant_bitrev16(x) \ 556d2f05 Yalin Wang 2014-11-03 53 ({ \ 556d2f05 Yalin Wang 2014-11-03 54 u16 __x = x; \ 556d2f05 Yalin Wang 2014-11-03 55 __x = (__x >> 8) | (__x << 8); \ 556d2f05 Yalin Wang 2014-11-03 56 __x = ((__x & (u16)0xF0F0U) >> 4) | ((__x & (u16)0x0F0FU) << 4); \ 556d2f05 Yalin Wang 2014-11-03 57 __x = ((__x & (u16)0xCCCCU) >> 2) | ((__x & (u16)0x3333U) << 2); \ 556d2f05 Yalin Wang 2014-11-03 58 __x = ((__x & (u16)0xAAAAU) >> 1) | ((__x & (u16)0x5555U) << 1); \ 556d2f05 Yalin Wang 2014-11-03 59 __x; \ 556d2f05 Yalin Wang 2014-11-03 60 }) 556d2f05 Yalin Wang 2014-11-03 61 69ff2a81 Joshua Clayton 2016-10-28 62 #define __constant_bitrev8x4(x) \ 69ff2a81 Joshua Clayton 2016-10-28 63 ({ \ 69ff2a81 Joshua Clayton 2016-10-28 64 u32 __x = x; \ 69ff2a81 Joshua Clayton 2016-10-28 65 __x = ((__x & (u32)0xF0F0F0F0UL) >> 4) | ((__x & (u32)0x0F0F0F0FUL) << 4); \ 69ff2a81 Joshua Clayton 2016-10-28 66 __x = ((__x & (u32)0xCCCCCCCCUL) >> 2) | ((__x & (u32)0x33333333UL) << 2); \ 69ff2a81 Joshua Clayton 2016-10-28 67 __x = ((__x & (u32)0xAAAAAAAAUL) >> 1) | ((__x & (u32)0x55555555UL) << 1); \ 69ff2a81 Joshua Clayton 2016-10-28 68 __x; \ 69ff2a81 Joshua Clayton 2016-10-28 69 }) 69ff2a81 Joshua Clayton 2016-10-28 70 556d2f05 Yalin Wang 2014-11-03 71 #define __constant_bitrev8(x) \ 556d2f05 Yalin Wang 2014-11-03 72 ({ \ 556d2f05 Yalin Wang 2014-11-03 73 u8 __x = x; \ 556d2f05 Yalin Wang 2014-11-03 74 __x = (__x >> 4) | (__x << 4); \ 556d2f05 Yalin Wang 2014-11-03 75 __x = ((__x & (u8)0xCCU) >> 2) | ((__x & (u8)0x33U) << 2); \ 556d2f05 Yalin Wang 2014-11-03 76 __x = ((__x & (u8)0xAAU) >> 1) | ((__x & (u8)0x55U) << 1); \ 556d2f05 Yalin Wang 2014-11-03 77 __x; \ 556d2f05 Yalin Wang 2014-11-03 78 }) 556d2f05 Yalin Wang 2014-11-03 79 556d2f05 Yalin Wang 2014-11-03 80 #define bitrev32(x) \ 556d2f05 Yalin Wang 2014-11-03 81 ({ \ 556d2f05 Yalin Wang 2014-11-03 82 u32 __x = x; \ 556d2f05 Yalin Wang 2014-11-03 83 __builtin_constant_p(__x) ? \ 556d2f05 Yalin Wang 2014-11-03 84 __constant_bitrev32(__x) : \ 556d2f05 Yalin Wang 2014-11-03 85 __bitrev32(__x); \ 556d2f05 Yalin Wang 2014-11-03 86 }) 556d2f05 Yalin Wang 2014-11-03 87 556d2f05 Yalin Wang 2014-11-03 88 #define bitrev16(x) \ 556d2f05 Yalin Wang 2014-11-03 89 ({ \ 556d2f05 Yalin Wang 2014-11-03 90 u16 __x = x; \ 556d2f05 Yalin Wang 2014-11-03 91 __builtin_constant_p(__x) ? \ 556d2f05 Yalin Wang 2014-11-03 92 __constant_bitrev16(__x) : \ 556d2f05 Yalin Wang 2014-11-03 93 __bitrev16(__x); \ 556d2f05 Yalin Wang 2014-11-03 94 }) a5cfc1ec Akinobu Mita 2006-12-08 95 69ff2a81 Joshua Clayton 2016-10-28 96 #define bitrev8x4(x) \ 69ff2a81 Joshua Clayton 2016-10-28 97 ({ \ 69ff2a81 Joshua Clayton 2016-10-28 98 u32 __x = x; \ 69ff2a81 Joshua Clayton 2016-10-28 99 __builtin_constant_p(__x) ? \ 69ff2a81 Joshua Clayton 2016-10-28 100 __constant_bitrev8x4(__x) : \ 69ff2a81 Joshua Clayton 2016-10-28 @101 __bitrev8x4(__x); \ 69ff2a81 Joshua Clayton 2016-10-28 102 }) 69ff2a81 Joshua Clayton 2016-10-28 103 556d2f05 Yalin Wang 2014-11-03 104 #define bitrev8(x) \ :::::: The code at line 12 was first introduced by commit :::::: 69ff2a81709e0969b2d1a0efaa9a010e0093917c lib: add bitrev8x4() :::::: TO: Joshua Clayton <stillcompiling@gmail.com> :::::: CC: 0day robot <fengguang.wu@intel.com> --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Joshua, [auto build test ERROR on linus/master] [also build test ERROR on v4.9-rc2 next-20161028] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] [Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on] [Check https://git-scm.com/docs/git-format-patch for more information] url: https://github.com/0day-ci/linux/commits/Joshua-Clayton/lib-add-bitrev8x4/20161029-012535 config: openrisc-allmodconfig (attached as .config) compiler: or32-linux-gcc (GCC) 4.5.1-or32-1.0rc1 reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=openrisc All errors (new ones prefixed by >>): drivers/fpga/cyclone-ps-spi.c: In function 'cyclonespi_write': drivers/fpga/cyclone-ps-spi.c:89:19: error: 'SZ_4K' undeclared (first use in this function) drivers/fpga/cyclone-ps-spi.c:89:19: note: each undeclared identifier is reported only once for each function it appears in >> drivers/fpga/cyclone-ps-spi.c:89:19: error: type defaults to 'int' in declaration of '__UNIQUE_ID_min2_15' vim +89 drivers/fpga/cyclone-ps-spi.c 83 struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv; 84 const char *fw_data = buf; 85 const char *fw_data_end = fw_data + count; 86 87 while (fw_data < fw_data_end) { 88 int ret; > 89 size_t stride = min(fw_data_end - fw_data, SZ_4K); 90 91 rev_buf((void *)fw_data, stride); 92 ret = spi_write(conf->spi, fw_data, stride); --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Dang it! This was flagged last time around and I forgot to fix it. On 10/28/2016 01:41 PM, kbuild test robot wrote: > Hi Joshua, > > [auto build test ERROR on linus/master] > [also build test ERROR on v4.9-rc2 next-20161028] > [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] > [Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on] > [Check https://git-scm.com/docs/git-format-patch for more information] > > url: https://github.com/0day-ci/linux/commits/Joshua-Clayton/lib-add-bitrev8x4/20161029-012535 > config: openrisc-allmodconfig (attached as .config) > compiler: or32-linux-gcc (GCC) 4.5.1-or32-1.0rc1 > reproduce:Dang it! > wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross > chmod +x ~/bin/make.cross > # save the attached .config to linux build tree > make.cross ARCH=openrisc > > All errors (new ones prefixed by >>): > > drivers/fpga/cyclone-ps-spi.c: In function 'cyclonespi_write': > drivers/fpga/cyclone-ps-spi.c:89:19: error: 'SZ_4K' undeclared (first use in this function) > drivers/fpga/cyclone-ps-spi.c:89:19: note: each undeclared identifier is reported only once for each function it appears in >>> drivers/fpga/cyclone-ps-spi.c:89:19: error: type defaults to 'int' in declaration of '__UNIQUE_ID_min2_15' > vim +89 drivers/fpga/cyclone-ps-spi.c > > 83 struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv; > 84 const char *fw_data = buf; > 85 const char *fw_data_end = fw_data + count; > 86 > 87 while (fw_data < fw_data_end) { > 88 int ret; > > 89 size_t stride = min(fw_data_end - fw_data, SZ_4K); > 90 > 91 rev_buf((void *)fw_data, stride); > 92 ret = spi_write(conf->spi, fw_data, stride); > > --- > 0-DAY kernel test infrastructure Open Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation Thanks, kbuild test robot. Will fix this time.
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index cd84934..2462707 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -13,6 +13,13 @@ config FPGA if FPGA +config FPGA_MGR_CYCLONE_PS_SPI + tristate "Altera Cyclone FPGA Passive Serial over SPI" + depends on SPI + help + FPGA manager driver support for Altera Cyclone using the + passive serial interface over SPI + config FPGA_MGR_SOCFPGA tristate "Altera SOCFPGA FPGA Manager" depends on ARCH_SOCFPGA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 8d83fc6..8f93930 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers +obj-$(CONFIG_FPGA_MGR_CYCLONE_PS_SPI) += cyclone-ps-spi.o obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o diff --git a/drivers/fpga/cyclone-ps-spi.c b/drivers/fpga/cyclone-ps-spi.c new file mode 100644 index 0000000..4b70d5c --- /dev/null +++ b/drivers/fpga/cyclone-ps-spi.c @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2015 United Western Technologies, Corporation + * + * Joshua Clayton <stillcompiling@gmail.com> + * + * Manage Altera fpga firmware that is loaded over spi. + * Firmware must be in binary "rbf" format. + * Works on Cyclone V. Should work on cyclone series. + * May work on other Altera fpgas. + * + */ + +#include <linux/bitrev.h> +#include <linux/delay.h> +#include <linux/fpga/fpga-mgr.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/of_gpio.h> +#include <linux/spi/spi.h> + +#define FPGA_RESET_TIME 50 /* time in usecs to trigger FPGA config */ +#define FPGA_MIN_DELAY 250 /* min usecs to wait for config status */ + +struct cyclonespi_conf { + struct gpio_desc *config; + struct gpio_desc *status; + struct spi_device *spi; +}; + +static const struct of_device_id of_ef_match[] = { + { .compatible = "altr,cyclone-ps-spi-fpga-mgr", }, + {} +}; +MODULE_DEVICE_TABLE(of, of_ef_match); + +static enum fpga_mgr_states cyclonespi_state(struct fpga_manager *mgr) +{ + return mgr->state; +} + +static int cyclonespi_write_init(struct fpga_manager *mgr, u32 flags, + const char *buf, size_t count) +{ + struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv; + + if (flags & FPGA_MGR_PARTIAL_RECONFIG) { + dev_err(&mgr->dev, "Partial reconfiguration not supported.\n"); + return -EINVAL; + } + + gpiod_set_value(conf->config, 0); + usleep_range(FPGA_RESET_TIME, FPGA_RESET_TIME + 20); + if (gpiod_get_value(conf->status) == 1) { + dev_err(&mgr->dev, "Status pin should be low.\n"); + return -EIO; + } + + gpiod_set_value(conf->config, 1); + usleep_range(FPGA_MIN_DELAY, FPGA_MIN_DELAY + 20); + if (gpiod_get_value(conf->status) == 0) { + dev_err(&mgr->dev, "Status pin not ready.\n"); + return -EIO; + } + + return 0; +} + +static void rev_buf(void *buf, size_t len) +{ + u32 *fw32 = (u32 *)buf; + const u32 *fw_end = (u32 *)(buf + len); + + /* set buffer to lsb first */ + while (fw32 < fw_end) { + *fw32 = bitrev8x4(*fw32); + fw32++; + } +} + +static int cyclonespi_write(struct fpga_manager *mgr, const char *buf, + size_t count) +{ + struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv; + const char *fw_data = buf; + const char *fw_data_end = fw_data + count; + + while (fw_data < fw_data_end) { + int ret; + size_t stride = min(fw_data_end - fw_data, SZ_4K); + + rev_buf((void *)fw_data, stride); + ret = spi_write(conf->spi, fw_data, stride); + if (ret) { + dev_err(&mgr->dev, "spi error in firmware write: %d\n", + ret); + return ret; + } + fw_data += stride; + } + + return 0; +} + +static int cyclonespi_write_complete(struct fpga_manager *mgr, u32 flags) +{ + struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv; + + if (gpiod_get_value(conf->status) == 0) { + dev_err(&mgr->dev, "Error during configuration.\n"); + return -EIO; + } + + return 0; +} + +static const struct fpga_manager_ops cyclonespi_ops = { + .state = cyclonespi_state, + .write_init = cyclonespi_write_init, + .write = cyclonespi_write, + .write_complete = cyclonespi_write_complete, +}; + +static int cyclonespi_probe(struct spi_device *spi) +{ + struct cyclonespi_conf *conf = devm_kzalloc(&spi->dev, sizeof(*conf), + GFP_KERNEL); + + if (!conf) + return -ENOMEM; + + conf->spi = spi; + conf->config = devm_gpiod_get(&spi->dev, "config", GPIOD_OUT_LOW); + if (IS_ERR(conf->config)) { + dev_err(&spi->dev, "Failed to get config gpio: %ld\n", + PTR_ERR(conf->config)); + return PTR_ERR(conf->config); + } + + conf->status = devm_gpiod_get(&spi->dev, "status", GPIOD_IN); + if (IS_ERR(conf->status)) { + dev_err(&spi->dev, "Failed to get status gpio: %ld\n", + PTR_ERR(conf->status)); + return PTR_ERR(conf->status); + } + + return fpga_mgr_register(&spi->dev, + "Altera Cyclone PS SPI FPGA Manager", + &cyclonespi_ops, conf); +} + +static int cyclonespi_remove(struct spi_device *spi) +{ + fpga_mgr_unregister(&spi->dev); + + return 0; +} + +static struct spi_driver cyclonespi_driver = { + .driver = { + .name = "cyclone-ps-spi", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(of_ef_match), + }, + .probe = cyclonespi_probe, + .remove = cyclonespi_remove, +}; + +module_spi_driver(cyclonespi_driver) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Joshua Clayton <stillcompiling@gmail.com>"); +MODULE_DESCRIPTION("Module to load Altera FPGA firmware over spi");
cyclone-ps-spi loads FPGA firmware over spi, using the "passive serial" interface on Altera Cyclone FPGAS. This is one of the simpler ways to set up an FPGA at runtime. The signal interface is close to unidirectional spi with lsb first. Signed-off-by: Joshua Clayton <stillcompiling@gmail.com> --- drivers/fpga/Kconfig | 7 ++ drivers/fpga/Makefile | 1 + drivers/fpga/cyclone-ps-spi.c | 172 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/fpga/cyclone-ps-spi.c