Framework 16 to MXM Gpu - V0.1 Prototype design

Reading the 0xfed815a0 from Linux userspace:

See example program below:

// mmio_dev_mem.c
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>

int main(int argc, char **argv) {
    if (argc != 4) {
        fprintf(stderr, "Usage: %s <phys_addr_hex> <offset_hex> <length>\n", argv[0]);
        return 2;
    }

    unsigned long phys = strtoul(argv[1], NULL, 0);
    unsigned long offset = strtoul(argv[2], NULL, 0);
    size_t length = (size_t)strtoul(argv[3], NULL, 0);

    int fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (fd < 0) {
        fprintf(stderr, "open /dev/mem failed: %s\n", strerror(errno));
        return 1;
    }

    unsigned long page_size = sysconf(_SC_PAGESIZE);
    unsigned long page_base = phys & ~(page_size - 1);
    unsigned long page_offset = phys - page_base;
    size_t map_len = page_offset + length;

    void *map = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_base);
    if (map == MAP_FAILED) {
        fprintf(stderr, "mmap failed: %s\n", strerror(errno));
        close(fd);
        return 1;
    }

    volatile uint32_t *reg = (volatile uint32_t *)((char *)map + page_offset + offset);

    // Read 32-bit register
    uint32_t val = *reg;
    __sync_synchronize(); // compiler memory barrier
    printf("Read 0x%08x from phys 0x%lx + 0x%lx\n", val, phys, offset);

    // Write 32-bit register (example)
    //uint32_t newval = 0xA5A5A5A5;
    //*reg = newval;
    //__sync_synchronize();
    // printf("Wrote 0x%08x\n", newval);

    if (munmap(map, map_len) != 0) {
        fprintf(stderr, "munmap failed: %s\n", strerror(errno));
    }
    close(fd);
    return 0;
}

compile with:
gcc -O2 -Wall -o mmio_dev_mem mmio_dev_mem.c

Read the mmio 0xfed815a0 value:

sudo ./mmio_dev_mem 0xFED81000 0x05a0 0x1000
Read 0x00e50000 from phys 0xfed81000 + 0x5a0

Note: You can also write values, see the commented out write bit in the C code.
It uses “/dev/mem”. Some kernel / Linux configurations block it, so you might need to unblock it before the program works.

I think it will be difficult to program, unless we know what each bit does, because my guess is that some bits set the GPIO for in/out/tristate, whether it triggers an interrupt, if the interrupt is level or edge triggered etc. with only 1 of the 32 bits being the actual set it high or low bit.

1 Like