diff options
-rw-r--r-- | cf-code/cf-fsi-fw.S | 76 | ||||
-rw-r--r-- | cf-fsi-fw.h | 85 | ||||
-rw-r--r-- | cf-fsi-test.c | 38 |
3 files changed, 122 insertions, 77 deletions
diff --git a/cf-code/cf-fsi-fw.S b/cf-code/cf-fsi-fw.S index aa6a388..b771b79 100644 --- a/cf-code/cf-fsi-fw.S +++ b/cf-code/cf-fsi-fw.S @@ -161,13 +161,37 @@ _vecs: .endr /* - * Main entry point + * Header info */ .org 0x400 +_header_info: + .short SYS_SIG /* 0x00 */ + .short FW_VERSION /* 0x02 */ + .byte API_VERSION_MAJ /* 0x04 */ + .byte API_VERSION_MIN /* 0x05 */ + .byte 0,0 /* 0x06 pad */ +#ifdef ENABLE_TRACE + .long FW_OPTION_TRACE_EN /* 0x08 */ +#else + .long 0 +#endif + + /* + * Config area + */ + .org 0x400 + HDR_CMD_STAT_AREA +_cmd_stat_base: + .long SRAM_BASE_BE + + /* + * Main entry point + */ + .org 0x500 .global _start _start: /* Get base addresses */ - movea.l #SRAM_BASE_BE,%a1 + lea %pc@(_cmd_stat_base),%a0 + movea.l %a0@(0),%a1 movea.l #GPIO_BASE,%a4 movea.l %a4,%a5 add.l #CLOCK_GPIO_VREG,%a5 @@ -240,18 +264,8 @@ _start: /* Configure GPIOs to output */ bsr config_gpio_out - /* Populate version & signature */ - move.w #SYS_SIG,%a1@(SYS_SIG_REG) - move.b #FW_VERSION,%a1@(FW_VERS_REG) - - /* This must happen last as it's the signal to the host - * that we are ready - */ -#ifdef ENABLE_TRACE - move.b #(API_VERSION + API_VERSION_TRACE_EN),%a1@(API_VERS_REG) -#else - move.b #API_VERSION,%a1@(API_VERS_REG) -#endif + /* Mark command complete, indicates we are ready */ + move.b #STAT_COMPLETE,%a1@(CMD_STAT_REG) /* * Main command loop @@ -266,7 +280,7 @@ main_loop: */ 1: move.b %a1@(ARB_REG),%d2 bne arbitration_request - move.l %a1@(CMD_REG),%d2 + move.l %a1@(CMD_STAT_REG),%d2 tst.b %d2 bne command_request stop #0x2000 @@ -301,11 +315,9 @@ command_request: /* Mask interrupts */ move.w #0x2007,%sr - /* Mark ourselves as sending a command */ - move.b #STAT_SENDING,%a1@(STAT_REG) - - /* Clear command register */ - move.b #CMD_NONE,%a1@(CMD_REG + 3) + /* Clear the command/status register */ + moveq.l #0,%d0 + move.l %d0,%a1@(CMD_STAT_REG) /* Start command ? */ cmpi.b #CMD_COMMAND,%d2 @@ -320,7 +332,7 @@ command_request: beq start_idle_clocks /* Error */ - move.b #STAT_ERR_INVAL_CMD,%a1@(STAT_REG) + move.b #STAT_ERR_INVAL_CMD,%a1@(CMD_STAT_REG) bra main_loop /* @@ -389,7 +401,7 @@ start_command: beq 1f subq.l #1,%d3 bne 0b - move.b #STAT_ERR_MTOE,%a1@(STAT_REG) + move.b #STAT_ERR_MTOE,%a1@(CMD_STAT_REG) bra send_delay 1: /* Got start bit, clock in slave ID and response tag */ @@ -454,7 +466,9 @@ start_command: move.b %d4,%a1@(STAT_RCRC) /* Mark command complete */ - move.b #STAT_COMPLETE,%a1@(STAT_REG) + moveq.l #STAT_COMPLETE,%d0 + byterev %d0 + move.l %d0,%a1@(CMD_STAT_REG) send_delay: /* Send delay after every command */ @@ -485,8 +499,11 @@ start_break: move.l #FSI_POST_BREAK_CLOCKS,%d3 clock_out_zeros %d3 - /* That's it */ - move.b #STAT_COMPLETE,%a1@(STAT_REG) + /* Mark command complete */ + moveq.l #STAT_COMPLETE,%d0 + byterev %d0 + move.l %d0,%a1@(CMD_STAT_REG) + bra main_loop start_idle_clocks: @@ -498,8 +515,11 @@ start_idle_clocks: move.b %d2,%d3 clock_out_zeros %d3 - /* That's it */ - move.b #STAT_COMPLETE,%a1@(STAT_REG) + /* Mark command complete */ + moveq.l #STAT_COMPLETE,%d0 + byterev %d0 + move.l %d0,%a1@(CMD_STAT_REG) + bra main_loop config_gpio_out: @@ -549,7 +569,7 @@ bad_exception: sub.l %d1,%d0 lsr.l #2,%d0 move.b %d0,%a1@(BAD_INT_VEC) - move.b #STAT_ERR_INVAL_IRQ,%a1@(STAT_REG) + move.b #STAT_ERR_INVAL_IRQ,%a1@(CMD_STAT_REG) halt /* Bad exception stubs */ diff --git a/cf-fsi-fw.h b/cf-fsi-fw.h index 4942901..0c4453f 100644 --- a/cf-fsi-fw.h +++ b/cf-fsi-fw.h @@ -2,16 +2,52 @@ #define __CF_FSI_FW_H /* - * SRAM layout: Main part + * uCode file layout + * + * 0000...03ff : m68k exception vectors + * 0400...04ff : Header info & boot config block + * 0500....... : Code & stack */ -/* Command register: +/* + * Header info & boot config area + * + * The Header info is built into the ucode and provide version and + * platform information. + * + * the Boot config needs to be adjusted by the ARM prior to starting + * the ucode if the Command/Status area isn't at 0x320000 in CF space + * (ie. beginning of SRAM). + */ + +#define HDR_OFFSET 0x400 + +/* Info: Signature & version */ +#define HDR_SYS_SIG 0x00 /* 2 bytes system signature */ +#define SYS_SIG_ROMULUS 0x526d /* 'Rm' */ +#define SYS_SIG_WITHERSPOON 0x5773 /* 'Ws' */ +#define HDR_FW_VERS 0x02 /* 2 bytes Major.Minor */ +#define HDR_API_VERS 0x04 /* 2 bytes Major.Minor */ +#define API_VERSION_MAJ 1 /* Current version */ +#define API_VERSION_MIN 1 +#define HDR_FW_OPTIONS 0x08 /* 4 bytes option flags */ +#define FW_OPTION_TRACE_EN 0x00000001 /* FW tracing enabled */ + +/* Boot Config: Address of Command/Status area */ +#define HDR_CMD_STAT_AREA 0x80 /* 4 bytes CF address */ + +/* + * Command/Status area layout: Main part + */ + +/* Command/Status register: * * +---------------------------+ - * | rsvd | RLEN | CLEN | CMD | + * | STAT | RLEN | CLEN | CMD | * | 8 | 8 | 8 | 8 | * +---------------------------+ - * | | | + * | | | | + * status | | | * Response len | | * (in bits) | | * | | @@ -19,8 +55,11 @@ * (in bits) | * | * Command code + * + * Due to the big endian layout, that means that a byte read will + * return the status byte */ -#define CMD_REG 0x00 +#define CMD_STAT_REG 0x00 #define CMD_REG_CMD_MASK 0x000000ff #define CMD_REG_CMD_SHIFT 0 #define CMD_NONE 0x00 @@ -32,40 +71,24 @@ #define CMD_REG_CLEN_SHIFT 8 #define CMD_REG_RLEN_MASK 0x00ff0000 #define CMD_REG_RLEN_SHIFT 16 +#define CMD_REG_STAT_MASK 0xff000000 +#define CMD_REG_STAT_SHIFT 24 +#define STAT_WORKING 0x00 +#define STAT_COMPLETE 0x01 +#define STAT_ERR_INVAL_CMD 0x80 +#define STAT_ERR_INVAL_IRQ 0x81 +#define STAT_ERR_MTOE 0x82 -/* Status register - * - */ -#define STAT_REG 0x04 /* Status */ -#define STAT_STOPPED 0x00 -#define STAT_SENDING 0x01 -#define STAT_COMPLETE 0x02 -#define STAT_ERR_INVAL_CMD 0x80 -#define STAT_ERR_INVAL_IRQ 0x81 -#define STAT_ERR_MTOE 0x82 - -/* Response tag */ -#define STAT_RTAG 0x05 +/* Response tag & CRC */ +#define STAT_RTAG 0x04 /* Response CRC */ -#define STAT_RCRC 0x06 +#define STAT_RCRC 0x05 /* Echo and Send delay */ #define ECHO_DLY_REG 0x08 #define SEND_DLY_REG 0x09 -/* Signature & version */ -#define SYS_SIG_REG 0x0c /* 2 bytes system signature */ -#define SYS_SIG_ROMULUS 0x526d /* 'Rm' */ -#define SYS_SIG_WITHERSPOON 0x5773 /* 'Ws' */ -#define FW_VERS_REG 0x0e -#define API_VERS_REG 0x0f - -/* Current API version */ -#define API_VERSION_MASK 0x7f -#define API_VERSION 1 -#define API_VERSION_TRACE_EN 0x80 - /* Command data area * * Last byte of message must be left aligned diff --git a/cf-fsi-test.c b/cf-fsi-test.c index ef9435b..bf209f3 100644 --- a/cf-fsi-test.c +++ b/cf-fsi-test.c @@ -222,12 +222,26 @@ static void start_cf(void) static void load_cf_code(void) { extern uint8_t cf_code_start, cf_code_end; + uint16_t sig, fw_vers, api_vers; + uint32_t fw_options; uint8_t *code = &cf_code_start; uint8_t *mem = cfmem; while(code < &cf_code_end) writeb(*(code++), mem++); + + sig = ntohs(readw(cfmem + HDR_OFFSET + HDR_SYS_SIG)); + fw_vers = ntohs(readw(cfmem + HDR_OFFSET + HDR_FW_VERS)); + api_vers = ntohs(readw(cfmem + HDR_OFFSET + HDR_API_VERS)); + fw_options = ntohl(readl(cfmem + HDR_OFFSET + HDR_FW_OPTIONS)); + + trace_enabled = !!(fw_options & FW_OPTION_TRACE_EN); + + printf("SYS_SIG=%.4x FW_VERSION=%d API_VERSION=%d.%d (trace %s)\n", + sig, fw_vers, api_vers >> 8, api_vers & 0xff, + trace_enabled ? "enabled" : "disabled"); + } static void gpio_source_arm(void) @@ -544,9 +558,8 @@ static void dump_stuff(void) { int i; - printf("CMD:%08x STAT:%02x RTAG=%02x RCRC=%02x RDATA=%02x #INT=%08x\n", - ntohl(readl(sysreg + SRAM_BASE + CMD_REG)), - readb(sysreg + SRAM_BASE + STAT_REG), + printf("CMD:%08x RTAG=%02x RCRC=%02x RDATA=%02x #INT=%08x\n", + ntohl(readl(sysreg + SRAM_BASE + CMD_STAT_REG)), readb(sysreg + SRAM_BASE + STAT_RTAG), readb(sysreg + SRAM_BASE + STAT_RCRC), ntohl(readl(sysreg + SRAM_BASE + RSP_DATA)), @@ -564,11 +577,8 @@ static int do_command(uint32_t op) uint32_t timeout = 100000; uint8_t stat; - /* Clear status reg */ - writeb(0, sysreg + SRAM_BASE + STAT_REG); - /* Send command */ - writel(htonl(op), sysreg + SRAM_BASE + CMD_REG); + writel(htonl(op), sysreg + SRAM_BASE + CMD_STAT_REG); /* Ring doorbell */ writel(0x2, sysreg + CVIC_BASE + CVIC_TRIG_REG); @@ -581,7 +591,7 @@ static int do_command(uint32_t op) dump_stuff(); return -ETIMEDOUT; } - stat = readb(sysreg + SRAM_BASE + STAT_REG); + stat = readb(sysreg + SRAM_BASE + CMD_STAT_REG); } while(stat < STAT_COMPLETE || stat == 0xff); if (stat == STAT_COMPLETE) @@ -738,19 +748,11 @@ int main(int argc, char *argv[]) /* Start ColdFire */ start_cf(); - /* Wait for ack API version register*/ + /* Wait for status register to say command complete */ do { - val = readb(sysreg + SRAM_BASE + API_VERS_REG); + val = readb(sysreg + SRAM_BASE + CMD_STAT_REG); } while (val == 0x00); - trace_enabled = !!(val & API_VERSION_TRACE_EN); - - printf("SYS_SIG=%.4x FW_VERSION=%d API_VERSION=%d (trace %s)\n", - ntohs(readw(sysreg + SRAM_BASE + SYS_SIG_REG)), - readb(sysreg + SRAM_BASE + FW_VERS_REG), - val & API_VERSION_MASK, - trace_enabled ? "enabled" : "disabled"); - /* Configure echo & send delay */ writeb(16, sysreg + SRAM_BASE + ECHO_DLY_REG); writeb(16, sysreg + SRAM_BASE + SEND_DLY_REG); |