mcap: Add MCAP Linux Library

The MCAP interface enables an embedded microprocessor, such as MicroBlaze,
    to read and write the FPGA configuration memory.
    This library allows user to access the MCAP i/f.

Signed-off-by: Srikanth Thokala <sthokal@xilinx.com>
Signed-off-by: Kedareswara rao Appana <appanad@xilinx.com>
This commit is contained in:
Kedareswara rao Appana 2014-10-16 12:44:02 +05:30 committed by Suneel Garapati
parent e3b8e045d0
commit e29e5689e0
6 changed files with 1045 additions and 12 deletions

View file

@ -6,12 +6,15 @@ All software is version less and divided into three directories
- license.txt
contains information about the various licenses and copyrights
- XilinxProcessorIPLib
contains all drivers
- ThirdParty
software from third party like light weight IP stack
Every driver/lib/apps/services has these sub-directories
contains all drivers
- ThirdParty
software from third party like light weight IP stack
- mcap
software for using MCAP interface on Ultra Scale boards to
program 2nd level bitstream
Every driver/lib/apps/services has these sub-directories
1. data - contains tcl, mdd, testapp tcl or header files used in SDK
2. doc - documentation of source code in form of pdf or html
3. examples - illustrating different use cases of driver
@ -53,12 +56,15 @@ Every driver/lib/apps/services has these sub-directories
|
| Note - All these are libraries and utilize drivers
|
|-ThirdParty
| |- sw_services
| |- lwip140
Building FSBL from git:
|-ThirdParty
| |- sw_services
| |- lwip140
|
|-mcap
| |-linux
Building FSBL from git:
FSBL has 3 directories.
1. data - It contains files for SDK

35
mcap/linux/Makefile Normal file
View file

@ -0,0 +1,35 @@
# Makefile for Xilinx MCAP Interface Library
# (c) 2014 Xilinx Inc.
PCIUTILS_PATH =
PCILIB_PATH=$(PCIUTILS_PATH)/lib/
INCLUDES = -I$(PCILIB_PATH) -I$(PCIUTILS_PATH) -I.
OPT=-O2
CFLAGS=$(OPT) -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes $(INCLUDES)
LDFLAGS = -L$(PCILIB_PATH)
LDLIBS = -lpci
PCILIB = $(PCILIB_PATH)/libpci.a
MCAPLIB = libmcap.a
MCAPINC = mcap_lib.h
OBJ = mcap_lib.o
all: $(MCAPLIB) mcap
$(MCAPLIB): $(OBJ)
ar rcs $(MCAPLIB) $(OBJ)
$(OBJ):
gcc $(LDFLAGS) $(CFLAGS) -c mcap_lib.c $< -o $@ $(LDLIBS)
mcap: mcap.o
gcc $(CFLAGS) mcap.c $(MCAPLIB) $(PCILIB) -lz -o mcap
clean:
rm -f *.o *.a mcap

56
mcap/linux/README Normal file
View file

@ -0,0 +1,56 @@
Steps to compile
################
1. Download the latest PCI Utilites source from
https://www.kernel.org/pub/software/utils/pciutils/
(Or) Source can be clone from the GIT repository,
http://git.kernel.org/cgit/utils/pciutils/pciutils.git/
2. Compile the PCI Utilities by the following command,
$pci-utils> make
3. Compile the MCAP Library by the following make command,
$mcap-lib> make PCIUTILS_PATH=<PATH to PCI Utilities Source>
4. Compiling the MCAP library generates 'libmcap.a' and
example elf 'mcap' built on top of generated library.
Steps to Run
############
-> Running the 'mcap.elf' with '-h' lists all the options
that are available to communicate with the underlying
MCAP device,
$Linux> ./mcap -h
Usage: mcap [options]
Options:
-x Specify MCAP Device ID in hex (Mandatory)
-p <file> Program Bitstream (.bin/.bit/.rbt)
-r Performs Simple Reset
-m Performs Module Reset
-f Performs Full Reset
-D Read Data Registers
-d Dump all the MCAP Registers
-v Verbose information of MCAP Device
-h/H Help
-c <address> [type [data]] Access Device Configuration Space
NOTE: Specifying MCAP Device Id option is mandatory for the application
to run. For example,
$Linux> ./mcap -x 0x8011
Xilinx MCAP Device Found
NOTES
#####
. PCI Extended Capability Registers in Linux will only be
accessible with privileged user access. So, the example elf should
be run with ROOT permissions.
. To access device configuration space, 'type' in the above syntax should
be either b/h/w (byte/half-word/word). For example,
-> Reading a byte
./mcap -x 0x8011 -c 0x354 b
-> Writing a word
./mcap -x 0x8011 -c 0x354 w 0x3

167
mcap/linux/mcap.c Normal file
View file

@ -0,0 +1,167 @@
/******************************************************************************
* Copyright (C) 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file mcap.c
* MCAP Interface Library Test Application
*
******************************************************************************/
#include "mcap_lib.h"
static const char options[] = "x:p:rmfdvHhDc::";
static char help_msg[] =
"Usage: mcap [options]\n"
"\n"
"Options:\n"
"\t-x\t\tSpecify MCAP Device Id in hex (MANDATORY)\n"
"\t-p <file>\tProgram Bitstream (.bin/.bit/.rbt)\n"
"\t-r\t\tPerforms Simple Reset\n"
"\t-m\t\tPerforms Module Reset\n"
"\t-f\t\tPerforms Full Reset\n"
"\t-D\t\tRead Data Registers\n"
"\t-d\t\tDump all the MCAP Registers\n"
"\t-v\t\tVerbose information of MCAP Device\n"
"\t-h/H\t\tHelp\n"
"\t-c <address> [type [data]] Access Device Configuration Space\n"
"\n"
;
int main(int argc, char **argv)
{
struct mcap_dev *mdev;
int i, modreset = 0, fullreset = 0, reset = 0;
int program = 0, verbose = 0, device_id = 0;
int data_regs = 0, dump_regs = 0, access_config = 0;
while ((i = getopt(argc, argv, options)) != -1) {
switch (i) {
case 'c':
access_config = 1;
break;
case 'd':
dump_regs = 1;
break;
case 'm':
modreset = 1;
break;
case 'f':
fullreset = 1;
break;
case 'r':
reset = 1;
break;
case 'D':
data_regs = 1;
break;
case 'h':
case 'H':
printf("%s", help_msg);
return 1;
case 'p':
program = 1;
break;
case 'v':
verbose++;
break;
case 'x':
device_id = (int) strtol(argv[2], NULL, 16);
break;
default:
printf("%s", help_msg);
return 1;
}
}
if (!device_id) {
printf("No device id specified...\n");
printf("%s", help_msg);
return 1;
}
mdev = (struct mcap_dev *)MCapLibInit(device_id);
if (!mdev)
return 1;
if (verbose) {
MCapShowDevice(mdev, verbose);
goto free;
}
if (access_config) {
if (argc < 6) {
printf("%s", help_msg);
goto free;
}
if (MCapAccessConfigSpace(mdev, argc, argv))
printf("%s", help_msg);
goto free;
}
if (fullreset) {
MCapFullReset(mdev);
goto free;
}
if (modreset) {
MCapModuleReset(mdev);
goto free;
}
if (reset) {
MCapReset(mdev);
goto free;
}
if (program) {
MCapConfigureFPGA(mdev, argv[4]);
goto free;
}
if (dump_regs) {
MCapDumpRegs(mdev);
goto free;
}
if (data_regs) {
MCapDumpReadRegs(mdev);
goto free;
}
if (i == -1 && argc == 1)
MCapShowDevice(mdev, 0);
free:
MCapLibFree(mdev);
return 0;
}

