cregit-Linux how code gets into the kernel

Release 4.11 drivers/staging/gs_fpgaboot/gs_fpgaboot.c

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/firmware.h>

#include "gs_fpgaboot.h"
#include "io.h"


#define DEVICE_NAME "device"

#define CLASS_NAME  "fpgaboot"


static u8 bits_magic[] = {
	0x0, 0x9, 0xf, 0xf0, 0xf, 0xf0,
	0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x1};

/* fake device for request_firmware */

static struct platform_device	*firmware_pdev;


static char	*file = "xlinx_fpga_firmware.bit";
module_param(file, charp, 0444);
MODULE_PARM_DESC(file, "Xilinx FPGA firmware file.");


static void read_bitstream(char *bitdata, char *buf, int *offset, int rdsize) { memcpy(buf, bitdata + *offset, rdsize); *offset += rdsize; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song38100.00%1100.00%
Total38100.00%1100.00%


static void readinfo_bitstream(char *bitdata, char *buf, int *offset) { char tbuf[64]; s32 len; /* read section char */ read_bitstream(bitdata, tbuf, offset, 1); /* read length */ read_bitstream(bitdata, tbuf, offset, 2); len = tbuf[0] << 8 | tbuf[1]; read_bitstream(bitdata, buf, offset, len); buf[len] = '\0'; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song8298.80%150.00%
Ben Marsh11.20%150.00%
Total83100.00%2100.00%

/* * read bitdata length */
static int readlength_bitstream(char *bitdata, int *lendata, int *offset) { char tbuf[64]; /* read section char */ read_bitstream(bitdata, tbuf, offset, 1); /* make sure it is section 'e' */ if (tbuf[0] != 'e') { pr_err("error: length section is not 'e', but %c\n", tbuf[0]); return -1; } /* read 4bytes length */ read_bitstream(bitdata, tbuf, offset, 4); *lendata = tbuf[0] << 24 | tbuf[1] << 16 | tbuf[2] << 8 | tbuf[3]; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song106100.00%1100.00%
Total106100.00%1100.00%

/* * read first 13 bytes to check bitstream magic number */
static int readmagic_bitstream(char *bitdata, int *offset) { char buf[13]; int r; read_bitstream(bitdata, buf, offset, 13); r = memcmp(buf, bits_magic, 13); if (r) { pr_err("error: corrupted header"); return -1; } pr_info("bitstream file magic number Ok\n"); *offset = 13; /* magic length */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song74100.00%1100.00%
Total74100.00%1100.00%

/* * NOTE: supports only bitstream format */
static enum fmt_image get_imageformat(struct fpgaimage *fimage) { return f_bit; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song15100.00%1100.00%
Total15100.00%1100.00%


static void gs_print_header(struct fpgaimage *fimage) { pr_info("file: %s\n", fimage->filename); pr_info("part: %s\n", fimage->part); pr_info("date: %s\n", fimage->date); pr_info("time: %s\n", fimage->time); pr_info("lendata: %d\n", fimage->lendata); }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song56100.00%1100.00%
Total56100.00%1100.00%


static void gs_read_bitstream(struct fpgaimage *fimage) { char *bitdata; int offset; offset = 0; bitdata = (char *)fimage->fw_entry->data; readmagic_bitstream(bitdata, &offset); readinfo_bitstream(bitdata, fimage->filename, &offset); readinfo_bitstream(bitdata, fimage->part, &offset); readinfo_bitstream(bitdata, fimage->date, &offset); readinfo_bitstream(bitdata, fimage->time, &offset); readlength_bitstream(bitdata, &fimage->lendata, &offset); fimage->fpgadata = bitdata + offset; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song111100.00%1100.00%
Total111100.00%1100.00%


static int gs_read_image(struct fpgaimage *fimage) { int img_fmt; img_fmt = get_imageformat(fimage); switch (img_fmt) { case f_bit: pr_info("image is bitstream format\n"); gs_read_bitstream(fimage); break; default: pr_err("unsupported fpga image format\n"); return -1; } gs_print_header(fimage); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song59100.00%1100.00%
Total59100.00%1100.00%


static int gs_load_image(struct fpgaimage *fimage, char *fw_file) { int err; pr_info("load fpgaimage %s\n", fw_file); err = request_firmware(&fimage->fw_entry, fw_file, &firmware_pdev->dev); if (err != 0) { pr_err("firmware %s is missing, cannot continue.\n", fw_file); return err; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song5993.65%150.00%
Devendra Naga46.35%150.00%
Total63100.00%2100.00%


static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes) { char *bitdata; int size, i, cnt; cnt = 0; bitdata = (char *)fimage->fpgadata; size = fimage->lendata; #ifdef DEBUG_FPGA print_hex_dump_bytes("bitfile sample: ", DUMP_PREFIX_OFFSET, bitdata, 0x100); #endif /* DEBUG_FPGA */ if (!xl_supported_prog_bus_width(bus_bytes)) { pr_err("unsupported program bus width %d\n", bus_bytes); return -1; } /* Bring csi_b, rdwr_b Low and program_b High */ xl_program_b(1); xl_rdwr_b(0); xl_csi_b(0); /* Configuration reset */ xl_program_b(0); msleep(20); xl_program_b(1); /* Wait for Device Initialization */ while (xl_get_init_b() == 0) ; pr_info("device init done\n"); for (i = 0; i < size; i += bus_bytes) xl_shift_bytes_out(bus_bytes, bitdata + i); pr_info("program done\n"); /* Check INIT_B */ if (xl_get_init_b() == 0) { pr_err("init_b 0\n"); return -1; } while (xl_get_done_b() == 0) { if (cnt++ > MAX_WAIT_DONE) { pr_err("init_B %d\n", xl_get_init_b()); break; } } if (cnt > MAX_WAIT_DONE) { pr_err("fpga download fail\n"); return -1; } pr_info("download fpgaimage\n"); /* Compensate for Special Startup Conditions */ xl_shift_cclk(8); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song23198.30%150.00%
Joe Perches41.70%150.00%
Total235100.00%2100.00%


static int gs_release_image(struct fpgaimage *fimage) { release_firmware(fimage->fw_entry); pr_info("release fpgaimage\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song26100.00%1100.00%
Total26100.00%1100.00%

/* * NOTE: supports systemmap parallel programming */
static int gs_set_download_method(struct fpgaimage *fimage) { pr_info("set program method\n"); fimage->dmethod = m_systemmap; pr_info("systemmap program method\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song30100.00%1100.00%
Total30100.00%1100.00%


static int init_driver(void) { firmware_pdev = platform_device_register_simple("fpgaboot", -1, NULL, 0); return PTR_ERR_OR_ZERO(firmware_pdev); }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song2796.43%150.00%
Fengguang Wu13.57%150.00%
Total28100.00%2100.00%


static int gs_fpgaboot(void) { int err; struct fpgaimage *fimage; fimage = kmalloc(sizeof(*fimage), GFP_KERNEL); if (!fimage) return -ENOMEM; err = gs_load_image(fimage, file); if (err) { pr_err("gs_load_image error\n"); goto err_out1; } err = gs_read_image(fimage); if (err) { pr_err("gs_read_image error\n"); goto err_out2; } err = gs_set_download_method(fimage); if (err) { pr_err("gs_set_download_method error\n"); goto err_out2; } err = gs_download_image(fimage, bus_2byte); if (err) { pr_err("gs_download_image error\n"); goto err_out2; } err = gs_release_image(fimage); if (err) { pr_err("gs_release_image error\n"); goto err_out1; } kfree(fimage); return 0; err_out2: err = gs_release_image(fimage); if (err) pr_err("gs_release_image error\n"); err_out1: kfree(fimage); return -1; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song17796.20%133.33%
Dzmitry Sledneu52.72%133.33%
Ben Marsh21.09%133.33%
Total184100.00%3100.00%


static int __init gs_fpgaboot_init(void) { int err; pr_info("FPGA DOWNLOAD --->\n"); pr_info("FPGA image file name: %s\n", file); err = init_driver(); if (err) { pr_err("FPGA DRIVER INIT FAIL!!\n"); return err; } err = xl_init_io(); if (err) { pr_err("GPIO INIT FAIL!!\n"); goto errout; } err = gs_fpgaboot(); if (err) { pr_err("FPGA DOWNLOAD FAIL!!\n"); goto errout; } pr_info("FPGA DOWNLOAD DONE <---\n"); return 0; errout: platform_device_unregister(firmware_pdev); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song9292.93%133.33%
Eva Rachel Retuya44.04%133.33%
Devendra Naga33.03%133.33%
Total99100.00%3100.00%


static void __exit gs_fpgaboot_exit(void) { platform_device_unregister(firmware_pdev); pr_info("FPGA image download module removed\n"); }

Contributors

PersonTokensPropCommitsCommitProp
Insop Song1578.95%150.00%
Eva Rachel Retuya421.05%150.00%
Total19100.00%2100.00%

module_init(gs_fpgaboot_init); module_exit(gs_fpgaboot_exit); MODULE_AUTHOR("Insop Song"); MODULE_DESCRIPTION("Xlinix FPGA firmware download"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Insop Song134197.74%19.09%
Eva Rachel Retuya80.58%19.09%
Devendra Naga70.51%218.18%
Dzmitry Sledneu50.36%19.09%
Ben Marsh40.29%218.18%
Joe Perches40.29%19.09%
Rehas Sachdeva10.07%19.09%
Shyam Saini10.07%19.09%
Fengguang Wu10.07%19.09%
Total1372100.00%11100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.