Optimization and cleanup in HPS-FPGA communication.

This commit is contained in:
sorgelig
2020-05-17 19:51:49 +08:00
parent ee008ba89f
commit 018b189951
10 changed files with 184 additions and 218 deletions

View File

@@ -533,33 +533,19 @@ int fpga_load_rbf(const char *name, const char *cfg, const char *xml)
return ret;
}
int fpga_io_init()
{
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) return -1;
map_base = (uint32_t*)mmap(0, FPGA_REG_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, FPGA_REG_BASE);
if (map_base == (void *)-1)
{
printf("Unable to mmap(/dev/mem)\n");
close(fd);
return -1;
}
return 0;
}
static uint32_t gpo_copy = 0;
void fpga_gpo_write(uint32_t value)
void inline fpga_gpo_write(uint32_t value)
{
gpo_copy = value;
writel(value, (void*)(SOCFPGA_MGR_ADDRESS + 0x10));
}
uint32_t fpga_gpo_read()
uint32_t inline fpga_gpo_read()
{
return gpo_copy; //readl((void*)(SOCFPGA_MGR_ADDRESS + 0x10));
}
int fpga_gpi_read()
int inline fpga_gpi_read()
{
return readl((void*)(SOCFPGA_MGR_ADDRESS + 0x14));
}
@@ -575,6 +561,22 @@ uint32_t fpga_core_read(uint32_t offset)
return 0;
}
int fpga_io_init()
{
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) return -1;
map_base = (uint32_t*)mmap(0, FPGA_REG_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, FPGA_REG_BASE);
if (map_base == (void *)-1)
{
printf("Unable to mmap(/dev/mem)\n");
close(fd);
return -1;
}
fpga_gpo_write(0);
return 0;
}
int fpga_core_id()
{
uint32_t gpo = (fpga_gpo_read() & 0x7FFFFFFF);
@@ -672,3 +674,55 @@ int is_fpga_ready(int quick)
return fpgamgr_test_fpga_ready();
}
#define SSPI_STROBE (1<<17)
#define SSPI_ACK SSPI_STROBE
void fpga_spi_en(uint32_t mask, uint32_t en)
{
uint32_t gpo = fpga_gpo_read() | 0x80000000;
fpga_gpo_write(en ? gpo | mask : gpo & ~mask);
}
uint16_t fpga_spi(uint16_t word)
{
uint32_t gpo = (fpga_gpo_read() & ~(0xFFFF | SSPI_STROBE)) | word;
fpga_gpo_write(gpo);
fpga_gpo_write(gpo | SSPI_STROBE);
int gpi;
do
{
gpi = fpga_gpi_read();
if (gpi < 0)
{
printf("GPI[31]==1. FPGA is uninitialized?\n");
return 0;
}
} while (!(gpi & SSPI_ACK));
fpga_gpo_write(gpo);
do
{
gpi = fpga_gpi_read();
if (gpi < 0)
{
printf("GPI[31]==1. FPGA is uninitialized?\n");
return 0;
}
} while (gpi & SSPI_ACK);
return (uint16_t)gpi;
}
uint16_t fpga_spi_fast(uint16_t word)
{
uint32_t gpo = (fpga_gpo_read() & ~(0xFFFF | SSPI_STROBE)) | word;
fpga_gpo_write(gpo);
fpga_gpo_write(gpo | SSPI_STROBE);
fpga_gpo_write(gpo);
return (uint16_t)fpga_gpi_read();
}

View File

@@ -9,9 +9,9 @@
int fpga_io_init();
void fpga_gpo_write(uint32_t value);
uint32_t fpga_gpo_read();
int fpga_gpi_read();
void fpga_spi_en(uint32_t mask, uint32_t en);
uint16_t fpga_spi(uint16_t word);
uint16_t fpga_spi_fast(uint16_t word);
void fpga_set_led(uint32_t on);
int fpga_get_buttons();
@@ -26,10 +26,10 @@ int is_fpga_ready(int quick);
int fpga_get_fio_size();
int fpga_get_io_version();
int fpga_load_rbf(const char *name, const char *cfg = NULL, const char *xml=NULL);
int fpga_load_rbf(const char *name, const char *cfg = 0, const char *xml = 0);
void reboot(int cold);
void app_restart(const char *path, const char *xml=NULL);
void app_restart(const char *path, const char *xml = 0);
char *getappname();
#endif

