Commit 6d0101d6 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

added host tools

parent 13c454c6
CFLAGS = -Wall -ggdb -I. -I../include
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
all: zpu-loader genraminit vuart_console
OBJS_LOADER = zpu-loader.o rr_io.o
zpu-loader: $(OBJS_LOADER)
${CC} -o zpu-loader $(OBJS_LOADER)
genraminit: genraminit.o
${CC} -o genraminit genraminit.o
vuart_console: vuart_console.o rr_io.o
${CC} -o vuart_console vuart_console.o rr_io.o
%.o: %.c
${CC} -c $^ $(CFLAGS) -O0
clean:
rm -f $(ALL) *.o *~
#include <stdio.h>
#include <stdlib.h>
main(int argc, char *argv[])
{
if(argc < 3) return -1;
FILE *f = fopen(argv[1],"rb");
if(!f) return -1;
unsigned char x[4];
int i=0;
int n = atoi(argv[2]);
while(!feof(f))
{
fread(x,1,4,f);
printf("%d => x\"%02X%02X%02X%02X\",\n", i++, x[0],x[1],x[2],x[3]);
}
for(;i<n;)
{
printf("%d => x\"%02X%02X%02X%02X\",\n", i++, 0,0,0,0);
}
fclose(f);
return 0;
}
\ No newline at end of file
/*
* Public header for the raw I/O interface for PCI or PCI express interfaces
*
* Copyright (C) 2010 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* Released according to the GNU GPL, version 2 or any later version.
*
* This work is part of the White Rabbit project, a research effort led
* by CERN, the European Institute for Nuclear Research.
*/
#ifndef __RAWRABBIT_H__
#define __RAWRABBIT_H__
#include <linux/types.h>
#include <linux/ioctl.h>
#ifdef __KERNEL__ /* The initial part of the file is driver-internal stuff */
#include <linux/pci.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include <linux/wait.h>
struct rr_devsel;
struct rr_dev {
struct rr_devsel *devsel;
struct pci_driver *pci_driver;
struct pci_device_id *id_table;
struct pci_dev *pdev; /* non-null after pciprobe */
struct mutex mutex;
wait_queue_head_t q;
void *dmabuf;
struct timespec irqtime;
unsigned long irqcount;
struct completion complete;
struct resource *area[3]; /* bar 0, 2, 4 */
void *remap[3]; /* ioremap of bar 0, 2, 4 */
unsigned long flags;
struct work_struct work;
const struct firmware *fw;
int usecount;
};
#define RR_FLAG_REGISTERED 0x00000001
#define RR_FLAG_IRQDISABLE 0x00000002
#define RR_FLAG_IRQREQUEST 0x00000002
#define RR_PROBE_TIMEOUT (HZ/10) /* for pci_register_drv */
/* These two live in ./loader.c */
extern void rr_ask_firmware(struct rr_dev *dev);
extern void rr_load_firmware(struct work_struct *work);
#endif /* __KERNEL__ */
/* By default, the driver registers for this vendor/devid */
#define RR_DEFAULT_VENDOR 0x1a39
#define RR_DEFAULT_DEVICE 0x0004
#define RR_DEFAULT_FWNAME "rrabbit-%P-%p@%b"
#define RR_MAX_FWNAME_SIZE 64
#define RR_DEFAULT_BUFSIZE (1<<20) /* 1MB */
#define RR_PLIST_SIZE 4096 /* no PAGE_SIZE in user space */
#define RR_PLIST_LEN (RR_PLIST_SIZE / sizeof(void *))
#define RR_MAX_BUFSIZE (RR_PLIST_SIZE * RR_PLIST_LEN)
/* This structure is used to select the device to be accessed, via ioctl */
struct rr_devsel {
__u16 vendor;
__u16 device;
__u16 subvendor; /* RR_DEVSEL_UNUSED to ignore subvendor/dev */
__u16 subdevice;
__u16 bus; /* RR_DEVSEL_UNUSED to ignore bus and devfn */
__u16 devfn;
};
#define RR_DEVSEL_UNUSED 0xffff
/* Offsets for BAR areas in llseek() and/or ioctl */
#define RR_BAR_0 0x00000000
#define RR_BAR_2 0x20000000
#define RR_BAR_4 0x40000000
#define RR_BAR_BUF 0xc0000000 /* The DMA buffer */
#define RR_IS_DMABUF(addr) ((addr) >= RR_BAR_BUF)
#define __RR_GET_BAR(x) ((x) >> 28)
#define __RR_SET_BAR(x) ((x) << 28)
#define __RR_GET_OFF(x) ((x) & 0x0fffffff)
static inline int rr_is_valid_bar(unsigned long address)
{
int bar = __RR_GET_BAR(address);
return bar == 0 || bar == 2 || bar == 4 || bar == 0x0c;
}
static inline int rr_is_dmabuf_bar(unsigned long address)
{
int bar = __RR_GET_BAR(address);
return bar == 0x0c;
}
struct rr_iocmd {
__u32 address; /* bar and offset */
__u32 datasize; /* 1 or 2 or 4 or 8 */
union {
__u8 data8;
__u16 data16;
__u32 data32;
__u64 data64;
};
};
/* ioctl commands */
#define __RR_IOC_MAGIC '4' /* random or so */
#define RR_DEVSEL _IOW(__RR_IOC_MAGIC, 0, struct rr_devsel)
#define RR_DEVGET _IOR(__RR_IOC_MAGIC, 1, struct rr_devsel)
#define RR_READ _IOWR(__RR_IOC_MAGIC, 2, struct rr_iocmd)
#define RR_WRITE _IOW(__RR_IOC_MAGIC, 3, struct rr_iocmd)
#define RR_IRQWAIT _IO(__RR_IOC_MAGIC, 4)
#define RR_IRQENA _IO(__RR_IOC_MAGIC, 5)
#define RR_GETDMASIZE _IO(__RR_IOC_MAGIC, 6)
/* #define RR_SETDMASIZE _IO(__RR_IOC_MAGIC, 7, unsigned long) */
#define RR_GETPLIST _IO(__RR_IOC_MAGIC, 8) /* returns a whole page */
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
/* Registers from the gennum header files */
enum {
FCL_BASE = 0xB00,
FCL_CTRL = FCL_BASE,
FCL_STATUS = FCL_BASE + 0x4,
FCL_IODATA_IN = FCL_BASE + 0x8,
FCL_IODATA_OUT = FCL_BASE + 0xC,
FCL_EN = FCL_BASE + 0x10,
FCL_TIMER_0 = FCL_BASE + 0x14,
FCL_TIMER_1 = FCL_BASE + 0x18,
FCL_CLK_DIV = FCL_BASE + 0x1C,
FCL_IRQ = FCL_BASE + 0x20,
FCL_TIMER_CTRL = FCL_BASE + 0x24,
FCL_IM = FCL_BASE + 0x28,
FCL_TIMER2_0 = FCL_BASE + 0x2C,
FCL_TIMER2_1 = FCL_BASE + 0x30,
FCL_DBG_STS = FCL_BASE + 0x34,
FCL_FIFO = 0xE00,
PCI_SYS_CFG_SYSTEM = 0x800
};
#endif /* __RAWRABBIT_H__ */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <rawrabbit.h>
#include "rr_io.h"
#define DEVNAME "/dev/rawrabbit"
static int fd;
int rr_init()
{
struct rr_devsel devsel;
int ret = -EINVAL;
fd = open(DEVNAME, O_RDWR);
if (fd < 0) {
return -1;
}
return 0;
}
int rr_writel(uint32_t data, uint32_t addr)
{
struct rr_iocmd iocmd;
iocmd.datasize = 4;
iocmd.address = addr;
iocmd.address |= __RR_SET_BAR(0);
iocmd.data32 = data;
ioctl(fd, RR_WRITE, &iocmd);
}
uint32_t rr_readl(uint32_t addr)
{
struct rr_iocmd iocmd;
iocmd.datasize = 4;
iocmd.address = addr;
iocmd.address |= __RR_SET_BAR(0);
if(ioctl(fd, RR_READ, &iocmd) < 0) perror("ioctl");
return iocmd.data32;
}
static void gennum_writel(uint32_t data, uint32_t addr)
{
struct rr_iocmd iocmd;
iocmd.datasize = 4;
iocmd.address = addr;
iocmd.address |= __RR_SET_BAR(4);
iocmd.data32 = data;
ioctl(fd, RR_WRITE, &iocmd);
}
static uint32_t gennum_readl(uint32_t addr)
{
struct rr_iocmd iocmd;
iocmd.datasize = 4;
iocmd.address = addr;
iocmd.address |= __RR_SET_BAR(4);
ioctl(fd, RR_READ, &iocmd);
return iocmd.data32;
}
static inline int64_t get_tics()
{
struct timezone tz= {0,0};
struct timeval tv;
gettimeofday(&tv, &tz);
return (int64_t)tv.tv_sec * 1000000LL + (int64_t) tv.tv_usec;
}
int rr_load_bitstream(const void *data, int size8)
{
int i, ctrl, done = 0, wrote = 0;
unsigned long j;
uint8_t val8;
const uint8_t *data8 = data;
const uint32_t *data32 = data;
int size32 = (size8 + 3) >> 2;
// fprintf(stderr,"Loading %d bytes...\n", size8);
if (1) {
/*
* Hmmm.... revers bits for xilinx images?
* We can't do in kernel space anyways, as the pages are RO
*/
uint8_t *d8 = (uint8_t *)data8; /* Horrible: kill const */
for (i = 0; i < size8; i++) {
val8 = d8[i];
d8[i] = 0
| ((val8 & 0x80) >> 7)
| ((val8 & 0x40) >> 5)
| ((val8 & 0x20) >> 3)
| ((val8 & 0x10) >> 1)
| ((val8 & 0x08) << 1)
| ((val8 & 0x04) << 3)
| ((val8 & 0x02) << 5)
| ((val8 & 0x01) << 7);
}
}
/* Do real stuff */
gennum_writel(0x00, FCL_CLK_DIV);
gennum_writel(0x40, FCL_CTRL); /* Reset */
i = gennum_readl( FCL_CTRL);
if (i != 0x40) {
fprintf(stderr, "%s: %i: error\n", __func__, __LINE__);
return;
}
gennum_writel(0x00, FCL_CTRL);
gennum_writel(0x00, FCL_IRQ); /* clear pending irq */
switch(size8 & 3) {
case 3: ctrl = 0x116; break;
case 2: ctrl = 0x126; break;
case 1: ctrl = 0x136; break;
case 0: ctrl = 0x106; break;
}
gennum_writel(ctrl, FCL_CTRL);
gennum_writel(0x00, FCL_CLK_DIV); /* again? maybe 1 or 2? */
gennum_writel(0x00, FCL_TIMER_CTRL); /* "disable FCL timer func" */
gennum_writel(0x10, FCL_TIMER_0); /* "pulse width" */
gennum_writel(0x00, FCL_TIMER_1);
/* Set delay before data and clock is applied by FCL after SPRI_STATUS is
detected being assert.
*/
gennum_writel(0x08, FCL_TIMER2_0); /* "delay before data/clock..." */
gennum_writel(0x00, FCL_TIMER2_1);
gennum_writel(0x17, FCL_EN); /* "output enable" */
ctrl |= 0x01; /* "start FSM configuration" */
gennum_writel(ctrl, FCL_CTRL);
while(size32 > 0)
{
/* Check to see if FPGA configuation has error */
i = gennum_readl( FCL_IRQ);
if ( (i & 8) && wrote) {
done = 1;
fprintf(stderr,"EarlyDone");
// fprintf(stderr,"%s: %idone after %i\n", __func__, __LINE__, wrote);
} else if ( (i & 0x4) && !done) {
fprintf(stderr,"Error after %i\n", wrote);
return -1;
}
// fprintf(stderr,".");
while(gennum_readl(FCL_IRQ) & (1<<5)); // wait until at least 1/2 of the FIFO is empty
/* Write 64 dwords into FIFO at a time. */
for (i = 0; size32 && i < 32; i++) {
gennum_writel(*data32, FCL_FIFO);
data32++; size32--; wrote++;
// udelay(20);
}
}
gennum_writel(0x186, FCL_CTRL); /* "last data written" */
int64_t tstart = get_tics();
//j = jiffies + 2 * HZ;
/* Wait for DONE interrupt */
while(!done) {
// fprintf(stderr,stderr, "Wait!");
i = gennum_readl( FCL_IRQ);
printf("irqr: %x %x\n", FCL_IRQ, i);
if (i & 0x8) {
fprintf(stderr,"done after %i\n", wrote);
done = 1;
} else if( (i & 0x4) && !done) {
fprintf(stderr,"Error after %i\n", wrote);
return -1;
}
usleep(10000);
if(get_tics() - tstart > 1000000LL)
{
fprintf(stderr,"Loader: DONE timeout. Did you choose proper bitgen options?\n");
return;
}
/*if (time_after(jiffies, j)) {
printk("%s: %i: tout after %i\n", __func__, __LINE__,
wrote);
return;
} */
}
return done?0:-1;
}
int rr_load_bitstream_from_file(const char *file_name)
{
uint8_t *buf;
FILE *f;
uint32_t size;
f=fopen(file_name,"rb");
if(!f) return -1;
fseek(f, 0, SEEK_END);
size = ftell(f);
buf = malloc(size);
if(!buf)
{
fclose(f);
return -1;
}
fseek(f, 0, SEEK_SET);
fread(buf, 1, size, f);
fclose(f);
int rval = rr_load_bitstream(buf, size);
free(buf);
return rval;
}
\ No newline at end of file
#ifndef __RR_IO_H
#define __RR_IO_H
#include <stdint.h>
int rr_init();
int rr_writel(uint32_t data, uint32_t addr);
uint32_t rr_readl(uint32_t addr);
int rr_load_bitstream(const void *data, int size8);
int rr_load_bitstream_from_file(const char *file_name);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "wb_vuart.h"
#include "rr_io.h"
#define BASE_VUART (0x80000 + 0x60800)
main()
{
if(rr_init())
{
perror("rr_init");
return -1;
}
for(;;)
{
int csr ;
csr = rr_readl(BASE_VUART + UART_REG_DEBUG_CSR);
if(! (csr & UART_DEBUG_CSR_EMPTY))
{
char c = rr_readl(BASE_VUART + UART_REG_DEBUG_R0) & 0xff;
fprintf(stderr, "%c", c);
} else
usleep(1000);
}
return 0;
}
\ No newline at end of file
/*
Register definitions for slave core: Virtual UART
* File : wb_vuart.h
* Author : auto-generated by wbgen2 from wb_virtual_uart.wb
* Created : Thu Apr 7 00:51:02 2011
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wb_virtual_uart.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_WB_VIRTUAL_UART_WB
#define __WBGEN2_REGDEFS_WB_VIRTUAL_UART_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Status Register */
/* definitions for field: TX busy in reg: Status Register */
#define UART_SR_TX_BUSY WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX ready in reg: Status Register */
#define UART_SR_RX_RDY WBGEN2_GEN_MASK(1, 1)
/* definitions for register: Baudrate control register */
/* definitions for register: Transmit data regsiter */
/* definitions for field: Transmit data in reg: Transmit data regsiter */
#define UART_TDR_TX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_TDR_TX_DATA_SHIFT 0
#define UART_TDR_TX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_TDR_TX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: Receive data regsiter */
/* definitions for field: Received data in reg: Receive data regsiter */
#define UART_RDR_RX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_RDR_RX_DATA_SHIFT 0
#define UART_RDR_RX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_RDR_RX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: FIFO 'UART TX FIFO' data output register 0 */
/* definitions for field: Char sent by UART to TX in reg: FIFO 'UART TX FIFO' data output register 0 */
#define UART_DEBUG_R0_TX_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_DEBUG_R0_TX_SHIFT 0
#define UART_DEBUG_R0_TX_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_DEBUG_R0_TX_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: FIFO 'UART TX FIFO' data output register 1 */
/* definitions for field: Dupa in reg: FIFO 'UART TX FIFO' data output register 1 */
#define UART_DEBUG_R1_DUPA_MASK WBGEN2_GEN_MASK(0, 32)
#define UART_DEBUG_R1_DUPA_SHIFT 0
#define UART_DEBUG_R1_DUPA_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define UART_DEBUG_R1_DUPA_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: FIFO 'UART TX FIFO' control/status register */
/* definitions for field: FIFO full flag in reg: FIFO 'UART TX FIFO' control/status register */
#define UART_DEBUG_CSR_FULL WBGEN2_GEN_MASK(16, 1)
/* definitions for field: FIFO empty flag in reg: FIFO 'UART TX FIFO' control/status register */
#define UART_DEBUG_CSR_EMPTY WBGEN2_GEN_MASK(17, 1)
/* definitions for field: FIFO counter in reg: FIFO 'UART TX FIFO' control/status register */
#define UART_DEBUG_CSR_USEDW_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_DEBUG_CSR_USEDW_SHIFT 0
#define UART_DEBUG_CSR_USEDW_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_DEBUG_CSR_USEDW_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* [0x0]: REG Status Register */
#define UART_REG_SR 0x00000000
/* [0x4]: REG Baudrate control register */
#define UART_REG_BCR 0x00000004
/* [0x8]: REG Transmit data regsiter */
#define UART_REG_TDR 0x00000008
/* [0xc]: REG Receive data regsiter */
#define UART_REG_RDR 0x0000000c
/* [0x10]: REG FIFO 'UART TX FIFO' data output register 0 */
#define UART_REG_DEBUG_R0 0x00000010
/* [0x14]: REG FIFO 'UART TX FIFO' data output register 1 */
#define UART_REG_DEBUG_R1 0x00000014
/* [0x18]: REG FIFO 'UART TX FIFO' control/status register */
#define UART_REG_DEBUG_CSR 0x00000018
#endif
/*
* Copyright (c) 2011 Grzegorz Daniluk <g.daniluk@elproma.com.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* zpu-loader is a simple program created for White Rabbit PTP Core(WRPC).
* It loads the zpu firmware, given as the argument, directly to a dual-port RAM,
* which is the part of WRPC. This way, there is no need to synthesize whole
* FPGA project if one change anything in ZPU firmware.
* The binary file taken by zpu-loader is the result of the following action:
*
* ${CC} -o $(OUTPUT).elf $(OBJS) $(LDFLAGS)
* ${OBJCOPY} -O binary $(OUTPUT).elf $(OUTPUT).bin
*
* zpu-loader uses rawrabbit kernel driver written by Alessandro Rubini.
*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/ioctl.h>
#include"rawrabbit.h"
#define DEVNAME "/dev/rawrabbit"
#define RST_ADDR 0xE2000
int rst_zpu(int spec, int rst);
int copy(int spec, int srcbin, unsigned int baseaddr);
int verify(int spec, int srcbin, unsigned int baseaddr);
int conv_endian(int x);
int main(int argc, char **argv)
{
unsigned int addr = 0x80000;
int spec, srcbin;
unsigned int bytes;
if(argc<2)
{
fprintf(stderr, "No parameters specified !\n");
fprintf(stderr, "Usage:\n\t./loadsw <binary file> [base address]\n");
return -1;
}
if(argc==3)
addr = atoi(argv[2]);
spec = open(DEVNAME, O_RDWR);
if(spec < 0)
{
perror("Could not open device");
return -1;
}
srcbin = open(argv[1], O_RDONLY);
if(srcbin < 0)
{
perror("Could not open binary file");
close(spec);
return -1;
}
rst_zpu(spec, 1);
bytes = copy(spec, srcbin, addr);
if(bytes < 0)
{
close(srcbin);
close(spec);
return -1;
}
printf("Wrote %u bytes\n", bytes);
verify(spec, srcbin, addr);
rst_zpu(spec, 0);
close(srcbin);
close(spec);
return 0;
}
int copy(int spec, int srcbin, unsigned int baseaddr)
{
unsigned int bytes, word;
struct rr_iocmd iocmd;
int ret;
printf("Writing memory: ");
bytes=0;
while(1)
{
ret = read(srcbin, &word, 4); /*read 32-bit word*/
if(ret<0)
{
perror("Error while reading binary file");
return -1;
}
else if(ret==0)
{
printf("Done\n");
break;
}
iocmd.address = baseaddr+bytes;
bytes += ret; //address shift for next write
iocmd.address |= __RR_SET_BAR(0); //bar0
iocmd.datasize = 4;
iocmd.data32 = conv_endian(word);
ret = ioctl(spec, RR_WRITE, &iocmd);
if(ret<0)
{
perror("Error while writing to SPEC");
return -1;
}
printf(".");
}
return bytes;
}
int verify(int spec, int srcbin, unsigned int baseaddr)
{
unsigned int wbin;
struct rr_iocmd iocmd;
unsigned int bytes;
int ret;
printf("Verifing: ");
bytes = 0;
while(1)
{
ret = read(srcbin, &wbin, 4); /*read 32-bit word*/
if(ret<0)
{
perror("Error while reading binary file");
return -1;
}
else if(ret==0)
{
printf("OK !\n");
break;
}
iocmd.address = baseaddr+bytes;
bytes += ret;
iocmd.address |= __RR_SET_BAR(0); //bar0
iocmd.datasize = 4;
ret = ioctl(spec, RR_READ, &iocmd);
if(ret<0)
{
perror("Error while reading SPEC memory");
return -1;
}
if(iocmd.data32 != conv_endian(wbin))
{
printf("Error (@word %u)\n", bytes/4);
return -1;
}
printf(".");
return 0;
}
return 0;
}
int rst_zpu(int spec, int rst)
{
struct rr_iocmd iocmd;
iocmd.address = RST_ADDR;
iocmd.address |= __RR_SET_BAR(0); //bar0
iocmd.datasize = 4;
iocmd.data32 = rst;
if( ioctl(spec, RR_WRITE, &iocmd) < 0)
{
perror("Could not reset ZPU");
return -1;
}
return 0;
}
int conv_endian(int x)
{
return ((x&0xff000000)>>24) + ((x&0x00ff0000)>>8) + ((x&0x0000ff00)<<8) + ((x&0x000000ff)<<24);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment