On Thu, 17 Mar 2016 13:55:25 +0100 Bernhard Nortmann <[email protected]> wrote:
> Am Montag, 25. Januar 2016 05:51:02 UTC+1 schrieb Siarhei Siamashka: > > 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]> > > I can confirm/reproduce this behaviour on my A20 when accessing the SID > register. Interesting enough, the bytes that actually do get read (i.e. > end up != 0) are "correct", as if the aw_usb_read() somehow truncates > everything down to single-byte range: > > sunxi-tools # ./sunxi-fel hexdump 0x01c23800 16 > 01c23800: 4f 00 00 00 86 00 00 00 48 00 00 00 e9 00 00 00 > > Your "readl" retrieves the expected results (correct 32-bit values for > the SID registers). > > > > --- > > 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); > > Can't we do away with the "val" variable here, and just use > printf("0x%08x\n", aw_fel_readl(handle, addr)); instead? Yes, we can make the code one line shorter this way. > > + 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 > > > Tested-by: Bernhard Nortmann <[email protected]> > > Regards, NiteHawk Thanks. -- Best regards, Siarhei Siamashka -- 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.