View File

@@ -46,7 +46,6 @@ int main(int argc, char *argv[])
sched_setaffinity(0, sizeof(set), &set);
fpga_io_init();
fpga_gpo_write(0);
DISKLED_OFF;

168
spi.cpp
View File

@@ -2,73 +2,20 @@
#include "hardware.h"
#include "fpga_io.h"
#define SSPI_STROBE (1<<17)
#define SSPI_ACK SSPI_STROBE
#define SSPI_FPGA_EN (1<<18)
#define SSPI_OSD_EN (1<<19)
#define SSPI_IO_EN (1<<20)
#define SWAPW(a) ((((a)<<8)&0xff00)|(((a)>>8)&0x00ff))
static void spi_en(uint32_t mask, uint32_t en)
{
uint32_t gpo = fpga_gpo_read() | 0x80000000;
fpga_gpo_write(en ? gpo | mask : gpo & ~mask);
}
uint16_t spi_w(uint16_t word)
{
uint32_t gpo = (fpga_gpo_read() & ~(0xFFFF | SSPI_STROBE)) | word;
fpga_gpo_write(gpo);
fpga_gpo_write(gpo | SSPI_STROBE);
int gpi;
do
{
gpi = fpga_gpi_read();
if (gpi < 0)
{
printf("GPI[31]==1. FPGA is uninitialized?\n");
return 0;
}
} while (!(gpi & SSPI_ACK));
fpga_gpo_write(gpo);
do
{
gpi = fpga_gpi_read();
if (gpi < 0)
{
printf("GPI[31]==1. FPGA is uninitialized?\n");
return 0;
}
} while (gpi & SSPI_ACK);
return (uint16_t)gpi;
}
void spi_init(int enable)
{
(void)enable;
printf("Init SPI.\n");
}
uint8_t spi_b(uint8_t parm)
{
return (uint8_t)spi_w(parm);
}
void EnableFpga()
{
spi_en(SSPI_FPGA_EN, 1);
fpga_spi_en(SSPI_FPGA_EN, 1);
}
void DisableFpga()
{
spi_en(SSPI_FPGA_EN, 0);
fpga_spi_en(SSPI_FPGA_EN, 0);
}
static int osd_target = OSD_ALL;
@@ -87,56 +34,25 @@ void EnableOsd()
if (osd_target & OSD_HDMI) mask &= ~SSPI_FPGA_EN;
if (osd_target & OSD_VGA) mask &= ~SSPI_IO_EN;
spi_en(mask, 1);
fpga_spi_en(mask, 1);
}
void DisableOsd()
{
spi_en(SSPI_OSD_EN | SSPI_IO_EN | SSPI_FPGA_EN, 0);
fpga_spi_en(SSPI_OSD_EN | SSPI_IO_EN | SSPI_FPGA_EN, 0);
}
void EnableIO()
{
spi_en(SSPI_IO_EN, 1);
fpga_spi_en(SSPI_IO_EN, 1);
}
void DisableIO()
{
spi_en(SSPI_IO_EN, 0);
fpga_spi_en(SSPI_IO_EN, 0);
}
uint8_t spi_in()
{
return spi_b(0);
}
void spi8(uint8_t parm)
{
spi_b(parm);
}
void spi16(uint16_t parm)
{
spi8(parm >> 8);
spi8(parm >> 0);
}
void spi24(uint32_t parm)
{
spi8(parm >> 16);
spi8(parm >> 8);
spi8(parm >> 0);
}
void spi32(uint32_t parm)
{
spi8(parm >> 24);
spi8(parm >> 16);
spi8(parm >> 8);
spi8(parm >> 0);
}
uint32_t spi32w(uint32_t parm)
uint32_t spi32_w(uint32_t parm)
{
uint32_t res;
res = spi_w(parm);
@@ -145,19 +61,19 @@ uint32_t spi32w(uint32_t parm)
}
// little endian: lsb first
void spi32le(uint32_t parm)
void spi32_b(uint32_t parm)
{
spi8(parm >> 0);
spi8(parm >> 8);
spi8(parm >> 16);
spi8(parm >> 24);
spi_b(parm >> 0);
spi_b(parm >> 8);
spi_b(parm >> 16);
spi_b(parm >> 24);
}
/* OSD related SPI functions */
void spi_osd_cmd_cont(uint8_t cmd)
{
EnableOsd();
spi8(cmd);
spi_b(cmd);
}
void spi_osd_cmd(uint8_t cmd)
@@ -169,8 +85,8 @@ void spi_osd_cmd(uint8_t cmd)
void spi_osd_cmd8_cont(uint8_t cmd, uint8_t parm)
{
EnableOsd();
spi8(cmd);
spi8(parm);
spi_b(cmd);
spi_b(parm);
}
void spi_osd_cmd8(uint8_t cmd, uint8_t parm)
@@ -179,17 +95,11 @@ void spi_osd_cmd8(uint8_t cmd, uint8_t parm)
DisableOsd();
}
void spi_uio_cmd32le_cont(uint8_t cmd, uint32_t parm)
void spi_uio_cmd32_cont(uint8_t cmd, uint32_t parm)
{
EnableIO();
spi8(cmd);
spi32le(parm);
}
void spi_uio_cmd32le(uint8_t cmd, uint32_t parm)
{
spi_uio_cmd32le_cont(cmd, parm);
DisableIO();
spi_b(cmd);
spi32_b(parm);
}
/* User_io related SPI functions */
@@ -209,8 +119,8 @@ uint8_t spi_uio_cmd(uint8_t cmd)
void spi_uio_cmd8_cont(uint8_t cmd, uint8_t parm)
{
EnableIO();
spi8(cmd);
spi8(parm);
spi_b(cmd);
spi_b(parm);
}
void spi_uio_cmd8(uint8_t cmd, uint8_t parm)
@@ -229,7 +139,7 @@ void spi_uio_cmd16(uint8_t cmd, uint16_t parm)
void spi_uio_cmd32(uint8_t cmd, uint32_t parm, int wide)
{
EnableIO();
spi8(cmd);
spi_b(cmd);
if (wide)
{
spi_w((uint16_t)parm);
@@ -237,17 +147,17 @@ void spi_uio_cmd32(uint8_t cmd, uint32_t parm, int wide)
}
else
{
spi8(parm);
spi8(parm >> 8);
spi8(parm >> 16);
spi8(parm >> 24);
spi_b(parm);
spi_b(parm >> 8);
spi_b(parm >> 16);
spi_b(parm >> 24);
}
DisableIO();
}
void spi_n(uint8_t value, uint16_t cnt)
{
while (cnt--) spi8(value);
while (cnt--) spi_b(value);
}
void spi_read(uint8_t *addr, uint16_t len, int wide)
@@ -276,18 +186,38 @@ void spi_write(const uint8_t *addr, uint16_t len, int wide)
}
else
{
while (len--) spi8(*addr++);
while (len--) spi_b(*addr++);
}
}
void spi_block_read(uint8_t *addr, int wide)
{
spi_read(addr, 512, wide);
if (wide)
{
uint16_t len16 = 256;
uint16_t *a16 = (uint16_t*)addr;
while (len16--) *a16++ = fpga_spi_fast(0);
}
else
{
uint16_t len = 512;
while (len--) *addr++ = fpga_spi_fast(0);
}
}
void spi_block_write(const uint8_t *addr, int wide)
{
spi_write(addr, 512, wide);
if (wide)
{
uint16_t len16 = 256;
uint16_t *a16 = (uint16_t*)addr;
while (len16--) fpga_spi_fast(*a16++);
}
else
{
uint16_t len = 512;
while (len--) fpga_spi_fast(*addr++);
}
}
void spi_block_write_16be(const uint16_t *addr)

