Commit 3269b963 authored by Bernhard Nortmann's avatar Bernhard Nortmann
Browse files

fel: Add "readl" and "writel" commands


Signed-off-by: default avatarBernhard Nortmann <bernhard.nortmann@web.de>

Squashed commit of the following:

commit 95f3614357446c4a35ec541bb2c21503c54d3fac
Author: Bernhard Nortmann <bernhard.nortmann@web.de>
Date:   Fri Apr 8 09:10:17 2016 +0200

    fel: Add support for multiple sequential readl/writel

    There are cases where "long" reads/writes might be used to transfer
    multiple values from/to sequential addresses.

    When doing so, we can avoid having to setup and upload the entire
    scratch buffer (ARM code) every time, by making the underlying
    functions auto-increment the address on each invocation.

    The patch implements this functionality, and maps the existing
    aw_fel_readl() and aw_fel_writel() to special cases (count == 1).
Signed-off-by: default avatarBernhard Nortmann <bernhard.nortmann@web.de>

commit 20ececdfc7f3c4070469a7b74ba77bb74e01f876
Author: Bernhard Nortmann <bernhard.nortmann@web.de>
Date:   Fri Apr 8 09:00:20 2016 +0200

    fel: Modify handling of command line args for "readl"/"writel"

    Most other commands use their decoded argument values directly,
    without storing them to local vars first. Also "writel" needs
    an (argc > 3).
Signed-off-by: default avatarBernhard Nortmann <bernhard.nortmann@web.de>

commit b4216371b97e9f1dd19f7fc2ce720b9cb8e2434e
Author: Siarhei Siamashka <siarhei.siamashka@gmail.com>
Date:   Sat Dec 19 08:22:26 2015 +0200

    fel: Add "readl" and "writel" commands

    The read/write operations done by FEL are not suitable for accessing
    hardware registers. For example, trying to read a SID value using
    the "read" or "hexdump" commands results in the following:

      $ sunxi-fel hexdump 0x01c23800 4
      01c23800: 87 00 00 00 __ __ __ __ __ __ __ __ __ __ __ __

    Apparently, FEL tries to read data one byte at a time and this does
    not always work correctly. Introducing new commands to explicitly
    do 32-bit reads and writes helps:

      $ sunxi-fel readl 0x01c23800
      0x16254187
