Commit b9371ef8 authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

removing flash-write/read tools, now moved to spec-sw

parent 75a43094
...@@ -4,7 +4,7 @@ SDBFS ?= no ...@@ -4,7 +4,7 @@ SDBFS ?= no
CFLAGS = -Wall -ggdb -I../include CFLAGS = -Wall -ggdb -I../include
LDFLAGS = -lutil LDFLAGS = -lutil
ALL = genraminit genramvhd genrammif wrpc-uart-sw ALL = genraminit genramvhd genrammif wrpc-uart-sw
ALL += wrpc-w1-read wrpc-w1-write flash-write flash-read ALL += wrpc-w1-read wrpc-w1-write
ifneq ($(EB),no) ifneq ($(EB),no)
ALL += eb-w1-write ALL += eb-w1-write
...@@ -40,15 +40,5 @@ eb-w1-write: eb-w1-write.c ../dev/w1.c ../dev/w1-eeprom.c eb-w1.c ...@@ -40,15 +40,5 @@ eb-w1-write: eb-w1-write.c ../dev/w1.c ../dev/w1-eeprom.c eb-w1.c
sdb-wrpc.bin: sdbfs sdb-wrpc.bin: sdbfs
$(SDBFS)/gensdbfs $< $@ $(SDBFS)/gensdbfs $< $@
flash-write: flash-write.c flash-host/libflash.a
$(CC) $(CFLAGS) -Iflash-host $^ -o $@
flash-read: flash-read.c flash-host/libflash.a
$(CC) $(CFLAGS) -Iflash-host $^ -o $@
flash-host/libflash.a:
$(MAKE) -C flash-host
clean: clean:
rm -f $(ALL) *.o *~ rm -f $(ALL) *.o *~
$(MAKE) -C flash-host clean
all: libflash.a
libflash.a: flash.o
ar r $@ $^
clean:
rm -f *.o *.a *~
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Theodor Stana <t.stana@cern.ch>
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <stdint.h>
#include <stdio.h>
#include "flash.h"
struct SYSCON_WB {
uint32_t RSTR; /*Syscon Reset Register */
uint32_t GPSR; /*GPIO Set/Readback Register */
uint32_t GPCR; /*GPIO Clear Register */
uint32_t HWFR; /*Hardware Feature Register */
uint32_t TCR; /*Timer Control Register */
uint32_t TVR; /*Timer Counter Value Register */
};
/*GPIO pins*/
#define GPIO_SPI_SCLK 10
#define GPIO_SPI_NCS 11
#define GPIO_SPI_MOSI 12
#define GPIO_SPI_MISO 13
static volatile struct SYSCON_WB *syscon;
void *BASE_SYSCON;
/****************************
* GPIO
***************************/
static inline void gpio_out(int pin, int val)
{
if (val)
syscon->GPSR = 1 << pin;
else
syscon->GPCR = 1 << pin;
}
static inline int gpio_in(int pin)
{
return syscon->GPSR & (1 << pin) ? 1 : 0;
}
/*
* Delay function
*/
static void delay()
{
int i;
for (i = 0; i < 4; i++)
asm volatile ("nop");
}
/*
* Bit-bang SPI transfer function
*/
static uint8_t bbspi_transfer(uint8_t cspin, uint8_t val)
{
uint8_t i;
gpio_out(GPIO_SPI_NCS, cspin);
delay();
for (i = 0; i < 8; i++) {
gpio_out(GPIO_SPI_SCLK, 0);
if (val & 0x80) {
gpio_out(GPIO_SPI_MOSI, 1);
}
else {
gpio_out(GPIO_SPI_MOSI, 0);
}
delay();
gpio_out(GPIO_SPI_SCLK, 1);
val <<= 1;
val |= gpio_in(GPIO_SPI_MISO);
delay();
}
gpio_out(GPIO_SPI_SCLK, 0);
return val;
}
/*
* Init function (just set the SPI pins for idle)
*/
void flash_init()
{
syscon = (volatile struct SYSCON_WB *)BASE_SYSCON;
gpio_out(GPIO_SPI_NCS, 1);
gpio_out(GPIO_SPI_SCLK, 0);
gpio_out(GPIO_SPI_MOSI, 0);
}
/*
* Write data to flash chip
*/
int flash_write(uint32_t addr, uint8_t *buf, int count)
{
int i;
bbspi_transfer(1,0);
bbspi_transfer(0,0x06);
bbspi_transfer(1,0);
bbspi_transfer(0,0x02);
bbspi_transfer(0,(addr & 0xFF0000) >> 16);
bbspi_transfer(0,(addr & 0xFF00) >> 8);
bbspi_transfer(0,(addr & 0xFF));
for ( i = 0; i < count; i++ ) {
bbspi_transfer(0,buf[i]);
}
bbspi_transfer(1,0);
return count;
}
/*
* Read data from flash
*/
int flash_read(uint32_t addr, uint8_t *buf, int count)
{
int i;
bbspi_transfer(1,0);
bbspi_transfer(0,0x0b);
bbspi_transfer(0,(addr & 0xFF0000) >> 16);
bbspi_transfer(0,(addr & 0xFF00) >> 8);
bbspi_transfer(0,(addr & 0xFF));
bbspi_transfer(0,0);
for ( i = 0; i < count; i++ ) {
buf[i] = bbspi_transfer(0, 0);
}
bbspi_transfer(1,0);
return count;
}
/*
* Sector erase
*/
void flash_serase(uint32_t addr)
{
bbspi_transfer(1,0);
bbspi_transfer(0,0x06);
bbspi_transfer(1,0);
bbspi_transfer(0,0xD8);
bbspi_transfer(0,(addr & 0xFF0000) >> 16);
bbspi_transfer(0,(addr & 0xFF00) >> 8);
bbspi_transfer(0,(addr & 0xFF));
bbspi_transfer(1,0);
}
/*
* Read status register
*/
uint8_t flash_rsr()
{
uint8_t retval;
bbspi_transfer(1,0);
bbspi_transfer(0,0x05);
retval = bbspi_transfer(0,0);
bbspi_transfer(1,0);
return retval;
}
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Theodor Stana <t.stana@cern.ch>
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#ifndef __FLASH_H_
#define __FLASH_H_
#include <stdint.h>
/* Flash interface functions */
void flash_init();
int flash_write(uint32_t addr, uint8_t *buf, int count);
int flash_read(uint32_t addr, uint8_t *buf, int count);
void flash_serase(uint32_t addr);
uint8_t flash_rsr();
#endif // __FLASH_H_
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Theodor Stana <t.stana@cern.ch>
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include "flash.h"
#define SPEC_SYSCON_OFFSET 0x20400 /* from "sdb" on the shell, current gateware */
#define MAX_DEVICES 8 /* no alloc, me lazy */
static struct spec_pci_id {
unsigned pci_v;
unsigned pci_d;
} spec_devices[] = {
{ 0x10dc /* CERN */, 0x018d /* SPEC */ },
{ 0x1a39 /* Gennum */, 0x0004 /* GN4124 */ },
{ 0, },
};
struct spec_device {
void *mapaddr;
int mapsize;
int busid;
};
static struct spec_device devs[MAX_DEVICES];
char *prgname;
int verbose;
uint32_t syscon_offset;
extern void *BASE_SYSCON;
/*
* Read the flash chip
*/
static int spec_read_flash(struct spec_device *spec, int addr, int len)
{
int i;
int startlen = len;
int startaddr = addr;
/* Initializations */
uint8_t *buf = malloc(len);
if (buf == NULL) {
fprintf(stderr, "Memory not available for read buffer!");
return -1;
}
BASE_SYSCON = spec->mapaddr + syscon_offset;
flash_init();
if (verbose) {
fprintf(stderr, "Reading device on bus %i: "
"offset %i (0x%X), len %i\n", spec->busid,
addr, addr, len);
}
/* Read data and put it in buffer */
while (len) {
i = len;
if (i > 256) i = 256;
flash_read(addr, buf, i);
len -= i;
addr += i;
buf += i;
}
/* Pull buffer pointer back to start of buffer */
buf -= startlen;
/* Print read values */
if (verbose) {
for (i = 0; i < startlen; i++) {
fprintf(stderr, "offset %4i (0x%03x): %3i (0x%02x)\n",
startaddr + i, startaddr + i, buf[i], buf[i]);
}
} else {
fwrite(buf, 1, startlen, stdout);
}
/* Free buffer and exit */
free(buf);
return 0;
}
/*
* What follows is mostly generic, should be librarized in a way
*/
/* Access a PCI device, mmap and so on */
static void *spec_access_pci(char *name, int index)
{
struct spec_device *dev = devs + index;
char path[PATH_MAX];
struct stat stbuf;
int fd;
memset(dev, 0, sizeof(*dev));
sprintf(path, "/sys/bus/pci/devices/%s/resource0", name);
if ((fd = open(path, O_RDWR | O_SYNC)) < 0) {
fprintf(stderr, "%s: %s: %s\n", prgname, path,
strerror(errno));
return NULL;
}
fstat(fd, &stbuf);
dev->mapsize = stbuf.st_size;
dev->mapaddr = mmap(0, stbuf.st_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (dev->mapaddr == MAP_FAILED) {
fprintf(stderr, "%s: mmap(%s): %s\n", prgname, path,
strerror(errno));
return NULL;
}
if (sscanf(name, "%*x:%x", &dev->busid) != 1)
return NULL;
return dev->mapaddr;
}
/* Scan PCI space for vendor and device; return number of successes */
static int spec_scan_pci(struct spec_pci_id *id, struct spec_device *arr,
int alen)
{
char path[PATH_MAX];
FILE *f;
struct dirent **namelist;
int i, j, n, ndevs;
unsigned v, d;
n = scandir("/sys/bus/pci/devices", &namelist, 0, 0);
if (n < 0) {
fprintf(stderr, "%s: /sys/bus/pci/devices: %s\n", prgname,
strerror(errno));
return -1;
}
for (i = ndevs = 0; i < n; i++) {
if (namelist[i]->d_name[0] == '.')
continue;
/* check vendor */
sprintf(path, "/sys/bus/pci/devices/%s/vendor",
namelist[i]->d_name);
f = fopen(path, "r");
if (!f) {
fprintf(stderr, "%s: %s: %s\n", prgname, path,
strerror(errno));
continue;
}
if (fscanf(f, "%i", &v) != 1)
continue;
fclose(f);
/* check device */
sprintf(path, "/sys/bus/pci/devices/%s/device",
namelist[i]->d_name);
f = fopen(path, "r");
if (!f) {
fprintf(stderr, "%s: %s: %s\n", prgname, path,
strerror(errno));
continue;
}
if (fscanf(f, "%i", &d) != 1)
continue;
fclose(f);
for (j = 0; id[j].pci_v; j++)
if (id[j].pci_v == v && id[j].pci_d == d)
break;
if (!spec_devices[j].pci_v)
continue; /* not found in whole array */
/* Ok, so this is ours. Celebrate, and open it */
if (verbose)
fprintf(stderr, "%s: found device %04x:%04x: %s\n",
prgname, v, d, namelist[i]->d_name);
if (ndevs == alen) {
fprintf(stderr, "%s: array overflow, ignoring card\n",
prgname);
continue;
}
if (spec_access_pci(namelist[i]->d_name, ndevs) == NULL)
continue;
ndevs++;
}
return ndevs;
}
static int help(void)
{
fprintf(stderr, "%s: Use: \"%s [-v] [-b <bus>] <addr> <len>\n",
prgname, prgname);
return 1;
}
int main(int argc, char **argv)
{
int ndev, i, c, bus = -1;
struct spec_device *spec = NULL;
prgname = argv[0];
syscon_offset = SPEC_SYSCON_OFFSET;
while ((c = getopt(argc, argv, "b:vc:")) != -1) {
switch(c) {
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'v':
verbose++;
break;
case 'c':
sscanf(optarg, "%i", &syscon_offset);
break;
default:
exit(help());
}
}
if (optind != argc - 2)
exit(help());
/* find which one to use */
ndev = spec_scan_pci(spec_devices, devs, MAX_DEVICES);
if (ndev < 1) {
fprintf(stderr, "%s: no suitable PCI devices\n", prgname);
exit(1);
}
if (bus == -1 && ndev == 1) {
spec = devs;
} else if (bus == -1) {
fprintf(stderr, "%s: several devices found, please choose:\n",
prgname);
for (i = 0; i < ndev; i++) {
fprintf(stderr, " -b %i\n", devs[i].busid);
}
exit(1);
} else {
for (i = 0; i < ndev; i++)
if (bus == devs[i].busid)
break;
if (i == ndev) {
fprintf(stderr, "%s: no device on bus %i\n", prgname,
bus);
exit(1);
}
spec = devs + i;
}
i = spec_read_flash(spec, atoi(argv[optind]), atoi(argv[optind + 1]));
return i;
}
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Theodor Stana <t.stana@cern.ch>
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include "flash.h"
#define SPEC_SYSCON_OFFSET 0x20400 /* from "sdb" on the shell, current gateware */
#define MAX_DEVICES 8 /* no alloc, me lazy */
static struct spec_pci_id {
unsigned pci_v;
unsigned pci_d;
} spec_devices[] = {
{ 0x10dc /* CERN */, 0x018d /* SPEC */ },
{ 0x1a39 /* Gennum */, 0x0004 /* GN4124 */ },
{ 0, },
};
struct spec_device {
void *mapaddr;
int mapsize;
int busid;
};
static struct spec_device devs[MAX_DEVICES];
char *prgname;
int verbose;
uint32_t syscon_offset;
extern void *BASE_SYSCON;
int c =0;
static int spec_write_flash(struct spec_device *spec, int addr, int len)
{
int i;
int startlen = len;
/* Initializations */
uint8_t *buf = malloc(len);
if (buf == NULL) {
fprintf(stderr, "Memory not available for write buffer!");
return -1;
}
BASE_SYSCON = spec->mapaddr + syscon_offset;
flash_init();
if (verbose) {
fprintf(stderr, "Writing device on bus %i: "
"offset %i (0x%X), len %i\n", spec->busid,
addr, addr, len);
}
if (isatty(fileno(stdin)))
fprintf(stderr, "Reading from stdin, please type the data\n");
i = fread(buf, 1, len, stdin);
if (i != len) {
fprintf(stderr, "%s: read error (%i, expeted %i)\n", prgname,
i, len);
return 1;
}
/* Sending the data to the flash */
while (len) {
/* Set write length */
i = len;
if (len > 256)
i = 256;
/* Erase if sector boundary */
if ((addr % 0x10000) == 0) {
if (verbose) {
fprintf(stderr, "Erasing at address 0x%06X\n",
addr);
}
flash_serase(addr);
while (flash_rsr() & 0x01)
;
}
/* Write to flash */
if (verbose) {
fprintf(stderr, "Writing %3i bytes at address 0x%06X\n",
i, addr);
}
flash_write(addr, buf, i);
while (flash_rsr() & 0x01)
;
/* Setup next length, address and buffer pointer */
len -= i;
addr += i;
buf += i;
}
/* pull back buffer so we can free */
buf -= startlen;
free(buf);
return 0;
}
/*
* What follows is mostly generic, should be librarized in a way
*/
/* Access a PCI device, mmap and so on */
static void *spec_access_pci(char *name, int index)
{
struct spec_device *dev = devs + index;
char path[PATH_MAX];
struct stat stbuf;
int fd;
memset(dev, 0, sizeof(*dev));
sprintf(path, "/sys/bus/pci/devices/%s/resource0", name);
if ((fd = open(path, O_RDWR | O_SYNC)) < 0) {
fprintf(stderr, "%s: %s: %s\n", prgname, path,
strerror(errno));
return NULL;
}
fstat(fd, &stbuf);
dev->mapsize = stbuf.st_size;
dev->mapaddr = mmap(0, stbuf.st_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (dev->mapaddr == MAP_FAILED) {
fprintf(stderr, "%s: mmap(%s): %s\n", prgname, path,
strerror(errno));
return NULL;
}
if (sscanf(name, "%*x:%x", &dev->busid) != 1)
return NULL;
return dev->mapaddr;
}
/* Scan PCI space for vendor and device; return number of successes */
static int spec_scan_pci(struct spec_pci_id *id, struct spec_device *arr,
int alen)
{
char path[PATH_MAX];
FILE *f;
struct dirent **namelist;
int i, j, n, ndevs;
unsigned v, d;
n = scandir("/sys/bus/pci/devices", &namelist, 0, 0);
if (n < 0) {
fprintf(stderr, "%s: /sys/bus/pci/devices: %s\n", prgname,
strerror(errno));
return -1;
}
for (i = ndevs = 0; i < n; i++) {
if (namelist[i]->d_name[0] == '.')
continue;
/* check vendor */
sprintf(path, "/sys/bus/pci/devices/%s/vendor",
namelist[i]->d_name);
f = fopen(path, "r");
if (!f) {
fprintf(stderr, "%s: %s: %s\n", prgname, path,
strerror(errno));
continue;
}
if (fscanf(f, "%i", &v) != 1)
continue;
fclose(f);
/* check device */
sprintf(path, "/sys/bus/pci/devices/%s/device",
namelist[i]->d_name);
f = fopen(path, "r");
if (!f) {
fprintf(stderr, "%s: %s: %s\n", prgname, path,
strerror(errno));
continue;
}
if (fscanf(f, "%i", &d) != 1)
continue;
fclose(f);
for (j = 0; id[j].pci_v; j++)
if (id[j].pci_v == v && id[j].pci_d == d)
break;
if (!spec_devices[j].pci_v)
continue; /* not found in whole array */
/* Ok, so this is ours. Celebrate, and open it */
if (verbose)
fprintf(stderr, "%s: found device %04x:%04x: %s\n",
prgname, v, d, namelist[i]->d_name);
if (ndevs == alen) {
fprintf(stderr, "%s: array overflow, ignoring card\n",
prgname);
continue;
}
if (spec_access_pci(namelist[i]->d_name, ndevs) == NULL)
continue;
ndevs++;
}
return ndevs;
}
static int help(void)
{
fprintf(stderr, "%s: Use: \"%s [-v] [-b <bus>] <addr> <len>\n",
prgname, prgname);
return 1;
}
int main(int argc, char **argv)
{
int ndev, i, c, bus = -1;
struct spec_device *spec = NULL;
prgname = argv[0];
syscon_offset = SPEC_SYSCON_OFFSET;
while ((c = getopt(argc, argv, "b:vc:")) != -1) {
switch(c) {
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'v':
verbose++;
break;
case 'c':
sscanf(optarg, "%i", &syscon_offset);
break;
default:
exit(help());
}
}
if (optind != argc - 2)
exit(help());
/* find which one to use */
ndev = spec_scan_pci(spec_devices, devs, MAX_DEVICES);
if (ndev < 1) {
fprintf(stderr, "%s: no suitable PCI devices\n", prgname);
exit(1);
}
if (bus == -1 && ndev == 1) {
spec = devs;
} else if (bus == -1) {
fprintf(stderr, "%s: several devices found, please choose:\n",
prgname);
for (i = 0; i < ndev; i++) {
fprintf(stderr, " -b %i\n", devs[i].busid);
}
exit(1);
} else {
for (i = 0; i < ndev; i++)
if (bus == devs[i].busid)
break;
if (i == ndev) {
fprintf(stderr, "%s: no device on bus %i\n", prgname,
bus);
exit(1);
}
spec = devs + i;
}
i = spec_write_flash(spec, atoi(argv[optind]), atoi(argv[optind + 1]));
return i;
}
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