Commit f4c3d2a0 authored by Marek Vasut's avatar Marek Vasut

mxssb: Implement DCD check and NOOP commands

Implement the remaining documented DCD commands so we have a complete
support for this. The check command tests memory area in a loop and
the NOOP command does nothing.
Signed-off-by: Marek Vasut's avatarMarek Vasut <marex@denx.de>
parent ab2a63b5
......@@ -127,6 +127,27 @@ These semantics and rules will be outlined now.
- Read the "u32_address", perform a bitwise-AND with the complement of
"u32_value" and write the result back to "u32_address".
EQZ.n u32_address u32_count
- Read the "u32_address" at most "u32_count" times and test if the value
read is zero. If it is, break the loop earlier.
NEZ.n u32_address u32_count
- Read the "u32_address" at most "u32_count" times and test if the value
read is non-zero. If it is, break the loop earlier.
EQ.n u32_address u32_mask
- Read the "u32_address" in a loop and test if the result masked with
"u32_mask" equals the "u32_mask". If the values are equal, break the
reading loop.
NEQ.n u32_address u32_mask
- Read the "u32_address" in a loop and test if the result masked with
"u32_mask" does not equal the "u32_mask". If the values are not equal,
break the reading loop.
NOOP
- This instruction does nothing.
- If the verbose output from the BootROM is enabled by passing the "-v" option
to MXSSB, the BootROM will produce a letter on the Debug UART for each
instruction it started processing. Here is a mapping between the above
......
......@@ -50,6 +50,21 @@ enum sb_dcd_cmd {
SB_DCD_ORR1 = 0xcc000019, /* Addr.1 |= Value.1 */
SB_DCD_ORR2 = 0xcc00001a, /* Addr.2 |= Value.2 */
SB_DCD_ORR4 = 0xcc00001c, /* Addr.4 |= Value.4 */
SB_DCD_CHK_EQZ1 = 0xcf000001, /* (Addr.1 & Value.1) == 0 */
SB_DCD_CHK_EQZ2 = 0xcf000002, /* (Addr.2 & Value.2) == 0 */
SB_DCD_CHK_EQZ4 = 0xcf000004, /* (Addr.4 & Value.4) == 0 */
SB_DCD_CHK_EQ1 = 0xcf000011, /* (Addr.1 & Value.1) == Value.1 */
SB_DCD_CHK_EQ2 = 0xcf000012, /* (Addr.2 & Value.2) == Value.2 */
SB_DCD_CHK_EQ4 = 0xcf000014, /* (Addr.4 & Value.4) == Value.4 */
SB_DCD_CHK_NEQ1 = 0xcf000009, /* (Addr.1 & Value.1) != Value.1 */
SB_DCD_CHK_NEQ2 = 0xcf00000a, /* (Addr.2 & Value.2) != Value.2 */
SB_DCD_CHK_NEQ4 = 0xcf00000c, /* (Addr.4 & Value.4) != Value.4 */
SB_DCD_CHK_NEZ1 = 0xcf000019, /* (Addr.1 & Value.1) != 0 */
SB_DCD_CHK_NEZ2 = 0xcf00001a, /* (Addr.2 & Value.2) != 0 */
SB_DCD_CHK_NEZ4 = 0xcf00001c, /* (Addr.4 & Value.4) != 0 */
SB_DCD_NOOP = 0xc0000000, /* NOP */
};
struct sb_dcd_ctx {
......@@ -664,12 +679,23 @@ static int sb_build_dcd_block(struct sb_image_ctx *ictx,
struct sb_dcd_ctx *dctx = ictx->dcd_tail;
uint32_t *dcd;
if (dctx->prev_dcd_head &&
if (dctx->prev_dcd_head && (type != SB_DCD_NOOP) &&
((dctx->prev_dcd_head[0] & 0xff0000ff) == type)) {
/* Same instruction as before, just append it. */
ret = sb_grow_dcd(dctx, 8);
if (ret)
return ret;
} else if (type == SB_DCD_NOOP) {
ret = sb_grow_dcd(dctx, 4);
if (ret)
return ret;
/* Update DCD command block pointer. */
dctx->prev_dcd_head = dctx->payload +
dctx->size / sizeof(*dctx->payload) - 1;
/* NOOP has only 4 bytes and no payload. */
goto noop;
} else {
/*
* Either a different instruction block started now
......@@ -725,6 +751,7 @@ static int sb_build_dcd_block(struct sb_image_ctx *ictx,
dcd[0] = htonl(address);
dcd[1] = htonl(value);
noop:
/* Update the DCD command block. */
length = dctx->size -
((dctx->prev_dcd_head - dctx->payload) * sizeof(*dctx->payload));
......@@ -1533,6 +1560,32 @@ static int sb_parse_line(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_ORR2);
else if (ictx->in_dcd && !strcmp(tok, "ORR.4"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_ORR4);
else if (ictx->in_dcd && !strcmp(tok, "EQZ.1"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_EQZ1);
else if (ictx->in_dcd && !strcmp(tok, "EQZ.2"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_EQZ2);
else if (ictx->in_dcd && !strcmp(tok, "EQZ.4"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_EQZ4);
else if (ictx->in_dcd && !strcmp(tok, "EQ.1"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_EQ1);
else if (ictx->in_dcd && !strcmp(tok, "EQ.2"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_EQ2);
else if (ictx->in_dcd && !strcmp(tok, "EQ.4"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_EQ4);
else if (ictx->in_dcd && !strcmp(tok, "NEQ.1"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_NEQ1);
else if (ictx->in_dcd && !strcmp(tok, "NEQ.2"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_NEQ2);
else if (ictx->in_dcd && !strcmp(tok, "NEQ.4"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_NEQ4);
else if (ictx->in_dcd && !strcmp(tok, "NEZ.1"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_NEZ1);
else if (ictx->in_dcd && !strcmp(tok, "NEZ.2"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_NEZ2);
else if (ictx->in_dcd && !strcmp(tok, "NEZ.4"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_CHK_NEZ4);
else if (ictx->in_dcd && !strcmp(tok, "NOOP"))
ret = sb_build_dcd_block(ictx, cmd, SB_DCD_NOOP);
else {
fprintf(stderr, "#%i ERR: Unsupported instruction '%s'!\n",
cmd->lineno, tok);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment