|
|
|
@ -1,6 +1,7 @@
|
|
|
|
|
/*
|
|
|
|
|
* Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
|
|
|
|
|
* Copyright (C) 2009 RIEGL Research ForschungsGmbH
|
|
|
|
|
* Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
|
|
|
|
|
*
|
|
|
|
@ -30,104 +31,127 @@
|
|
|
|
|
|
|
|
|
|
/** BEGIN: Low-Level I/O Implementation **/
|
|
|
|
|
|
|
|
|
|
#ifdef XSVFTOOL_RLMS_VLINE
|
|
|
|
|
|
|
|
|
|
// Simple example with MPC8349E GPIO pins
|
|
|
|
|
// (RIEGL LMS V-Line motherboard)
|
|
|
|
|
// Raspberry PI GPIO driver
|
|
|
|
|
// TMS: 18
|
|
|
|
|
// TDI: 23
|
|
|
|
|
// TDO: 24
|
|
|
|
|
// TCK: 25
|
|
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
|
|
#define IO_PORT_ADDR 0xE0000C00
|
|
|
|
|
#define BCM2708_PERI_BASE 0x20000000
|
|
|
|
|
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
|
|
|
|
|
|
|
|
|
|
struct io_layout {
|
|
|
|
|
unsigned long tdi:1;
|
|
|
|
|
unsigned long tdo:1;
|
|
|
|
|
unsigned long tms:1;
|
|
|
|
|
unsigned long tck:1;
|
|
|
|
|
unsigned long reserved:28;
|
|
|
|
|
};
|
|
|
|
|
#define PAGE_SIZE (4*1024)
|
|
|
|
|
#define BLOCK_SIZE (4*1024)
|
|
|
|
|
|
|
|
|
|
int mem_fd;
|
|
|
|
|
char *gpio_mem, *gpio_map;
|
|
|
|
|
char *spi0_mem, *spi0_map;
|
|
|
|
|
|
|
|
|
|
// I/O access
|
|
|
|
|
volatile unsigned *gpio;
|
|
|
|
|
|
|
|
|
|
static volatile struct io_layout *io_direction;
|
|
|
|
|
static volatile struct io_layout *io_opendrain;
|
|
|
|
|
static volatile struct io_layout *io_data;
|
|
|
|
|
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
|
|
|
|
|
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
|
|
|
|
|
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
|
|
|
|
|
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
|
|
|
|
|
|
|
|
|
|
#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
|
|
|
|
|
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
|
|
|
|
|
|
|
|
|
|
#define GPLEV0 *(gpio+13)
|
|
|
|
|
|
|
|
|
|
static void io_setup(void)
|
|
|
|
|
{
|
|
|
|
|
/* open /dev/mem device file */
|
|
|
|
|
int fd = open("/dev/mem", O_RDWR);
|
|
|
|
|
if (fd < 0) {
|
|
|
|
|
fprintf(stderr, "Can't open /dev/mem: %s\n", strerror(errno));
|
|
|
|
|
exit(1);
|
|
|
|
|
/* open /dev/mem */
|
|
|
|
|
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
|
|
|
|
|
printf("can't open /dev/mem \n");
|
|
|
|
|
exit (-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* calculate offsets to page and within page */
|
|
|
|
|
unsigned long psize = getpagesize();
|
|
|
|
|
unsigned long off_inpage = IO_PORT_ADDR % psize;
|
|
|
|
|
unsigned long off_topage = IO_PORT_ADDR - off_inpage;
|
|
|
|
|
unsigned long mapsize = off_inpage + sizeof(struct io_layout) * 3;
|
|
|
|
|
|
|
|
|
|
/* map it into logical memory */
|
|
|
|
|
void *io_addr_map = mmap(0, mapsize, PROT_WRITE, MAP_SHARED, fd, off_topage);
|
|
|
|
|
if (io_addr_map == MAP_FAILED) {
|
|
|
|
|
fprintf(stderr, "Can't map physical memory: %s\n", strerror(errno));
|
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
|
|
/* mmap GPIO */
|
|
|
|
|
|
|
|
|
|
// Allocate MAP block
|
|
|
|
|
if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
|
|
|
|
|
printf("allocation error \n");
|
|
|
|
|
exit (-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure pointer is on 4K boundary
|
|
|
|
|
if ((unsigned long)gpio_mem % PAGE_SIZE) {
|
|
|
|
|
gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now map it
|
|
|
|
|
gpio_map = (unsigned char *)mmap(
|
|
|
|
|
(caddr_t)gpio_mem,
|
|
|
|
|
BLOCK_SIZE,
|
|
|
|
|
PROT_READ|PROT_WRITE,
|
|
|
|
|
MAP_SHARED|MAP_FIXED,
|
|
|
|
|
mem_fd,
|
|
|
|
|
GPIO_BASE
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ((long)gpio_map < 0) {
|
|
|
|
|
printf("mmap error %d\n", (int)gpio_map);
|
|
|
|
|
exit (-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Always use volatile pointer!
|
|
|
|
|
gpio = (volatile unsigned *)gpio_map;
|
|
|
|
|
|
|
|
|
|
// Set GPIO pins 18, 23, 25 to output
|
|
|
|
|
INP_GPIO(18); // must use INP_GPIO before we can use OUT_GPIO
|
|
|
|
|
INP_GPIO(23); // must use INP_GPIO before we can use OUT_GPIO
|
|
|
|
|
INP_GPIO(25); // must use INP_GPIO before we can use OUT_GPIO
|
|
|
|
|
|
|
|
|
|
/* calculate register addresses */
|
|
|
|
|
io_direction = io_addr_map + off_inpage;
|
|
|
|
|
io_opendrain = io_addr_map + off_inpage + 4;
|
|
|
|
|
io_data = io_addr_map + off_inpage + 8;
|
|
|
|
|
|
|
|
|
|
/* set direction reg */
|
|
|
|
|
io_direction->tms = 1;
|
|
|
|
|
io_direction->tck = 1;
|
|
|
|
|
io_direction->tdo = 0;
|
|
|
|
|
io_direction->tdi = 1;
|
|
|
|
|
|
|
|
|
|
/* set open drain reg */
|
|
|
|
|
io_opendrain->tms = 0;
|
|
|
|
|
io_opendrain->tck = 0;
|
|
|
|
|
io_opendrain->tdo = 0;
|
|
|
|
|
io_opendrain->tdi = 0;
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_TRST
|
|
|
|
|
/* for boards with TRST, must be driven high */
|
|
|
|
|
io_data->trst = 1;
|
|
|
|
|
io_direction->trst = 1;
|
|
|
|
|
io_opendrain->trst = 0;
|
|
|
|
|
#endif
|
|
|
|
|
OUT_GPIO(18); // output
|
|
|
|
|
OUT_GPIO(23); // output
|
|
|
|
|
INP_GPIO(24); // input
|
|
|
|
|
OUT_GPIO(25); // output
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_shutdown(void)
|
|
|
|
|
{
|
|
|
|
|
/* set all to z-state */
|
|
|
|
|
io_direction->tms = 0;
|
|
|
|
|
io_direction->tck = 0;
|
|
|
|
|
io_direction->tdo = 0;
|
|
|
|
|
io_direction->tdi = 0;
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_TRST
|
|
|
|
|
/* for boards with TRST, assuming there is a pull-down resistor */
|
|
|
|
|
io_direction->trst = 0;
|
|
|
|
|
#endif
|
|
|
|
|
INP_GPIO(18);
|
|
|
|
|
INP_GPIO(23);
|
|
|
|
|
INP_GPIO(24);
|
|
|
|
|
INP_GPIO(25);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_tms(int val)
|
|
|
|
|
{
|
|
|
|
|
io_data->tms = val;
|
|
|
|
|
if (val) {
|
|
|
|
|
GPIO_SET = 1<<18;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
GPIO_CLR = 1<<18;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_tdi(int val)
|
|
|
|
|
{
|
|
|
|
|
io_data->tdi = val;
|
|
|
|
|
if (val) {
|
|
|
|
|
GPIO_SET = 1<<23;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
GPIO_CLR = 1<<23;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_tck(int val)
|
|
|
|
|
{
|
|
|
|
|
io_data->tck = val;
|
|
|
|
|
if (val) {
|
|
|
|
|
GPIO_SET = 1<<25;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
GPIO_CLR = 1<<25;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// usleep(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -143,46 +167,9 @@ static void io_trst(int val)
|
|
|
|
|
|
|
|
|
|
static int io_tdo()
|
|
|
|
|
{
|
|
|
|
|
return io_data->tdo ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
static void io_setup(void)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_shutdown(void)
|
|
|
|
|
{
|
|
|
|
|
return (GPLEV0 & (1<<24)) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_tms(int val)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_tdi(int val)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_tck(int val)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_sck(int val)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void io_trst(int val)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int io_tdo()
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/** END: Low-Level I/O Implementation **/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|