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: Siarhei Siamashka <[email protected]>
---
 fel.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/fel.c b/fel.c
index a597e11..d3d6f62 100644
--- a/fel.c
+++ b/fel.c
@@ -654,6 +654,38 @@ void aw_write_arm_cp_reg(libusb_device_handle *usb, 
soc_sram_info *sram_info,
        aw_fel_execute(usb, sram_info->scratch_addr);
 }
 
+uint32_t aw_fel_readl(libusb_device_handle *usb, uint32_t addr)
+{
+       soc_sram_info *sram_info = aw_fel_get_sram_info(usb);
+       uint32_t val = 0;
+       uint32_t arm_code[] = {
+               htole32(0xe59f0008), /* ldr        r0, [pc, #8]             */
+               htole32(0xe5900000), /* ldr        r0, [r0]                 */
+               htole32(0xe58f0000), /* str        r0, [pc]                 */
+               htole32(0xe12fff1e), /* bx         lr                       */
+               htole32(addr)
+       };
+       aw_fel_write(usb, arm_code, sram_info->scratch_addr, sizeof(arm_code));
+       aw_fel_execute(usb, sram_info->scratch_addr);
+       aw_fel_read(usb, sram_info->scratch_addr + 16, &val, sizeof(val));
+       return le32toh(val);
+}
+
+void aw_fel_writel(libusb_device_handle *usb, uint32_t addr, uint32_t val)
+{
+       soc_sram_info *sram_info = aw_fel_get_sram_info(usb);
+       uint32_t arm_code[] = {
+               htole32(0xe59f0008), /* ldr        r0, [pc, #8]             */
+               htole32(0xe59f1008), /* ldr        r1, [pc, #8]             */
+               htole32(0xe5801000), /* str        r1, [r0]                 */
+               htole32(0xe12fff1e), /* bx         lr                       */
+               htole32(addr),
+               htole32(val)
+       };
+       aw_fel_write(usb, arm_code, sram_info->scratch_addr, sizeof(arm_code));
+       aw_fel_execute(usb, sram_info->scratch_addr);
+}
+
 void aw_enable_l2_cache(libusb_device_handle *usb, soc_sram_info *sram_info)
 {
        uint32_t arm_code[] = {
@@ -1314,6 +1346,8 @@ int main(int argc, char **argv)
                        "       hex[dump] address length        Dumps memory 
region in hex\n"
                        "       dump address length             Binary memory 
dump\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"
                        "       write address file              Store file 
contents into memory\n"
                        "       write-with-progress addr file   \"write\" with 
progress bar\n"
@@ -1380,6 +1414,16 @@ int main(int argc, char **argv)
                } else if (strncmp(argv[1], "dump", 4) == 0 && argc > 3) {
                        aw_fel_dump(handle, strtoul(argv[2], NULL, 0), 
strtoul(argv[3], NULL, 0));
                        skip = 3;
+               } else if (strcmp(argv[1], "readl") == 0 && argc > 2) {
+                       uint32_t addr = strtoul(argv[2], NULL, 0);
+                       uint32_t val = aw_fel_readl(handle, addr);
+                       printf("0x%08x\n", val);
+                       skip = 2;
+               } else if (strcmp(argv[1], "writel") == 0 && argc > 2) {
+                       uint32_t addr = strtoul(argv[2], NULL, 0);
+                       uint32_t val = strtoul(argv[3], NULL, 0);
+                       aw_fel_writel(handle, addr, val);
+                       skip = 3;
                } else if (strncmp(argv[1], "exe", 3) == 0 && argc > 2) {
                        aw_fel_execute(handle, strtoul(argv[2], NULL, 0));
                        skip=3;
-- 
2.4.10

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to