TS-4800 MUXBUS Access

From Technologic Systems Manuals

On this board the MUXBUS memory window is available at 0xb0017000. The first 64KB of memwindow space are for using the external bus in 16 bit mode. The next 64KB are for the external bus in 8 bit mode. For 8 bit mode, the memwindow core will emit 8 bit wishbone cycles, but the external bus core expects 16 bit cycles. The adapter handles this adjustment. This scheme allows for memwindow optimization features on the 8 bit muxbus. This will almost double the bandwidth, in practice, to an off-board 8 bit SRAM.

Register Map
Offset Bits Access Description
0x0 15:0 Read/Write Address bits 26-11
0x2 15:14 Read/Write
Bus Width
Value Description
0 Reserved
1 32 bit
2 16 bit
3 8 bit
13:12 Read/Write
Data Config
Value Description
0 Normal
1 two-cycle split [1]
3 two-cycle combine [2]
11 Read/Write Auto increment enable [3]
10:0 Read/Write Address bits 10-0
0x4 15:0 Read/Write Data register 1 [4]
0x6 15:0 Read/Write Data register 2[4]
  1. Write 1 16 bit data register to write 2x 8bit cycles.
  2. Write 2 16 bit values to perform 1 32 bit cycle.
  3. When accessing data register 2 the auto increment will step the address by the number of bytes written each time, otherwise writing multiple times will go to the same address.
  4. 4.0 4.1 Data register 1 and 2 both read/write to the same address, but data register 2 can auto increment the address from the number of bytes after each read/write cycle. Data register 1 will ignore 0x2 and will not increment the address.

The below C example can access 8 and 16 bit registers on the muxbus:

#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>

static volatile uint16_t *mwin;

void mwinen()
{
        int mem;
	volatile uint16_t *syscon;
        mem = open("/dev/mem", O_RDWR|O_SYNC);
        syscon = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, mem, 0xb0010000);
        mwin = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, mem, 0xb0017000);

	assert(syscon != NULL);
	assert(mwin != NULL);

	// Set up muxbus timing register.
	syscon[0x12/2] = 0x321;
	close(mem);
}

uint16_t mwinpeek16(uint32_t addr)
{
	mwin[0x0] = addr >> 11; // This register contains the upper bits of address
	// Sets the remaining address bits, and requests a 16 bit bus cycle
	mwin[0x2/2] = (addr & 0x7ff) | 0x8000;

	return mwin[0x4/2];
}

void mwinpoke16(uint32_t addr, uint16_t value)
{
	mwin[0x0] = addr >> 11;
	mwin[0x2/2] = (addr & 0x7ff) | 0x8000;

	mwin[0x4/2] = value;
}

uint8_t mwinpeek8(uint32_t addr)
{
	// 8-bit addr starts 64k into the memory window
	addr = 0x10000 | addr;

	mwin[0x0] = addr >> 11;
	// Similar to the 16 bit transactions, but requests 8 bit bus cycles
	mwin[0x2/2] = (addr & 0x7ff) | 0xc000;

	return mwin[0x4/2];
}

void mwinpoke8(uint32_t addr, uint8_t value)
{
	// 8-bit addr starts 64k into the memory window
	addr = 0x10000 | addr;

	mwin[0x0] = addr >> 11;
	mwin[0x2/2] = (addr & 0x7ff) | 0xc000;

	mwin[0x4/2] = value;
}

int main(int argc, char **argv)
{
	mwinen();
	printf("16-bit read 0x0: 0x%x\n", mwinpeek16(0x0));
	printf("8-bit read 0x0: 0x%x\n", mwinpeek8(0x0));

	return 0;
}

Note that baseboards may use different offsets for 8-bit and 16-bit off-board peripherals such as PC104 devices.