#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <fcntl.h> | |
#include <sys/mman.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <unistd.h> | |
#include <byteswap.h> | |
#include <stdint.h> | |
#include <stdbool.h> | |
#include <getopt.h> | |
#include <limits.h> | |
#include <arpa/inet.h> | |
#include <assert.h> | |
#include "io.h" | |
void *ahb_reg_map; | |
void *ahb_flash_map; | |
uint32_t ahb_flash_base, ahb_flash_size; | |
void *gpio_ctrl; | |
int ast_copy_to_ahb(uint32_t reg, const void *src, uint32_t len) | |
{ | |
if (reg < ahb_flash_base || | |
(reg + len) > (ahb_flash_base + ahb_flash_size)) | |
return -1; | |
reg -= ahb_flash_base; | |
if (((reg | (unsigned long)src | len) & 3) == 0) { | |
while(len > 3) { | |
uint32_t val = *(uint32_t *)src; | |
writel(val, ahb_flash_map + reg); | |
src += 4; | |
reg += 4; | |
len -= 4; | |
} | |
} | |
while(len--) { | |
uint8_t val = *(uint8_t *)src; | |
writeb(val, ahb_flash_map + reg++); | |
src += 1; | |
} | |
return 0; | |
} | |
int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len) | |
{ | |
if (reg < ahb_flash_base || | |
(reg + len) > (ahb_flash_base + ahb_flash_size)) | |
return -1; | |
reg -= ahb_flash_base; | |
if (((reg | (unsigned long)dst | len) & 3) == 0) { | |
while(len > 3) { | |
*(uint32_t *)dst = readl(ahb_flash_map + reg); | |
dst += 4; | |
reg += 4; | |
len -= 4; | |
} | |
} | |
while(len--) { | |
*(uint8_t *)dst = readb(ahb_flash_map + reg++); | |
dst += 1; | |
} | |
return 0; | |
} | |
/* | |
* GPIO stuff to be replaced by higher level accessors for | |
* controlling the flash write lock via sysfs | |
*/ | |
static inline uint32_t gpio_ctl_readl(uint32_t offset) | |
{ | |
return readl(gpio_ctrl + offset); | |
} | |
static inline void gpio_ctl_writel(uint32_t val, uint32_t offset) | |
{ | |
writel(val, gpio_ctrl + offset); | |
} | |
bool set_wrprotect(bool protect) | |
{ | |
uint32_t reg; | |
bool was_protected; | |
reg = gpio_ctl_readl(0x20); | |
was_protected = !!(reg & 0x00004000); | |
if (protect) | |
reg |= 0x00004000; /* GPIOF[6] value */ | |
else | |
reg &= ~0x00004000; /* GPIOF[6] value */ | |
gpio_ctl_writel(reg, 0x20); | |
reg = gpio_ctl_readl(0x24); | |
reg |= 0x00004000; /* GPIOF[6] direction */ | |
gpio_ctl_writel(reg, 0x24); | |
return was_protected; | |
} | |
void open_devs(bool use_lpc, bool bmc_flash) | |
{ | |
int fd; | |
(void)use_lpc; | |
fd = open("/dev/mem", O_RDWR | O_SYNC); | |
if (fd < 0) { | |
perror("can't open /dev/mem"); | |
exit(1); | |
} | |
ahb_reg_map = mmap(0, AHB_REGS_SIZE, PROT_READ | PROT_WRITE, | |
MAP_SHARED, fd, AHB_REGS_BASE); | |
if (ahb_reg_map == MAP_FAILED) { | |
perror("can't map AHB registers /dev/mem"); | |
exit(1); | |
} | |
gpio_ctrl = mmap(0, GPIO_CTRL_SIZE, PROT_READ | PROT_WRITE, | |
MAP_SHARED, fd, GPIO_CTRL_BASE); | |
if (gpio_ctrl == MAP_FAILED) { | |
perror("can't map GPIO control via /dev/mem"); | |
exit(1); | |
} | |
ahb_flash_base = bmc_flash ? BMC_FLASH_BASE : PNOR_FLASH_BASE; | |
ahb_flash_size = bmc_flash ? BMC_FLASH_SIZE : PNOR_FLASH_SIZE; | |
ahb_flash_map = mmap(0, ahb_flash_size, PROT_READ | PROT_WRITE, | |
MAP_SHARED, fd, ahb_flash_base); | |
if (ahb_flash_map == MAP_FAILED) { | |
perror("can't map flash via /dev/mem"); | |
exit(1); | |
} | |
} |