⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbus.c

📁 Sigma SMP8634 Mrua v. 2.8.2.0
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "../../llad/include/gbus.h"#include "../../llad/include/dmacpy.h"#include "../include/mbus.h"#include "../../emhwlib_hal/include/emhwlib_registers.h"#include "../../emhwlib/include/emhwlib_chipspecific.h"#if 0#define MBUSDBG ENABLE#else#define MBUSDBG DISABLE#endif#define PCI_TIMEOUT_COUNT (1024*2014)static inline RMint32 wait_for_mbus(struct gbus *pgbus, RMuint32 cmd_addr){	RMuint32 mbus_count = 0;	while (gbus_read_uint32(pgbus, cmd_addr) & 7) {		mbus_count ++;		if (mbus_count>PCI_TIMEOUT_COUNT) {			RMDBGLOG((ENABLE, "MBUS FROZEN\n"));			return 1;		}	}	return 0;}static inline RMint32 get_mbus_status(struct gbus *pgbus, RMuint32 cmd_addr){	static RMuint32 mbus_count = 0;	if (gbus_read_uint32(pgbus, cmd_addr) & 7) {		mbus_count ++;		if (mbus_count>PCI_TIMEOUT_COUNT) {			RMDBGLOG((ENABLE, "MBUS FROZEN\n"));			return 1;		}		return -mbus_count;	}	mbus_count = 0;	return 0;}static inline RMint32 wait_for_pci(struct gbus *pgbus, RMuint32 pci_en_addr, RMuint32 pci_cnt_addr){	RMuint32 pci_count = 0, old_pci_count = 0;	RMuint32 i = 0;	if (gbus_read_uint32(pgbus, pci_en_addr)) {		while ((pci_count = gbus_read_uint32(pgbus, pci_cnt_addr))) {			if (old_pci_count == pci_count) 				i++;			else 				i = 0;			old_pci_count = pci_count;			if (i>PCI_TIMEOUT_COUNT) {				RMDBGLOG((ENABLE, "PCI FROZEN\n"));				return -pci_count;			}		}		gbus_write_uint32(pgbus, pci_en_addr, 0);	}	return 0;}static inline RMint32 get_pci_status(struct gbus *pgbus, RMuint32 pci_cnt_addr){	static RMuint32 pci_count = 0;	static RMuint32 old_pci_count = 0;	static RMuint32 i = 0;	if ((pci_count = gbus_read_uint32(pgbus, pci_cnt_addr))) {		if (old_pci_count == pci_count) 			i++;		else 			i = 0;		old_pci_count = pci_count;		if (i>PCI_TIMEOUT_COUNT) {			RMDBGLOG((ENABLE, "PCI FROZEN\n"));			return -pci_count;		}		return 1;	}	i = 0;	return 0;}RMint32 mbus_write_dram(struct llad *pllad, RMuint32 addr, RMuint8 *data, RMuint32 size, RMuint32 max_pci_size){	RMuint32 pci_size = size;    	RMuint32 mbus_size = size;	RMuint32 dma_size, dma_bus_address, half_dma_size, offset;	RMuint32 xfer_dma_size = 0;	RMint32 status = 0;	struct gbus *pgbus;	struct dmacpy *pdmacpy; 	if (max_pci_size > 65532) {		RMDBGLOG((MBUSDBG, "bad value for max_pci_size %lu\n", max_pci_size));		return max_pci_size;	}	pgbus = gbus_open(pllad);	pdmacpy = dmacpy_open(pllad);	dmacpy_get_info(pdmacpy, &dma_size, &dma_bus_address);	half_dma_size = dma_size / 2;	offset = 0;	RMDBGLOG((MBUSDBG, "dma size is %lu bytes at bus address 0x%08x\n", dma_size, dma_bus_address));	// Wait for MBUS interface	if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_W1_CMD)))		goto exit_mbus_write_dram;	// Wait for PCI Master	if ((status = wait_for_pci(pgbus, REG_BASE_host_interface+READ_ENABLE, REG_BASE_host_interface+READ_COUNTER)))		goto exit_mbus_write_dram;	// Program the switchbox	hostsbox_pcimaster_channel1(pgbus);	// Program endianness (0 on little-endian systems, 1 on big-endian systems)	gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_REVERSE, 0x0);	gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_SKIP, 0);    	while (mbus_size || pci_size) {		if ((xfer_dma_size == 0) && (pci_size > 0)) {			xfer_dma_size = RMmin(max_pci_size, RMmin(half_dma_size, pci_size));			dmacpy_write_data(pdmacpy, offset, data, xfer_dma_size);		}					// MBUS side		if (mbus_size > 0) {			status = get_mbus_status(pgbus, REG_BASE_host_interface+MIF_W1_CMD);			if (status == 0) {				RMuint32 xfer_size = RMmin(8191, mbus_size);				RMDBGLOG((MBUSDBG, "program a mbus xfer. addr=0x%08x, size=%lu\n", addr, xfer_size));				gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_ADD, addr);				gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_CNT, xfer_size);				gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_CMD, MBUS_LINEAR);				addr += xfer_size;				mbus_size -= xfer_size;			}			else if (status > 0) 				goto exit_mbus_write_dram;		}				// PCI Master side		if (xfer_dma_size > 0) {			status = get_pci_status(pgbus, REG_BASE_host_interface+READ_COUNTER);			if (status == 0) {				RMDBGLOG((MBUSDBG, "program a pci xfer. addr=0x%08x, size=%lu\n", dma_bus_address + offset, xfer_dma_size));				gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_ENABLE, 0);				gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_ADDRESS, dma_bus_address + offset);				gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_COUNTER, xfer_dma_size);				gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_ENABLE, 1);				data += xfer_dma_size;				pci_size -= xfer_dma_size;				offset = (offset + half_dma_size) & (dma_size - 1); // dma_size is a power of 2				xfer_dma_size = 0;			}			else if (status < 0)				goto exit_mbus_write_dram;		}	}	// Push a void command to the command FIFO and wait for its completion	if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_W1_CMD))) 		goto exit_mbus_write_dram;	gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_CMD, MBUS_VOID);	if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_W1_CMD)))		goto exit_mbus_write_dram;		// Wait for PCI to finish	if ((status = wait_for_pci(pgbus, REG_BASE_host_interface+READ_ENABLE, REG_BASE_host_interface+READ_COUNTER)))		goto exit_mbus_write_dram; exit_mbus_write_dram:	dmacpy_close(pdmacpy);	gbus_close(pgbus);	return status;}RMint32 mbus_read_dram(struct llad *pllad, RMuint32 addr, RMuint8 *data, RMuint32 size, RMuint32 max_pci_size){	RMuint32 pci_size = size;	RMuint32 read_size = 0, old_read_size = 0;	RMuint32 dma_size, dma_bus_address, half_dma_size, offset;	RMint32 status = 0;	struct gbus *pgbus;	struct dmacpy *pdmacpy; 	if (size % 4)  {		RMDBGLOG((MBUSDBG, "size not a multiple of 4 bytes %lu\n", size));		return size;	} 	if ((max_pci_size % 4) || (max_pci_size > 65532)) {		RMDBGLOG((MBUSDBG, "bad value for max_pci_size %lu\n", max_pci_size));		return max_pci_size;	}	pgbus = gbus_open(pllad);	pdmacpy = dmacpy_open(pllad);	dmacpy_get_info(pdmacpy, &dma_size, &dma_bus_address);	half_dma_size = dma_size / 2;	offset = 0;	RMDBGLOG((MBUSDBG, "dma size is %lu bytes at bus address 0x%08x\n", dma_size, dma_bus_address));	// Wait for MBUS interface	if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_R1_CMD)))		goto exit_mbus_read_dram;	// Wait for PCI Master	if ((status = wait_for_pci(pgbus, REG_BASE_host_interface+WRITE_ENABLE, REG_BASE_host_interface+WRITE_COUNTER)))		goto exit_mbus_read_dram;	// Program the switchbox	hostsbox_pcimaster_channel1(pgbus);	// Program endianness (0 on little-endian systems, 1 on big-endian systems)	gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_REVERSE, 0x0);	gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_SKIP, 0);	while (pci_size) {		RMuint32 xfer_dma_size;		xfer_dma_size = RMmin(half_dma_size, RMmin(max_pci_size, pci_size));		old_read_size = read_size;		read_size = xfer_dma_size;				RMDBGLOG((MBUSDBG, "program a pci xfer. addr=0x%08x, size=%lu\n", dma_bus_address + offset, xfer_dma_size));		gbus_write_uint32(pgbus, REG_BASE_host_interface+WRITE_ENABLE, 0);		gbus_write_uint32(pgbus, REG_BASE_host_interface+WRITE_ADDRESS, dma_bus_address + offset);		gbus_write_uint32(pgbus, REG_BASE_host_interface+WRITE_COUNTER, xfer_dma_size);		gbus_write_uint32(pgbus, REG_BASE_host_interface+WRITE_ENABLE, 1);		pci_size -= xfer_dma_size;		while (xfer_dma_size > 0) {			RMuint32 mbus_size = RMmin(8191, xfer_dma_size);						RMDBGLOG((MBUSDBG, "program a mbus xfer. addr=0x%08x, size=%lu\n", addr, mbus_size));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -