aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Vanek <vanekt@fbl.cz>2023-04-02 18:49:12 +0200
committerAntonio Borneo <borneo.antonio@gmail.com>2024-01-06 13:56:02 +0000
commitffdcec938fb6bd2d6f7f1f4aed7b41c627934a24 (patch)
tree775bb8eb9ac82e21fea24aef7e35ba66b9610b07
parent5039848424f818241a8d256b7e49f6c3152c4dc6 (diff)
downloadriscv-openocd-ffdcec938fb6bd2d6f7f1f4aed7b41c627934a24.zip
riscv-openocd-ffdcec938fb6bd2d6f7f1f4aed7b41c627934a24.tar.gz
riscv-openocd-ffdcec938fb6bd2d6f7f1f4aed7b41c627934a24.tar.bz2
target/arm_adi_v5: rework Nuvoton NPCX quirk workaround.
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>
-rw-r--r--src/target/arm_adi_v5.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index 6998577..0f1e648 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -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) {