summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-06-11 18:27:44 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-06-11 20:29:47 +1000
commit2afecf01ee2e948176124f917b5c000fdf95c41b (patch)
tree86f1e753bd9e3c10d7676fdfb5e9d8828ca04863
parent28f10b0fd0f638662f88a221d81e7e8e8c40e5c0 (diff)
downloadcf-fsi-2afecf01ee2e948176124f917b5c000fdf95c41b.tar.gz
cf-fsi-2afecf01ee2e948176124f917b5c000fdf95c41b.zip
Rework interfaces
We now use a portion of the ucode itself for version information and to configure the base of SRAM, this will allow the driver to use a pool allocator with less constraints. We put the status register as part of the command register, this speeds things up a bit and remove the need to clear it from the host. We also turn some SRAM stores from byte to long stores, they seem to be faster (still room for improvement) Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--cf-code/cf-fsi-fw.S76
-rw-r--r--cf-fsi-fw.h85
-rw-r--r--cf-fsi-test.c38
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);
OpenPOWER on IntegriCloud