diff --git a/fpga/xilinx/programmer/svfplayer/xsvf-rpi.c b/fpga/xilinx/programmer/svfplayer/xsvf-rpi.c index c46e4d7..45d8c78 100644 --- a/fpga/xilinx/programmer/svfplayer/xsvf-rpi.c +++ b/fpga/xilinx/programmer/svfplayer/xsvf-rpi.c @@ -1,6 +1,7 @@ /* * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players * + * Copyright (C) 2012 Timothy Pearson * Copyright (C) 2009 RIEGL Research ForschungsGmbH * Copyright (C) 2009 Clifford Wolf * @@ -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 #include #include #include -#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 **/