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

staging: fpgaboot: Xilinx FPGA firmware download driver

This driver downloads Xilinx FPGA firmware using gpio pins.
It loads Xilinx FPGA bitstream format firmware image and
program the Xilinx FPGA using SelectMAP (parallel) mode.

Signed-off-by: Insop Song <insop.song@gainspeed.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Insop Song and committed by
Greg Kroah-Hartman
e7185c69 86f78b8b

+958
+2
drivers/staging/Kconfig
··· 146 146 147 147 source "drivers/staging/dgap/Kconfig" 148 148 149 + source "drivers/staging/gs_fpgaboot/Kconfig" 150 + 149 151 endif # STAGING
+1
drivers/staging/Makefile
··· 65 65 obj-$(CONFIG_DGNC) += dgnc/ 66 66 obj-$(CONFIG_DGAP) += dgap/ 67 67 obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand/ 68 + obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/
+8
drivers/staging/gs_fpgaboot/Kconfig
··· 1 + # 2 + # "xilinx FPGA firmware download, fpgaboot" 3 + # 4 + config GS_FPGABOOT 5 + tristate "Xilinx FPGA firmware download module" 6 + default n 7 + help 8 + Xilinx FPGA firmware download module
+4
drivers/staging/gs_fpgaboot/Makefile
··· 1 + gs_fpga-y += gs_fpgaboot.o io.o 2 + obj-$(CONFIG_GS_FPGABOOT) += gs_fpga.o 3 + 4 + ccflags-$(CONFIG_GS_FPGA_DEBUG) := -DDEBUG
+71
drivers/staging/gs_fpgaboot/README
··· 1 + ============================================================================== 2 + Linux Driver Source for Xilinx FPGA firmware download 3 + ============================================================================== 4 + 5 + 6 + TABLE OF CONTENTS. 7 + 8 + 1. SUMMARY 9 + 2. BACKGROUND 10 + 3. DESIGN 11 + 4. HOW TO USE 12 + 5. REFERENCE 13 + 14 + 1. SUMMARY 15 + 16 + - Download Xilinx FPGA firmware 17 + - This module downloads Xilinx FPGA firmware using gpio pins. 18 + 19 + 2. BACKGROUND 20 + 21 + An FPGA (Field Programmable Gate Array) is a programmable hardware that is 22 + used in various applications. Hardware design needs to programmed through 23 + a dedicated device or CPU assisted way (serial or parallel). 24 + This driver provides a way to download FPGA firmware. 25 + 26 + 3. DESIGN 27 + 28 + - load Xilinx FPGA bitstream format[1] firmware image file using 29 + kernel firmware framework, request_firmware() 30 + - program the Xilinx FPGA using SelectMAP (parallel) mode [2] 31 + - FPGA prgram is done by gpio based bit-banging, as an example 32 + - platform independent file: gs_fpgaboot.c 33 + - platform dependent file: io.c 34 + 35 + 36 + 4. HOW TO USE 37 + 38 + $ insmod gs_fpga.ko file="xlinx_fpga_top_bitstream.bit" 39 + $ rmmod gs_fpga 40 + 41 + 5. USE CASE (from a mailing list discussion with Greg) 42 + 43 + a. As a FPGA development support tool, 44 + During FPGA firmware development, you need to download a new FPGA 45 + image frequently. 46 + You would do that with a dedicated JTAG, which usually a limited 47 + resource in the lab. 48 + However, if you use my driver, you don't have to have a dedicated JTAG. 49 + This is a real gain :) 50 + 51 + b. For the FPGA that runs without config after the download, which 52 + doesn't talk to any of Linux interfaces (such as PCIE). 53 + 54 + We download FPGA firmware from user triggered or some other way, and that's it. 55 + Since that FPGA runs on its own, it doesn't require a linux driver 56 + after the download. 57 + 58 + c. For the FPGA that requires config after the download, which talk to 59 + any of linux interfaces (such as PCIE) 60 + 61 + Then, this type of FPGA config can be put into device tree and have a 62 + separate driver (pcie or others), then THAT driver calls my driver to 63 + download FPGA firmware during the Linux boot, the take over the device 64 + through the interface. 65 + 66 + 6. REFERENCE 67 + 68 + 1. Xilinx APP NOTE XAPP583: 69 + http://www.xilinx.com/support/documentation/application_notes/xapp583-fpga-configuration.pdf 70 + 2. bitstream file info: 71 + http://home.earthlink.net/~davesullins/software/bitinfo.html
+7
drivers/staging/gs_fpgaboot/TODO
··· 1 + TODO: 2 + - get bus width input instead of hardcoded bus width 3 + - get it reviewed 4 + 5 + Please send any patches for this driver to Insop Song<insop.song@gainspeed.com> 6 + and Greg Kroah-Hartman <gregkh@linuxfoundation.org>. 7 + And please CC to "Staging subsystem" mail list <devel@driverdev.osuosl.org> too.
+425
drivers/staging/gs_fpgaboot/gs_fpgaboot.c
··· 1 + /* 2 + * This program is free software; you can redistribute it and/or modify 3 + * it under the terms of the GNU General Public License as published by 4 + * the Free Software Foundation; either version 2 of the License, or 5 + * (at your option) any later version. 6 + * 7 + * This program is distributed in the hope that it will be useful, 8 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + * GNU General Public License for more details. 11 + * 12 + * You should have received a copy of the GNU General Public License 13 + * along with this program; if not, write to the Free Software 14 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 15 + */ 16 + 17 + #include <linux/kernel.h> 18 + #include <linux/init.h> 19 + #include <linux/module.h> 20 + #include <linux/moduleparam.h> 21 + #include <linux/types.h> 22 + #include <linux/device.h> 23 + #include <linux/string.h> 24 + #include <linux/slab.h> 25 + #include <linux/fs.h> 26 + #include <linux/platform_device.h> 27 + #include <linux/of.h> 28 + #include <linux/delay.h> 29 + #include <linux/io.h> 30 + #include <linux/firmware.h> 31 + 32 + #include "gs_fpgaboot.h" 33 + #include "io.h" 34 + 35 + #define DEVICE_NAME "device" 36 + #define CLASS_NAME "fpgaboot" 37 + 38 + static uint8_t bits_magic[] = { 39 + 0x0, 0x9, 0xf, 0xf0, 0xf, 0xf0, 40 + 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x1}; 41 + 42 + /* fake device for request_firmware */ 43 + static struct platform_device *firmware_pdev; 44 + 45 + static char *file = "xlinx_fpga_firmware.bit"; 46 + module_param(file, charp, S_IRUGO); 47 + MODULE_PARM_DESC(file, "Xilinx FPGA firmware file."); 48 + 49 + #ifdef DEBUG_FPGA 50 + static void datadump(char *msg, void *m, int n) 51 + { 52 + int i; 53 + unsigned char *c; 54 + 55 + pr_info("=== %s ===\n", msg); 56 + 57 + c = m; 58 + 59 + for (i = 0; i < n; i++) { 60 + if ((i&0xf) == 0) 61 + pr_info(KERN_INFO "\n 0x%4x: ", i); 62 + 63 + pr_info("%02X ", c[i]); 64 + } 65 + 66 + pr_info("\n"); 67 + } 68 + #endif /* DEBUG_FPGA */ 69 + 70 + static void read_bitstream(char *bitdata, char *buf, int *offset, int rdsize) 71 + { 72 + memcpy(buf, bitdata + *offset, rdsize); 73 + *offset += rdsize; 74 + } 75 + 76 + static void readinfo_bitstream(char *bitdata, char *buf, int *offset) 77 + { 78 + char tbuf[64]; 79 + int32_t len; 80 + 81 + /* read section char */ 82 + read_bitstream(bitdata, tbuf, offset, 1); 83 + 84 + /* read length */ 85 + read_bitstream(bitdata, tbuf, offset, 2); 86 + 87 + len = tbuf[0] << 8 | tbuf[1]; 88 + 89 + read_bitstream(bitdata, buf, offset, len); 90 + buf[len] = '\0'; 91 + } 92 + 93 + /* 94 + * read bitdata length 95 + */ 96 + static int readlength_bitstream(char *bitdata, int *lendata, int *offset) 97 + { 98 + char tbuf[64]; 99 + 100 + /* read section char */ 101 + read_bitstream(bitdata, tbuf, offset, 1); 102 + 103 + /* make sure it is section 'e' */ 104 + if (tbuf[0] != 'e') { 105 + pr_err("error: length section is not 'e', but %c\n", tbuf[0]); 106 + return -1; 107 + } 108 + 109 + /* read 4bytes length */ 110 + read_bitstream(bitdata, tbuf, offset, 4); 111 + 112 + *lendata = tbuf[0] << 24 | tbuf[1] << 16 | 113 + tbuf[2] << 8 | tbuf[3]; 114 + 115 + return 0; 116 + } 117 + 118 + 119 + /* 120 + * read first 13 bytes to check bitstream magic number 121 + */ 122 + static int readmagic_bitstream(char *bitdata, int *offset) 123 + { 124 + char buf[13]; 125 + int r; 126 + 127 + read_bitstream(bitdata, buf, offset, 13); 128 + r = memcmp(buf, bits_magic, 13); 129 + if (r) { 130 + pr_err("error: corrupted header"); 131 + return -1; 132 + } 133 + pr_info("bitstream file magic number Ok\n"); 134 + 135 + *offset = 13; /* magic length */ 136 + 137 + return 0; 138 + } 139 + 140 + /* 141 + * NOTE: supports only bitstream format 142 + */ 143 + static enum fmt_image get_imageformat(struct fpgaimage *fimage) 144 + { 145 + return f_bit; 146 + } 147 + 148 + static void gs_print_header(struct fpgaimage *fimage) 149 + { 150 + pr_info("file: %s\n", fimage->filename); 151 + pr_info("part: %s\n", fimage->part); 152 + pr_info("date: %s\n", fimage->date); 153 + pr_info("time: %s\n", fimage->time); 154 + pr_info("lendata: %d\n", fimage->lendata); 155 + } 156 + 157 + static void gs_read_bitstream(struct fpgaimage *fimage) 158 + { 159 + char *bitdata; 160 + int size; 161 + int offset; 162 + 163 + offset = 0; 164 + bitdata = (char *)fimage->fw_entry->data; 165 + size = fimage->fw_entry->size; 166 + 167 + readmagic_bitstream(bitdata, &offset); 168 + readinfo_bitstream(bitdata, fimage->filename, &offset); 169 + readinfo_bitstream(bitdata, fimage->part, &offset); 170 + readinfo_bitstream(bitdata, fimage->date, &offset); 171 + readinfo_bitstream(bitdata, fimage->time, &offset); 172 + readlength_bitstream(bitdata, &fimage->lendata, &offset); 173 + 174 + fimage->fpgadata = bitdata + offset; 175 + } 176 + 177 + static int gs_read_image(struct fpgaimage *fimage) 178 + { 179 + int img_fmt; 180 + 181 + img_fmt = get_imageformat(fimage); 182 + 183 + switch (img_fmt) { 184 + case f_bit: 185 + pr_info("image is bitstream format\n"); 186 + gs_read_bitstream(fimage); 187 + break; 188 + default: 189 + pr_err("unsupported fpga image format\n"); 190 + return -1; 191 + }; 192 + 193 + gs_print_header(fimage); 194 + 195 + return 0; 196 + } 197 + 198 + static int gs_load_image(struct fpgaimage *fimage, char *file) 199 + { 200 + int err; 201 + 202 + pr_info("load fpgaimage %s\n", file); 203 + 204 + err = request_firmware(&fimage->fw_entry, file, &firmware_pdev->dev); 205 + if (err != 0) { 206 + pr_err("firmware %s is missing, cannot continue.\n", file); 207 + return err; 208 + } 209 + 210 + return 0; 211 + } 212 + 213 + static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes) 214 + { 215 + char *bitdata; 216 + int size, i, cnt; 217 + cnt = 0; 218 + 219 + bitdata = (char *)fimage->fpgadata; 220 + size = fimage->lendata; 221 + 222 + #ifdef DEBUG_FPGA 223 + datadump("bitfile sample", bitdata, 0x100); 224 + #endif /* DEBUG_FPGA */ 225 + 226 + if (!xl_supported_prog_bus_width(bus_bytes)) { 227 + pr_err("unsupported program bus width %d\n", 228 + bus_bytes); 229 + return -1; 230 + } 231 + 232 + /* Bring csi_b, rdwr_b Low and program_b High */ 233 + xl_program_b(1); 234 + xl_rdwr_b(0); 235 + xl_csi_b(0); 236 + 237 + /* Configuration reset */ 238 + xl_program_b(0); 239 + msleep(20); 240 + xl_program_b(1); 241 + 242 + /* Wait for Device Initialization */ 243 + while (xl_get_init_b() == 0) 244 + ; 245 + 246 + pr_info("device init done\n"); 247 + 248 + for (i = 0; i < size; i += bus_bytes) 249 + xl_shift_bytes_out(bus_bytes, bitdata+i); 250 + 251 + pr_info("program done\n"); 252 + 253 + /* Check INIT_B */ 254 + if (xl_get_init_b() == 0) { 255 + pr_err("init_b 0\n"); 256 + return -1; 257 + } 258 + 259 + while (xl_get_done_b() == 0) { 260 + if (cnt++ > MAX_WAIT_DONE) { 261 + pr_err("init_B %d\n", xl_get_init_b()); 262 + break; 263 + } 264 + } 265 + 266 + if (cnt > MAX_WAIT_DONE) { 267 + pr_err("fpga download fail\n"); 268 + return -1; 269 + } 270 + 271 + pr_info("download fpgaimage\n"); 272 + 273 + /* Compensate for Special Startup Conditions */ 274 + xl_shift_cclk(8); 275 + 276 + return 0; 277 + } 278 + 279 + static int gs_release_image(struct fpgaimage *fimage) 280 + { 281 + release_firmware(fimage->fw_entry); 282 + pr_info("release fpgaimage\n"); 283 + 284 + return 0; 285 + } 286 + 287 + /* 288 + * NOTE: supports systemmap parallel programming 289 + */ 290 + static int gs_set_download_method(struct fpgaimage *fimage) 291 + { 292 + pr_info("set program method\n"); 293 + 294 + fimage->dmethod = m_systemmap; 295 + 296 + pr_info("systemmap program method\n"); 297 + 298 + return 0; 299 + } 300 + 301 + static int init_driver(void) 302 + { 303 + firmware_pdev = platform_device_register_simple("fpgaboot", -1, 304 + NULL, 0); 305 + if (IS_ERR(firmware_pdev)) 306 + return PTR_ERR(firmware_pdev); 307 + 308 + return 0; 309 + } 310 + 311 + static void finish_driver(void) 312 + { 313 + platform_device_unregister(firmware_pdev); 314 + } 315 + 316 + static int gs_fpgaboot(void) 317 + { 318 + int err; 319 + struct fpgaimage *fimage; 320 + 321 + fimage = kmalloc(sizeof(struct fpgaimage), GFP_KERNEL); 322 + if (fimage == NULL) { 323 + pr_err("No memory is available\n"); 324 + goto err_out; 325 + } 326 + 327 + err = gs_load_image(fimage, file); 328 + if (err) { 329 + pr_err("gs_load_image error\n"); 330 + goto err_out1; 331 + } 332 + 333 + err = gs_read_image(fimage); 334 + if (err) { 335 + pr_err("gs_read_image error\n"); 336 + goto err_out2; 337 + } 338 + 339 + err = gs_set_download_method(fimage); 340 + if (err) { 341 + pr_err("gs_set_download_method error\n"); 342 + goto err_out2; 343 + } 344 + 345 + err = gs_download_image(fimage, bus_2byte); 346 + if (err) { 347 + pr_err("gs_download_image error\n"); 348 + goto err_out2; 349 + } 350 + 351 + err = gs_release_image(fimage); 352 + if (err) { 353 + pr_err("gs_release_image error\n"); 354 + goto err_out1; 355 + } 356 + 357 + kfree(fimage); 358 + return 0; 359 + 360 + err_out2: 361 + err = gs_release_image(fimage); 362 + if (err) 363 + pr_err("gs_release_image error\n"); 364 + err_out1: 365 + kfree(fimage); 366 + 367 + err_out: 368 + return -1; 369 + 370 + } 371 + 372 + static int __init gs_fpgaboot_init(void) 373 + { 374 + int err, r; 375 + 376 + r = -1; 377 + 378 + pr_info("FPGA DOWNLOAD --->\n"); 379 + pr_info("built at %s UTC\n", __TIMESTAMP__); 380 + 381 + pr_info("FPGA image file name: %s\n", file); 382 + 383 + err = init_driver(); 384 + if (err != 0) { 385 + pr_err("FPGA DRIVER INIT FAIL!!\n"); 386 + return r; 387 + } 388 + 389 + err = xl_init_io(); 390 + if (err) { 391 + pr_err("GPIO INIT FAIL!!\n"); 392 + r = -1; 393 + goto errout; 394 + } 395 + 396 + err = gs_fpgaboot(); 397 + if (err) { 398 + pr_err("FPGA DOWNLOAD FAIL!!\n"); 399 + r = -1; 400 + goto errout; 401 + } 402 + 403 + pr_info("FPGA DOWNLOAD DONE <---\n"); 404 + 405 + r = 0; 406 + return r; 407 + 408 + errout: 409 + finish_driver(); 410 + 411 + return r; 412 + } 413 + 414 + static void __exit gs_fpgaboot_exit(void) 415 + { 416 + finish_driver(); 417 + pr_info("FPGA image download module removed\n"); 418 + } 419 + 420 + module_init(gs_fpgaboot_init); 421 + module_exit(gs_fpgaboot_exit); 422 + 423 + MODULE_AUTHOR("Insop Song"); 424 + MODULE_DESCRIPTION("Xlinix FPGA firmware download"); 425 + MODULE_LICENSE("GPL");
+56
drivers/staging/gs_fpgaboot/gs_fpgaboot.h
··· 1 + /* 2 + * This program is free software; you can redistribute it and/or modify 3 + * it under the terms of the GNU General Public License as published by 4 + * the Free Software Foundation; either version 2 of the License, or 5 + * (at your option) any later version. 6 + * 7 + * This program is distributed in the hope that it will be useful, 8 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + * 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program; if not, write to the Free Software 15 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 + */ 17 + 18 + #include <linux/firmware.h> 19 + 20 + #define MAX_STR 256 21 + 22 + enum fmt_image { 23 + f_bit, /* only bitstream is supported */ 24 + f_rbt, 25 + f_bin, 26 + f_mcs, 27 + f_hex, 28 + }; 29 + 30 + enum mdownload { 31 + m_systemmap, /* only system map is supported */ 32 + m_serial, 33 + m_jtag, 34 + }; 35 + 36 + /* 37 + * xilinx fpgaimage information 38 + * NOTE: use MAX_STR instead of dynamic alloc for simplicity 39 + */ 40 + struct fpgaimage { 41 + enum fmt_image fmt_img; 42 + enum mdownload dmethod; 43 + 44 + const struct firmware *fw_entry; 45 + 46 + /* 47 + * the followings can be read from bitstream, 48 + * but other image format should have as well 49 + */ 50 + char filename[MAX_STR]; 51 + char part[MAX_STR]; 52 + char date[MAX_STR]; 53 + char time[MAX_STR]; 54 + int32_t lendata; 55 + char *fpgadata; 56 + };
+294
drivers/staging/gs_fpgaboot/io.c
··· 1 + /* 2 + * This program is free software; you can redistribute it and/or modify 3 + * it under the terms of the GNU General Public License as published by 4 + * the Free Software Foundation; either version 2 of the License, or 5 + * (at your option) any later version. 6 + * 7 + * This program is distributed in the hope that it will be useful, 8 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + * 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program; if not, write to the Free Software 15 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 + */ 17 + 18 + #include <linux/kernel.h> 19 + #include <linux/init.h> 20 + #include <linux/module.h> 21 + #include <linux/types.h> 22 + #include <linux/device.h> 23 + #include <linux/string.h> 24 + #include <linux/slab.h> 25 + #include <linux/fs.h> 26 + #include <linux/platform_device.h> 27 + #include <linux/of.h> 28 + #include <linux/of_address.h> 29 + #include <linux/firmware.h> 30 + #include <linux/io.h> 31 + 32 + #include "io.h" 33 + 34 + #ifdef CONFIG_B4860G100 35 + static struct gpiobus gbus; 36 + #endif /* CONFIG_B4860G100 */ 37 + 38 + static inline void byte0_out(unsigned char data); 39 + static inline void byte1_out(unsigned char data); 40 + static inline void xl_cclk_b(int32_t i); 41 + 42 + 43 + /* Assert and Deassert CCLK */ 44 + void xl_shift_cclk(int count) 45 + { 46 + int i; 47 + for (i = 0; i < count; i++) { 48 + xl_cclk_b(1); 49 + xl_cclk_b(0); 50 + } 51 + } 52 + 53 + int xl_supported_prog_bus_width(enum wbus bus_bytes) 54 + { 55 + switch (bus_bytes) { 56 + case bus_1byte: 57 + break; 58 + case bus_2byte: 59 + break; 60 + default: 61 + pr_err("unsupported program bus width %d\n", 62 + bus_bytes); 63 + return 0; 64 + } 65 + 66 + return 1; 67 + } 68 + 69 + /* Serialize byte and clock each bit on target's DIN and CCLK pins */ 70 + void xl_shift_bytes_out(enum wbus bus_byte, unsigned char *pdata) 71 + { 72 + /* 73 + * supports 1 and 2 bytes programming mode 74 + */ 75 + if (likely(bus_byte == bus_2byte)) 76 + byte0_out(pdata[0]); 77 + 78 + byte1_out(pdata[1]); 79 + xl_shift_cclk(1); 80 + } 81 + 82 + /* 83 + * generic bit swap for xilinx SYSTEMMAP FPGA programming 84 + */ 85 + static inline unsigned char bitswap(unsigned char s) 86 + { 87 + unsigned char d; 88 + d = (((s&0x80)>>7) | ((s&0x40)>>5) | ((s&0x20)>>3) | ((s&0x10)>>1) | 89 + ((s&0x08)<<1) | ((s&0x04)<<3) | ((s&0x02)<<5) | ((s&0x01)<<7)); 90 + return d; 91 + } 92 + 93 + #ifdef CONFIG_B4860G100 94 + /* 95 + * ====================================================================== 96 + * board specific configuration 97 + */ 98 + 99 + static inline void mpc85xx_gpio_set_dir( 100 + int32_t port, 101 + uint32_t mask, 102 + uint32_t dir) 103 + { 104 + dir |= (in_be32(gbus.r[port]+GPDIR) & ~mask); 105 + out_be32(gbus.r[port]+GPDIR, dir); 106 + } 107 + 108 + static inline void mpc85xx_gpio_set(int32_t port, uint32_t mask, uint32_t val) 109 + { 110 + /* First mask off the unwanted parts of "dir" and "val" */ 111 + val &= mask; 112 + 113 + /* Now read in the values we're supposed to preserve */ 114 + val |= (in_be32(gbus.r[port]+GPDAT) & ~mask); 115 + 116 + out_be32(gbus.r[port]+GPDAT, val); 117 + } 118 + 119 + static inline uint32_t mpc85xx_gpio_get(int32_t port, uint32_t mask) 120 + { 121 + /* Read the requested values */ 122 + return in_be32(gbus.r[port]+GPDAT) & mask; 123 + } 124 + 125 + static inline void mpc85xx_gpio_set_low(int32_t port, uint32_t gpios) 126 + { 127 + mpc85xx_gpio_set(port, gpios, 0x00000000); 128 + } 129 + 130 + static inline void mpc85xx_gpio_set_high(int32_t port, uint32_t gpios) 131 + { 132 + mpc85xx_gpio_set(port, gpios, 0xFFFFFFFF); 133 + } 134 + 135 + static inline void gpio_set_value(int32_t port, uint32_t gpio, uint32_t value) 136 + { 137 + int32_t g; 138 + g = 31 - gpio; 139 + if (value) 140 + mpc85xx_gpio_set_high(port, 1U << g); 141 + else 142 + mpc85xx_gpio_set_low(port, 1U << g); 143 + } 144 + 145 + static inline int gpio_get_value(int32_t port, uint32_t gpio) 146 + { 147 + int32_t g; 148 + g = 31 - gpio; 149 + return !!mpc85xx_gpio_get(port, 1U << g); 150 + } 151 + 152 + static inline void xl_cclk_b(int32_t i) 153 + { 154 + gpio_set_value(XL_CCLK_PORT, XL_CCLK_PIN, i); 155 + } 156 + 157 + void xl_program_b(int32_t i) 158 + { 159 + gpio_set_value(XL_PROGN_PORT, XL_PROGN_PIN, i); 160 + } 161 + 162 + void xl_rdwr_b(int32_t i) 163 + { 164 + gpio_set_value(XL_RDWRN_PORT, XL_RDWRN_PIN, i); 165 + } 166 + 167 + void xl_csi_b(int32_t i) 168 + { 169 + gpio_set_value(XL_CSIN_PORT, XL_CSIN_PIN, i); 170 + } 171 + 172 + int xl_get_init_b(void) 173 + { 174 + return gpio_get_value(XL_INITN_PORT, XL_INITN_PIN); 175 + } 176 + 177 + int xl_get_done_b(void) 178 + { 179 + return gpio_get_value(XL_DONE_PORT, XL_DONE_PIN); 180 + } 181 + 182 + 183 + /* G100 specific bit swap and remmap (to gpio pins) for byte 0 */ 184 + static inline uint32_t bit_remap_byte0(uint32_t s) 185 + { 186 + uint32_t d; 187 + d = (((s&0x80)>>7) | ((s&0x40)>>5) | ((s&0x20)>>3) | ((s&0x10)>>1) | 188 + ((s&0x08)<<1) | ((s&0x04)<<3) | ((s&0x02)<<6) | ((s&0x01)<<9)); 189 + return d; 190 + } 191 + 192 + /* 193 + * G100 specific MSB, in this order [byte0 | byte1], out 194 + */ 195 + static inline void byte0_out(unsigned char data) 196 + { 197 + uint32_t swap32; 198 + swap32 = bit_remap_byte0((uint32_t) data) << 8; 199 + 200 + mpc85xx_gpio_set(0, 0x0002BF00, (uint32_t) swap32); 201 + } 202 + 203 + /* 204 + * G100 specific LSB, in this order [byte0 | byte1], out 205 + */ 206 + static inline void byte1_out(unsigned char data) 207 + { 208 + mpc85xx_gpio_set(0, 0x000000FF, (uint32_t) bitswap(data)); 209 + } 210 + 211 + /* 212 + * configurable per device type for different I/O config 213 + */ 214 + int xl_init_io() 215 + { 216 + struct device_node *np; 217 + const u32 *p_reg; 218 + int reg, cnt; 219 + 220 + cnt = 0; 221 + memset(&gbus, 0, sizeof(struct gpiobus)); 222 + for_each_compatible_node(np, NULL, "fsl,qoriq-gpio") { 223 + p_reg = of_get_property(np, "reg", NULL); 224 + if (p_reg == NULL) 225 + break; 226 + reg = (int) *p_reg; 227 + gbus.r[cnt] = of_iomap(np, 0); 228 + 229 + if (!gbus.r[cnt]) { 230 + pr_err("not findding gpio cell-index %d\n", cnt); 231 + return -ENODEV; 232 + } 233 + cnt++; 234 + } 235 + mpc85xx_gpio_set_dir(0, 0x0002BFFF, 0x0002BFFF); 236 + mpc85xx_gpio_set_dir(1, 0x00240060, 0x00240060); 237 + 238 + gbus.ngpio = cnt; 239 + 240 + return 0; 241 + } 242 + 243 + 244 + #else /* placeholder for boards with different config */ 245 + 246 + void xl_program_b(int32_t i) 247 + { 248 + return; 249 + } 250 + 251 + void xl_rdwr_b(int32_t i) 252 + { 253 + return; 254 + } 255 + 256 + void xl_csi_b(int32_t i) 257 + { 258 + return; 259 + } 260 + 261 + int xl_get_init_b(void) 262 + { 263 + return -1; 264 + } 265 + 266 + int xl_get_done_b(void) 267 + { 268 + return -1; 269 + } 270 + 271 + static inline void byte0_out(unsigned char data) 272 + { 273 + return; 274 + } 275 + 276 + static inline void byte1_out(unsigned char data) 277 + { 278 + return; 279 + } 280 + 281 + static inline void xl_cclk_b(int32_t i) 282 + { 283 + return; 284 + } 285 + 286 + /* 287 + * configurable per device type for different I/O config 288 + */ 289 + int xl_init_io() 290 + { 291 + return -1; 292 + } 293 + 294 + #endif /* CONFIG_B4860G100 */
+90
drivers/staging/gs_fpgaboot/io.h
··· 1 + /* 2 + * This program is free software; you can redistribute it and/or modify 3 + * it under the terms of the GNU General Public License as published by 4 + * the Free Software Foundation; either version 2 of the License, or 5 + * (at your option) any later version. 6 + * 7 + * This program is distributed in the hope that it will be useful, 8 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + * 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program; if not, write to the Free Software 15 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 + */ 17 + 18 + #define GPDIR 0 19 + #define GPCFG 4 /* open drain or not */ 20 + #define GPDAT 8 21 + 22 + /* 23 + * gpio port and pin definitions 24 + * NOTE: port number starts from 0 25 + */ 26 + #define XL_INITN_PORT 1 27 + #define XL_INITN_PIN 14 28 + #define XL_RDWRN_PORT 1 29 + #define XL_RDWRN_PIN 13 30 + #define XL_CCLK_PORT 1 31 + #define XL_CCLK_PIN 10 32 + #define XL_PROGN_PORT 1 33 + #define XL_PROGN_PIN 25 34 + #define XL_CSIN_PORT 1 35 + #define XL_CSIN_PIN 26 36 + #define XL_DONE_PORT 1 37 + #define XL_DONE_PIN 27 38 + 39 + /* 40 + * gpio mapping 41 + * 42 + XL_config_D0 – gpio1_31 43 + Xl_config_d1 – gpio1_30 44 + Xl_config_d2 – gpio1_29 45 + Xl_config_d3 – gpio1_28 46 + Xl_config_d4 – gpio1_27 47 + Xl_config_d5 – gpio1_26 48 + Xl_config_d6 – gpio1_25 49 + Xl_config_d7 – gpio1_24 50 + Xl_config_d8 – gpio1_23 51 + Xl_config_d9 – gpio1_22 52 + Xl_config_d10 – gpio1_21 53 + Xl_config_d11 – gpio1_20 54 + Xl_config_d12 – gpio1_19 55 + Xl_config_d13 – gpio1_18 56 + Xl_config_d14 – gpio1_16 57 + Xl_config_d15 – gpio1_14 58 + * 59 + */ 60 + 61 + /* 62 + * program bus width in bytes 63 + */ 64 + enum wbus { 65 + bus_1byte = 1, 66 + bus_2byte = 2, 67 + }; 68 + 69 + 70 + #define MAX_WAIT_DONE 10000 71 + 72 + 73 + struct gpiobus { 74 + int ngpio; 75 + void __iomem *r[4]; 76 + }; 77 + 78 + int xl_supported_prog_bus_width(enum wbus bus_bytes); 79 + 80 + void xl_program_b(int32_t i); 81 + void xl_rdwr_b(int32_t i); 82 + void xl_csi_b(int32_t i); 83 + 84 + int xl_get_init_b(void); 85 + int xl_get_done_b(void); 86 + 87 + void xl_shift_cclk(int count); 88 + void xl_shift_bytes_out(enum wbus bus_byte, unsigned char *pdata); 89 + 90 + int xl_init_io(void);