38
spi.h
View File

@@ -2,14 +2,12 @@
#define SPI_H
#include <inttypes.h>
#include "fpga_io.h"
#define OSD_HDMI 1
#define OSD_VGA 2
#define OSD_ALL (OSD_VGA|OSD_HDMI)
/* main init functions */
void spi_init(int enable);
/* chip select functions */
void EnableFpga();
void DisableFpga();
@@ -19,25 +17,32 @@ void EnableIO();
void DisableIO();
// base functions
uint8_t spi_b(uint8_t parm);
uint16_t spi_w(uint16_t word);
uint8_t inline spi_b(uint8_t parm)
{
return (uint8_t)fpga_spi(parm);
}
uint16_t inline spi_w(uint16_t word)
{
return fpga_spi(word);
}
// input only helper
uint8_t spi_in();
uint8_t inline spi_in()
{
return (uint8_t)fpga_spi(0);
}
void spi8(uint8_t parm);
void spi16(uint16_t parm);
void spi24(uint32_t parm);
void spi32(uint32_t parm);
void spi32le(uint32_t parm);
void spi_n(uint8_t value, uint16_t cnt);
uint32_t spi32w(uint32_t parm);
#define spi8(x) spi_b(x)
void spi32_b(uint32_t parm);
uint32_t spi32_w(uint32_t parm);
/* block transfer functions */
void spi_block_read(uint8_t *addr, int wide);
void spi_read(uint8_t *addr, uint16_t len, int wide);
void spi_block_write(const uint8_t *addr, int wide);
void spi_write(const uint8_t *addr, uint16_t len, int wide);
void spi_block_read(uint8_t *addr, int wide);
void spi_block_write(const uint8_t *addr, int wide);
void spi_block_write_16be(const uint16_t *addr);
void spi_block_read_16be(uint16_t *addr);
@@ -55,7 +60,6 @@ void spi_uio_cmd8(uint8_t cmd, uint8_t parm);
void spi_uio_cmd8_cont(uint8_t cmd, uint8_t parm);
void spi_uio_cmd16(uint8_t cmd, uint16_t parm);
void spi_uio_cmd32(uint8_t cmd, uint32_t parm, int wide);
void spi_uio_cmd32le_cont(uint8_t cmd, uint32_t parm);
void spi_uio_cmd32le(uint8_t cmd, uint32_t parm);
void spi_uio_cmd32_cont(uint8_t cmd, uint32_t parm);
#endif // SPI_H

View File

@@ -18,7 +18,7 @@ static uint8_t buffer[1024];
static void mem_upload_init(unsigned long addr)
{
spi_uio_cmd32le_cont(UIO_MM2_WR, addr);
spi_uio_cmd32_cont(UIO_MM2_WR, addr);
}
static void mem_upload_fini()

View File

@@ -129,7 +129,7 @@ static char UploadKickstart(char *name)
FileClose(&file);
//clear tag (write 0 to $fc0000) to force bootrom to load Kickstart from disk
//and not use one which was already there.
spi_uio_cmd32le_cont(UIO_MM2_WR, 0xfc0000);
spi_uio_cmd32_cont(UIO_MM2_WR, 0xfc0000);
spi8(0x00);spi8(0x00);
DisableIO();
return(1);
@@ -139,7 +139,7 @@ static char UploadKickstart(char *name)
BootPrint("Uploading A1000 boot ROM");
SendFileV2(&file, NULL, 0, 0xf80000, file.size >> 9);
FileClose(&file);
spi_uio_cmd32le_cont(UIO_MM2_WR, 0xfc0000);
spi_uio_cmd32_cont(UIO_MM2_WR, 0xfc0000);
spi8(0x00);spi8(0x00);
DisableIO();
return(1);
@@ -205,7 +205,7 @@ static char UploadActionReplay()
SendFileV2(&file, NULL, 0, 0xa10000, (file.size + 511) >> 9);
// HRTmon config
adr = 0xa10000 + 20;
spi_uio_cmd32le_cont(UIO_MM2_WR, adr);
spi_uio_cmd32_cont(UIO_MM2_WR, adr);
data = 0x00800000; // mon_size, 4 bytes
spi8((data >> 24) & 0xff); spi8((data >> 16) & 0xff);
spi8((data >> 8) & 0xff); spi8((data >> 0) & 0xff);
@@ -247,7 +247,7 @@ static char UploadActionReplay()
spi8((data >> 0) & 0xff);
DisableIO();
adr = 0xa10000 + 68;
spi_uio_cmd32le_cont(UIO_MM2_WR, adr);
spi_uio_cmd32_cont(UIO_MM2_WR, adr);
data = ((minimig_config.memory & 0x3) + 1) * 512 * 1024; // maxchip, 4 bytes TODO is this correct?
spi8((data >> 24) & 0xff); spi8((data >> 16) & 0xff);
spi8((data >> 8) & 0xff); spi8((data >> 0) & 0xff);

