diff options
Diffstat (limited to 'servers/fpga_server_lin/src/bbb-gpmc-init.cpp')
-rw-r--r-- | servers/fpga_server_lin/src/bbb-gpmc-init.cpp | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/servers/fpga_server_lin/src/bbb-gpmc-init.cpp b/servers/fpga_server_lin/src/bbb-gpmc-init.cpp new file mode 100644 index 0000000..961c560 --- /dev/null +++ b/servers/fpga_server_lin/src/bbb-gpmc-init.cpp @@ -0,0 +1,181 @@ +/* + * Remote Laboratory FPGA Server GPMC Interface (Beaglebone Black) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (c) 2012-2014 Timothy Pearson + * Raptor Engineering + * http://www.raptorengineeringinc.com + */ + +/** BEGIN: Low-Level I/O Implementation **/ + +// Beaglebone Black GPMC driver + +#include <sys/time.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> + +#define MEMORY_SPACE_ADDRESS_BITS 16 + +#define GPMC_BASE 0x50000000 +#define GPMC_REGLEN 0x10000000 + +#define GPMC_CHIPSELECTCONFIGDISPLACEMENT (0x30 / 4) + +#define GPMC_CONFIG (0x50 / 4) +#define GPMC_CONFIG1 (0x60 / 4) +#define GPMC_CONFIG2 (0x64 / 4) +#define GPMC_CONFIG3 (0x68 / 4) +#define GPMC_CONFIG4 (0x6c / 4) +#define GPMC_CONFIG5 (0x70 / 4) +#define GPMC_CONFIG6 (0x74 / 4) +#define GPMC_CONFIG7 (0x78 / 4) + +#define MEMORY_SIZE (1 << MEMORY_SPACE_ADDRESS_BITS) + +int mem_fd = 0; +int gpmc_mem_fd = 0; +char *gpio_mem, *gpio_map, *gpmc_map; + +// I/O access +volatile unsigned int *gpio = NULL; +volatile unsigned char *gpio_char = NULL; +volatile unsigned int *gpmc = NULL; + +void gpmc_mapregisters() { + /* open /dev/mem */ + if ((gpmc_mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { + printf("[FATAL] can't open /dev/mem\n"); + return; + } + + /* mmap GPMC */ + gpmc_map = (char *)mmap( + 0, + GPMC_REGLEN, + PROT_READ|PROT_WRITE, + MAP_SHARED, + gpmc_mem_fd, + GPMC_BASE + ); + + if (gpmc_map == MAP_FAILED) { + printf("[FATAL] mmap error %d\n", (int)gpmc_map); + return; + } + + // Always use volatile pointer! + gpmc = (volatile unsigned *)gpmc_map; +} + +void gpmc_unmapregisters() { + munmap((void*) gpmc, GPMC_REGLEN); + if (gpmc_mem_fd != -1) { + close(gpmc_mem_fd); + } +} + +void gpmc_setup(void) { + gpmc_mapregisters(); + + if (gpmc != NULL) { + int chipselect = 0; + int displacement = GPMC_CHIPSELECTCONFIGDISPLACEMENT * chipselect; + + // disable before playing with the registers + *(gpmc + displacement + GPMC_CONFIG7) = 0x00000000; + + *(gpmc + displacement + GPMC_CONFIG) = 0x00000000; // Unlimited address space + *(gpmc + displacement + GPMC_CONFIG1) = 0x00000000; // No burst, async, 8-bit, non multiplexed + *(gpmc + displacement + GPMC_CONFIG2) = 0x00001000; // Assert CS on fclk0, deassert CS on fclk16 + *(gpmc + displacement + GPMC_CONFIG3) = 0x00000400; // Assert ADV on fclk 0, deassert ADV on fclk 4 + *(gpmc + displacement + GPMC_CONFIG4) = 0x0c041004; // Assert WE on fclk4, deassert WE on fclk12, assert OE on fclk4, deassert OE on fclk16 + *(gpmc + displacement + GPMC_CONFIG5) = 0x000c1010; // Data valid on fclk 12, cycle time 16 fclks + *(gpmc + displacement + GPMC_CONFIG6) = 0x00000000; // No back to back cycle restrictions + *(gpmc + displacement + GPMC_CONFIG7) = 0x00000e50; // CS0: Set base address 0x10000000, 32MB region, and enable CS + + gpmc_unmapregisters(); + } +} + +int setup_gpmc_bbb(void) { + /* open /dev/mem */ + if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { + printf("[FATAL] can't open /dev/mem\n"); + return -1; + } + + /* mmap GPIO */ + gpio_map = (char *)mmap( + 0, + MEMORY_SIZE, + PROT_READ|PROT_WRITE, + MAP_SHARED, + mem_fd, + 0x10000000 + ); + + if (gpio_map == MAP_FAILED) { + printf("[FATAL] mmap error %d\n", (int)gpio_map); + return -1; + } + + // Always use volatile pointers! + gpio = (volatile unsigned *)gpio_map; + gpio_char = (volatile unsigned char *)gpio_map; + + return 0; +} + +int shutdown_gpmc_bbb(void) { + return 0; +} + +void write_gpmc(unsigned int register_offset, unsigned char data) { + *(gpio_char + register_offset) = data; +} + +unsigned char read_gpmc(unsigned int register_offset) { + return *(gpio_char + register_offset); +} + +void memcpy_from_gpmc(char* destination, unsigned int register_offset, unsigned int length) { + unsigned int i; + for (i=0; i<length; i++) { + *destination = *(gpio_char + register_offset); + destination++; + register_offset++; + } +} + +void memcpy_to_gpmc(char* source, unsigned int register_offset, unsigned int length) { + unsigned int i; + for (i=0; i<length; i++) { + *(gpio_char + register_offset) = *source; + source++; + register_offset++; + } +} + +/** END: Low-Level I/O Implementation **/
\ No newline at end of file |