1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2013-2014,2019-2020 Synopsys, Inc. *
5 * Frank Dols <frank.dols@synopsys.com> *
6 * Mischa Jonker <mischa.jonker@synopsys.com> *
7 * Anton Kolesov <anton.kolesov@synopsys.com> *
8 * Evgeniy Didin <didin@synopsys.com> *
9 ***************************************************************************/
17 /* ----- Supporting functions ---------------------------------------------- */
18 static bool arc_mem_is_slow_memory(struct arc_common
*arc
, uint32_t addr
,
19 uint32_t size
, uint32_t count
)
21 uint32_t addr_end
= addr
+ size
* count
;
22 /* `_end` field can overflow - it points to the first byte after the end,
23 * therefore if DCCM is right at the end of memory address space, then
24 * dccm_end will be 0. */
25 assert(addr_end
>= addr
|| addr_end
== 0);
27 return !((addr
>= arc
->dccm_start
&& addr_end
<= arc
->dccm_end
) ||
28 (addr
>= arc
->iccm0_start
&& addr_end
<= arc
->iccm0_end
) ||
29 (addr
>= arc
->iccm1_start
&& addr_end
<= arc
->iccm1_end
));
32 /* Write word at word-aligned address */
33 static int arc_mem_write_block32(struct target
*target
, uint32_t addr
,
34 uint32_t count
, void *buf
)
36 struct arc_common
*arc
= target_to_arc(target
);
38 LOG_DEBUG("Write 4-byte memory block: addr=0x%08" PRIx32
", count=%" PRIu32
,
44 /* We need to flush the cache since it might contain dirty
45 * lines, so the cache invalidation may cause data inconsistency. */
46 CHECK_RETVAL(arc_cache_flush(target
));
49 /* No need to flush cache, because we don't read values from memory. */
50 CHECK_RETVAL(arc_jtag_write_memory(&arc
->jtag_info
, addr
, count
,
53 /* Invalidate caches. */
54 CHECK_RETVAL(arc_cache_invalidate(target
));
59 /* Write half-word at half-word-aligned address */
60 static int arc_mem_write_block16(struct target
*target
, uint32_t addr
,
61 uint32_t count
, void *buf
)
63 struct arc_common
*arc
= target_to_arc(target
);
66 uint8_t buffer_te
[sizeof(uint32_t)];
67 uint8_t halfword_te
[sizeof(uint16_t)];
69 LOG_DEBUG("Write 2-byte memory block: addr=0x%08" PRIx32
", count=%" PRIu32
,
75 /* We will read data from memory, so we need to flush the cache. */
76 CHECK_RETVAL(arc_cache_flush(target
));
78 /* non-word writes are less common than 4-byte writes, so I suppose we can
79 * allow ourselves to write this in a cycle, instead of calling arc_jtag
81 for (i
= 0; i
< count
; i
++) {
82 /* We can read only word at word-aligned address. Also *jtag_read_memory
83 * functions return data in host endianness, so host endianness !=
84 * target endianness we have to convert data back to target endianness,
85 * or bytes will be at the wrong places.So:
87 * 2) convert to target endianness
89 * 4) convert back to host endianness
90 * 5) write word back to target.
92 bool is_slow_memory
= arc_mem_is_slow_memory(arc
,
93 (addr
+ i
* sizeof(uint16_t)) & ~3u, 4, 1);
94 CHECK_RETVAL(arc_jtag_read_memory(&arc
->jtag_info
,
95 (addr
+ i
* sizeof(uint16_t)) & ~3u, 1, &buffer_he
,
97 target_buffer_set_u32(target
, buffer_te
, buffer_he
);
99 /* buf is in host endianness, convert to target */
100 target_buffer_set_u16(target
, halfword_te
, ((uint16_t *)buf
)[i
]);
102 memcpy(buffer_te
+ ((addr
+ i
* sizeof(uint16_t)) & 3u),
103 halfword_te
, sizeof(uint16_t));
105 buffer_he
= target_buffer_get_u32(target
, buffer_te
);
107 CHECK_RETVAL(arc_jtag_write_memory(&arc
->jtag_info
,
108 (addr
+ i
* sizeof(uint16_t)) & ~3u, 1, &buffer_he
));
111 /* Invalidate caches. */
112 CHECK_RETVAL(arc_cache_invalidate(target
));
117 /* Write byte at address */
118 static int arc_mem_write_block8(struct target
*target
, uint32_t addr
,
119 uint32_t count
, void *buf
)
121 struct arc_common
*arc
= target_to_arc(target
);
124 uint8_t buffer_te
[sizeof(uint32_t)];
127 LOG_DEBUG("Write 1-byte memory block: addr=0x%08" PRIx32
", count=%" PRIu32
,
130 /* We will read data from memory, so we need to flush the cache. */
131 CHECK_RETVAL(arc_cache_flush(target
));
133 /* non-word writes are less common than 4-byte writes, so I suppose we can
134 * allow ourselves to write this in a cycle, instead of calling arc_jtag
136 for (i
= 0; i
< count
; i
++) {
137 /* See comment in arc_mem_write_block16 for details. Since it is a byte
138 * there is not need to convert write buffer to target endianness, but
139 * we still have to convert read buffer. */
140 CHECK_RETVAL(arc_jtag_read_memory(&arc
->jtag_info
, (addr
+ i
) & ~3, 1, &buffer_he
,
141 arc_mem_is_slow_memory(arc
, (addr
+ i
) & ~3, 4, 1)));
142 target_buffer_set_u32(target
, buffer_te
, buffer_he
);
143 memcpy(buffer_te
+ ((addr
+ i
) & 3), (uint8_t *)buf
+ i
, 1);
144 buffer_he
= target_buffer_get_u32(target
, buffer_te
);
145 CHECK_RETVAL(arc_jtag_write_memory(&arc
->jtag_info
, (addr
+ i
) & ~3, 1, &buffer_he
));
148 /* Invalidate caches. */
149 CHECK_RETVAL(arc_cache_invalidate(target
));
154 /* ----- Exported functions ------------------------------------------------ */
155 int arc_mem_write(struct target
*target
, target_addr_t address
, uint32_t size
,
156 uint32_t count
, const uint8_t *buffer
)
158 int retval
= ERROR_OK
;
161 LOG_DEBUG("address: 0x%08" TARGET_PRIxADDR
", size: %" PRIu32
", count: %" PRIu32
,
162 address
, size
, count
);
164 if (target
->state
!= TARGET_HALTED
) {
165 LOG_TARGET_ERROR(target
, "not halted");
166 return ERROR_TARGET_NOT_HALTED
;
169 /* sanitize arguments */
170 if (((size
!= 4) && (size
!= 2) && (size
!= 1)) || !(count
) || !(buffer
))
171 return ERROR_COMMAND_SYNTAX_ERROR
;
173 if (((size
== 4) && (address
& 0x3u
)) || ((size
== 2) && (address
& 0x1u
)))
174 return ERROR_TARGET_UNALIGNED_ACCESS
;
176 /* correct endianness if we have word or hword access */
179 * arc_..._write_mem with size 4/2 requires uint32_t/uint16_t
180 * in host endianness, but byte array represents target endianness.
182 tunnel
= calloc(1, count
* size
* sizeof(uint8_t));
185 LOG_ERROR("Unable to allocate memory");
191 target_buffer_get_u32_array(target
, buffer
, count
,
195 target_buffer_get_u16_array(target
, buffer
, count
,
203 retval
= arc_mem_write_block32(target
, address
, count
, (void *)buffer
);
204 } else if (size
== 2) {
205 /* We convert buffer from host endianness to target. But then in
206 * write_block16, we do the reverse. Is there a way to avoid this without
207 * breaking other cases? */
208 retval
= arc_mem_write_block16(target
, address
, count
, (void *)buffer
);
210 retval
= arc_mem_write_block8(target
, address
, count
, (void *)buffer
);
218 static int arc_mem_read_block(struct target
*target
, target_addr_t addr
,
219 uint32_t size
, uint32_t count
, void *buf
)
221 struct arc_common
*arc
= target_to_arc(target
);
223 LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR
", size=%" PRIu32
224 ", count=%" PRIu32
, addr
, size
, count
);
228 /* Flush cache before memory access */
229 CHECK_RETVAL(arc_cache_flush(target
));
231 CHECK_RETVAL(arc_jtag_read_memory(&arc
->jtag_info
, addr
, count
, buf
,
232 arc_mem_is_slow_memory(arc
, addr
, size
, count
)));
237 int arc_mem_read(struct target
*target
, target_addr_t address
, uint32_t size
,
238 uint32_t count
, uint8_t *buffer
)
240 int retval
= ERROR_OK
;
243 uint32_t words_to_read
, bytes_to_read
;
246 LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR
", size=%" PRIu32
247 ", count=%" PRIu32
, address
, size
, count
);
249 if (target
->state
!= TARGET_HALTED
) {
250 LOG_WARNING("target not halted");
251 return ERROR_TARGET_NOT_HALTED
;
254 /* Sanitize arguments */
255 if (((size
!= 4) && (size
!= 2) && (size
!= 1)) || !(count
) || !(buffer
))
256 return ERROR_COMMAND_SYNTAX_ERROR
;
258 if (((size
== 4) && (address
& 0x3u
)) || ((size
== 2) && (address
& 0x1u
)))
259 return ERROR_TARGET_UNALIGNED_ACCESS
;
261 /* Reads are word-aligned, so padding might be required if count > 1.
262 * NB: +3 is a padding for the last word (in case it's not aligned;
263 * addr&3 is a padding for the first word (since address can be
264 * unaligned as well). */
265 bytes_to_read
= (count
* size
+ 3 + (address
& 3u)) & ~3u;
266 words_to_read
= bytes_to_read
>> 2;
267 tunnel_he
= calloc(1, bytes_to_read
);
268 tunnel_te
= calloc(1, bytes_to_read
);
270 if (!tunnel_he
|| !tunnel_te
) {
271 LOG_ERROR("Unable to allocate memory");
277 /* We can read only word-aligned words. */
278 retval
= arc_mem_read_block(target
, address
& ~3u, sizeof(uint32_t),
279 words_to_read
, tunnel_he
);
281 /* arc_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */
282 /* endianness, but byte array should represent target endianness */
284 if (retval
== ERROR_OK
) {
287 target_buffer_set_u32_array(target
, buffer
, count
,
291 target_buffer_set_u32_array(target
, tunnel_te
,
292 words_to_read
, tunnel_he
);
293 /* Will that work properly with count > 1 and big endian? */
294 memcpy(buffer
, tunnel_te
+ (address
& 3u),
295 count
* sizeof(uint16_t));
298 target_buffer_set_u32_array(target
, tunnel_te
,
299 words_to_read
, tunnel_he
);
300 /* Will that work properly with count > 1 and big endian? */
301 memcpy(buffer
, tunnel_te
+ (address
& 3u), count
);