2014-10-16 12:44:02 +05:30
|
|
|
/******************************************************************************
|
2015-05-27 18:54:52 +05:30
|
|
|
* Copyright (C) 2014-2015 Xilinx, Inc. All rights reserved.
|
2014-10-16 12:44:02 +05:30
|
|
|
*
|
|
|
|
* 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
|
|
|
|
|
2015-05-27 18:44:42 +05:30
|
|
|
#define MCAP_SYNC_DWORD 0xFFFFFFFF
|
2014-10-16 12:44:02 +05:30
|
|
|
#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) {
|
2015-05-27 18:44:42 +05:30
|
|
|
if (raw[0] != '1' && raw[1] != '0')
|
2014-10-16 12:44:02 +05:30
|
|
|
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;
|
2015-05-27 18:44:42 +05:30
|
|
|
len ++;
|
2014-10-16 12:44:02 +05:30
|
|
|
result = count = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:44:42 +05:30
|
|
|
return len;
|
2014-10-16 12:44:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2015-05-27 18:44:42 +05:30
|
|
|
len++; if (value == MCAP_SYNC_BYTE0)
|
|
|
|
if ((err = fread(&value, 1, 1, fptr)) == 1) {
|
|
|
|
len++; if (value == MCAP_SYNC_BYTE1)
|
|
|
|
if ((err = fread(&value, 1, 1, fptr)) == 1) {
|
|
|
|
len++; if (value == MCAP_SYNC_BYTE2)
|
|
|
|
if ((err = fread(&value, 1, 1, fptr)) == 1) {
|
|
|
|
len++; if (value == MCAP_SYNC_BYTE3)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-10-16 12:44:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
while ((err = fread(buf, sz - len, 1, fptr)) == 1)
|
|
|
|
;
|
|
|
|
|
|
|
|
if (err != 1 && !feof(fptr)) {
|
|
|
|
pr_err("Failed to Read BIT file\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:44:42 +05:30
|
|
|
return (sz - len)/4 + 1;
|
2014-10-16 12:44:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:49:40 +05:30
|
|
|
static int Checkforcompletion(struct mcap_dev *mdev)
|
|
|
|
{
|
|
|
|
unsigned long retry_count = 0;
|
|
|
|
u32 delay;
|
|
|
|
int sr, i;
|
|
|
|
|
|
|
|
sr = MCapRegRead(mdev, MCAP_STATUS);
|
|
|
|
while (!(sr & MCAP_STS_EOS_MASK)) {
|
|
|
|
|
|
|
|
usleep(2);
|
|
|
|
for (i=0 ; i < EMCAP_EOS_LOOP_COUNT; i++) {
|
|
|
|
MCapRegWrite(mdev, MCAP_DATA, EMCAP_NOOP_VAL);
|
|
|
|
}
|
|
|
|
sr = MCapRegRead(mdev, MCAP_STATUS);
|
|
|
|
retry_count++;
|
|
|
|
if (retry_count > EMCAP_EOS_RETRY_COUNT) {
|
|
|
|
pr_err("Error: The MCAP EOS bit did not assert after");
|
|
|
|
pr_err(" programming the specified programming file\n");
|
|
|
|
return -EMCAPREQ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:51:42 +05:30
|
|
|
static int MCapWritePartialBitStream(struct mcap_dev *mdev, u32 *data,
|
|
|
|
int len, u8 bswap)
|
|
|
|
{
|
|
|
|
u32 set, restore;
|
|
|
|
int err, count = 0, i;
|
|
|
|
|
|
|
|
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]));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0 ; i < EMCAP_EOS_LOOP_COUNT; i++) {
|
|
|
|
MCapRegWrite(mdev, MCAP_DATA, EMCAP_NOOP_VAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsErrSet(mdev) || IsFifoOverflow(mdev)) {
|
|
|
|
pr_err("Failed to Write Bitstream\n");
|
|
|
|
MCapRegWrite(mdev, MCAP_CONTROL, restore);
|
2015-05-28 11:26:21 +05:30
|
|
|
MCapFullReset(mdev);
|
2015-05-27 18:51:42 +05:30
|
|
|
return -EMCAPWRITE;
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:35:37 +05:30
|
|
|
if (!mdev->is_multiplebit) {
|
|
|
|
pr_info("Info: A partial reconfiguration clear file (-C) was");
|
|
|
|
pr_info(" loaded without a partial reconfiguration file (-p)");
|
|
|
|
pr_info(" as result the MCAP Control register was not restored");
|
|
|
|
pr_info(" to its original value\n\r");
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:51:42 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-16 12:44:02 +05:30
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:35:37 +05:30
|
|
|
if (!mdev->is_multiplebit) {
|
|
|
|
/* 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;
|
2014-10-16 12:44:02 +05:30
|
|
|
|
2015-05-27 18:35:37 +05:30
|
|
|
/* 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);
|
2014-10-16 12:44:02 +05:30
|
|
|
|
2015-05-27 18:35:37 +05:30
|
|
|
MCapRegWrite(mdev, MCAP_CONTROL, set);
|
|
|
|
}
|
2014-10-16 12:44:02 +05:30
|
|
|
|
|
|
|
/* 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]));
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:49:40 +05:30
|
|
|
/* Check for Completion */
|
|
|
|
err = Checkforcompletion(mdev);
|
|
|
|
if (err)
|
|
|
|
return -EMCAPCFG;
|
|
|
|
|
2014-10-16 12:44:02 +05:30
|
|
|
if (IsErrSet(mdev) || IsFifoOverflow(mdev)) {
|
|
|
|
pr_err("Failed to Write Bitstream\n");
|
|
|
|
MCapRegWrite(mdev, MCAP_CONTROL, restore);
|
2015-05-28 11:26:21 +05:30
|
|
|
MCapFullReset(mdev);
|
2014-10-16 12:44:02 +05:30
|
|
|
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();
|
|
|
|
|
2015-05-27 18:35:37 +05:30
|
|
|
mdev->is_multiplebit = 0;
|
|
|
|
|
2014-10-16 12:44:02 +05:30
|
|
|
/* 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);
|
|
|
|
|
2015-04-21 11:36:49 +05:30
|
|
|
if (!(read_cnt) || !(IsRegReadComplete(mdev))) {
|
|
|
|
MCapRegWrite(mdev, MCAP_CONTROL, restore);
|
|
|
|
return EMCAPREAD;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsErrSet(mdev) || IsFifoOverflow(mdev)) {
|
2014-10-16 12:44:02 +05:30
|
|
|
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];
|
2015-04-21 11:36:49 +05:30
|
|
|
u32 status;
|
|
|
|
|
|
|
|
status = MCapReadDataRegisters(mdev, data);
|
|
|
|
if (status == EMCAPREAD)
|
|
|
|
return;
|
2014-10-16 12:44:02 +05:30
|
|
|
|
2015-04-21 11:36:49 +05:30
|
|
|
if (status) {
|
2014-10-16 12:44:02 +05:30
|
|
|
pr_err("Failed Reading Registers.. This may be");
|
2015-04-21 11:36:49 +05:30
|
|
|
pr_err(" due to inappropriate FPGA configuration.");
|
|
|
|
pr_err(" Make sure you downloaded the correct bitstream\n");
|
2014-10-16 12:44:02 +05:30
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:51:42 +05:30
|
|
|
int MCapConfigureFPGA(struct mcap_dev *mdev, char *file_path, u32 bitfile_type)
|
2014-10-16 12:44:02 +05:30
|
|
|
{
|
|
|
|
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 {
|
2015-11-18 15:50:06 +05:30
|
|
|
pr_err("Unknown File Format.. This may be");
|
|
|
|
pr_err(" due to .bit/.bin/.rbt files does not exist at the.");
|
|
|
|
pr_err(" specified location, Please cross check the");
|
|
|
|
pr_err(" path is correct or not\n");
|
2014-10-16 12:44:02 +05:30
|
|
|
goto free_resources;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Program FPGA */
|
2015-05-27 18:51:42 +05:30
|
|
|
if (bitfile_type == EMCAP_PARTIALCONFIG_FILE) {
|
|
|
|
err = MCapWritePartialBitStream(mdev, data, wrdatasz, bswap);
|
|
|
|
if (err)
|
|
|
|
return -EMCAPCFG;
|
|
|
|
pr_info("FPGA Partial Configuration Done!!\n");
|
|
|
|
} else if (bitfile_type == EMCAP_CONFIG_FILE) {
|
|
|
|
err = MCapWriteBitStream(mdev, data, wrdatasz, bswap);
|
|
|
|
if (err)
|
|
|
|
return -EMCAPCFG;
|
|
|
|
pr_info("FPGA Configuration Done!!\n");
|
|
|
|
}
|
2014-10-16 12:44:02 +05:30
|
|
|
|
|
|
|
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);
|
|
|
|
}
|