611
mcap/linux/mcap_lib.c Normal file
View file

@ -0,0 +1,611 @@
/******************************************************************************
* Copyright (C) 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file mcap_lib.c
* MCAP Interface Library functions
*
******************************************************************************/
#include "mcap_lib.h"
/* Library Specific Definitions */
#define MCAP_VENDOR_ID 0x10EE
#define MCAP_LOOP_COUNT 1000000
#define MCAP_SYNC_DWORD 0xaa995566
#define MCAP_SYNC_BYTE0 ((MCAP_SYNC_DWORD & 0xFF000000) >> 24)
#define MCAP_SYNC_BYTE1 ((MCAP_SYNC_DWORD & 0x00FF0000) >> 16)
#define MCAP_SYNC_BYTE2 ((MCAP_SYNC_DWORD & 0x0000FF00) >> 8)
#define MCAP_SYNC_BYTE3 ((MCAP_SYNC_DWORD & 0x000000FF) >> 0)
#define MCAP_RBT_FILE ".rbt"
#define MCAP_BIT_FILE ".bit"
#define MCAP_BIN_FILE ".bin"
static char *MCapFindTypeofFile(const char *s1, const char *s2)
{
size_t l1, l2;
l2 = strlen(s2);
if (!l2)
return (char *)s1;
l1 = strlen(s1);
while (l1 >= l2) {
l1--;
if (!strncasecmp(s1, s2, l2))
return (char *)s1;
s1++;
}
return NULL;
}
static u32 MCapProcessRBT(FILE *fptr, u32 *buf)
{
char *raw = NULL;
int i, read;
size_t linelen;
u32 count = 0, len = 0, result = 0;
while ((read = getline(&raw, &linelen, fptr)) != -1) {
if (raw[0] == '/' && raw[1] == '/')
continue;
for (i = 0; i < read - 1; i++) {
if (raw[i] == '1' || raw[i] == '0') {
result = (result << 1) | (raw[i] - 0x30);
count++;
if (count == 32) {
*buf++ = result;
len += 4;
result = count = 0;
break;
}
}
}
}
return len/4;
}
static u32 MCapProcessBIT(FILE *fptr, u32 *buf, int sz)
{
int err;
u8 value, len = 0;
/*
* .bit files are not guaranteed to be aligned with
* the bitstream sync word on a 32-bit boundary. So,
* we need to check every byte here.
*/
while ((err = fread(&value, 1, 1, fptr)) == 1) {
if (value == MCAP_SYNC_BYTE0)
if ((err = fread(&value, 1, 1, fptr)) == 1)
if (value == MCAP_SYNC_BYTE1)
if ((err = fread(&value, 1, 1, fptr)) == 1)
if (value == MCAP_SYNC_BYTE2)
if ((err = fread(&value, 1, 1, fptr)) == 1)
if (value == MCAP_SYNC_BYTE3)
break;
}
if (err != 1 && !feof(fptr)) {
pr_err("Failed to Read BIT file\n");
return 0;
}
if (err != 1 && feof(fptr)) {
pr_err("Failed to find SYNC Word in BIT file\n");
return 0;
}
*buf++ = __bswap_32(MCAP_SYNC_DWORD);
len += 4;
while ((err = fread(buf, sz - len, 1, fptr)) == 1)
;
if (err != 1 && !feof(fptr)) {
pr_err("Failed to Read BIT file\n");
return 0;
}
return (sz - len)/4;
}
static u32 MCapProcessBIN(FILE *fptr, u32 *buf, int sz)
{
int err;
err = fread(buf, sz, 1, fptr);
if (err != 1 && !feof(fptr)) {
pr_err("Failed to Read BIN file\n");
return 0;
}
return sz/4;
}
static int MCapDoBusWalk(struct mcap_dev *mdev)
{
struct pci_cap *c;
c = pci_find_cap(mdev->pdev, MCAP_EXT_CAP_ID, PCI_CAP_EXTENDED);
if (!c)
return -EMCAPBUSWALK;
mdev->reg_base = c->addr;
return 0;
}
static int MCapClearRequestByConfigure(struct mcap_dev *mdev, u32 *restore)
{
u32 set;
int loop = MCAP_LOOP_COUNT;
set = *restore = MCapRegRead(mdev, MCAP_CONTROL);
if (IsConfigureMCapReqSet(mdev)) {
/* Set 'Mode' and 'In Use by PCIe' bits */
set |= (MCAP_CTRL_MODE_MASK | MCAP_CTRL_IN_USE_MASK);
MCapRegWrite(mdev, MCAP_CONTROL, set);
do {
if (!(IsConfigureMCapReqSet(mdev)))
break;
} while (loop--);
if (!loop) {
pr_err("Failed to clear MCAP Request by config bit\n");
MCapRegWrite(mdev, MCAP_CONTROL, *restore);
return -EMCAPREQ;
}
}
pr_dbg("Request by Configure bit cleared!!\n");
return 0;
}
static int MCapWriteBitStream(struct mcap_dev *mdev, u32 *data,
int len, u8 bswap)
{
u32 set, restore;
int err, count = 0;
if (!data || !len) {
pr_err("Invalid Arguments\n");
return -EMCAPWRITE;
}
err = MCapClearRequestByConfigure(mdev, &restore);
if (err)
return err;
if (IsErrSet(mdev) || IsRegReadComplete(mdev) ||
IsFifoOverflow(mdev)) {
pr_err("Failed to initialize configuring FPGA\n");
MCapRegWrite(mdev, MCAP_CONTROL, restore);
return -EMCAPWRITE;
}
/* Set 'Mode', 'In Use by PCIe' and 'Data Reg Protect' bits */
set = MCapRegRead(mdev, MCAP_CONTROL);
set |= MCAP_CTRL_MODE_MASK | MCAP_CTRL_IN_USE_MASK |
MCAP_CTRL_DATA_REG_PROT_MASK;
/* Clear 'Reset', 'Module Reset' and 'Register Read' bits */
set &= ~(MCAP_CTRL_RESET_MASK | MCAP_CTRL_MOD_RESET_MASK |
MCAP_CTRL_REG_READ_MASK | MCAP_CTRL_DESIGN_SWITCH_MASK);
MCapRegWrite(mdev, MCAP_CONTROL, set);
/* Write Data */
if (!bswap) {
for (count = 0; count < len; count++)
MCapRegWrite(mdev, MCAP_DATA, data[count]);
} else {
for (count = 0; count < len; count++)
MCapRegWrite(mdev, MCAP_DATA, __bswap_32(data[count]));
}
if (IsErrSet(mdev) || IsFifoOverflow(mdev)) {
pr_err("Failed to Write Bitstream\n");
MCapRegWrite(mdev, MCAP_CONTROL, restore);
return -EMCAPWRITE;
}
/* Enable PCIe BAR reads/writes in the PCIe hardblock */
restore |= MCAP_CTRL_DESIGN_SWITCH_MASK;
MCapRegWrite(mdev, MCAP_CONTROL, restore);
return 0;
}
void MCapLibFree(struct mcap_dev *mdev)
{
if (mdev) {
pci_cleanup(mdev->pacc);
free(mdev);
}
}
struct mcap_dev *MCapLibInit(int device_id)
{
struct pci_dev *dev;
struct mcap_dev *mdev;
/* Allocate MCAP device */
mdev = malloc(sizeof(struct mcap_dev));
if (!mdev)
return NULL;
/* Get the pci_access structure */
mdev->pacc = pci_alloc();
/* Initialize the PCI library */
pci_init(mdev->pacc);
/* Get the list of devices */
pci_scan_bus(mdev->pacc);
for (dev = mdev->pacc->devices; dev; dev = dev->next) {
/* Fill in header info we need */
pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES |
PCI_FILL_CLASS);
if (dev->vendor_id == MCAP_VENDOR_ID &&
dev->device_id == device_id) {
pr_info("Xilinx MCAP device found\n");
mdev->pdev = dev;
} else {
continue;
}
}
if (!mdev->pdev) {
pr_err("Xilinx MCAP device not found .. Exiting ...\n");
goto free_resources;
}
/* Get the MCAP Register base */
if (MCapDoBusWalk(mdev)) {
pr_err("Unable to get the Register Base\n");
goto free_resources;
}
return mdev;
free_resources:
MCapLibFree(mdev);
return NULL;
}
int MCapReset(struct mcap_dev *mdev)
{
u32 set, restore;
int err;
err = MCapClearRequestByConfigure(mdev, &restore);
if (err)
return err;
/* Set 'Mode', 'In Use by PCIe' and 'Reset' bits */
set = MCapRegRead(mdev, MCAP_CONTROL);
set |= MCAP_CTRL_MODE_MASK | MCAP_CTRL_IN_USE_MASK |
MCAP_CTRL_RESET_MASK;
MCapRegWrite(mdev, MCAP_CONTROL, set);
if (IsErrSet(mdev) || !(IsResetSet(mdev))) {
pr_err("Failed to Reset\n");
MCapRegWrite(mdev, MCAP_CONTROL, restore);
return -EMCAPRESET;
}
MCapRegWrite(mdev, MCAP_CONTROL, restore);
pr_info("Reset Done!!\n");
return 0;
}
int MCapModuleReset(struct mcap_dev *mdev)
{
u32 set, restore;
int err;
err = MCapClearRequestByConfigure(mdev, &restore);
if (err)
return err;
/* Set 'Mode', 'In Use by PCIe' and 'Module Reset' bits */
set = MCapRegRead(mdev, MCAP_CONTROL);
set |= MCAP_CTRL_MODE_MASK | MCAP_CTRL_IN_USE_MASK |
MCAP_CTRL_MOD_RESET_MASK;
MCapRegWrite(mdev, MCAP_CONTROL, set);
if (IsErrSet(mdev) || !(IsModuleResetSet(mdev))) {
pr_err("Failed to Reset Module\n");
MCapRegWrite(mdev, MCAP_CONTROL, restore);
return -EMCAPMODRESET;
}
MCapRegWrite(mdev, MCAP_CONTROL, restore);
pr_info("Module Reset Done!!\n");
return 0;
}
int MCapFullReset(struct mcap_dev *mdev)
{
u32 set, restore;
int err;
err = MCapClearRequestByConfigure(mdev, &restore);
if (err)
return err;
/* Set 'Mode', 'In Use by PCIe' and 'Module Reset' bits */
set = MCapRegRead(mdev, MCAP_CONTROL);
set |= MCAP_CTRL_MODE_MASK | MCAP_CTRL_IN_USE_MASK |
MCAP_CTRL_RESET_MASK | MCAP_CTRL_MOD_RESET_MASK;
MCapRegWrite(mdev, MCAP_CONTROL, set);
if (IsErrSet(mdev) || !(IsModuleResetSet(mdev)) ||
!(IsResetSet(mdev))) {
pr_err("Failed to Full Reset\n");
MCapRegWrite(mdev, MCAP_CONTROL, restore);
return -EMCAPFULLRESET;
}
MCapRegWrite(mdev, MCAP_CONTROL, restore);
pr_info("Full Reset Done!!\n");
return 0;
}
static int MCapReadDataRegisters(struct mcap_dev *mdev, u32 *data)
{
u32 set, restore, read_cnt;
int err;
if (!data) {
pr_err("Invalid Arguments\n");
return -EMCAPREAD;
}
err = MCapClearRequestByConfigure(mdev, &restore);
if (err)
return err;
/* Set 'Mode', 'In Use by PCIe' and 'Data Reg Protect' bits */
set = MCapRegRead(mdev, MCAP_CONTROL);
set |= MCAP_CTRL_MODE_MASK | MCAP_CTRL_IN_USE_MASK |
MCAP_CTRL_REG_READ_MASK;
/* Clear 'Reset', 'Module Reset' and 'Register Read' bits */
set &= ~(MCAP_CTRL_RESET_MASK | MCAP_CTRL_MOD_RESET_MASK);
MCapRegWrite(mdev, MCAP_CONTROL, set);
read_cnt = GetRegReadCount(mdev);
if (IsErrSet(mdev) || IsFifoOverflow(mdev) ||
!(read_cnt) || !(IsRegReadComplete(mdev))) {
pr_err("Read Register Set Configuration Failed\n");
MCapRegWrite(mdev, MCAP_CONTROL, restore);
return -EMCAPREAD;
}
switch (read_cnt) {
case 7: case 6: case 5: case 4:
data[3] = MCapRegRead(mdev, MCAP_READ_DATA_3);
/* Fall-through */
case 3:
data[2] = MCapRegRead(mdev, MCAP_READ_DATA_2);
/* Fall-through */
case 2:
data[1] = MCapRegRead(mdev, MCAP_READ_DATA_1);
/* Fall-through */
case 1:
data[0] = MCapRegRead(mdev, MCAP_READ_DATA_0);
break;
}
MCapRegWrite(mdev, MCAP_CONTROL, restore);
pr_dbg("Read Data Registers Complete!\n");
return 0;
}
void MCapDumpReadRegs(struct mcap_dev *mdev)
{
u32 data[4];
if (MCapReadDataRegisters(mdev, data)) {
pr_err("Failed Reading Registers.. This may be");
pr_err("due to inappropriate FPGA configuration.");
pr_err("Make sure you downloaded the correct bitstream\n");
return;
}
pr_info("Register Read Data 0:\t0x%08x\n", data[0]);
pr_info("Register Read Data 1:\t0x%08x\n", data[1]);
pr_info("Register Read Data 2:\t0x%08x\n", data[2]);
pr_info("Register Read Data 3:\t0x%08x\n", data[3]);
}
void MCapDumpRegs(struct mcap_dev *mdev)
{
pr_info("Extended Capability:\t0x%08x\n",
MCapRegRead(mdev, MCAP_EXT_CAP_HEADER));
pr_info("Vendor Specific Header:\t0x%08x\n",
MCapRegRead(mdev, MCAP_VEND_SPEC_HEADER));
pr_info("FPGA JTAG ID:\t\t0x%08x\n",
MCapRegRead(mdev, MCAP_FPGA_JTAG_ID));
pr_info("FPGA Bit-Stream Version:0x%08x\n",
MCapRegRead(mdev, MCAP_FPGA_BIT_VERSION));
pr_info("Status:\t\t\t0x%08x\n",
MCapRegRead(mdev, MCAP_STATUS));
pr_info("Control:\t\t0x%08x\n",
MCapRegRead(mdev, MCAP_CONTROL));
pr_info("Data:\t\t\t0x%08x\n",
MCapRegRead(mdev, MCAP_DATA));
MCapDumpReadRegs(mdev);
}
int MCapConfigureFPGA(struct mcap_dev *mdev, char *file_path)
{
FILE *fptr;
u32 *data;
u32 binsz, wrdatasz;
int err = 0;
u8 bswap = 0;
/* Get the size */
fptr = fopen(file_path, "rb");
if (fptr == NULL)
return -EMCAPCFG;
fseek(fptr, 0L, SEEK_END);
binsz = ftell(fptr);
fseek(fptr, 0L, SEEK_SET);
/* Allocate the buffer */
data = malloc(binsz);
if (data == NULL)
return -EMCAPCFG;
/* Process files and Read the data */
if (MCapFindTypeofFile(file_path, MCAP_RBT_FILE)) {
/* Read the RBT file */
wrdatasz = MCapProcessRBT(fptr, data);
} else if (MCapFindTypeofFile(file_path, MCAP_BIT_FILE)) {
/* Read the BIT file */
wrdatasz = MCapProcessBIT(fptr, data, binsz);
bswap = 1;
} else if (MCapFindTypeofFile(file_path, MCAP_BIN_FILE)) {
/* Read the BIN file */
wrdatasz = MCapProcessBIN(fptr, data, binsz);
bswap = 1;
} else {
pr_err("Unknown File Format\n");
goto free_resources;
}
/* Program FPGA */
err = MCapWriteBitStream(mdev, data, wrdatasz, bswap);
if (err)
return -EMCAPCFG;
pr_info("FPGA Configuration Done!!\n");
free_resources:
if (data)
free(data);
fclose(fptr);
return err;
}
int MCapAccessConfigSpace(struct mcap_dev *mdev, int argc, char **argv)
{
unsigned long wrval, rdval;
int pos, access_type;
pos = (int) strtol(argv[4], NULL, 16);
access_type = tolower(argv[5][0]);
if (argc == 6) {
switch (access_type) {
case 'b':
rdval = pci_read_byte(mdev->pdev, pos);
break;
case 'h':
rdval = pci_read_word(mdev->pdev, pos);
break;
case 'w':
rdval = pci_read_long(mdev->pdev, pos);
break;
default:
return -EMCAPCFGACC;
}
pr_info("Read 0x%08lx @ 0x%x\n", rdval, pos);
}
if (argc > 6) {
wrval = strtoul(argv[6], 0, 0);
switch (access_type) {
case 'b':
pci_write_byte(mdev->pdev, pos, wrval);
break;
case 'h':
pci_write_word(mdev->pdev, pos, wrval);
break;
case 'w':
pci_write_long(mdev->pdev, pos, wrval);
break;
default:
return -EMCAPCFGACC;
}
pr_info("Written 0x%08lx @ 0x%x\n", wrval, pos);
}
return 0;
}
int MCapShowDevice(struct mcap_dev *mdev, int verbose)
{
char command[80];
u16 vendor_id, device_id;
vendor_id = mdev->pdev->vendor_id;
device_id = mdev->pdev->device_id;
if (verbose == 1)
sprintf(command, "lspci -vd %x:%x", vendor_id, device_id);
if (verbose >= 2)
sprintf(command, "lspci -vvd %x:%x", vendor_id, device_id);
if (!verbose)
sprintf(command, "lspci -d %x:%x", vendor_id, device_id);
return system(command);
}

158
mcap/linux/mcap_lib.h Normal file
View file

@ -0,0 +1,158 @@
/******************************************************************************
* Copyright (C) 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file mcap_lib.h
* MCAP Interface Library support header file
*
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "pci.h"
#include "lspci.h"
#include "byteswap.h"
/* Register Definitions */
#define MCAP_EXT_CAP_HEADER 0x00
#define MCAP_VEND_SPEC_HEADER 0x04
#define MCAP_FPGA_JTAG_ID 0x08
#define MCAP_FPGA_BIT_VERSION 0x0C
#define MCAP_STATUS 0x10
#define MCAP_CONTROL 0x14
#define MCAP_DATA 0x18
#define MCAP_READ_DATA_0 0x1C
#define MCAP_READ_DATA_1 0x20
#define MCAP_READ_DATA_2 0x24
#define MCAP_READ_DATA_3 0x28
#define MCAP_CTRL_MODE_MASK (1 << 0)
#define MCAP_CTRL_REG_READ_MASK (1 << 1)
#define MCAP_CTRL_RESET_MASK (1 << 4)
#define MCAP_CTRL_MOD_RESET_MASK (1 << 5)
#define MCAP_CTRL_IN_USE_MASK (1 << 8)
#define MCAP_CTRL_DESIGN_SWITCH_MASK (1 << 12)
#define MCAP_CTRL_DATA_REG_PROT_MASK (1 << 16)
#define MCAP_STS_ERR_MASK (1 << 0)
#define MCAP_STS_EOS_MASK (1 << 1)
#define MCAP_STS_REG_READ_CMP_MASK (1 << 4)
#define MCAP_STS_REG_READ_COUNT_MASK (7 << 5)
#define MCAP_STS_FIFO_OVERFLOW_MASK (1 << 8)
#define MCAP_STS_FIFO_OCCUPANCY_MASK (15 << 12)
#define MCAP_STS_CFG_MCAP_REQ_MASK (1 << 24)
/* Maximum FIFO Depth */
#define MCAP_FIFO_DEPTH 16
/* PCIe Extended Capability Id */
#define MCAP_EXT_CAP_ID 0xB
/* Error Values */
#define EMCAPREQ 120
#define EMCAPRESET 121
#define EMCAPMODRESET 122
#define EMCAPFULLRESET 123
#define EMCAPWRITE 124
#define EMCAPREAD 125
#define EMCAPCFG 126
#define EMCAPBUSWALK 127
#define EMCAPCFGACC 128
#undef DEBUG
#ifndef DEBUG
#define pr_dbg(fmt, ...) do {} while (0)
#else
#define pr_dbg printf
#endif
#define pr_info printf
#define pr_err printf
/* MCAP Device Information */
struct mcap_dev {
struct pci_dev *pdev;
struct pci_access *pacc;
unsigned int reg_base;
};
#define MCapRegWrite(mdev, offset, value) \
pci_write_long(mdev->pdev, mdev->reg_base + offset, value)
#define MCapRegRead(mdev, offset) \
pci_read_long(mdev->pdev, mdev->reg_base + offset)
#define IsResetSet(mdev) \
(MCapRegRead(mdev, MCAP_CONTROL) & \
MCAP_CTRL_RESET_MASK ? 1 : 0)
#define IsModuleResetSet(mdev) \
(MCapRegRead(mdev, MCAP_CONTROL) & \
MCAP_CTRL_MOD_RESET_MASK ? 1 : 0)
#define IsConfigureMCapReqSet(mdev) \
(MCapRegRead(mdev, MCAP_STATUS) & \
MCAP_STS_CFG_MCAP_REQ_MASK ? 1 : 0)
#define IsErrSet(mdev) \
(MCapRegRead(mdev, MCAP_STATUS) & \
MCAP_STS_ERR_MASK ? 1 : 0)
#define IsRegReadComplete(mdev) \
(MCapRegRead(mdev, MCAP_STATUS) & \
MCAP_STS_REG_READ_CMP_MASK ? 1 : 0)
#define IsFifoOverflow(mdev) \
(MCapRegRead(mdev, MCAP_STATUS) & \
MCAP_STS_FIFO_OVERFLOW_MASK ? 1 : 0)
#define GetRegReadCount(mdev) \
((MCapRegRead(mdev, MCAP_STATUS) & \
MCAP_STS_REG_READ_COUNT_MASK) >> 5)
/* Function Prototypes */
struct mcap_dev *MCapLibInit(int device_id);
void MCapLibFree(struct mcap_dev *mdev);
void MCapDumpRegs(struct mcap_dev *mdev);
void MCapDumpReadRegs(struct mcap_dev *mdev);
int MCapReset(struct mcap_dev *mdev);
int MCapModuleReset(struct mcap_dev *mdev);
int MCapFullReset(struct mcap_dev *mdev);
int MCapShowDevice(struct mcap_dev *mdev, int verbose);
int MCapConfigureFPGA(struct mcap_dev *mdev, char *file_path);
int MCapReadRegisters(struct mcap_dev *mdev, u32 *data);
int MCapAccessConfigSpace(struct mcap_dev *mdev, int argc, char **argv);