target/arm_adi_v5: rework Nuvoton NPCX quirk workaround. 75/7575/3
authorTomas Vanek <vanekt@fbl.cz>
Sun, 2 Apr 2023 16:49:12 +0000 (18:49 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 6 Jan 2024 13:56:02 +0000 (13:56 +0000)
Prevent packed writes with Nuvoton NPCX quirks because the workaround
uses all byte lanes for one byte or halfword and thus precludes packing.

Eliminate quirk code for size 4 as it is equivalent to the common code.

Make the quirk code for sizes 2 and 1 easier readable.

Change-Id: I72324e56a49b4712bd3769e03dce01427d9fcd73
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/7575
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
src/target/arm_adi_v5.c

index 6998577731602abb51f06b131b2c384533dad2d1..0f1e648a9e103acbb75f1f833095758f090f1086 100644 (file)
@@ -376,6 +376,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
 
                /* Select packed transfer if possible */
                if (addrinc && ap->packed_transfers && nbytes >= 4
+                               && !dap->nu_npcx_quirks
                                && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {
                        this_size = 4;
                        retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED);
@@ -394,25 +395,28 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
                 * depends on the type of transfer and alignment. See ARM document IHI0031C. */
                uint32_t outvalue = 0;
                uint32_t drw_byte_idx = address;
-               if (dap->nu_npcx_quirks) {
+               if (dap->nu_npcx_quirks && this_size <= 2) {
                        switch (this_size) {
-                       case 4:
-                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3);
-                               break;
                        case 2:
-                               outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3);
-                               outvalue |= (uint32_t)*(buffer+1) << 8 * (drw_byte_idx++ & 3);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3);
+                               {
+                                       /* Alternate low and high byte to all byte lanes */
+                                       uint32_t low = *buffer++;
+                                       uint32_t high = *buffer++;
+                                       outvalue |= low << 8 * (drw_byte_idx++ & 3);
+                                       outvalue |= high << 8 * (drw_byte_idx++ & 3);
+                                       outvalue |= low << 8 * (drw_byte_idx++ & 3);
+                                       outvalue |= high << 8 * (drw_byte_idx & 3);
+                               }
                                break;
                        case 1:
-                               outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3);
-                               outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3);
-                               outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3);
+                               {
+                                       /* Mirror output byte to all byte lanes */
+                                       uint32_t data = *buffer++;
+                                       outvalue |= data;
+                                       outvalue |= data << 8;
+                                       outvalue |= data << 16;
+                                       outvalue |= data << 24;
+                               }
                        }
                } else {
                        switch (this_size) {

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)