View File

@@ -61,7 +61,7 @@ static void set_control(uint32_t ctrl)
ctrl = uart_mode ? (ctrl | TOS_CONTROL_REDIR0) : (ctrl & ~TOS_CONTROL_REDIR0);
spi_uio_cmd_cont(UIO_SET_STATUS2);
spi32w(ctrl);
spi32_w(ctrl);
DisableIO();
}

View File

@@ -88,8 +88,8 @@ static void dma_set(uint32_t address, uint32_t data)
{
EnableIO();
spi8(UIO_DMA_WRITE);
spi32w(address);
spi32w(data);
spi32_w(address);
spi32_w(data);
DisableIO();
}
@@ -97,8 +97,8 @@ static void dma_sendbuf(uint32_t address, uint32_t length, uint32_t *data)
{
EnableIO();
spi8(UIO_DMA_WRITE);
spi32w(address);
while (length--) spi32w(*data++);
spi32_w(address);
while (length--) spi32_w(*data++);
DisableIO();
}
@@ -106,8 +106,8 @@ static void dma_rcvbuf(uint32_t address, uint32_t length, uint32_t *data)
{
EnableIO();
spi8(UIO_DMA_READ);
spi32w(address);
while (length--) *data++ = spi32w(0);
spi32_w(address);
while (length--) *data++ = spi32_w(0);
DisableIO();
}
@@ -123,7 +123,7 @@ static int load_bios(const char* name, uint8_t index)
EnableIO();
spi8(UIO_DMA_WRITE);
spi32w( index ? 0x80C0000 : 0x80F0000 );
spi32_w( index ? 0x80C0000 : 0x80F0000 );
while (bytes2send)
{
@@ -136,7 +136,7 @@ static int load_bios(const char* name, uint8_t index)
chunk = (chunk + 3) >> 2;
uint32_t* p = buf;
while(chunk--) spi32w(*p++);
while(chunk--) spi32_w(*p++);
}
DisableIO();
FileClose(&f);

View File