Signed-off-by: default avatarSiarhei Siamashka <siarhei.siamashka@gmail.com>
Tested-by: default avatarBernhard Nortmann <bernhard.nortmann@web.de>
parent 118dfa8e
...@@ -662,6 +662,80 @@ void aw_write_arm_cp_reg(libusb_device_handle *usb, soc_sram_info *sram_info, ...@@ -662,6 +662,80 @@ void aw_write_arm_cp_reg(libusb_device_handle *usb, soc_sram_info *sram_info,
aw_fel_execute(usb, sram_info->scratch_addr); aw_fel_execute(usb, sram_info->scratch_addr);
} }
/* multiple "readl" from sequential addresses to a destination buffer */
void aw_fel_readl_n(libusb_device_handle *usb, uint32_t addr,
uint32_t *dst, size_t count)
{
soc_sram_info *sram_info = aw_fel_get_sram_info(usb);
uint32_t val;
uint32_t arm_code[] = {
htole32(0xe59f0010), /* ldr r0, [pc, #16] */
htole32(0xe5901000), /* ldr r1, [r0] */
htole32(0xe58f100c), /* str r1, [pc, #12] */
htole32(0xe2800004), /* add r0, r0, #4 */
htole32(0xe58f0000), /* str r0, [pc] */
htole32(0xe12fff1e), /* bx lr */
htole32(addr),
/* value goes here */
};
/* scratch buffer setup: transfers ARM code and also sets the addr */
aw_fel_write(usb, arm_code, sram_info->scratch_addr, sizeof(arm_code));
while (count-- > 0) {
/*
* Since the scratch code auto-increments addr, we can simply
* execute it repeatedly for sequential "readl"s; retrieving
* one uint32_t each time.
*/
aw_fel_execute(usb, sram_info->scratch_addr);
aw_fel_read(usb, sram_info->scratch_addr + 28, &val, sizeof(val));
*dst++ = le32toh(val);
}
}
/* "readl" of a single value */
uint32_t aw_fel_readl(libusb_device_handle *usb, uint32_t addr)
{
uint32_t val;
aw_fel_readl_n(usb, addr, &val, 1);
return val;
}
/* multiple "writel" from a source buffer to sequential addresses */
void aw_fel_writel_n(libusb_device_handle *usb, uint32_t addr,
uint32_t *src, size_t count)
{
if (count == 0) return; /* on zero count, do not access *src at all */
soc_sram_info *sram_info = aw_fel_get_sram_info(usb);
uint32_t arm_code[] = {
htole32(0xe59f0010), /* ldr r0, [pc, #16] */
htole32(0xe59f1010), /* ldr r1, [pc, #16] */
htole32(0xe5801000), /* str r1, [r0] */
htole32(0xe2800004), /* add r0, r0, #4 */
htole32(0xe58f0000), /* str r0, [pc] */
htole32(0xe12fff1e), /* bx lr */
htole32(addr),
htole32(*src++)
};
/* scratch buffer setup: transfers ARM code, addr and first value */
aw_fel_write(usb, arm_code, sram_info->scratch_addr, sizeof(arm_code));
aw_fel_execute(usb, sram_info->scratch_addr); /* stores first value */
while (--count > 0) {
/*
* Subsequent transfers only need to set up the next value
* to store (since the scratch code auto-increments addr).
*/
aw_fel_write(usb, src++, sram_info->scratch_addr + 28, sizeof(uint32_t));
aw_fel_execute(usb, sram_info->scratch_addr);
}
}
/* "writel" of a single value */
void aw_fel_writel(libusb_device_handle *usb, uint32_t addr, uint32_t val)
{
aw_fel_writel_n(usb, addr, &val, 1);
}
void aw_enable_l2_cache(libusb_device_handle *usb, soc_sram_info *sram_info) void aw_enable_l2_cache(libusb_device_handle *usb, soc_sram_info *sram_info)
{ {
uint32_t arm_code[] = { uint32_t arm_code[] = {
...@@ -1389,6 +1463,8 @@ int main(int argc, char **argv) ...@@ -1389,6 +1463,8 @@ int main(int argc, char **argv)
" hex[dump] address length Dumps memory region in hex\n" " hex[dump] address length Dumps memory region in hex\n"
" dump address length Binary memory dump\n" " dump address length Binary memory dump\n"
" exe[cute] address Call function address\n" " exe[cute] address Call function address\n"
" readl address Read 32-bit value from device memory\n"
" writel address value Write 32-bit value to device memory\n"
" read address length file Write memory contents into file\n" " read address length file Write memory contents into file\n"
" write address file Store file contents into memory\n" " write address file Store file contents into memory\n"
" write-with-progress addr file \"write\" with progress bar\n" " write-with-progress addr file \"write\" with progress bar\n"
...@@ -1461,6 +1537,12 @@ int main(int argc, char **argv) ...@@ -1461,6 +1537,12 @@ int main(int argc, char **argv)
} else if (strncmp(argv[1], "dump", 4) == 0 && argc > 3) { } else if (strncmp(argv[1], "dump", 4) == 0 && argc > 3) {
aw_fel_dump(handle, strtoul(argv[2], NULL, 0), strtoul(argv[3], NULL, 0)); aw_fel_dump(handle, strtoul(argv[2], NULL, 0), strtoul(argv[3], NULL, 0));
skip = 3; skip = 3;
} else if (strcmp(argv[1], "readl") == 0 && argc > 2) {
printf("0x%08x\n", aw_fel_readl(handle, strtoul(argv[2], NULL, 0)));
skip = 2;
} else if (strcmp(argv[1], "writel") == 0 && argc > 3) {
aw_fel_writel(handle, strtoul(argv[2], NULL, 0), strtoul(argv[3], NULL, 0));
skip = 3;
} else if (strncmp(argv[1], "exe", 3) == 0 && argc > 2) { } else if (strncmp(argv[1], "exe", 3) == 0 && argc > 2) {
aw_fel_execute(handle, strtoul(argv[2], NULL, 0)); aw_fel_execute(handle, strtoul(argv[2], NULL, 0));
skip=3; skip=3;
......
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