Initial version

Committed on the Free edition of March Hare Software CVSNT Server.
Upgrade to CVS Suite for more features and support:
http://march-hare.com/cvsnt/


git-svn-id: http://moon:8086/svn/vhdl/trunk@640 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2009-11-08 13:07:55 +00:00
parent 9413b8d798
commit c465b190a0
3 changed files with 2179 additions and 0 deletions
+949
View File
@@ -0,0 +1,949 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "libsys.h"
#include "hpi.h"
static volatile UINT32 _g_int_active;
static volatile UINT32 _g_mbx_return;
static volatile UINT32 _g_mbx_in_flag;
// ---------------------------------------------------------
// Globals
// ---------------------------------------------------------
typedef struct _susb_t
{
fp_t fptr_ept[USB_MAX_NUM_EPT];
void *aptr_ept[USB_MAX_NUM_EPT];
fp_t fptr_rst;
void *aptr_rst;
fp_t fptr_sof;
void *aptr_sof;
fp_t fptr_cfg;
void *aptr_cfg;
fp_t fptr_sus;
void *aptr_sus;
fp_t fptr_id;
void *aptr_id;
fp_t fptr_vbus;
void *aptr_vbus;
} usb_t;
static usb_t _g_usb[USB_MAX_NUM_PORTS];
//static usb_irp_t *_g_usb_irp_ptr[USB_MAX_NUM_PORTS][USB_MAX_NUM_EPT];
// ---------------------------------------------------------
// HPI ISR
// ---------------------------------------------------------
void cy67k3_isr(void)
{
INT32 i;
UINT16 sie_msg, hpi_status;
UINT32 port, siemsg_handled, int_handled;
_g_int_active = 1;
// sputs("--------------------------------------------------------\n");
// sputs("USB-Interrupt(4)\n");
// sputs("HPI Status : ");
hpi_status = cy67k3_read_HPI_STATUS();
// print_word(hpi_status);
// sputs("\n");
// sputs("MAILBOX (REG): ");
// cy67k3_write(HPI_ADDRESS, HPI_REG_MAILBOX);
// print_word(cy67k3_read_HPI_DATA());
// sputs("\n");
int_handled = 0;
if (hpi_status & HPI_STATUS_MBX_IN)
{
int_handled = 1;
// sputs("MAILBOX (HPI): ");
_g_mbx_return = cy67k3_read_HPI_MAILBOX();
_g_mbx_in_flag = 1;
// print_word(_g_mbx_return);
// sputs("\n");
}
if (hpi_status & HPI_STATUS_RESET1)
{
int_handled = 1;
hpi_read_reg(SUSB1_REG_STATUS);
hpi_comm_exec_int(SUSB_INIT_INT, 2, R1, 0, R2, 1);
// sputs("RESET 1\n");
}
if (hpi_status & HPI_STATUS_RESET2)
{
int_handled = 1;
hpi_read_reg(SUSB2_REG_STATUS);
hpi_comm_exec_int(SUSB_INIT_INT, 2, R1, 0, R2, 2);
// sputs("RESET 2\n");
}
if (hpi_status & HPI_STATUS_DONE1)
{
int_handled = 1;
// sputs("DONE 1\n");
}
if (hpi_status & HPI_STATUS_DONE2)
{
int_handled = 1;
// sputs("DONE 2\n");
}
if (hpi_status & HPI_STATUS_SOFEOP1)
{
int_handled = 1;
hpi_read_reg(SUSB1_REG_STATUS);
// sputs("SOF/EOP 1\n");
}
if (hpi_status & HPI_STATUS_SOFEOP2)
{
int_handled = 1;
hpi_read_reg(SUSB2_REG_STATUS);
// sputs("SOF/EOP 2\n");
}
port = 0;
siemsg_handled = 0;
if (hpi_status & HPI_STATUS_SIEMSG1)
{
int_handled = 1;
sie_msg = hpi_read_reg(HPI_REG_SIE1MSG);
// Reset message register
hpi_write_reg(HPI_REG_SIE1MSG, 0x0000);
if (sie_msg & SUSB_RST_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_rst)
(_g_usb[port].fptr_rst)(_g_usb[port].aptr_rst);
}
if (sie_msg & SUSB_SOF_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_sof)
(_g_usb[port].fptr_sof)(_g_usb[port].aptr_sof);
}
if (sie_msg & SUSB_CFG_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_cfg)
(_g_usb[port].fptr_cfg)(_g_usb[port].aptr_cfg);
}
if (sie_msg & SUSB_SUS_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_sus)
(_g_usb[port].fptr_sus)(_g_usb[port].aptr_sus);
}
if (sie_msg & SUSB_ID_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_id)
(_g_usb[port].fptr_id)(_g_usb[port].aptr_id);
}
if (sie_msg & SUSB_VBUS_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_vbus)
(_g_usb[port].fptr_vbus)(_g_usb[port].aptr_vbus);
}
for (i=0; i < 8; i++)
{
if (sie_msg & (SUSB_EP0_MSG << i))
{
siemsg_handled = 1;
if (_g_usb[port].fptr_ept[i])
(_g_usb[port].fptr_ept[i])(_g_usb[port].aptr_ept[i]);
}
}
if (!siemsg_handled)
{
sputs("Unhandled SIE1 message ");
print_word(sie_msg);
sputs("!\n");
}
}
port = 1;
siemsg_handled = 0;
if (hpi_status & HPI_STATUS_SIEMSG2)
{
int_handled = 1;
sie_msg = hpi_read_reg(HPI_REG_SIE2MSG);
// Reset message register
hpi_write_reg(HPI_REG_SIE2MSG, 0x0000);
if (sie_msg & SUSB_RST_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_rst)
(_g_usb[port].fptr_rst)(_g_usb[port].aptr_rst);
}
if (sie_msg & SUSB_SOF_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_sof)
(_g_usb[port].fptr_sof)(_g_usb[port].aptr_sof);
}
if (sie_msg & SUSB_CFG_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_cfg)
(_g_usb[port].fptr_cfg)(_g_usb[port].aptr_cfg);
}
if (sie_msg & SUSB_SUS_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_sus)
(_g_usb[port].fptr_sus)(_g_usb[port].aptr_sus);
}
if (sie_msg & SUSB_ID_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_id)
(_g_usb[port].fptr_id)(_g_usb[port].aptr_id);
}
if (sie_msg & SUSB_VBUS_MSG)
{
siemsg_handled = 1;
if (_g_usb[port].fptr_vbus)
(_g_usb[port].fptr_vbus)(_g_usb[port].aptr_vbus);
}
for (i=0; i < 8; i++)
{
if (sie_msg & (SUSB_EP0_MSG << i))
{
siemsg_handled = 1;
if (_g_usb[port].fptr_ept[i])
(_g_usb[port].fptr_ept[i])(_g_usb[port].aptr_ept[i]);
}
}
if (!siemsg_handled)
{
sputs("Unhandled SIE2 message ");
print_word(sie_msg);
sputs("!\n");
}
}
if (!int_handled)
{
sputs("Unhandled interrupt (status = ");
print_word(hpi_status);
sputs(")!\n");
}
// sputs("--------------------------------------------------------\n");
_g_int_active = 0;
}
// ---------------------------------------------------------
// CY7C67300 low-level routines
// ---------------------------------------------------------
void cy67k3_reset(void)
{
int i;
volatile UINT32 *pHpi = (UINT32*)SYS_USB_CTRL;
*pHpi = 3;
for (i=0; i <160; i++)
{
__asm __volatile
(
".set noreorder\n"
"nop\n"
"nop\n"
"nop\n"
"nop\n"
".set reorder\n"
);
}
*pHpi = 2;
}
UINT16 cy67k3_read_HPI_DATA(void)
{
volatile UINT32 *pHpi = (UINT32*)SYS_USB_DATA;
return (UINT16)*pHpi;
}
UINT16 cy67k3_read_HPI_MAILBOX(void)
{
volatile UINT32 *pHpi = (UINT32*)SYS_USB_MBX;
return (UINT16)*pHpi;
}
UINT16 cy67k3_read_HPI_ADDRESS(void)
{
volatile UINT32 *pHpi = (UINT32*)SYS_USB_ADDR;
return (UINT16)*pHpi;
}
UINT16 cy67k3_read_HPI_STATUS(void)
{
volatile UINT32 *pHpi = (UINT32*)SYS_USB_STATUS;
return (UINT16)*pHpi;
}
void cy67k3_write_HPI_DATA(UINT16 data)
{
volatile UINT32 *pHpi = (UINT32*)SYS_USB_DATA;
*pHpi = (UINT32)data;
}
void cy67k3_write_HPI_MAILBOX(UINT16 data)
{
volatile UINT32 *pHpi = (UINT32*)SYS_USB_MBX;
*pHpi = (UINT32)data;
}
void cy67k3_write_HPI_ADDRESS(UINT16 data)
{
volatile UINT32 *pHpi = (UINT32*)SYS_USB_ADDR;
*pHpi = (UINT32)data;
}
void cy67k3_write_HPI_STATUS(UINT16 data)
{
volatile UINT32 *pHpi = (UINT32*)SYS_USB_STATUS;
*pHpi = (UINT32)data;
}
// ---------------------------------------------------------
// HPI API
// ---------------------------------------------------------
UINT32 hpi_init(void)
{
volatile UINT32 *pHpi = (UINT32*)SYS_USB_CTRL;
int i;
UINT16 reg;
// ToDo: Enable HPI interrupt
_g_int_active = 0;
hpi_write_reg(HPI_REG_SIE1MSG, 0x0000);
hpi_write_reg(HPI_REG_SIE2MSG, 0x0000);
hpi_write_reg(SUSB1_REG_STATUS, 0xFFFF);
hpi_write_reg(SUSB2_REG_STATUS, 0xFFFF);
// Init 1
for(i=0; i < USB_MAX_NUM_EPT; i++)
{
hpi_write_reg(SUSB1_REG_EP_ADDR0 + 16*i, 0);
hpi_write_reg(SUSB1_REG_EP_CNTRES0 + 16*i, 0);
hpi_write_reg(SUSB1_REG_EP_COUNT0 + 16*i, 0);
hpi_write_reg(SUSB1_REG_EP_CTRL0 + 16*i, 0);
hpi_write_reg(SUSB1_REG_EP_STATUS0 + 16*i, 0);
}
// Init 2
for(i=0; i < USB_MAX_NUM_EPT; i++)
{
hpi_write_reg(SUSB2_REG_EP_ADDR0 + 16*i, 0);
hpi_write_reg(SUSB2_REG_EP_CNTRES0 + 16*i, 0);
hpi_write_reg(SUSB2_REG_EP_COUNT0 + 16*i, 0);
hpi_write_reg(SUSB2_REG_EP_CTRL0 + 16*i, 0);
hpi_write_reg(SUSB2_REG_EP_STATUS0 + 16*i, 0);
}
hpi_write_reg(HPI_REG_INTROUTE, 0x0000);
reg = hpi_read_reg(HPI_REG_INTROUTE);
// hpi_write_reg(HPI_REG_INTROUTE, reg | 0x0202); // Route reset {1,2} to HPI only
// hpi_write_reg(HPI_REG_INTROUTE, reg | 0x2800); // Route SOF/EOP {1,2} to HPI only
// hpi_write_reg(HPI_REG_INTROUTE, reg | 0x1400); // Route SOF/EOP {1,2} to CY16 only
hpi_write_reg(HPI_REG_INTROUTE, reg | 0x3C00); // Route SOF/EOP {1,2} to HPI and CY16
interrupt_register(4, cy67k3_isr);
interrupt_enable(4);
*pHpi = 0x02;
return HPI_NOERROR;
}
void hpi_mbx_write(UINT16 msgcode)
{
_g_mbx_in_flag = 0;
cy67k3_write_HPI_MAILBOX(msgcode);
}
UINT32 hpi_mbx_read(void)
{
UINT32 err;
UINT16 cy_return;
if (_g_int_active)
{
while (!(cy67k3_read_HPI_STATUS() & HPI_STATUS_MBX_IN));
cy_return = cy67k3_read_HPI_MAILBOX();
}
else
{
while(!_g_mbx_in_flag);
cy_return = _g_mbx_return;
}
switch (cy_return)
{
case COMM_ACK:
err = cy_return;
break;
case COMM_NAK:
case COMM_ASYNC:
err = HPI_ERR_PREFIX_MBX | cy_return;
break;
default:
err = HPI_ERR_PREFIX_MBX | cy_return;
break;
}
return err;
}
UINT32 hpi_check_addr(UINT16 addr)
{
if ((addr >= 0x0000) && (addr < 0x4000))
return 0;
if ((addr >= 0xC080) && (addr < 0xC0BC))
return 0;
if (addr >= 0xE000)
return 0;
sputs("Invalid address for HPI direct access! Use LCP-command instead!\n");
return HPI_ERR_INVPARAM;
}
UINT32 hpi_read_reg(UINT16 addr)
{
UINT32 result;
result = hpi_check_addr(addr);
if (IS_ERROR(result))
return result;
cy67k3_write_HPI_ADDRESS(addr);
return cy67k3_read_HPI_DATA();
}
UINT32 hpi_write_reg(UINT16 addr, UINT16 data)
{
UINT32 result;
result = hpi_check_addr(addr);
if (IS_ERROR(result))
return result;
cy67k3_write_HPI_ADDRESS(addr);
cy67k3_write_HPI_DATA(data);
}
UINT32 hpi_write_ram(UINT16 addr, UINT16 *pData, UINT32 len)
{
int i, num_words;
if (addr > 0x3FFE)
return HPI_ERR_INVPARAM;
if (addr & 1) // Not 16bit aligned?
return HPI_ERR_INVPARAM;
cy67k3_write_HPI_ADDRESS(addr);
num_words = len/2;
if (len % 2)
num_words++;
for (i=0; i < num_words; i++)
cy67k3_write_HPI_DATA(pData[i]);
return len;
}
UINT32 hpi_read_ram(UINT16 addr, UINT16 *pData, UINT32 len)
{
int i, num_words;
if (addr > 0x3FFE)
return HPI_ERR_INVPARAM;
if (addr & 1) // Not 16bit aligned?
return HPI_ERR_INVPARAM;
cy67k3_write_HPI_ADDRESS(addr);
num_words = len/2;
if (len % 2)
num_words++;
for (i=0; i < num_words; i++)
pData[i] = cy67k3_read_HPI_DATA();
return len;
}
UINT32 hpi_comm_reset(void)
{
hpi_mbx_write(COMM_RESET);
return hpi_mbx_read();
}
UINT32 hpi_comm_jump2code(UINT16 addr)
{
cy67k3_write_HPI_ADDRESS(addr);
hpi_mbx_write(COMM_JUMP2CODE);
return hpi_mbx_read();
}
UINT32 hpi_comm_callcode(UINT16 addr)
{
hpi_write_reg(COMM_CODE_ADDR, addr);
hpi_mbx_write(COMM_CALL_CODE);
return hpi_mbx_read();
}
UINT32 hpi_comm_write_ctrl_reg(UINT16 addr, UINT16 data, UINT16 logic)
{
hpi_write_reg(COMM_CTRL_REG_ADDR, addr);
hpi_write_reg(COMM_CTRL_REG_DATA, data);
hpi_write_reg(COMM_CTRL_REG_LOGIC, logic);
hpi_mbx_write(COMM_WRITE_CTRL_REG);
return hpi_mbx_read();
}
UINT32 hpi_comm_read_ctrl_reg(UINT16 addr)
{
UINT32 result;
hpi_write_reg(COMM_CTRL_REG_ADDR, addr);
hpi_mbx_write(COMM_READ_CTRL_REG);
result = hpi_mbx_read();
if (IS_ERROR(result))
return result;
cy67k3_write_HPI_ADDRESS(COMM_CTRL_REG_DATA);
return (UINT32)cy67k3_read_HPI_DATA();
}
UINT32 hpi_comm_write_xmem(UINT16 addr, UINT8 *pData, UINT16 len)
{
return HPI_ERR_NOTIMPL;
}
UINT32 hpi_comm_read_xmem(UINT16 addr, UINT8 *pData, UINT16 len)
{
return HPI_ERR_NOTIMPL;
}
typedef struct _sreg_param_t
{
UINT32 id;
UINT16 val;
} reg_param_t;
UINT32 hpi_comm_exec_int(UINT16 intnum, UINT32 nargs, ...)
{
int i;
UINT32 result;
va_list args;
reg_param_t reg_param[MAX_NUM_REGS];
va_start(args, nargs);
if (nargs > MAX_NUM_REGS)
{
fprintf(stderr, "hpi_comm_exec_int(): Number (%d), of arguments exceeds %d!\n", nargs, MAX_NUM_REGS);
return HPI_ERR_INVPARAM;
}
for (i=0; i < nargs; i++)
{
reg_param[i].id = va_arg(args, UINT32);
if (reg_param[i].id > MAX_NUM_REGS)
{
fprintf(stderr, "hpi_comm_exec_int(): Invalid register R%d!\n", reg_param[i].id);
return HPI_ERR_INVPARAM;
}
reg_param[i].val = (UINT16)va_arg(args, UINT32);
}
va_end(args);
hpi_write_reg(COMM_INT_NUM, intnum);
for (i=0; i < nargs; i++)
{
hpi_write_reg(COMM_R0 + 2*reg_param[i].id, reg_param[i].val);
}
hpi_mbx_write(COMM_EXEC_INT);
result = hpi_mbx_read();
if (IS_ERROR(result))
return result;
return (UINT32)hpi_read_reg(COMM_R0);
}
UINT32 usb_init(void)
{
INT32 i;
for (i=0; i < USB_MAX_NUM_PORTS; i++)
{
memset(&_g_usb[i], 0, sizeof(usb_t));
}
return 0;
}
UINT32 usb_callback_register(UINT32 port, UINT32 type, fp_t pFunc, void *pArg)
{
UINT32 result;
if (port >= USB_MAX_NUM_PORTS)
return -1;
result = 0;
switch (type)
{
case SUSB_EP0_MSG:
_g_usb[port].fptr_ept[0] = pFunc;
_g_usb[port].aptr_ept[0] = pArg;
break;
case SUSB_EP1_MSG:
_g_usb[port].fptr_ept[1] = pFunc;
_g_usb[port].aptr_ept[1] = pArg;
break;
case SUSB_EP2_MSG:
_g_usb[port].fptr_ept[2] = pFunc;
_g_usb[port].aptr_ept[2] = pArg;
break;
case SUSB_EP3_MSG:
_g_usb[port].fptr_ept[3] = pFunc;
_g_usb[port].aptr_ept[3] = pArg;
break;
case SUSB_EP4_MSG:
_g_usb[port].fptr_ept[4] = pFunc;
_g_usb[port].aptr_ept[4] = pArg;
break;
case SUSB_EP5_MSG:
_g_usb[port].fptr_ept[5] = pFunc;
_g_usb[port].aptr_ept[5] = pArg;
break;
case SUSB_EP6_MSG:
_g_usb[port].fptr_ept[6] = pFunc;
_g_usb[port].aptr_ept[6] = pArg;
break;
case SUSB_EP7_MSG:
_g_usb[port].fptr_ept[7] = pFunc;
_g_usb[port].aptr_ept[7] = pArg;
break;
case SUSB_RST_MSG:
_g_usb[port].fptr_rst = pFunc;
_g_usb[port].aptr_rst = pArg;
break;
case SUSB_SOF_MSG:
_g_usb[port].fptr_sof = pFunc;
_g_usb[port].aptr_sof = pArg;
break;
case SUSB_CFG_MSG:
_g_usb[port].fptr_cfg = pFunc;
_g_usb[port].aptr_cfg = pArg;
break;
case SUSB_SUS_MSG:
_g_usb[port].fptr_sus = pFunc;
_g_usb[port].aptr_sus = pArg;
break;
case SUSB_ID_MSG:
_g_usb[port].fptr_id = pFunc;
_g_usb[port].aptr_id = pArg;
break;
case SUSB_VBUS_MSG:
_g_usb[port].fptr_vbus = pFunc;
_g_usb[port].aptr_vbus = pArg;
break;
default:
result = -1;
break;
}
return result;
}
UINT32 usb_irp_register(usb_irp_t *pIRP, UINT32 port, UINT32 ept, UINT32 size, UINT32 is_out)
{
if (!pIRP)
return -1;
if (port >= USB_MAX_NUM_PORTS)
return -1;
if (ept >= USB_MAX_NUM_EPT)
return -1;
if (size >= USB_MAX_IMG_SIZE)
return -1;
memset(pIRP, 0, sizeof(usb_irp_t));
pIRP->is_out = is_out;
pIRP->is_in = !is_out;
pIRP->tsize = size;
pIRP->port = port;
pIRP->ept = ept;
pIRP->cy_irp_addr = USB_IRP_BASE + port*USB_MAX_NUM_EPT*sizeof(cy_req_t) + ept*sizeof(cy_req_t);
pIRP->cy_req.next = 0;
pIRP->cy_req.addr = USB_IMG_BASE + port*USB_MAX_NUM_EPT*USB_MAX_IMG_SIZE + ept*USB_MAX_IMG_SIZE;
pIRP->cy_req.size = size;
pIRP->cy_req.callback = 0;
fifo_alloc(&pIRP->fifo, 8*USB_MAX_IMG_SIZE);
return 0;
}
UINT32 usb_irp_enqueue(usb_irp_t *pIRP)
{
UINT32 result;
if (!pIRP)
{
// sputs ("usb_irp_enqueue(): Invalid IRP!\n");
return -1;
}
// printf("cy_addr: %4.4X, Next: %4.4X, Addr: %4.4X, Size: %4.4X, CB: %4.4X\n", pIRP->cy_irp_addr, pIRP->cy_req.next, pIRP->cy_req.addr, pIRP->cy_req.size, pIRP->cy_req.callback);
if (pIRP->is_out)
{
hpi_write_ram(pIRP->cy_irp_addr, (UINT16*)&pIRP->cy_req, sizeof(cy_req_t));
if (pIRP->port == 0)
result = hpi_comm_exec_int(SUSB1_RECEIVE_INT, 2, R1, pIRP->ept, R8, pIRP->cy_irp_addr);
if (pIRP->port == 1)
result = hpi_comm_exec_int(SUSB2_RECEIVE_INT, 2, R1, pIRP->ept, R8, pIRP->cy_irp_addr);
}
if (pIRP->is_in)
{
pIRP->tx_in_progress = 1;
hpi_write_ram(pIRP->cy_irp_addr, (UINT16*)&pIRP->cy_req, sizeof(cy_req_t));
if (pIRP->port == 0)
result = hpi_comm_exec_int(SUSB1_SEND_INT, 2, R1, pIRP->ept, R8, pIRP->cy_irp_addr);
if (pIRP->port == 1)
result = hpi_comm_exec_int(SUSB2_SEND_INT, 2, R1, pIRP->ept, R8, pIRP->cy_irp_addr);
}
// if (result)
// printf ("usb_irp_enqueue(): Result = %8.8X\n", result);
return result;
}
UINT32 fifo_alloc(fifo_t *pObj, UINT32 size)
{
pObj->pBuf = (UINT8*)malloc(size);
if (!pObj->pBuf)
{
// printf ("fifo_alloc(): Error allocating memory!\n");
return -1;
}
// printf ("fifo_alloc(): pBuf at %8.8X\n", (UINT32)pObj->pBuf);
pObj->size = size;
pObj->pPtr_wr = pObj->pBuf;
pObj->pPtr_rd = pObj->pBuf;
return 0;
}
UINT32 fifo_free(fifo_t *pObj)
{
if (pObj->pBuf)
free(pObj->pBuf);
return 0;
}
UINT32 fifo_flush(fifo_t *pObj)
{
pObj->pPtr_wr = pObj->pBuf;
pObj->pPtr_rd = pObj->pBuf;
return 0;
}
UINT32 fifo_is_empty(fifo_t *pObj)
{
return (pObj->pPtr_wr == pObj->pPtr_rd);
}
UINT32 fifo_is_full(fifo_t *pObj)
{
UINT8 *pNext, *pEnd;
pEnd = pObj->pBuf + pObj->size;
pNext = pObj->pPtr_wr + 1;
if (pNext == pEnd)
pNext = pObj->pBuf;
return (pNext == pObj->pPtr_rd);
}
UINT32 fifo_read(fifo_t *pObj, UINT8 *pData, UINT32 size, UINT32 timeout, UINT32 do_block)
{
UINT32 i;
UINT32 wait_4ever, timeout_cnt, cnt;
UINT8 *pEnd;
pEnd = pObj->pBuf + pObj->size;
wait_4ever = (timeout == 0);
cnt = 0;
while(size)
{
timeout_cnt = timeout;
while(fifo_is_empty(pObj))
{
if (!do_block)
return cnt;
if (!wait_4ever)
{
if (timeout_cnt)
{
timeout_cnt--;
sleep(1);
}
else
{
return cnt;
}
}
}
if (pData)
pData[cnt] = *(pObj->pPtr_rd);
cnt++;
pObj->pPtr_rd++;
if (pObj->pPtr_rd == pEnd)
pObj->pPtr_rd = pObj->pBuf;
size--;
}
return cnt;
}
UINT32 fifo_write(fifo_t *pObj, UINT8 *pData, UINT32 size, UINT32 timeout, UINT32 do_block)
{
UINT32 wait_4ever, timeout_cnt, cnt;
UINT8 *pEnd;
pEnd = pObj->pBuf + pObj->size;
wait_4ever = (timeout == 0);
cnt = 0;
while(size)
{
timeout_cnt = timeout;
while(fifo_is_full(pObj))
{
if (!do_block)
return cnt;
if (!wait_4ever)
{
if (timeout_cnt)
{
timeout_cnt--;
sleep(1);
}
else
{
return cnt;
}
}
}
if (pData)
*(pObj->pPtr_wr) = pData[cnt];
cnt++;
pObj->pPtr_wr++;
if (pObj->pPtr_wr == pEnd)
pObj->pPtr_wr = pObj->pBuf;
size--;
}
return cnt;
}
// ---------------------------------------------------------
+384
View File
@@ -0,0 +1,384 @@
#ifndef HPI_H
#define HPI_H
// ---------------------------------------------------------
// API related
// ---------------------------------------------------------
//#define IS_ERROR(e) (0 != (e & HPI_ERROR))
#define HPI_NOERROR 0
#define HPI_ERROR 0x80000000
#define HPI_ERR_NOTIMPL (HPI_ERROR + 1)
#define HPI_ERR_INVPARAM (HPI_ERROR + 2)
#define HPI_ERR_TIMEOUT (HPI_ERROR + 3)
#define HPI_ERR_PREFIX_MBX (HPI_ERROR + 0x00010000)
#define MAX_NUM_REGS 14
#define R0 0
#define R1 1
#define R2 2
#define R3 3
#define R4 4
#define R5 5
#define R6 6
#define R7 7
#define R8 8
#define R9 9
#define R10 10
#define R11 11
#define R12 12
#define R13 13
#define USB_MAX_NUM_PORTS 2
#define USB_MAX_NUM_EPT 8
#define USB_MAX_IMG_SIZE 512
#define USB_IRP_BASE 0x0F80
#define USB_IMG_BASE 0x1000
typedef void (*fp_t)(void*);
// Receive buffer on EP
typedef struct _scy_req_t
{
UINT16 next;
UINT16 addr;
UINT16 size;
UINT16 callback;
} cy_req_t;
typedef struct _sfifo_t
{
UINT32 size;
UINT8 *pBuf;
UINT8 * volatile pPtr_wr, * volatile pPtr_rd;
} fifo_t;
typedef struct _susb_irp_t
{
UINT16 tsize;
UINT32 is_in, is_out;
UINT32 port, ept;
UINT16 cy_irp_addr;
fifo_t fifo;
UINT32 tx_in_progress;
cy_req_t cy_req;
} usb_irp_t;
// ---------------------------------------------------------
// CY7C67300 related
// ---------------------------------------------------------
#define HPI_WAITACK 1
#define HPI_NOWAIT 0
// ---------------------------------------------------------
// HPI status flags
#define HPI_STATUS_MBX_IN 0x0001
#define HPI_STATUS_RESET1 0x0002
#define HPI_STATUS_DONE1 0x0004
#define HPI_STATUS_DONE2 0x0008
#define HPI_STATUS_SIEMSG1 0x0010
#define HPI_STATUS_SIEMSG2 0x0020
#define HPI_STATUS_RESUME1 0x0040
#define HPI_STATUS_RESUME2 0x0080
#define HPI_STATUS_MBX_OUT 0x0100
#define HPI_STATUS_RESET2 0x0200
#define HPI_STATUS_SOFEOP1 0x0400
#define HPI_STATUS_SOFEOP2 0x1000
#define HPI_STATUS_ID 0x4000
#define HPI_STATUS_VBUS 0x8000
// ---------------------------------------------------------
// LCP command codes
#define COMM_RESET 0xFA50
#define COMM_JUMP2CODE 0xCE00
#define COMM_EXEC_INT 0xCE01
#define COMM_READ_CTRL_REG 0xCE02
#define COMM_WRITE_CTRL_REG 0xCE03
#define COMM_CALL_CODE 0xCE04
#define COMM_READ_XMEM 0xCE05
#define COMM_WRITE_XMEM 0xCE06
#define C0MM_CONFIG 0xCE07
#define COMM_READ_MEM 0xCE08
#define COMM_WRITE_MEM 0xCE09
// LCP response codes
#define COMM_ACK 0x0FED
#define COMM_NAK 0xDEAD
#define COMM_ASYNC 0xF00D
// ---------------------------------------------------------
// LCP memory addresses
#define COMM_PORT_CMD 0x01BA // For PORT Command
#define COMM_MEM_ADDR 0x01BC // Address for COMM_RD/WR_MEM
#define COMM_MEM_LEN 0x01BE // Address for COMM_RD/WR_MEM
#define COMM_LAST_DATA 0x01C0 // memory pointer for xmem
#define COMM_CTRL_REG_ADDR 0x01BC // Address for COMM_RD/WR_CTRL_REG
#define COMM_CTRL_REG_DATA 0x01BE // Address for COMM_RD/WR_CTRL_REG
#define COMM_CTRL_REG_LOGIC 0x01C0 // Address used for AND/OR
#define REG_WRITE_FLG 0x0000 // Value for COMM_CTRL_REG_LOGIC
#define REG_AND_FLG 0x0001 // Value for COMM_CTRL_REG_LOGIC
#define REG_OR_FLG 0x0002 // Value for COMM_CTRL_REG_LOGIC
#define COMM_TIMEOUT 0x01BE // Address setting Timeout for sending response to host
#define COMM_CODE_ADDR 0x01BC // Address for COMM_CALL_CODE and COMM_JUMP2CODE
#define COMM_INT_NUM 0x01C2 // Address used for COMM_EXEC_INT
#define COMM_R0 0x01C4 // CY16-R0 register
#define COMM_R1 0x01C6 // CY16-R1 register
#define COMM_R2 0x01C8 // CY16-R2 register
#define COMM_R3 0x01CA // CY16-R3 register
#define COMM_R4 0x01CC // CY16-R4 register
#define COMM_R5 0x01CE // CY16-R5 register
#define COMM_R6 0x01D0 // CY16-R6 register
#define COMM_R7 0x01D2 // CY16-R7 register
#define COMM_R8 0x01D4 // CY16-R8 register
#define COMM_R9 0x01D6 // CY16-R9 register
#define COMM_R10 0x01D8 // CY16-R10 register
#define COMM_R11 0x01DA // CY16-R11 register
#define COMM_R12 0x01DC // CY16-R12 register
#define COMM_R13 0x01DE // CY16-R13 register
// for COMM_CTRL_REG_LOGIC
#define LOGIC_DIRECT 0
#define LOGIC_AND 1
#define LOGIC_OR 2
// ---------------------------------------------------------
// Software interrupts
#define SUSB_INIT_INT 113
// USB 1
#define SUSB1_DEVICE_DESCRIPTOR_VEC 90
#define SUSB1_CONFIGURATION_DESCRIPTOR_VEC 91
#define SUSB1_STRING_DESCRIPTOR_VEC 92
#define SUSB1_FINISH_INT 89
#define SUSB1_STALL_INT 82
#define SUSB1_STANDARD_INT 83
#define SUSB1_SEND_INT 80
#define SUSB1_RECEIVE_INT 81
#define SUSB1_VENDOR_INT 85
#define SUSB1_CLASS_INT 87
#define SUSB1_LOADER_INT 94
#define SUSB1_DELTA_CONFIG_INT 95
// USB 2
#define SUSB2_DEVICE_DESCRIPTOR_VEC 106
#define SUSB2_CONFIGURATION_DESCRIPTOR_VEC 107
#define SUSB2_STRING_DESCRIPTOR_VEC 108
#define SUSB2_FINISH_INT 105
#define SUSB2_STALL_INT 98
#define SUSB2_STANDARD_INT 99
#define SUSB2_SEND_INT 96
#define SUSB2_RECEIVE_INT 97
#define SUSB2_VENDOR_INT 101
#define SUSB2_CLASS_INT 103
#define SUSB2_LOADER_INT 110
#define SUSB2_DELTA_CONFIG_INT 111
// ---------------------------------------------------------
// General USB Registers
#define USB_REG_FLAGS 0xC000 // CPU Flags
#define USB_REG_BANK 0xC002 // Register Bank
#define USB_REG_REVISON 0xC004 // Hardware Revision
#define USB_REG_SPEED 0xC008 // CPU Speed
#define USB_REG_PWRCTRL 0xC00A // Power Control
#define USB_REG_INTEN 0xC00E // Interrupt Enable
#define USB_REG_BP 0xC014 // Breakpoint
#define USB_REG_USBDIAG 0xC03C // USB Diagnostic
#define USB_REG_MEMDIAG 0xC03E // Memory Diagnostic
// HPI registers
#define HPI_REG_BP 0x0140 // HPI Breakpoint
#define HPI_REG_INTROUTE 0x0142 // Interrupt Routing
#define HPI_REG_SIE1MSG 0x0144 // SIE1msg
#define HPI_REG_SIE2MSG 0x0148 // SIE2msg
#define HPI_REG_MAILBOX 0xC0C6 // HPI Mailbox
// ---------------------------------------------------------
// General Device Registers
// Device 1
#define SUSB1_REG_PORTSEL 0xC084 // Port select
#define SUSB1_REG_USBCTRL 0xC08A // USB control
#define SUSB1_REG_INTEN 0xC08C // Interrupt enable
#define SUSB1_REG_ADDR 0xC08E // Address
#define SUSB1_REG_STATUS 0xC090 // Status
#define SUSB1_REG_FRAMENUM 0xC092 // Frame number
#define SUSB1_REG_SOFEOPCNT 0xC094 // SOF/EOP count
// Device 2
#define SUSB2_REG_PORTSEL 0xC0A4 // Port select
#define SUSB2_REG_USBCTRL 0xC0AA // USB control
#define SUSB2_REG_INTEN 0xC0AC // Interrupt enable
#define SUSB2_REG_ADDR 0xC0AE // Address
#define SUSB2_REG_STATUS 0xC0B0 // Status
#define SUSB2_REG_FRAMENUM 0xC0B2 // Frame number
#define SUSB2_REG_SOFEOPCNT 0xC0B4 // SOF/EOP count
// ---------------------------------------------------------
// Endpoint Registers
// Device 1 Control
#define SUSB1_REG_EP_CTRL0 0x0200
#define SUSB1_REG_EP_CTRL1 0x0210
#define SUSB1_REG_EP_CTRL2 0x0220
#define SUSB1_REG_EP_CTRL3 0x0230
#define SUSB1_REG_EP_CTRL4 0x0240
#define SUSB1_REG_EP_CTRL5 0x0250
#define SUSB1_REG_EP_CTRL6 0x0260
#define SUSB1_REG_EP_CTRL7 0x0270
// Device 1 Address
#define SUSB1_REG_EP_ADDR0 0x0202
#define SUSB1_REG_EP_ADDR1 0x0212
#define SUSB1_REG_EP_ADDR2 0x0222
#define SUSB1_REG_EP_ADDR3 0x0232
#define SUSB1_REG_EP_ADDR4 0x0242
#define SUSB1_REG_EP_ADDR5 0x0252
#define SUSB1_REG_EP_ADDR6 0x0262
#define SUSB1_REG_EP_ADDR7 0x0272
// Device 1 Count
#define SUSB1_REG_EP_COUNT0 0x0204
#define SUSB1_REG_EP_COUNT1 0x0214
#define SUSB1_REG_EP_COUNT2 0x0224
#define SUSB1_REG_EP_COUNT3 0x0234
#define SUSB1_REG_EP_COUNT4 0x0244
#define SUSB1_REG_EP_COUNT5 0x0254
#define SUSB1_REG_EP_COUNT6 0x0264
#define SUSB1_REG_EP_COUNT7 0x0274
// Device 1 Status
#define SUSB1_REG_EP_STATUS0 0x0206
#define SUSB1_REG_EP_STATUS1 0x0216
#define SUSB1_REG_EP_STATUS2 0x0226
#define SUSB1_REG_EP_STATUS3 0x0236
#define SUSB1_REG_EP_STATUS4 0x0246
#define SUSB1_REG_EP_STATUS5 0x0256
#define SUSB1_REG_EP_STATUS6 0x0266
#define SUSB1_REG_EP_STATUS7 0x0276
// Device 1 Count result
#define SUSB1_REG_EP_CNTRES0 0x0208
#define SUSB1_REG_EP_CNTRES1 0x0218
#define SUSB1_REG_EP_CNTRES2 0x0228
#define SUSB1_REG_EP_CNTRES3 0x0238
#define SUSB1_REG_EP_CNTRES4 0x0248
#define SUSB1_REG_EP_CNTRES5 0x0258
#define SUSB1_REG_EP_CNTRES6 0x0268
#define SUSB1_REG_EP_CNTRES7 0x0278
// Device 2 Control
#define SUSB2_REG_EP_CTRL0 0x0280
#define SUSB2_REG_EP_CTRL1 0x0290
#define SUSB2_REG_EP_CTRL2 0x02A0
#define SUSB2_REG_EP_CTRL3 0x02B0
#define SUSB2_REG_EP_CTRL4 0x02C0
#define SUSB2_REG_EP_CTRL5 0x02D0
#define SUSB2_REG_EP_CTRL6 0x02E0
#define SUSB2_REG_EP_CTRL7 0x02F0
// Device 2 Address
#define SUSB2_REG_EP_ADDR0 0x0282
#define SUSB2_REG_EP_ADDR1 0x0292
#define SUSB2_REG_EP_ADDR2 0x02A2
#define SUSB2_REG_EP_ADDR3 0x02B2
#define SUSB2_REG_EP_ADDR4 0x02C2
#define SUSB2_REG_EP_ADDR5 0x02D2
#define SUSB2_REG_EP_ADDR6 0x02E2
#define SUSB2_REG_EP_ADDR7 0x02F2
// Device 2 Count
#define SUSB2_REG_EP_COUNT0 0x0284
#define SUSB2_REG_EP_COUNT1 0x0294
#define SUSB2_REG_EP_COUNT2 0x02A4
#define SUSB2_REG_EP_COUNT3 0x02B4
#define SUSB2_REG_EP_COUNT4 0x02C4
#define SUSB2_REG_EP_COUNT5 0x02D4
#define SUSB2_REG_EP_COUNT6 0x02E4
#define SUSB2_REG_EP_COUNT7 0x02F4
// Device 2 Status
#define SUSB2_REG_EP_STATUS0 0x0286
#define SUSB2_REG_EP_STATUS1 0x0296
#define SUSB2_REG_EP_STATUS2 0x02A6
#define SUSB2_REG_EP_STATUS3 0x02B6
#define SUSB2_REG_EP_STATUS4 0x02C6
#define SUSB2_REG_EP_STATUS5 0x02D6
#define SUSB2_REG_EP_STATUS6 0x02E6
#define SUSB2_REG_EP_STATUS7 0x02F6
// Device 2 Count result
#define SUSB2_REG_EP_CNTRES0 0x0288
#define SUSB2_REG_EP_CNTRES1 0x0298
#define SUSB2_REG_EP_CNTRES2 0x02A8
#define SUSB2_REG_EP_CNTRES3 0x02B8
#define SUSB2_REG_EP_CNTRES4 0x02C8
#define SUSB2_REG_EP_CNTRES5 0x02D8
#define SUSB2_REG_EP_CNTRES6 0x02E8
#define SUSB2_REG_EP_CNTRES7 0x02F8
// ---------------------------------------------------------
// others
#define HUSB_TDLISTDONE 0x1000
#define HUSB_SOF 0x2000
#define HUSB_ARMV 0x0001
#define HUSB_AINS_FS 0x0002
#define HUSB_AINS_LS 0x0004
#define HUSB_AWAKEUP 0x0008
#define HUSB_BRMV 0x0010
#define HUSB_BINS_FS 0x0020
#define HUSB_BINS_LS 0x0040
#define HUSB_BWAKEUP 0x0080
#define SUSB_EP0_MSG 0x0001
#define SUSB_EP1_MSG 0x0002
#define SUSB_EP2_MSG 0x0004
#define SUSB_EP3_MSG 0x0008
#define SUSB_EP4_MSG 0x0010
#define SUSB_EP5_MSG 0x0020
#define SUSB_EP6_MSG 0x0040
#define SUSB_EP7_MSG 0x0080
#define SUSB_RST_MSG 0x0100
#define SUSB_SOF_MSG 0x0200
#define SUSB_CFG_MSG 0x0400
#define SUSB_SUS_MSG 0x0800
#define SUSB_ID_MSG 0x4000
#define SUSB_VBUS_MSG 0x8000
// ---------------------------------------------------------
// Functions
// ---------------------------------------------------------
// HPI low-level routines
void cy67k3_isr(void);
void cy67k3_reset(void);
UINT16 cy67k3_read_HPI_DATA(void);
UINT16 cy67k3_read_HPI_MAILBOX(void);
UINT16 cy67k3_read_HPI_ADDRESS(void);
UINT16 cy67k3_read_HPI_STATUS(void);
void cy67k3_write_HPI_DATA(UINT16 data);
void cy67k3_write_HPI_MAILBOX(UINT16 data);
void cy67k3_write_HPI_ADDRESS(UINT16 data);
void cy67k3_write_HPI_STATUS(UINT16 data);
// HPI API
UINT32 hpi_init(void);
void hpi_mbx_write(UINT16 msgcode);
UINT32 hpi_mbx_read(void);
UINT32 hpi_read_reg(UINT16 addr);
UINT32 hpi_write_reg(UINT16 addr, UINT16 data);
UINT32 hpi_write_ram(UINT16 addr, UINT16 *pData, UINT32 num_words);
UINT32 hpi_read_ram(UINT16 addr, UINT16 *pData, UINT32 num_words);
UINT32 hpi_comm_reset(void);
UINT32 hpi_comm_jump2code(UINT16 addr);
UINT32 hpi_comm_callcode(UINT16 addr);
UINT32 hpi_comm_write_ctrl_reg(UINT16 addr, UINT16 data, UINT16 logic);
UINT32 hpi_comm_read_ctrl_reg(UINT16 addr);
UINT32 hpi_comm_write_xmem(UINT16 addr, UINT8 *pData, UINT16 len);
UINT32 hpi_comm_read_xmem(UINT16 addr, UINT8 *pData, UINT16 len);
UINT32 hpi_comm_exec_int(UINT16 intnum, UINT32 nargs, ...);
// USB API
UINT32 usb_init(void);
UINT32 usb_irp_register(usb_irp_t *pIRP, UINT32 port, UINT32 ept, UINT32 size, UINT32 is_out);
UINT32 usb_irp_enqueue(usb_irp_t *pIRP);
UINT32 usb_callback_register(UINT32 port, UINT32 type, fp_t pFunc, void *pArg);
#define FIFO_BLOCK 1
#define FIFO_NONBLOCK 0
UINT32 fifo_alloc(fifo_t *pObj, UINT32 size);
UINT32 fifo_free(fifo_t *pObj);
UINT32 fifo_flush(fifo_t *pObj);
UINT32 fifo_is_full(fifo_t *pObj);
UINT32 fifo_is_empty(fifo_t *pObj);
UINT32 fifo_read(fifo_t *pObj, UINT8 *pData, UINT32 size, UINT32 timeout, UINT32 do_block);
UINT32 fifo_write(fifo_t *pObj, UINT8 *pData, UINT32 size, UINT32 timeout, UINT32 do_block);
#endif // HPI_H
+846
View File
@@ -0,0 +1,846 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "libsys.h"
#include "cfiflash.h"
#include "hpi.h"
static volatile UINT32 _g_uart_msg;
static volatile UINT32 _g_rst;
static volatile UINT32 _g_sus;
static volatile UINT32 _g_cfg;
void uart_handler(void)
{
volatile UINT32 *pUART_stat = (UINT32*)SYS_UART_STAT;
volatile UINT32 *pUART_data = (UINT32*)SYS_UART_DATA;
while((SYS_PS2_BIT_RX_AVAIL & *pUART_stat))
{
_g_uart_msg = *pUART_data;
}
}
void PrintDevRegs(UINT devid)
{
int i;
UINT32 reg_base1, reg_base2, reg_addr;
if ((devid < 1) || (devid > 2))
return;
printf("********************************************************\n");
printf("Device %d status\n", devid);
printf("********************************************************\n");
reg_base1 = 0x0200 + (devid-1)*0x80;
reg_base2 = 0xC080 + (devid-1)*0x20;
reg_addr = reg_base2 + 4;
printf("Port select (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base2 + 10;
printf("USB control (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base2 + 12;
printf("Int. enable (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base2 + 14;
printf("Address (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base2 + 16;
printf("Status (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base2 + 18;
printf("Frame # reg (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base2 + 20;
printf("SOF/EOP cnt (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
for (i=0; i < 8; i++)
{
printf("EP# %d\n", i);
reg_addr = reg_base1 + 16*i + 0;
printf("Control (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base1 + 16*i + 2;
printf("Address (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base1 + 16*i + 4;
printf("Count (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base1 + 16*i + 6;
printf("Status (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
reg_addr = reg_base1 + 16*i + 8;
printf("Count result (%4.4X) : %4.4X\n", reg_addr, hpi_read_reg(reg_addr));
}
}
typedef struct _sdev_descr_t
{
UINT8 size; // length
UINT8 type; // desc type
UINT16 usb_spec; // USB spec
UINT8 devclass; // device class
UINT8 subclass; // sub class
UINT8 protocol; // protocol
UINT8 max_packet_size; // max packet size for endpoint 0
UINT16 vendor_id; // Vendor ID
UINT16 product_id; // Product ID
UINT16 device_id; // device release number
UINT8 man_str_index; // index of manufacture string
UINT8 prod_str_index; // index of product string
UINT8 sn_str_index; // index of serial number string
UINT8 nconfs; // number of configurations
} __attribute__ ((__packed__)) dev_descr_t;
typedef struct _sconf_descr_t
{
UINT8 size; // length of this config
UINT8 type; // desc type
UINT16 total_size; // Total configuration desc length including this config and following descriptions
UINT8 nifaces; // Number of interface descriptions following this
UINT8 conf_id; // config number
UINT8 conf_str_index; // index of string describing config
UINT8 attr; // attributes (e.g. bus powered)
UINT8 current; // 2mA x <current> (max. 250 => 500mA)
} __attribute__ ((__packed__)) conf_descr_t;
typedef struct _siface_descr_t
{
UINT8 size; // length of this config
UINT8 type; // desc type
UINT8 base; // base number
UINT8 alt; // alt
UINT8 neps; // number of endpoint description following this
UINT8 iface_class; // interface class (vendor)
UINT8 subclass; // subclass
UINT8 iface_proto; // interface proto (vendor)
UINT8 iface_str_index;
} __attribute__ ((__packed__)) iface_descr_t;
typedef struct _sep_descr_t
{
UINT8 size; // length of this config
UINT8 type; // type (endpoint)
UINT8 type_num; // type/number (Host use WriteFile)
UINT8 bulk; // Bulk
UINT16 pkt_size; // packet size
UINT8 interval; // interval
} __attribute__ ((__packed__)) ep_descr_t;
typedef struct _sotg_descr_t
{
UINT8 size; // length of this config
UINT8 type; // type (OTG)
UINT8 hnp_srp; // HNP|SRP support
} __attribute__ ((__packed__)) otg_descr_t;
typedef struct _sstr_descr_hdr_t
{
UINT8 size; // length of this config
UINT8 type; // type
} __attribute__ ((__packed__)) str_descr_hdr_t;
typedef struct _scfg_inst_t
{
usb_irp_t *pIRP_rx;
usb_irp_t *pIRP_tx;
} cfg_inst_t;
UINT32 conf_write(UINT8 *pConfDescr, UINT32 neps, ep_descr_t *pEP)
{
UINT32 pos, size;
conf_descr_t cfg;
iface_descr_t iface;
otg_descr_t otg_descr;
// Fill config description
cfg.size = sizeof(conf_descr_t);
cfg.type = 2;
cfg.total_size = sizeof(conf_descr_t) + sizeof(iface_descr_t) + neps*sizeof(ep_descr_t) + sizeof(otg_descr_t);
cfg.nifaces = 1; // can handle only one interface per config
cfg.conf_id = 1;
cfg.conf_str_index = 0;
cfg.attr = 0x80;
cfg.current = 50;
// Copy config description
pos = 0;
size = sizeof(conf_descr_t);
memcpy(&pConfDescr[pos], &cfg, size);
// Fill interface description
iface.size = sizeof(iface_descr_t);
iface.type = 4;
iface.base = 0;
iface.alt = 0;
iface.neps = neps;
iface.iface_class = 0;
iface.subclass = 0;
iface.iface_proto = 0;
iface.iface_str_index = 0;
// Copy interface description
pos += size;
size = sizeof(iface_descr_t);
memcpy(&pConfDescr[pos], &iface, size);
// Copy N end point descriptions
pos += size;
size = neps*sizeof(ep_descr_t);
memcpy(&pConfDescr[pos], pEP, size);
// Fill OTG description
otg_descr.size = sizeof(otg_descr_t);
otg_descr.type = 9; // OTG
otg_descr.hnp_srp = 3; // HNP|SRP supported
// Copy OTG description
pos += size;
size = sizeof(ep_descr_t);
memcpy(&pConfDescr[pos], &otg_descr, size);
pos += size;
return pos;
}
UINT32 str_write(UINT8 *pStrDescr, UINT8 *pStr0, UINT8 *pStr1, UINT8 *pStr2)
{
int i;
UINT32 pos, size, strsize;
str_descr_hdr_t *pStrHdr;
UINT16 *pStr;
pos = 0;
size = sizeof(str_descr_hdr_t);
strsize = 2;
pStrHdr = (str_descr_hdr_t*)&pStrDescr[pos];
pStrHdr->size = size + strsize;
pStrHdr->type = 3;
pos += size;
pStr = (UINT16*)&pStrDescr[pos];
*pStr = 0x0409;
// String 0
pos += size;
size = sizeof(str_descr_hdr_t);
strsize = strlen(pStr0);
pStrHdr = (str_descr_hdr_t*)&pStrDescr[pos];
pStrHdr->size = sizeof(str_descr_hdr_t) + 2*strsize;
pStrHdr->type = 3;
pos += size;
size = 2*strsize;
pStr = (UINT16*)&pStrDescr[pos];
for (i=0; i < strsize; i++)
pStr[i] = (UINT16)pStr0[i];
// String 1
pos += size;
size = sizeof(str_descr_hdr_t);
strsize = strlen(pStr1);
pStrHdr = (str_descr_hdr_t*)&pStrDescr[pos];
pStrHdr->size = sizeof(str_descr_hdr_t) + 2*strsize;
pStrHdr->type = 3;
pos += size;
size = 2*strsize;
pStr = (UINT16*)&pStrDescr[pos];
for (i=0; i < strsize; i++)
pStr[i] = (UINT16)pStr1[i];
// String 2
pos += size;
size = sizeof(str_descr_hdr_t);
strsize = strlen(pStr2);
pStrHdr = (str_descr_hdr_t*)&pStrDescr[pos];
pStrHdr->size = sizeof(str_descr_hdr_t) + 2*strsize;
pStrHdr->type = 3;
pos += size;
size = 2*strsize;
pStr = (UINT16*)&pStrDescr[pos];
for (i=0; i < strsize; i++)
pStr[i] = (UINT16)pStr2[i];
pos += size;
return pos;
}
void ep0_func(void *pArg)
{
UINT32 result;
UINT16 buf[USB_MAX_IMG_SIZE/2], ep_cntres, ep_status, ep_count, tsize;
usb_irp_t *pIRP = (usb_irp_t*)pArg;
// printf("Callback with pArg = %8.8X\n", (UINT32)pArg);
ep_status = hpi_read_reg (SUSB2_REG_EP_STATUS0);
ep_cntres = hpi_read_reg (SUSB2_REG_EP_CNTRES0);
ep_count = hpi_read_reg (SUSB2_REG_EP_COUNT0);
if (ep_status & 0x10)
{
printf("Setup-flag detected. Status = %4.4X\n", ep_status);
}
}
void ep1_func(void *pArg)
{
UINT32 result;
UINT16 buf[USB_MAX_IMG_SIZE/2], ep_cntres, ep_status, ep_count, tsize;
usb_irp_t *pIRP = (usb_irp_t*)pArg;
// printf("Callback with pArg = %8.8X\n", (UINT32)pArg);
ep_status = hpi_read_reg (SUSB2_REG_EP_STATUS1);
ep_cntres = hpi_read_reg (SUSB2_REG_EP_CNTRES1);
ep_count = hpi_read_reg (SUSB2_REG_EP_COUNT1);
tsize = pIRP->tsize;
if (ep_status & 0x0020)
{
printf("Length exception result %4.4X with count = %d\n", ep_status, (INT16)ep_cntres);
if (ep_status & 0x0400)
tsize = (UINT16)((INT16)tsize - (INT16)ep_cntres);
if (ep_status & 0x0800)
tsize = (UINT16)((INT16)tsize - (INT16)ep_cntres);
}
result = hpi_read_ram(pIRP->cy_req.addr, buf, tsize);
usb_irp_enqueue(pIRP);
fifo_write(&pIRP->fifo, (UINT8*)buf, result, 0, FIFO_BLOCK);
// printf("Read %d bytes\n", result);
}
void ep2_func(void *pArg)
{
UINT32 result;
UINT16 buf[USB_MAX_IMG_SIZE/2], ep_cntres, ep_status, ep_count, tsize;
usb_irp_t *pIRP = (usb_irp_t*)pArg;
// printf("Callback with pArg = %8.8X\n", (UINT32)pArg);
ep_status = hpi_read_reg (SUSB2_REG_EP_STATUS2);
ep_cntres = hpi_read_reg (SUSB2_REG_EP_CNTRES2);
ep_count = hpi_read_reg (SUSB2_REG_EP_COUNT2);
tsize = pIRP->tsize;
if (ep_status & 0x0020)
{
printf("Length exception result %4.4X with count = %d\n", ep_status, (INT16)ep_cntres);
if (ep_status & 0x0400)
tsize = (UINT16)((INT16)tsize - (INT16)ep_cntres);
if (ep_status & 0x0800)
tsize = (UINT16)((INT16)tsize - (INT16)ep_cntres);
}
pIRP->tx_in_progress = 0;
result = fifo_read(&pIRP->fifo, (UINT8*)buf, pIRP->tsize, 0, FIFO_NONBLOCK);
if (!result)
return;
pIRP->cy_req.size = result;
hpi_write_ram(pIRP->cy_req.addr, (UINT16*)buf, result);
usb_irp_enqueue(pIRP);
// printf("Wrote %d bytes\n", result);
}
void rst_func(void *pArg)
{
volatile int *pLED = (int*)SYS_LED_PORT;
// printf("Callback with pArg = %8.8X\n", (UINT32)pArg);
sputs("SUSB_RST_MSG\n");
/// hpi_comm_reset();
_g_rst = 1;
*pLED = 0x40000000 + 1;
}
void sof_func(void *pArg)
{
volatile int *pLED = (int*)SYS_LED_PORT;
// printf("Callback with pArg = %8.8X\n", (UINT32)pArg);
sputs("SUSB_SOF_MSG\n");
*pLED = 0x40000000 + 2;
}
void cfg_func(void *pArg)
{
volatile int *pLED = (int*)SYS_LED_PORT;
cfg_inst_t *pCFG = (cfg_inst_t*)pArg;
usb_irp_t *pIRP_rx = (usb_irp_t*)pCFG->pIRP_rx;
usb_irp_t *pIRP_tx = (usb_irp_t*)pCFG->pIRP_tx;
// printf("Callback with pArg = %8.8X\n", (UINT32)pArg);
sputs("SUSB_CFG_MSG\n");
_g_cfg = 1;
usb_irp_enqueue(pIRP_rx);
fifo_flush(&pIRP_rx->fifo);
fifo_flush(&pIRP_tx->fifo);
pIRP_tx->tx_in_progress = 0;
*pLED = 0;
}
void sus_func(void *pArg)
{
volatile int *pLED = (int*)SYS_LED_PORT;
// printf("Callback with pArg = %8.8X\n", (UINT32)pArg);
sputs("SUSB_SUS_MSG\n");
*pLED = 0x40000000 + 3;
_g_sus = 1;
}
void id_func(void *pArg)
{
volatile int *pLED = (int*)SYS_LED_PORT;
// printf("Callback with pArg = %8.8X\n", (UINT32)pArg);
sputs("SUSB_ID_MSG\n");
*pLED = 0x40000000 + 4;
}
void vbus_func(void *pArg)
{
volatile int *pLED = (int*)SYS_LED_PORT;
// printf("Callback with pArg = %8.8X\n", (UINT32)pArg);
sputs("SUSB_VBUS_MSG\n");
*pLED = 0x40000000 + 5;
}
UINT32 usb_init_descr(void)
{
UINT32 result;
UINT16 buffer16[0x100];
UINT16 addr;
dev_descr_t dev_descr = {sizeof(dev_descr_t), 1, 0x0200, 0xFF, 0, 0, 8, 0x04B4, 0x7200, 0x0099, 1, 2, 3, 1};
ep_descr_t ep_descr[2] = {{sizeof(ep_descr_t), 5, 1, 2, 64, 0}, {sizeof(ep_descr_t), 5, 0x82, 2, 64, 0}};
// Set device descriptor
addr = 0xf516; // default
addr = 0xA00;
hpi_write_ram(addr, (UINT16*)&dev_descr, sizeof(dev_descr_t));
hpi_write_reg(2*SUSB2_DEVICE_DESCRIPTOR_VEC, addr);
// Set new configuration descriptor
// Write config and interface descriptor
result = conf_write((UINT8*)buffer16, sizeof(ep_descr)/sizeof(ep_descr_t), ep_descr);
addr = 0xf528; // default
addr = 0xB00;
hpi_write_ram(addr, (UINT16*)buffer16, result);
hpi_write_reg(2*SUSB2_CONFIGURATION_DESCRIPTOR_VEC, addr);
// Set string description
result = str_write((UINT8*)buffer16, "JDI Inc.", "JDI-USB (MIPS)", "311070");
addr = 0xf528; // default
addr = 0xC00;
hpi_write_ram(addr, (UINT16*)buffer16, result);
hpi_write_reg(2*SUSB2_STRING_DESCRIPTOR_VEC, addr);
return 0;
}
UINT32 usb_force_reconnect(UINT32 port)
{
UINT32 result;
UINT16 addr;
if (port >= USB_MAX_NUM_PORTS)
return -1;
if (port == 0)
{
// R1 = 0 : Full speed
// R2 = 1 : SIE1
addr = hpi_read_reg(SUSB1_REG_USBCTRL);
hpi_write_reg(SUSB1_REG_USBCTRL, addr | 0x0010);
result = hpi_comm_exec_int(SUSB_INIT_INT, 2, R1, 0, R2, 1);
hpi_write_reg(SUSB1_REG_USBCTRL, addr);
}
else
{
// R1 = 0 : Full speed
// R2 = 2 : SIE2
addr = hpi_read_reg(SUSB2_REG_USBCTRL);
hpi_write_reg(SUSB2_REG_USBCTRL, addr | 0x0010);
result = hpi_comm_exec_int(SUSB_INIT_INT, 2, R1, 0, R2, 2);
hpi_write_reg(SUSB2_REG_USBCTRL, addr);
}
return result;
}
UINT32 usb_recv(usb_irp_t *pObj, UINT8 *pData, UINT32 len, UINT32 timeout)
{
UINT32 result;
result = fifo_read(&pObj->fifo, pData, len, timeout, FIFO_BLOCK);
return result;
}
UINT32 usb_send(usb_irp_t *pObj, UINT8 *pData, UINT32 len, UINT32 timeout)
{
UINT32 result;
UINT8 buf[USB_MAX_IMG_SIZE];
// Fill-up FIFO
result = fifo_write(&pObj->fifo, pData, len, 0, FIFO_NONBLOCK);
if (!result)
return 0;
// Trigger TX
if (!pObj->tx_in_progress)
{
pObj->cy_req.size = fifo_read(&pObj->fifo, (UINT8*)buf, pObj->tsize, 0, FIFO_NONBLOCK);
hpi_write_ram(pObj->cy_req.addr, (UINT16*)buf, pObj->cy_req.size);
usb_irp_enqueue(pObj);
}
// If necessary, write rest to FIFO
result += fifo_write(&pObj->fifo, &pData[result], len - result, timeout, FIFO_BLOCK);
return result;
}
#define TEST_SIZE (2*1024*1024)
#define TRANSFER_SIZE 64
#define FLASH_IMAGE_SIZE (2*1024*1024)
int main(void)
{
int i;
UINT32 result, sync, cmd, len, buf_count, led_count, remain, tx_cnt, flash_offset;
UINT8 buffer8[2048];
UINT16 buffer16[0x2000];
UINT16 addr;
volatile UINT32 *pLED = (UINT32*)SYS_LED_PORT;
volatile UINT32 *pUART0_stat = (UINT32*)SYS_UART0_STAT;
UINT32 start, end;
UINT32 *pFlash32;
UINT8 *pFlash8;
UINT32 buffer32[16], *pBuf;
UINT64 *pBuf64;
usb_irp_t irp_rx, irp_tx;
fifo_t fifo_rx, fifo_tx;
cfg_inst_t cfg_inst;
flash_t flash;
volatile UINT32 *pVGA_ctrl = (UINT32*)SYS_VGA_CTRL;
volatile UINT32 *pVGA_moffs = (UINT32*)SYS_VGA_MOFFS;
_g_rst = 0;
_g_sus = 0;
_g_cfg = 0;
usb_init();
// enable EP#0 callback
usb_callback_register(1, SUSB_EP0_MSG, ep0_func, NULL);
// enable EP#1 callback
usb_irp_register(&irp_rx, 1, 1, TRANSFER_SIZE, 1);
usb_callback_register(1, SUSB_EP1_MSG, ep1_func, &irp_rx);
// enable EP#2 callback
usb_irp_register(&irp_tx, 1, 2, TRANSFER_SIZE, 0);
usb_callback_register(1, SUSB_EP2_MSG, ep2_func, &irp_tx);
usb_callback_register(1, SUSB_RST_MSG, rst_func, NULL);
usb_callback_register(1, SUSB_SOF_MSG, sof_func, NULL);
cfg_inst.pIRP_rx = &irp_rx;
cfg_inst.pIRP_tx = &irp_tx;
usb_callback_register(1, SUSB_CFG_MSG, cfg_func, &cfg_inst);
usb_callback_register(1, SUSB_SUS_MSG, sus_func, NULL);
usb_callback_register(1, SUSB_ID_MSG, id_func, NULL);
usb_callback_register(1, SUSB_VBUS_MSG, vbus_func, NULL);
printf("HPI-Test\n\n");
if (IS_ERROR(hpi_init()))
{
sputs("hpi_init(): error\n");
return 1;
}
printf("cy67k3_reset\n");
cy67k3_reset();
while(!_g_rst);
printf("hpi_comm_reset\n");
hpi_comm_reset();
while(!_g_sus);
printf("usb_init_descr\n");
usb_init_descr();
printf("hpi_comm_exec_int\n");
hpi_comm_exec_int(SUSB_INIT_INT, 2, R1, 0, R2, 2);
printf("usb_force_reconnect\n");
usb_force_reconnect(1);
while(!_g_cfg);
printf("USB-Ready\n");
printf("CY-Read..");
start = clock();
for (i=0; i < TEST_SIZE; i+=0x2000)
hpi_read_ram(0x2000, buffer16, 0x2000);
end = clock();
printf("done (%.2f Mbyte/s)\n", (double)TEST_SIZE/(1000*(end-start)));
printf("CY-Write..");
start = clock();
for (i=0; i < TEST_SIZE; i+=0x2000)
hpi_write_ram(0x2000, buffer16, 0x2000);
end = clock();
printf("done (%.2f Mbyte/s)\n", (double)TEST_SIZE/(1000*(end-start)));
sputs("HPI-Status : ");
print_word(cy67k3_read_HPI_STATUS());
sputs("\n");
sputs("HPI BP : ");
print_word(hpi_read_reg(HPI_REG_BP));
sputs("\n");
sputs("HPI IRR : ");
print_word(hpi_read_reg(HPI_REG_INTROUTE));
sputs("\n");
sputs("CPU Revision : ");
print_word(hpi_comm_read_ctrl_reg(USB_REG_REVISON));
sputs("\n");
hpi_comm_write_ctrl_reg(USB_REG_SPEED, 0x0000, LOGIC_DIRECT);
sputs("CPU Speed : ");
print_word(hpi_comm_read_ctrl_reg(USB_REG_SPEED));
sputs("\n");
// usb_init_descr();
// usb_force_reconnect(1);
// enable RX interrupt
*pUART0_stat |= (1 << 6);
interrupt_register(3, uart_handler);
interrupt_enable(3);
// Enable EP#1
hpi_write_reg(SUSB2_REG_EP_COUNT1, TRANSFER_SIZE);
hpi_write_reg(SUSB2_REG_EP_CTRL1, 2);
hpi_write_reg(SUSB2_REG_EP_CNTRES1, 0);
hpi_write_reg(SUSB2_REG_EP_STATUS1, 0);
// Enable EP#2
hpi_write_reg(SUSB2_REG_EP_COUNT2, TRANSFER_SIZE);
hpi_write_reg(SUSB2_REG_EP_CTRL2, 2);
hpi_write_reg(SUSB2_REG_EP_CNTRES2, 0);
hpi_write_reg(SUSB2_REG_EP_STATUS2, 0);
led_count = 0;
buf_count = 0;
pBuf64 = (UINT64*)malloc(FLASH_IMAGE_SIZE);
pBuf = (UINT32*)pBuf64;
*pVGA_moffs = (UINT32)pBuf64;
*pVGA_ctrl |= SYS_VGA_BIT_MSTEN;
if (IS_ERROR(flash_find(&flash, SYS_FLASH_IO)))
{
printf("Cannot find flash device. Exit now!\n");
return 1;
}
// Get flash offset by value of DIP-switch
flash_offset = flash_get_offset_by_blocknum(&flash, flash.info.nblocks-FLASH_IMAGE_SIZE/flash.info.blocksize);
printf("flash_offset: %08X\n", flash_offset);
pFlash32 = (UINT32*)(SYS_FLASH_IO + flash_offset);
pFlash8 = (UINT8*)pFlash32;
while(1)
{
switch (_g_uart_msg)
{
case '1':
_g_uart_msg = 0;
PrintDevRegs(1);
printf("\nSIEmsg1: %4.4X\n", hpi_read_reg(HPI_REG_SIE1MSG));
break;
case '2':
_g_uart_msg = 0;
PrintDevRegs(2);
printf("\nSIEmsg2: %4.4X\n", hpi_read_reg(HPI_REG_SIE2MSG));
break;
default:
break;
}
result = usb_recv(&irp_rx, (UINT8*)&sync, 4, 100);
if (!result)
continue;
*pLED = led_count++;
if (sync == 0xC24755AA)
{
printf("Sync found\n");
result = usb_recv(&irp_rx, (UINT8*)&cmd, 4, 1000);
if (!result)
continue;
result = usb_recv(&irp_rx, (UINT8*)&len, 4, 1000);
if (!result)
continue;
printf("Command %d with len %d found\n",cmd, len);
switch(cmd)
{
case 0x00000001:
result = usb_recv(&irp_rx, NULL, len, 1000);
if (result)
{
printf("Read %d bytes\n", result);
}
break;
case 0x00000002:
remain = len;
tx_cnt = 0;
while(remain)
{
len = sizeof(buffer8);
if (remain < len)
len = remain;
for (i=0; i < len; i++)
buffer8[i] = buf_count+i;
result = usb_send(&irp_tx, buffer8, len, 1000);
if (!result)
break;
tx_cnt += result;
remain -= result;
buf_count++;
}
printf("Wrote %d bytes\n", tx_cnt);
break;
case 0x00000003:
remain = len;
tx_cnt = 0;
while(remain)
{
len = 256;
if (remain < len)
len = remain;
result = usb_send(&irp_tx, (UINT8*)&pFlash8[tx_cnt], len, 1000);
if (!result)
break;
tx_cnt += result;
remain -= result;
buf_count++;
}
printf("Wrote %d bytes\n", tx_cnt);
break;
case 0x00000004:
*pVGA_ctrl &= ~SYS_VGA_BIT_MSTEN;
result = usb_recv(&irp_rx, (UINT8*)pBuf, len, 1000);
if (result)
{
printf("Read %d bytes\n", result);
}
len = result;
if (len > FLASH_IMAGE_SIZE)
{
printf("Cannot write flash: image to large!\n");
break;
}
printf("Flash erase...");
result = flash_erase(&flash, flash_offset, len);
if (IS_ERROR(result))
{
printf("failed (%08X)\n", result);
break;
}
printf("done\n");
printf("Flash write...");
result = flash_program(&flash, flash_offset, (UINT8*)pBuf, len);
if (IS_ERROR(result))
{
printf("failed (%08X)\n", result);
break;
}
printf("done\n");
printf("Flash verify...");
result = flash_verify(&flash, flash_offset, (UINT8*)pBuf, len);
if (IS_ERROR(result))
{
printf("failed (%08X)\n", result);
break;
}
printf("passed\n");
*pVGA_ctrl |= SYS_VGA_BIT_MSTEN;
break;
case 0x000000FF:
usb_force_reconnect(1);
break;
default:
break;
}
}
}
return 0;
}
// pMem = (UINT8*)0x40000000;
// result = fifo_write(&fifo_tx, pMem, 640, 0, FIFO_NONBLOCK);
// pMem += result;
// usb_irp_enqueue(&irp_tx);