@@ -742,7 +742,6 @@ void user_io_init(const char *path, const char *xml)
io_ver = 0;
}
spi_init(core_type != CORE_TYPE_UNKNOWN);
OsdSetSize(8);
user_io_read_confstr();
@@ -1199,7 +1198,7 @@ int user_io_file_mount(const char *name, unsigned char index, char pre)
FileClose(&sd_image[index]);
}
buffer_lba[index] = ULLONG_MAX;
buffer_lba[index] = -1;
if (!ret)
{
@@ -1235,15 +1234,13 @@ int user_io_file_mount(const char *name, unsigned char index, char pre)
if (io_ver)
{
spi_w((uint16_t)(size));
spi_w((uint16_t)(size>>16));
spi_w((uint16_t)(size>>32));
spi_w((uint16_t)(size>>48));
spi32_w(size);
spi32_w(size >> 32);
}
else
{
spi32le(size);
spi32le(size>>32);
spi32_b(size);
spi32_b(size>>32);
}
DisableIO();
@@ -1544,8 +1541,8 @@ static void check_status_change()
if ((stchg & 0xF0) == 0xA0 && last_status_change != (stchg & 0xF))
{
last_status_change = (stchg & 0xF);
uint32_t st0 = spi32w(0);
uint32_t st1 = spi32w(0);
uint32_t st0 = spi32_w(0);
uint32_t st1 = spi32_w(0);
DisableIO();
user_io_8bit_set_status(st0, ~UIO_STATUS_RESET, 0);
user_io_8bit_set_status(st1, 0xFFFFFFFF, 1);
@@ -1943,8 +1940,8 @@ uint32_t user_io_8bit_set_status(uint32_t new_status, uint32_t mask, int ex)
else
{
spi_uio_cmd_cont(UIO_SET_STATUS2);
spi32w(status[0]);
spi32w(status[1]);
spi32_w(status[0]);
spi32_w(status[1]);
DisableIO();
}
}
@@ -2192,7 +2189,7 @@ void user_io_poll()
{
if (is_st()) tos_poll();
static uint8_t buffer[4][512];
static uint8_t buffer[4][8192];
uint32_t lba;
uint16_t req_type = 0;
uint16_t c = user_io_sd_get_status(&lba, &req_type);
@@ -2222,15 +2219,13 @@ void user_io_poll()
{
//printf("SD WR %d on %d\n", lba, disk);
int done = 0;
buffer_lba[disk] = lba;
buffer_lba[disk] = -1;
// Fetch sector data from FPGA ...
spi_uio_cmd_cont(UIO_SECTOR_WR);
spi_block_read(buffer[disk], fio_size);
DisableIO();
if (sd_image[disk].type == 2 && !lba)
{
//Create the file
@@ -2240,7 +2235,6 @@ void user_io_poll()
if (FileWriteSec(&sd_image[disk], buffer[disk]))
{
sd_image[disk].size = 512;
done = 1;
}
}
else
@@ -2259,7 +2253,6 @@ void user_io_poll()
{
if (FileWriteSec(&sd_image[disk], buffer[disk]))
{
done = 1;
if (size == lba)
{
size++;
@@ -2269,8 +2262,6 @@ void user_io_poll()
}
}
}
if (!done) buffer_lba[disk] = -1;
}
}
else if (c & 0x0701)
@@ -2283,15 +2274,16 @@ void user_io_poll()
//printf("SD RD %d on %d, WIDE=%d\n", lba, disk, fio_size);
int done = 0;
uint32_t offset;
if (buffer_lba[disk] != lba)
if ((buffer_lba[disk] == (uint64_t)-1) || lba < buffer_lba[disk] || lba >(buffer_lba[disk] + 15))
{
if (sd_image[disk].size)
{
diskled_on();
if (FileSeekLBA(&sd_image[disk], lba))
{
if (FileReadSec(&sd_image[disk], buffer[disk]))
if (FileReadAdv(&sd_image[disk], buffer[disk], sizeof(buffer[disk])))
{
done = 1;
}
@@ -2326,34 +2318,21 @@ void user_io_poll()
memset(buffer[disk], 0, sizeof(buffer[disk]));
}
}
buffer_lba[disk] = lba;
offset = 0;
}
if (buffer_lba[disk] == lba)
else
{
//hexdump(buffer, 32, 0);
// data is now stored in buffer. send it to fpga
spi_uio_cmd_cont(UIO_SECTOR_RD);
spi_block_write(buffer[disk], fio_size);
DisableIO();
offset = (lba - buffer_lba[disk])*512;
}
// just load the next sector now, so it may be prefetched
// for the next request already
done = 0;
if (sd_image[disk].size)
{
diskled_on();
if (FileSeekLBA(&sd_image[disk], lba + 1))
{
if (FileReadSec(&sd_image[disk], buffer[disk]))
{
done = 1;
}
}
}
if (done) buffer_lba[disk] = lba + 1;
//hexdump(buffer, 32, 0);
// data is now stored in buffer. send it to fpga
spi_uio_cmd_cont(UIO_SECTOR_RD);
spi_block_write(buffer[disk] + offset, fio_size);
DisableIO();
if (sd_image[disk].type == 2)
{