* [PATCH] scripts: imx-usb-loader: implement DCD v2 check command
@ 2017-02-19 18:57 Alexander Kurz
2017-02-22 8:26 ` Sascha Hauer
0 siblings, 1 reply; 2+ messages in thread
From: Alexander Kurz @ 2017-02-19 18:57 UTC (permalink / raw)
To: barebox; +Cc: Alexander Kurz
The DCD v2 check command supported by i.MX53 and later SoC polls a given
memory location as long as a given condition is true.
Enable imx-usb-loader to perform this check. When the timeout is hit,
imx-usb-loader returns an error. For practical reasons the timeout
computation will differ from the native implementation, since performing
check commands via USB will be much slower compared to native processing.
Signed-off-by: Alexander Kurz <akurz@blala.de>
---
scripts/imx/imx-usb-loader.c | 95 +++++++++++++++++++++++++++++++++++++++++++-
scripts/imx/imx.h | 16 ++++++++
2 files changed, 109 insertions(+), 2 deletions(-)
diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 9de7bb3..4105ade 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -798,6 +798,98 @@ static int do_dcd_v2_cmd_write(const unsigned char *dcd)
return 0;
}
+static int do_dcd_v2_cmd_check(const unsigned char *dcd)
+{
+ uint32_t mask;
+ uint32_t poll_count = 0;
+ int bytes;
+ enum imx_dcd_v2_check_cond cond;
+ struct imx_dcd_v2_check *check = (struct imx_dcd_v2_check *) dcd;
+ switch (ntohs(check->length)) {
+ case 12:
+ /* poll indefinitely */
+ poll_count = 0xffffffff;
+ break;
+ case 16:
+ poll_count = ntohl(check->count);
+ if (poll_count == 0)
+ /* this command behaves as for NOP */
+ return 0;
+ break;
+ default:
+ fprintf(stderr, "Error: invalid DCD check length\n");
+ return -1;
+ }
+
+ switch (check->param & 7) {
+ case 1:
+ case 2:
+ case 4:
+ bytes = check->param & 7;
+ break;
+ default:
+ fprintf(stderr, "Error: invalid DCD check size\n");
+ return -1;
+ }
+
+ switch ((check->param & 0xf8) >> 3) {
+ case check_all_bits_clear:
+ case check_all_bits_set:
+ case check_any_bit_clear:
+ case check_any_bit_set:
+ cond = (check->param & 0xf8) >> 3;
+ break;
+ default:
+ fprintf(stderr, "Error: invalid DCD check condition\n");
+ return -1;
+ }
+
+ mask = ntohl(check->mask);
+
+ fprintf(stderr, "DCD check condition %i on address 0x%x\n",
+ cond, ntohl(check->addr));
+ /* Reduce the poll count to some arbitrary practical limit.
+ Polling via SRP commands will be much slower compared to
+ polling when DCD is interpreted by the SOC microcode.
+ */
+ if (poll_count > 1000)
+ poll_count = 1000;
+
+ while (poll_count > 0) {
+ uint32_t data = 0;
+ int ret = read_memory(ntohl(check->addr), &data, bytes);
+ if (ret < 0)
+ return ret;
+
+ data &= mask;
+
+ switch (cond) {
+ case check_all_bits_clear:
+ if (data != 0)
+ return 0;
+ break;
+ case check_all_bits_set:
+ if (data != mask)
+ return 0;
+ break;
+ case check_any_bit_clear:
+ if (data == mask)
+ return 0;
+ break;
+ case check_any_bit_set:
+ if (data == 0)
+ return 0;
+ break;
+ }
+ poll_count--;
+ }
+
+ fprintf(stderr, "Error: timeout waiting for DCD check condition %i "
+ "on address 0x%08x to match 0x%08x\n", cond,
+ ntohl(check->addr), ntohl(check->mask));
+ return -1;
+}
+
static int process_dcd_table_ivt(const struct imx_flash_header_v2 *hdr,
const unsigned char *file_start, unsigned cnt)
{
@@ -850,8 +942,7 @@ static int process_dcd_table_ivt(const struct imx_flash_header_v2 *hdr,
ret = do_dcd_v2_cmd_write(dcd);
break;
case TAG_CHECK:
- fprintf(stderr, "DCD check not implemented yet\n");
- usleep(50000);
+ ret = do_dcd_v2_cmd_check(dcd);
break;
case TAG_UNLOCK:
fprintf(stderr, "DCD unlock not implemented yet\n");
diff --git a/scripts/imx/imx.h b/scripts/imx/imx.h
index 57c7525..f32ae52 100644
--- a/scripts/imx/imx.h
+++ b/scripts/imx/imx.h
@@ -95,4 +95,20 @@ struct imx_dcd_v2_write {
struct imx_dcd_v2_write_rec data[MAX_RECORDS_DCD_V2];
} __attribute__((packed));
+struct imx_dcd_v2_check {
+ uint8_t tag;
+ uint16_t length;
+ uint8_t param;
+ uint32_t addr;
+ uint32_t mask;
+ uint32_t count;
+} __attribute__((packed));
+
+enum imx_dcd_v2_check_cond {
+ check_all_bits_clear = 0,
+ check_all_bits_set = 1,
+ check_any_bit_clear = 2,
+ check_any_bit_set = 3,
+} __attribute__((packed));
+
int parse_config(struct config_data *data, const char *filename);
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] scripts: imx-usb-loader: implement DCD v2 check command
2017-02-19 18:57 [PATCH] scripts: imx-usb-loader: implement DCD v2 check command Alexander Kurz
@ 2017-02-22 8:26 ` Sascha Hauer
0 siblings, 0 replies; 2+ messages in thread
From: Sascha Hauer @ 2017-02-22 8:26 UTC (permalink / raw)
To: Alexander Kurz; +Cc: barebox
On Sun, Feb 19, 2017 at 07:57:58PM +0100, Alexander Kurz wrote:
> The DCD v2 check command supported by i.MX53 and later SoC polls a given
> memory location as long as a given condition is true.
> Enable imx-usb-loader to perform this check. When the timeout is hit,
> imx-usb-loader returns an error. For practical reasons the timeout
> computation will differ from the native implementation, since performing
> check commands via USB will be much slower compared to native processing.
>
> Signed-off-by: Alexander Kurz <akurz@blala.de>
Nice work. Applied, thanks
Sascha
> ---
> scripts/imx/imx-usb-loader.c | 95 +++++++++++++++++++++++++++++++++++++++++++-
> scripts/imx/imx.h | 16 ++++++++
> 2 files changed, 109 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
> index 9de7bb3..4105ade 100644
> --- a/scripts/imx/imx-usb-loader.c
> +++ b/scripts/imx/imx-usb-loader.c
> @@ -798,6 +798,98 @@ static int do_dcd_v2_cmd_write(const unsigned char *dcd)
> return 0;
> }
>
> +static int do_dcd_v2_cmd_check(const unsigned char *dcd)
> +{
> + uint32_t mask;
> + uint32_t poll_count = 0;
> + int bytes;
> + enum imx_dcd_v2_check_cond cond;
> + struct imx_dcd_v2_check *check = (struct imx_dcd_v2_check *) dcd;
> + switch (ntohs(check->length)) {
> + case 12:
> + /* poll indefinitely */
> + poll_count = 0xffffffff;
> + break;
> + case 16:
> + poll_count = ntohl(check->count);
> + if (poll_count == 0)
> + /* this command behaves as for NOP */
> + return 0;
> + break;
> + default:
> + fprintf(stderr, "Error: invalid DCD check length\n");
> + return -1;
> + }
> +
> + switch (check->param & 7) {
> + case 1:
> + case 2:
> + case 4:
> + bytes = check->param & 7;
> + break;
> + default:
> + fprintf(stderr, "Error: invalid DCD check size\n");
> + return -1;
> + }
> +
> + switch ((check->param & 0xf8) >> 3) {
> + case check_all_bits_clear:
> + case check_all_bits_set:
> + case check_any_bit_clear:
> + case check_any_bit_set:
> + cond = (check->param & 0xf8) >> 3;
> + break;
> + default:
> + fprintf(stderr, "Error: invalid DCD check condition\n");
> + return -1;
> + }
> +
> + mask = ntohl(check->mask);
> +
> + fprintf(stderr, "DCD check condition %i on address 0x%x\n",
> + cond, ntohl(check->addr));
> + /* Reduce the poll count to some arbitrary practical limit.
> + Polling via SRP commands will be much slower compared to
> + polling when DCD is interpreted by the SOC microcode.
> + */
> + if (poll_count > 1000)
> + poll_count = 1000;
> +
> + while (poll_count > 0) {
> + uint32_t data = 0;
> + int ret = read_memory(ntohl(check->addr), &data, bytes);
> + if (ret < 0)
> + return ret;
> +
> + data &= mask;
> +
> + switch (cond) {
> + case check_all_bits_clear:
> + if (data != 0)
> + return 0;
> + break;
> + case check_all_bits_set:
> + if (data != mask)
> + return 0;
> + break;
> + case check_any_bit_clear:
> + if (data == mask)
> + return 0;
> + break;
> + case check_any_bit_set:
> + if (data == 0)
> + return 0;
> + break;
> + }
> + poll_count--;
> + }
> +
> + fprintf(stderr, "Error: timeout waiting for DCD check condition %i "
> + "on address 0x%08x to match 0x%08x\n", cond,
> + ntohl(check->addr), ntohl(check->mask));
> + return -1;
> +}
> +
> static int process_dcd_table_ivt(const struct imx_flash_header_v2 *hdr,
> const unsigned char *file_start, unsigned cnt)
> {
> @@ -850,8 +942,7 @@ static int process_dcd_table_ivt(const struct imx_flash_header_v2 *hdr,
> ret = do_dcd_v2_cmd_write(dcd);
> break;
> case TAG_CHECK:
> - fprintf(stderr, "DCD check not implemented yet\n");
> - usleep(50000);
> + ret = do_dcd_v2_cmd_check(dcd);
> break;
> case TAG_UNLOCK:
> fprintf(stderr, "DCD unlock not implemented yet\n");
> diff --git a/scripts/imx/imx.h b/scripts/imx/imx.h
> index 57c7525..f32ae52 100644
> --- a/scripts/imx/imx.h
> +++ b/scripts/imx/imx.h
> @@ -95,4 +95,20 @@ struct imx_dcd_v2_write {
> struct imx_dcd_v2_write_rec data[MAX_RECORDS_DCD_V2];
> } __attribute__((packed));
>
> +struct imx_dcd_v2_check {
> + uint8_t tag;
> + uint16_t length;
> + uint8_t param;
> + uint32_t addr;
> + uint32_t mask;
> + uint32_t count;
> +} __attribute__((packed));
> +
> +enum imx_dcd_v2_check_cond {
> + check_all_bits_clear = 0,
> + check_all_bits_set = 1,
> + check_any_bit_clear = 2,
> + check_any_bit_set = 3,
> +} __attribute__((packed));
> +
> int parse_config(struct config_data *data, const char *filename);
> --
> 2.1.4
>
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-02-22 8:27 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-19 18:57 [PATCH] scripts: imx-usb-loader: implement DCD v2 check command Alexander Kurz
2017-02-22 8:26 ` Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox