summaryrefslogtreecommitdiffstats
path: root/servers/fpga_server_lin/src/bbb-gpmc-init.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/fpga_server_lin/src/bbb-gpmc-init.cpp')
-rw-r--r--servers/fpga_server_lin/src/bbb-gpmc-init.cpp181
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