coding style: doc: remove empty lines at end of text files 70/5170/4 master
authorAntonio Borneo <borneo.antonio@gmail.com>
Sun, 12 May 2019 10:52:59 +0000 (12:52 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Mon, 24 Feb 2020 10:31:29 +0000 (10:31 +0000)
Empty lines at end of text files are useless.
Remove them.

Change-Id: I30e4d3d03c4ce846aa7bcefa7366f88732275557
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/5170
Tested-by: jenkins
470 files changed:
.gitmodules
NEWS-0.5.0
TODO
configure.ac
contrib/loaders/flash/at91sam7x/makefile
contrib/loaders/flash/sh_qspi/Makefile [new file with mode: 0644]
contrib/loaders/flash/sh_qspi/sh_qspi.S [new file with mode: 0644]
contrib/loaders/flash/sh_qspi/sh_qspi.inc [new file with mode: 0644]
contrib/loaders/flash/sh_qspi/sh_qspi.ld [new file with mode: 0644]
contrib/loaders/flash/stm32/stm32l4x.S
doc/fdl.texi
doc/openocd.texi
src/flash/nor/Makefile.am
src/flash/nor/ambiqmicro.c
src/flash/nor/cfi.c
src/flash/nor/cfi.h
src/flash/nor/drivers.c
src/flash/nor/dsp5680xx_flash.c
src/flash/nor/efm32.c
src/flash/nor/nrf5.c
src/flash/nor/numicro.c
src/flash/nor/psoc6.c
src/flash/nor/renesas_rpchf.c [new file with mode: 0644]
src/flash/nor/sh_qspi.c [new file with mode: 0644]
src/flash/nor/sim3x.c
src/flash/nor/stm32f1x.c
src/flash/nor/stm32h7x.c
src/flash/nor/stm32l4x.c
src/flash/nor/stm32lx.c
src/flash/nor/tcl.c
src/flash/startup.tcl
src/helper/log.c
src/helper/types.h
src/jtag/adapter.c
src/jtag/aice/aice_usb.c
src/jtag/core.c
src/jtag/drivers/Makefile.am
src/jtag/drivers/cmsis_dap_usb.c
src/jtag/drivers/ft232r.c
src/jtag/drivers/ftdi.c
src/jtag/drivers/jtag_vpi.c
src/jtag/drivers/kitprog.c
src/jtag/drivers/libusb0_common.c
src/jtag/drivers/libusb0_common.h
src/jtag/drivers/libusb1_common.c
src/jtag/drivers/libusb1_common.h
src/jtag/drivers/opendous.c
src/jtag/drivers/openjtag.c
src/jtag/drivers/osbdm.c
src/jtag/drivers/stlink_usb.c
src/jtag/drivers/usb_blaster/ublast2_access_libusb.c
src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c
src/jtag/drivers/xlnx-pcie-xvc.c [new file with mode: 0644]
src/jtag/interfaces.c
src/jtag/jtag.h
src/jtag/startup.tcl
src/jtag/tcl.c
src/rtos/embKernel.c
src/rtos/mqx.c
src/server/gdb_server.c
src/svf/svf.c
src/target/adi_v5_dapdirect.c
src/target/adi_v5_swd.c
src/target/arm_cti.c
src/target/armv8.c
src/target/avrt.c
src/target/cortex_m.c
src/target/dsp563xx_once.c
src/target/dsp563xx_once.h
src/target/dsp5680xx.h
src/target/mips_ejtag.c
src/target/mips_ejtag.h
src/target/nds32.h
src/target/riscv/riscv-013.c
src/target/startup.tcl
src/target/stm8.c
src/target/target.c
tcl/board/actux3.cfg
tcl/board/adsp-sc584-ezbrd.cfg
tcl/board/altera_sockit.cfg
tcl/board/arm_musca_a.cfg
tcl/board/arty_s7.cfg
tcl/board/at91cap7a-stk-sdram.cfg
tcl/board/at91eb40a.cfg
tcl/board/at91rm9200-dk.cfg
tcl/board/at91rm9200-ek.cfg
tcl/board/at91sam9g20-ek.cfg
tcl/board/atmel_sam3n_ek.cfg
tcl/board/avnet_ultrazed-eg.cfg
tcl/board/bcm28155_ap.cfg
tcl/board/colibri.cfg
tcl/board/crossbow_tech_imote2.cfg
tcl/board/csb337.cfg
tcl/board/csb732.cfg
tcl/board/digi_connectcore_wi-9c.cfg
tcl/board/digilent_analog_discovery.cfg
tcl/board/dk-tm4c129.cfg [changed mode: 0755->0644]
tcl/board/dm365evm.cfg
tcl/board/dp_busblaster_v3.cfg
tcl/board/efm32.cfg
tcl/board/ek-lm3s1968.cfg
tcl/board/embedded-artists_lpc2478-32.cfg
tcl/board/emcraft_imx8m-som-bsb.cfg
tcl/board/ethernut3.cfg
tcl/board/fsl_imx6q_sabresd.cfg
tcl/board/glyn_tonga2.cfg
tcl/board/gumstix-aerocore.cfg
tcl/board/hilscher_nxdb500sys.cfg
tcl/board/hilscher_nxeb500hmi.cfg
tcl/board/hilscher_nxhx10.cfg
tcl/board/hilscher_nxhx50.cfg
tcl/board/hilscher_nxhx500.cfg
tcl/board/hilscher_nxsb100.cfg
tcl/board/hitex_lpc1768stick.cfg
tcl/board/hitex_lpc2929.cfg
tcl/board/hitex_stm32-performancestick.cfg
tcl/board/hitex_str9-comstick.cfg
tcl/board/iar_str912_sk.cfg
tcl/board/icnova_imx53_sodimm.cfg
tcl/board/icnova_sam9g45_sodimm.cfg
tcl/board/imx27lnst.cfg
tcl/board/imx53-m53evk.cfg
tcl/board/imx53loco.cfg
tcl/board/imx8mp-evk.cfg [new file with mode: 0644]
tcl/board/insignal_arndale.cfg
tcl/board/kasli.cfg
tcl/board/kc705.cfg
tcl/board/kcu105.cfg
tcl/board/kindle2.cfg
tcl/board/lubbock.cfg
tcl/board/marsohod.cfg
tcl/board/marsohod2.cfg
tcl/board/marsohod3.cfg
tcl/board/mcb1700.cfg
tcl/board/microchip_saml11_xplained_pro.cfg
tcl/board/mini2440.cfg
tcl/board/mini6410.cfg
tcl/board/novena-internal-fpga.cfg
tcl/board/numato_mimas_a7.cfg
tcl/board/nxp_imx7sabre.cfg
tcl/board/nxp_mcimx8m-evk.cfg
tcl/board/olimex_sam7_la2.cfg
tcl/board/openrd.cfg
tcl/board/or1k_generic.cfg
tcl/board/phytec_lpc3250.cfg
tcl/board/pxa255_sst.cfg
tcl/board/quark_d2000_refboard.cfg
tcl/board/quark_x10xx_board.cfg
tcl/board/rigado_bmd300_ek.cfg
tcl/board/rsc-w910.cfg
tcl/board/sayma_amc.cfg
tcl/board/sheevaplug.cfg
tcl/board/sifive-e31arty.cfg
tcl/board/sifive-e51arty.cfg
tcl/board/sifive-hifive1.cfg
tcl/board/st_nucleo_h745zi.cfg
tcl/board/st_nucleo_wb55.cfg [new file with mode: 0644]
tcl/board/stm32f7discovery.cfg [changed mode: 0755->0644]
tcl/board/telo.cfg
tcl/board/ti_am437x_idk.cfg
tcl/board/ti_am43xx_evm.cfg
tcl/board/ti_beaglebone.cfg
tcl/board/ti_beaglebone_black.cfg
tcl/board/ti_cc13x0_launchpad.cfg
tcl/board/ti_cc13x2_launchpad.cfg
tcl/board/ti_cc26x0_launchpad.cfg
tcl/board/ti_cc26x2_launchpad.cfg
tcl/board/ti_cc3200_launchxl.cfg
tcl/board/ti_cc3220sf_launchpad.cfg
tcl/board/ti_cc32xx_launchpad.cfg
tcl/board/ti_msp432_launchpad.cfg
tcl/board/ti_tmdx570ls31usb.cfg
tcl/board/tocoding_poplar.cfg
tcl/board/topas910.cfg
tcl/board/topasa900.cfg
tcl/board/twr-vf65gs10.cfg
tcl/board/twr-vf65gs10_cmsisdap.cfg
tcl/board/verdex.cfg
tcl/board/voltcraft_dso-3062c.cfg
tcl/board/zy1000.cfg
tcl/interface/altera-usb-blaster.cfg
tcl/interface/altera-usb-blaster2.cfg
tcl/interface/arm-jtag-ew.cfg
tcl/interface/at91rm9200.cfg
tcl/interface/buspirate.cfg
tcl/interface/calao-usb-a9260.cfg
tcl/interface/chameleon.cfg
tcl/interface/cmsis-dap.cfg
tcl/interface/dummy.cfg
tcl/interface/estick.cfg
tcl/interface/flashlink.cfg
tcl/interface/ft232r.cfg
tcl/interface/ftdi/100ask-openjtag.cfg
tcl/interface/ftdi/axm0432.cfg
tcl/interface/ftdi/c232hm.cfg
tcl/interface/ftdi/calao-usb-a9260-c01.cfg
tcl/interface/ftdi/calao-usb-a9260-c02.cfg
tcl/interface/ftdi/cortino.cfg
tcl/interface/ftdi/digilent-hs1.cfg
tcl/interface/ftdi/digilent-hs2.cfg
tcl/interface/ftdi/digilent_jtag_hs3.cfg
tcl/interface/ftdi/digilent_jtag_smt2.cfg
tcl/interface/ftdi/digilent_jtag_smt2_nc.cfg
tcl/interface/ftdi/dlp-usb1232h.cfg
tcl/interface/ftdi/dp_busblaster.cfg
tcl/interface/ftdi/dp_busblaster_kt-link.cfg
tcl/interface/ftdi/flossjtag-noeeprom.cfg
tcl/interface/ftdi/flossjtag.cfg
tcl/interface/ftdi/flyswatter.cfg
tcl/interface/ftdi/flyswatter2.cfg
tcl/interface/ftdi/ft232h-module-swd.cfg
tcl/interface/ftdi/gw16042.cfg
tcl/interface/ftdi/hilscher_nxhx10_etm.cfg
tcl/interface/ftdi/hilscher_nxhx500_etm.cfg
tcl/interface/ftdi/hilscher_nxhx500_re.cfg
tcl/interface/ftdi/hilscher_nxhx50_etm.cfg
tcl/interface/ftdi/hilscher_nxhx50_re.cfg
tcl/interface/ftdi/hitex_lpc1768stick.cfg
tcl/interface/ftdi/hitex_str9-comstick.cfg
tcl/interface/ftdi/icebear.cfg
tcl/interface/ftdi/imx8mp-evk.cfg [new file with mode: 0644]
tcl/interface/ftdi/incircuit-icprog.cfg
tcl/interface/ftdi/iotlab-usb.cfg
tcl/interface/ftdi/isodebug.cfg [new file with mode: 0644]
tcl/interface/ftdi/jtag-lock-pick_tiny_2.cfg
tcl/interface/ftdi/jtagkey.cfg
tcl/interface/ftdi/jtagkey2.cfg
tcl/interface/ftdi/jtagkey2p.cfg
tcl/interface/ftdi/kt-link.cfg
tcl/interface/ftdi/lisa-l.cfg
tcl/interface/ftdi/luminary-icdi.cfg
tcl/interface/ftdi/luminary-lm3s811.cfg
tcl/interface/ftdi/luminary.cfg
tcl/interface/ftdi/m53evk.cfg
tcl/interface/ftdi/mbftdi.cfg
tcl/interface/ftdi/minimodule-swd.cfg
tcl/interface/ftdi/minimodule.cfg
tcl/interface/ftdi/minispartan6.cfg
tcl/interface/ftdi/neodb.cfg
tcl/interface/ftdi/ngxtech.cfg
tcl/interface/ftdi/olimex-arm-usb-ocd-h.cfg
tcl/interface/ftdi/olimex-arm-usb-ocd.cfg
tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg
tcl/interface/ftdi/olimex-jtag-tiny.cfg
tcl/interface/ftdi/oocdlink.cfg
tcl/interface/ftdi/opendous_ftdi.cfg
tcl/interface/ftdi/openocd-usb-hs.cfg
tcl/interface/ftdi/openocd-usb.cfg
tcl/interface/ftdi/openrd.cfg
tcl/interface/ftdi/pipistrello.cfg
tcl/interface/ftdi/redbee-econotag.cfg
tcl/interface/ftdi/redbee-usb.cfg
tcl/interface/ftdi/sheevaplug.cfg
tcl/interface/ftdi/signalyzer-lite.cfg
tcl/interface/ftdi/signalyzer.cfg
tcl/interface/ftdi/stm32-stick.cfg
tcl/interface/ftdi/ti-icdi.cfg
tcl/interface/ftdi/tumpa-lite.cfg
tcl/interface/ftdi/tumpa.cfg
tcl/interface/ftdi/turtelizer2-revB.cfg
tcl/interface/ftdi/turtelizer2-revC.cfg
tcl/interface/ftdi/um232h.cfg
tcl/interface/ftdi/vpaclink.cfg
tcl/interface/ftdi/xds100v2.cfg
tcl/interface/imx-native.cfg
tcl/interface/jlink.cfg
tcl/interface/jtag_vpi.cfg
tcl/interface/kitprog.cfg
tcl/interface/nds32-aice.cfg
tcl/interface/opendous.cfg
tcl/interface/openjtag.cfg
tcl/interface/osbdm.cfg
tcl/interface/parport.cfg
tcl/interface/parport_dlc5.cfg
tcl/interface/raspberrypi-native.cfg
tcl/interface/raspberrypi2-native.cfg
tcl/interface/rlink.cfg
tcl/interface/stlink-dap.cfg
tcl/interface/stlink.cfg
tcl/interface/sysfsgpio-raspberrypi.cfg
tcl/interface/ti-icdi.cfg
tcl/interface/ulink.cfg
tcl/interface/usb-jtag.cfg
tcl/interface/usbprog.cfg
tcl/interface/vsllink.cfg
tcl/interface/xds110.cfg
tcl/memory.tcl
tcl/target/1986ве1т.cfg
tcl/target/aduc702x.cfg
tcl/target/aducm360.cfg [changed mode: 0755->0644]
tcl/target/allwinner_v3s.cfg
tcl/target/altera_fpgasoc.cfg
tcl/target/amdm37x.cfg
tcl/target/ar71xx.cfg
tcl/target/at91sam3XXX.cfg
tcl/target/at91sam4XXX.cfg
tcl/target/at91sam4lXX.cfg
tcl/target/at91sam9.cfg
tcl/target/at91sam9260_ext_RAM_ext_flash.cfg
tcl/target/at91sam9g20.cfg
tcl/target/at91samdXX.cfg
tcl/target/atheros_ar9331.cfg
tcl/target/atmega128.cfg
tcl/target/atmega128rfa1.cfg
tcl/target/atsame5x.cfg
tcl/target/atsamv.cfg
tcl/target/avr32.cfg
tcl/target/bcm6348.cfg
tcl/target/bluenrg-x.cfg
tcl/target/c100.cfg
tcl/target/c100config.tcl
tcl/target/c100helper.tcl
tcl/target/cc2538.cfg [changed mode: 0755->0644]
tcl/target/dragonite.cfg
tcl/target/dsp56321.cfg
tcl/target/dsp568013.cfg
tcl/target/dsp568037.cfg
tcl/target/efm32.cfg
tcl/target/epc9301.cfg
tcl/target/esi32xx.cfg
tcl/target/feroceon.cfg
tcl/target/fm3.cfg
tcl/target/fm4.cfg
tcl/target/gp326xxxa.cfg
tcl/target/imx28.cfg
tcl/target/imx31.cfg
tcl/target/imx6.cfg
tcl/target/infineon/tle987x.cfg
tcl/target/is5114.cfg
tcl/target/k1921vk01t.cfg [changed mode: 0755->0644]
tcl/target/ke0x.cfg
tcl/target/klx.cfg
tcl/target/ks869x.cfg
tcl/target/kx.cfg
tcl/target/lpc1850.cfg
tcl/target/lpc1xxx.cfg
tcl/target/lpc2xxx.cfg
tcl/target/lpc3131.cfg
tcl/target/lpc4350.cfg
tcl/target/lpc4370.cfg
tcl/target/lpc8nxx.cfg
tcl/target/ls1012a.cfg
tcl/target/max32620.cfg
tcl/target/max32625.cfg
tcl/target/max3263x.cfg
tcl/target/mc13224v.cfg
tcl/target/mdr32f9q2i.cfg
tcl/target/nrf51.cfg
tcl/target/nrf52.cfg
tcl/target/numicro.cfg
tcl/target/omap3530.cfg
tcl/target/omap5912.cfg
tcl/target/omapl138.cfg
tcl/target/pic32mx.cfg
tcl/target/psoc4.cfg
tcl/target/psoc6.cfg
tcl/target/pxa255.cfg
tcl/target/pxa270.cfg
tcl/target/pxa3xx.cfg
tcl/target/qualcomm_qca4531.cfg
tcl/target/readme.txt
tcl/target/renesas_s7g2.cfg
tcl/target/samsung_s3c2450.cfg
tcl/target/samsung_s3c6410.cfg
tcl/target/sim3x.cfg [changed mode: 0755->0644]
tcl/target/smp8634.cfg
tcl/target/stellaris.cfg
tcl/target/stm32f0x.cfg
tcl/target/stm32f1x.cfg
tcl/target/stm32f2x.cfg
tcl/target/stm32f3x.cfg
tcl/target/stm32f4x.cfg
tcl/target/stm32f7x.cfg [changed mode: 0755->0644]
tcl/target/stm32h7x.cfg
tcl/target/stm32l0.cfg
tcl/target/stm32l1.cfg
tcl/target/stm32l4x.cfg
tcl/target/stm32wbx.cfg
tcl/target/stm8l.cfg
tcl/target/stm8s.cfg
tcl/target/str710.cfg
tcl/target/str730.cfg
tcl/target/str750.cfg
tcl/target/str912.cfg
tcl/target/swm050.cfg
tcl/target/ti-cjtag.cfg [changed mode: 0755->0644]
tcl/target/ti_calypso.cfg
tcl/target/ti_cc26x0.cfg
tcl/target/ti_cc32xx.cfg
tcl/target/ti_dm355.cfg
tcl/target/ti_dm365.cfg
tcl/target/ti_dm6446.cfg
tcl/target/ti_msp432.cfg
tcl/target/ti_tms570.cfg
tcl/target/tmpa900.cfg
tcl/target/tmpa910.cfg
tcl/target/u8500.cfg
tcl/target/vybrid_vf6xx.cfg
tcl/target/xmc1xxx.cfg
tcl/target/xmc4xxx.cfg
tcl/target/zynq_7000.cfg
tcl/target/к1879xб1я.cfg
tcl/test/selftest.cfg [changed mode: 0755->0644]
tcl/test/syntax1.cfg
tcl/tools/firmware-recovery.tcl
testing/build.test1/Makefile
testing/build.test1/README.TXT
testing/build.test1/mingw32_help/include/sys/cdefs.h
testing/build.test2/README.txt
testing/examples/AT91R40008Test/makefile
testing/examples/AT91R40008Test/prj/ethernut3_ram.ld
testing/examples/AT91R40008Test/src/crt.s
testing/examples/LPC2148Test/makefile
testing/examples/LPC2148Test/prj/eclipse_ram.gdb
testing/examples/LPC2148Test/prj/eclipse_rom.gdb
testing/examples/LPC2148Test/prj/lpc2148_ram.ld
testing/examples/LPC2148Test/prj/lpc2148_rom.ld
testing/examples/LPC2148Test/src/crt.s
testing/examples/LPC2294Test/makefile
testing/examples/LPC2294Test/prj/eclipse_ram.gdb
testing/examples/LPC2294Test/prj/eclipse_rom.gdb
testing/examples/LPC2294Test/prj/lpc2294_ram.ld
testing/examples/LPC2294Test/prj/lpc2294_rom.ld
testing/examples/LPC2294Test/src/crt.s
testing/examples/SAM7S256Test/makefile
testing/examples/SAM7S256Test/prj/sam7s256_ram.ld
testing/examples/SAM7S256Test/prj/sam7s256_rom.ld
testing/examples/SAM7S256Test/results/607.html
testing/examples/SAM7S256Test/src/crt.s
testing/examples/SAM7X256Test/makefile
testing/examples/SAM7X256Test/prj/sam7x256_ram.ld
testing/examples/SAM7X256Test/prj/sam7x256_rom.ld
testing/examples/SAM7X256Test/src/crt.s
testing/examples/STM32-103/readme.txt
testing/examples/STR710JtagSpeed/makefile
testing/examples/STR710JtagSpeed/prj/eclipse_ft2232_ram.gdb
testing/examples/STR710JtagSpeed/prj/str7_ram.ld
testing/examples/STR710JtagSpeed/src/crt.s
testing/examples/STR710Test/makefile
testing/examples/STR710Test/prj/eclipse_ram.gdb
testing/examples/STR710Test/prj/eclipse_rom.gdb
testing/examples/STR710Test/prj/hitex_str7_rom.ld
testing/examples/STR710Test/prj/str710_program.script
testing/examples/STR710Test/src/crt.s
testing/examples/STR912Test/makefile
testing/examples/STR912Test/prj/eclipse_ram.gdb
testing/examples/STR912Test/prj/eclipse_rom.gdb
testing/examples/STR912Test/prj/str912_program.script
testing/examples/STR912Test/prj/str912_ram.ld
testing/examples/STR912Test/prj/str912_rom.ld
testing/examples/ledtest-imx27ads/Makefile
testing/examples/ledtest-imx27ads/crt0.S
testing/examples/ledtest-imx27ads/gdbinit-imx27ads
testing/examples/ledtest-imx27ads/test.c
testing/examples/ledtest-imx31pdk/Makefile
testing/examples/ledtest-imx31pdk/crt0.S
testing/examples/ledtest-imx31pdk/gdbinit-imx31pdk
testing/examples/ledtest-imx31pdk/test.c
testing/profile_stm32.txt
testing/results/template.html
testing/results/v0.4.0-rc1/AT91FR40162.html
testing/results/v0.4.0-rc1/LPC2148.html
testing/results/v0.4.0-rc1/SAM7.html
testing/results/v0.4.0-rc1/STR710.html
testing/results/v0.4.0-rc1/STR912.html
testing/tcl_test.tcl
testing/testcases.html
tools/release/helpers.sh
tools/release/version.sh
tools/st7_dtc_as/st7_dtc_as.pl

index 5865ff9..958c5d9 100644 (file)
@@ -1,9 +1,9 @@
 [submodule "tools/git2cl"]
        path = tools/git2cl
-       url = http://repo.or.cz/r/git2cl.git
+       url = https://repo.or.cz/git2cl.git
 [submodule "jimtcl"]
        path = jimtcl
-       url = http://repo.or.cz/r/jimtcl.git
+       url = https://repo.or.cz/jimtcl.git
 [submodule "src/jtag/drivers/libjaylink"]
        path = src/jtag/drivers/libjaylink
-       url = http://repo.or.cz/r/libjaylink.git
+       url = https://repo.or.cz/libjaylink.git
index add6c1e..90ea35c 100644 (file)
@@ -71,4 +71,3 @@ For older NEWS, see the NEWS files associated with each release
 For more information about contributing test reports, bug fixes, or new
 features and device support, please read the new Developer Manual (or
 the BUGS and PATCHES.txt files in the source archive).
-
diff --git a/TODO b/TODO
index a4102eb..c73d772 100644 (file)
--- a/TODO
+++ b/TODO
@@ -392,4 +392,3 @@ to complete:
 /** @file
 This file contains the @ref thelist page.
 */
-
index b84e3e8..e87959c 100644 (file)
@@ -142,6 +142,9 @@ m4_define([LIBFTDI_ADAPTERS],
 m4_define([LIBJAYLINK_ADAPTERS],
        [[[jlink], [SEGGER J-Link Programmer], [JLINK]]])
 
+m4_define([PCIE_ADAPTERS],
+       [[[xlnx_pcie_xvc], [Xilinx XVC/PCIe], [XLNX_PCIE_XVC]]])
+
 
 AC_ARG_ENABLE([doxygen-html],
   AS_HELP_STRING([--disable-doxygen-html],
@@ -275,6 +278,20 @@ AC_ARG_ENABLE([ioutil],
   [build_ioutil=$enableval], [build_ioutil=no])
 
 AS_CASE(["${host_cpu}"],
+  [arm*|aarch64], [
+    AC_ARG_ENABLE([bcm2835gpio],
+      AS_HELP_STRING([--enable-bcm2835gpio], [Enable building support for bitbanging on BCM2835 (as found in Raspberry Pi)]),
+      [build_bcm2835gpio=$enableval], [build_bcm2835gpio=no])
+    AC_ARG_ENABLE([imx_gpio],
+      AS_HELP_STRING([--enable-imx_gpio], [Enable building support for bitbanging on NXP IMX processors]),
+      [build_imx_gpio=$enableval], [build_imx_gpio=no])
+  ],
+  [
+    build_bcm2835gpio=no
+    build_imx_gpio=no
+])
+
+AS_CASE(["${host_cpu}"],
   [arm*], [
     AC_ARG_ENABLE([ep93xx],
       AS_HELP_STRING([--enable-ep93xx], [Enable building support for EP93xx based SBCs]),
@@ -283,19 +300,10 @@ AS_CASE(["${host_cpu}"],
     AC_ARG_ENABLE([at91rm9200],
       AS_HELP_STRING([--enable-at91rm9200], [Enable building support for AT91RM9200 based SBCs]),
       [build_at91rm9200=$enableval], [build_at91rm9200=no])
-
-    AC_ARG_ENABLE([bcm2835gpio],
-      AS_HELP_STRING([--enable-bcm2835gpio], [Enable building support for bitbanging on BCM2835 (as found in Raspberry Pi)]),
-      [build_bcm2835gpio=$enableval], [build_bcm2835gpio=no])
-    AC_ARG_ENABLE([imx_gpio],
-      AS_HELP_STRING([--enable-imx_gpio], [Enable building support for bitbanging on NXP IMX processors]),
-      [build_imx_gpio=$enableval], [build_imx_gpio=no])
   ],
   [
     build_ep93xx=no
     build_at91rm9200=no
-    build_bcm2835gpio=no
-    build_imx_gpio=no
 ])
 
 AC_ARG_ENABLE([gw16012],
@@ -315,12 +323,20 @@ AC_ARG_ENABLE([sysfsgpio],
   AS_HELP_STRING([--enable-sysfsgpio], [Enable building support for programming driven via sysfs gpios.]),
   [build_sysfsgpio=$enableval], [build_sysfsgpio=no])
 
+AC_ARG_ENABLE([xlnx_pcie_xvc],
+  AS_HELP_STRING([--enable-xlnx-pcie-xvc], [Enable building support for Xilinx XVC/PCIe.]),
+  [build_xlnx_pcie_xvc=$enableval], [build_xlnx_pcie_xvc=no])
+
 AS_CASE([$host_os],
   [linux*], [],
   [
     AS_IF([test "x$build_sysfsgpio" = "xyes"], [
       AC_MSG_ERROR([sysfsgpio is only available on linux])
     ])
+
+    AS_IF([test "x$build_xlnx_pcie_xvc" = "xyes"], [
+      AC_MSG_ERROR([xlnx_pcie_xvc is only available on linux])
+    ])
 ])
 
 AC_ARG_ENABLE([minidriver_dummy],
@@ -580,6 +596,13 @@ AS_IF([test "x$build_sysfsgpio" = "xyes"], [
   AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.])
 ])
 
+AS_IF([test "x$build_xlnx_pcie_xvc" = "xyes"], [
+  build_xlnx_pcie_xvc=yes
+  AC_DEFINE([BUILD_XLNX_PCIE_XVC], [1], [1 if you want the Xilinx XVC/PCIe driver.])
+], [
+  AC_DEFINE([BUILD_XLNX_PCIE_XVC], [0], [0 if you don't want Xilinx XVC/PCIe driver.])
+])
+
 AS_IF([test "x$build_target64" = "xyes"], [
   AC_DEFINE([BUILD_TARGET64], [1], [1 if you want 64-bit addresses.])
 ], [
@@ -699,6 +722,7 @@ AM_CONDITIONAL([OOCD_TRACE], [test "x$build_oocd_trace" = "xyes"])
 AM_CONDITIONAL([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"])
 AM_CONDITIONAL([BUSPIRATE], [test "x$build_buspirate" = "xyes"])
 AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"])
+AM_CONDITIONAL([XLNX_PCIE_XVC], [test "x$build_xlnx_pcie_xvc" = "xyes"])
 AM_CONDITIONAL([USE_LIBUSB0], [test "x$use_libusb0" = "xyes"])
 AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"])
 AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"])
@@ -778,7 +802,7 @@ echo OpenOCD configuration summary
 echo --------------------------------------------------
 m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS,
        HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS,
-       LIBJAYLINK_ADAPTERS],
+       LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS],
        [s=m4_format(["%-40s"], ADAPTER_DESC([adapter]))
        AS_CASE([$ADAPTER_VAR([adapter])],
                [auto], [
index c3eaf12..3948297 100644 (file)
@@ -127,4 +127,4 @@ clean:
 #
 #-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
 
-# *** EOF ***
\ No newline at end of file
+# *** EOF ***
diff --git a/contrib/loaders/flash/sh_qspi/Makefile b/contrib/loaders/flash/sh_qspi/Makefile
new file mode 100644 (file)
index 0000000..2bfbad1
--- /dev/null
@@ -0,0 +1,37 @@
+CROSS_COMPILE=arm-linux-gnueabihf-
+BIN2C = ../../../../src/helper/bin2char.sh
+
+TGT = sh_qspi
+ASRC += sh_qspi.S
+LDS = sh_qspi.ld
+
+OBJS += $(ASRC:.S=.o)
+
+CC=$(CROSS_COMPILE)gcc
+OBJCOPY=$(CROSS_COMPILE)objcopy
+OBJDUMP=$(CROSS_COMPILE)objdump
+LD=$(CROSS_COMPILE)ld
+NM=$(CROSS_COMPILE)nm
+SIZE=$(CROSS_COMPILE)size
+
+CFLAGS=-Os -Wall -nostartfiles -marm -nostdinc -ffreestanding -mabi=aapcs-linux -mword-relocations -fno-pic -mno-unaligned-access -ffunction-sections -fdata-sections -fno-common -msoft-float -pipe -march=armv7-a -mtune=generic-armv7-a
+LDFLAGS=-T$(LDS) -nostdlib -Map=$(TGT).map
+
+all: $(TGT).inc
+
+%.o: %.S
+       $(CC) $(CFLAGS) -c $^ -o $@
+
+$(TGT).elf: $(OBJS)
+       $(LD) $(LDFLAGS) $^ -o $@
+
+$(TGT).bin: $(TGT).elf
+       $(OBJCOPY) $< -O binary $@
+       $(NM) -n $(TGT).elf > $(TGT).sym
+       $(SIZE) $(TGT).elf
+
+$(TGT).inc: $(TGT).bin
+       $(BIN2C) < $< > $@
+
+clean:
+       rm -rf *.elf *.hex *.map *.o *.disasm *.sym
diff --git a/contrib/loaders/flash/sh_qspi/sh_qspi.S b/contrib/loaders/flash/sh_qspi/sh_qspi.S
new file mode 100644 (file)
index 0000000..78eb1e8
--- /dev/null
@@ -0,0 +1,306 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * SH QSPI (Quad SPI) driver
+ * Copyright (C) 2019 Marek Vasut <marek.vasut@gmail.com>
+ */
+
+#define BIT(n)         (1UL << (n))
+/* SH QSPI register bit masks <REG>_<BIT> */
+#define SPCR_MSTR      0x08
+#define SPCR_SPE       0x40
+#define SPSR_SPRFF     0x80
+#define SPSR_SPTEF     0x20
+#define SPPCR_IO3FV    0x04
+#define SPPCR_IO2FV    0x02
+#define SPPCR_IO1FV    0x01
+#define SPBDCR_RXBC0   BIT(0)
+#define SPCMD_SCKDEN   BIT(15)
+#define SPCMD_SLNDEN   BIT(14)
+#define SPCMD_SPNDEN   BIT(13)
+#define SPCMD_SSLKP    BIT(7)
+#define SPCMD_BRDV0    BIT(2)
+#define SPCMD_INIT1    SPCMD_SCKDEN | SPCMD_SLNDEN | \
+                       SPCMD_SPNDEN | SPCMD_SSLKP | \
+                       SPCMD_BRDV0
+#define SPCMD_INIT2    SPCMD_SPNDEN | SPCMD_SSLKP | \
+                       SPCMD_BRDV0
+#define SPBFCR_TXRST   BIT(7)
+#define SPBFCR_RXRST   BIT(6)
+#define SPBFCR_TXTRG   0x30
+#define SPBFCR_RXTRG   0x07
+
+/* SH QSPI register set */
+#define SH_QSPI_SPCR           0x00
+#define SH_QSPI_SSLP           0x01
+#define SH_QSPI_SPPCR          0x02
+#define SH_QSPI_SPSR           0x03
+#define SH_QSPI_SPDR           0x04
+#define SH_QSPI_SPSCR          0x08
+#define SH_QSPI_SPSSR          0x09
+#define SH_QSPI_SPBR           0x0a
+#define SH_QSPI_SPDCR          0x0b
+#define SH_QSPI_SPCKD          0x0c
+#define SH_QSPI_SSLND          0x0d
+#define SH_QSPI_SPND           0x0e
+#define SH_QSPI_DUMMY0         0x0f
+#define SH_QSPI_SPCMD0         0x10
+#define SH_QSPI_SPCMD1         0x12
+#define SH_QSPI_SPCMD2         0x14
+#define SH_QSPI_SPCMD3         0x16
+#define SH_QSPI_SPBFCR         0x18
+#define SH_QSPI_DUMMY1         0x19
+#define SH_QSPI_SPBDCR         0x1a
+#define SH_QSPI_SPBMUL0                0x1c
+#define SH_QSPI_SPBMUL1                0x20
+#define SH_QSPI_SPBMUL2                0x24
+#define SH_QSPI_SPBMUL3                0x28
+
+.syntax unified
+.arm
+.text
+
+.macro wait_for_spsr, spsrbit
+       1:      ldrb    r12, [r0, #SH_QSPI_SPSR]
+               tst     r12, \spsrbit
+               beq     1b
+.endm
+
+.macro sh_qspi_xfer
+       bl      sh_qspi_cs_activate
+       str     r6, [r0, SH_QSPI_SPBMUL0]
+       bl      sh_qspi_xfer_common
+       bl      sh_qspi_cs_deactivate
+.endm
+
+.macro sh_qspi_write_enable
+       ldr     r4,     =SPIFLASH_WRITE_ENABLE
+       adr     r5,     _start
+       add     r4,     r5
+       mov     r5,     #0x0
+       mov     r6,     #0x1
+       sh_qspi_xfer
+.endm
+
+.macro sh_qspi_wait_till_ready
+       1:      ldr     r4,     =SPIFLASH_READ_STATUS
+               adr     r5,     _start
+               add     r4,     r5
+               mov     r5,     #0x0
+               mov     r6,     #0x2
+               sh_qspi_xfer
+               and     r13,    #0x1
+               cmp     r13,    #0x1
+               beq     1b
+.endm
+
+/*
+ * r0: controller base address
+ * r1: data buffer base address
+ * r2: BIT(31) -- page program (not read)
+ *     BIT(30) -- 4-byte address (not 3-byte)
+ *     BIT(29) -- 512-byte page (not 256-byte)
+ *     BIT(27:20) -- SF command
+ *     BIT(19:0)  -- amount of data to read/write
+ * r3: SF target address
+ *
+ * r7: data size
+ * r8: page size
+ *
+ * r14: lr, link register
+ * r15: pc, program counter
+ *
+ * Clobber: r4, r5, r6, r7, r8
+ */
+
+.global _start
+_start:
+       bic     r7,     r2, #0xff000000
+       bic     r7,     r7, #0x00f00000
+
+       and     r8,     r2, #(1 << 31)
+       cmp     r8,     #(1 << 31)
+       beq     do_page_program
+
+/* fast read */
+
+       bl      sh_qspi_cs_activate
+
+       bl      sh_qspi_setup_command
+       add     r8, r6, r7
+       str     r8, [r0, SH_QSPI_SPBMUL0]
+       bl      sh_qspi_xfer_common
+
+       mov     r4,     #0x0
+       mov     r5,     r1
+       mov     r6,     r7
+       bl      sh_qspi_xfer_common
+
+       bl      sh_qspi_cs_deactivate
+
+       b end
+
+do_page_program:
+
+       mov     r8,     #0x100
+       tst     r2,     (1 << 29)
+       movne   r8,     #0x200
+
+do_pp_next_page:
+       /* Check if less then page bytes left. */
+       cmp     r7,     r8
+       movlt   r8,     r7
+
+       sh_qspi_write_enable
+
+       bl      sh_qspi_cs_activate
+
+       bl      sh_qspi_setup_command
+       str     r6, [r0, SH_QSPI_SPBMUL0]
+       bl      sh_qspi_xfer_common
+
+       mov     r4,     r1
+       mov     r5,     #0x0
+       mov     r6,     r8
+
+       bl      sh_qspi_xfer_common
+
+       bl      sh_qspi_cs_deactivate
+
+       sh_qspi_wait_till_ready
+
+       add     r1,     r8
+       add     r3,     r8
+       sub     r7,     r8
+       cmp     r7,     #0
+
+       bne     do_pp_next_page
+
+end:
+       bkpt    #0
+
+sh_qspi_cs_activate:
+       /* Set master mode only */
+       mov     r12,    #SPCR_MSTR
+       strb    r12,    [r0, SH_QSPI_SPCR]
+
+       /* Set command */
+       mov     r12,    #SPCMD_INIT1
+       strh    r12,    [r0, SH_QSPI_SPCMD0]
+
+       /* Reset transfer and receive Buffer */
+       ldrb    r12,    [r0, SH_QSPI_SPSCR]
+       orr     r12,    #(SPBFCR_TXRST | SPBFCR_RXRST)
+       strb    r12,    [r0, SH_QSPI_SPBFCR]
+
+       /* Clear transfer and receive Buffer control bit */
+       ldrb    r12,    [r0, SH_QSPI_SPBFCR]
+       bic     r12,    #(SPBFCR_TXRST | SPBFCR_RXRST)
+       strb    r12,    [r0, SH_QSPI_SPBFCR]
+
+       /* Set sequence control method. Use sequence0 only */
+       mov     r12,    #0x00
+       strb    r12,    [r0, SH_QSPI_SPSCR]
+
+       /* Enable SPI function */
+       ldrb    r12,    [r0, SH_QSPI_SPCR]
+       orr     r12,    #SPCR_SPE
+       strb    r12,    [r0, SH_QSPI_SPCR]
+
+       mov     pc,     lr
+
+sh_qspi_cs_deactivate:
+       /* Disable SPI function */
+       ldrb    r12,    [r0, SH_QSPI_SPCR]
+       bic     r12,    #SPCR_SPE
+       strb    r12,    [r0, SH_QSPI_SPCR]
+
+       mov     pc,     lr
+
+/*
+ * r0, controller base address
+ * r4, tx buffer
+ * r5, rx buffer
+ * r6, xfer len, non-zero
+ *
+ * Upon exit, r13 contains the last byte in SPDR
+ *
+ * Clobber: r11, r12, r13
+ */
+sh_qspi_xfer_common:
+prepcopy:
+       ldr     r13, [r0, #SH_QSPI_SPBFCR]
+       orr     r13, #(SPBFCR_TXTRG | SPBFCR_RXTRG)
+       mov     r11, #32
+       cmp     r6, #32
+
+       biclt   r13, #(SPBFCR_TXTRG | SPBFCR_RXTRG)
+       movlt   r11, #1
+
+copy:
+       str     r13, [r0, #SH_QSPI_SPBFCR]
+
+       wait_for_spsr SPSR_SPTEF
+
+       mov     r12, r11
+       mov     r13, #0
+       cmp     r4, #0
+       beq     3f
+
+2:     ldrb    r13, [r4], #1
+       strb    r13, [r0, #SH_QSPI_SPDR]
+       subs    r12, #1
+       bne     2b
+       b       4f
+
+3:     strb    r13, [r0, #SH_QSPI_SPDR]
+       subs    r12, #1
+       bne     3b
+
+4:     wait_for_spsr SPSR_SPRFF
+
+       mov     r12, r11
+       cmp     r5, #0
+       beq     6f
+
+5:     ldrb    r13, [r0, #SH_QSPI_SPDR]
+       strb    r13, [r5], #1
+       subs    r12, #1
+       bne     5b
+       b       7f
+
+6:     ldrb    r13, [r0, #SH_QSPI_SPDR]
+       subs    r12, #1
+       bne     6b
+
+7:     subs    r6, r11
+       bne     prepcopy
+
+       mov     pc,     lr
+
+sh_qspi_setup_command:
+       ldr     r4,     =SPIFLASH_SCRATCH_DATA
+       adr     r5,     _start
+       add     r4,     r5
+       and     r12,    r2, #0x0ff00000
+       lsr     r12,    #20
+       strb    r12,    [r4]
+       mov     r12,    r3
+       strb    r12,    [r4, #4]
+       lsr     r12,    #8
+       strb    r12,    [r4, #3]
+       lsr     r12,    #8
+       strb    r12,    [r4, #2]
+       lsr     r12,    #8
+       strb    r12,    [r4, #1]
+       lsr     r12,    #8
+       mov     r5,     #0x0
+       mov     r6,     #0x4
+       tst     r2,     (1 << 30)
+       movne   r6,     #0x5
+
+       mov     pc,     lr
+
+SPIFLASH_READ_STATUS:  .byte   0x05 /* Read Status Register */
+SPIFLASH_WRITE_ENABLE: .byte   0x06 /* Write Enable */
+SPIFLASH_NOOP:         .byte   0x00
+SPIFLASH_SCRATCH_DATA: .byte   0x00, 0x0, 0x0, 0x0, 0x0
diff --git a/contrib/loaders/flash/sh_qspi/sh_qspi.inc b/contrib/loaders/flash/sh_qspi/sh_qspi.inc
new file mode 100644 (file)
index 0000000..ca91392
--- /dev/null
@@ -0,0 +1,37 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0xff,0x74,0xc2,0xe3,0x0f,0x76,0xc7,0xe3,0x02,0x81,0x02,0xe2,0x02,0x01,0x58,0xe3,
+0x0a,0x00,0x00,0x0a,0x32,0x00,0x00,0xeb,0x6c,0x00,0x00,0xeb,0x07,0x80,0x86,0xe0,
+0x1c,0x80,0x80,0xe5,0x42,0x00,0x00,0xeb,0x00,0x40,0xa0,0xe3,0x01,0x50,0xa0,0xe1,
+0x07,0x60,0xa0,0xe1,0x3e,0x00,0x00,0xeb,0x39,0x00,0x00,0xeb,0x27,0x00,0x00,0xea,
+0x01,0x8c,0xa0,0xe3,0x02,0x02,0x12,0xe3,0x02,0x8c,0xa0,0x13,0x08,0x00,0x57,0xe1,
+0x07,0x80,0xa0,0xb1,0xcc,0x41,0x9f,0xe5,0x60,0x50,0x4f,0xe2,0x05,0x40,0x84,0xe0,
+0x00,0x50,0xa0,0xe3,0x01,0x60,0xa0,0xe3,0x1d,0x00,0x00,0xeb,0x1c,0x60,0x80,0xe5,
+0x2f,0x00,0x00,0xeb,0x2a,0x00,0x00,0xeb,0x19,0x00,0x00,0xeb,0x53,0x00,0x00,0xeb,
+0x1c,0x60,0x80,0xe5,0x2a,0x00,0x00,0xeb,0x01,0x40,0xa0,0xe1,0x00,0x50,0xa0,0xe3,
+0x08,0x60,0xa0,0xe1,0x26,0x00,0x00,0xeb,0x21,0x00,0x00,0xeb,0x88,0x41,0x9f,0xe5,
+0xa8,0x50,0x4f,0xe2,0x05,0x40,0x84,0xe0,0x00,0x50,0xa0,0xe3,0x02,0x60,0xa0,0xe3,
+0x0b,0x00,0x00,0xeb,0x1c,0x60,0x80,0xe5,0x1d,0x00,0x00,0xeb,0x18,0x00,0x00,0xeb,
+0x01,0xd0,0x0d,0xe2,0x01,0x00,0x5d,0xe3,0xf3,0xff,0xff,0x0a,0x08,0x10,0x81,0xe0,
+0x08,0x30,0x83,0xe0,0x08,0x70,0x47,0xe0,0x00,0x00,0x57,0xe3,0xda,0xff,0xff,0x1a,
+0x70,0x00,0x20,0xe1,0x08,0xc0,0xa0,0xe3,0x00,0xc0,0xc0,0xe5,0x84,0xc0,0x0e,0xe3,
+0xb0,0xc1,0xc0,0xe1,0x08,0xc0,0xd0,0xe5,0xc0,0xc0,0x8c,0xe3,0x18,0xc0,0xc0,0xe5,
+0x18,0xc0,0xd0,0xe5,0xc0,0xc0,0xcc,0xe3,0x18,0xc0,0xc0,0xe5,0x00,0xc0,0xa0,0xe3,
+0x08,0xc0,0xc0,0xe5,0x00,0xc0,0xd0,0xe5,0x40,0xc0,0x8c,0xe3,0x00,0xc0,0xc0,0xe5,
+0x0e,0xf0,0xa0,0xe1,0x00,0xc0,0xd0,0xe5,0x40,0xc0,0xcc,0xe3,0x00,0xc0,0xc0,0xe5,
+0x0e,0xf0,0xa0,0xe1,0x18,0xd0,0x90,0xe5,0x37,0xd0,0x8d,0xe3,0x20,0xb0,0xa0,0xe3,
+0x20,0x00,0x56,0xe3,0x37,0xd0,0xcd,0xb3,0x01,0xb0,0xa0,0xb3,0x18,0xd0,0x80,0xe5,
+0x03,0xc0,0xd0,0xe5,0x20,0x00,0x1c,0xe3,0xfc,0xff,0xff,0x0a,0x0b,0xc0,0xa0,0xe1,
+0x00,0xd0,0xa0,0xe3,0x00,0x00,0x54,0xe3,0x04,0x00,0x00,0x0a,0x01,0xd0,0xd4,0xe4,
+0x04,0xd0,0xc0,0xe5,0x01,0xc0,0x5c,0xe2,0xfb,0xff,0xff,0x1a,0x02,0x00,0x00,0xea,
+0x04,0xd0,0xc0,0xe5,0x01,0xc0,0x5c,0xe2,0xfc,0xff,0xff,0x1a,0x03,0xc0,0xd0,0xe5,
+0x80,0x00,0x1c,0xe3,0xfc,0xff,0xff,0x0a,0x0b,0xc0,0xa0,0xe1,0x00,0x00,0x55,0xe3,
+0x04,0x00,0x00,0x0a,0x04,0xd0,0xd0,0xe5,0x01,0xd0,0xc5,0xe4,0x01,0xc0,0x5c,0xe2,
+0xfb,0xff,0xff,0x1a,0x02,0x00,0x00,0xea,0x04,0xd0,0xd0,0xe5,0x01,0xc0,0x5c,0xe2,
+0xfc,0xff,0xff,0x1a,0x0b,0x60,0x56,0xe0,0xd9,0xff,0xff,0x1a,0x0e,0xf0,0xa0,0xe1,
+0x58,0x40,0x9f,0xe5,0x77,0x5f,0x4f,0xe2,0x05,0x40,0x84,0xe0,0xff,0xc6,0x02,0xe2,
+0x2c,0xca,0xa0,0xe1,0x00,0xc0,0xc4,0xe5,0x03,0xc0,0xa0,0xe1,0x04,0xc0,0xc4,0xe5,
+0x2c,0xc4,0xa0,0xe1,0x03,0xc0,0xc4,0xe5,0x2c,0xc4,0xa0,0xe1,0x02,0xc0,0xc4,0xe5,
+0x2c,0xc4,0xa0,0xe1,0x01,0xc0,0xc4,0xe5,0x2c,0xc4,0xa0,0xe1,0x00,0x50,0xa0,0xe3,
+0x04,0x60,0xa0,0xe3,0x01,0x01,0x12,0xe3,0x05,0x60,0xa0,0x13,0x0e,0xf0,0xa0,0xe1,
+0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x02,0x00,0x00,0x20,0x02,0x00,0x00,
+0x23,0x02,0x00,0x00,
diff --git a/contrib/loaders/flash/sh_qspi/sh_qspi.ld b/contrib/loaders/flash/sh_qspi/sh_qspi.ld
new file mode 100644 (file)
index 0000000..2683c52
--- /dev/null
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+       . = 0x0;
+       . = ALIGN(4);
+       .text : {
+               sh_qspi.o (.text*)
+               *(.text*)
+       }
+}
index 9c49016..e0ce3cb 100644 (file)
@@ -71,7 +71,7 @@ busy:
        ldr     r6, [r4, #STM32_FLASH_SR_OFFSET]
        tst     r6, #0x10000    /* BSY (bit16) == 1 => operation in progress */
        bne     busy            /* wait more... */
-       tst     r6, #0xfa       /* PGSERR | PGPERR | PGAERR | WRPERR | PROGERR*/
+       tst     r6, #0xfa       /* PGSERR | SIZERR | PGAERR | WRPERR | PROGERR | OPERR */
        bne     error           /* fail... */
 
        cmp     r5, r1          /* wrap rp at end of buffer */
index a18c33e..33b2a16 100644 (file)
@@ -449,4 +449,3 @@ to permit their use in free software.
 @c Local Variables:
 @c ispell-local-pdict: "ispell-dict"
 @c End:
-
index c526a63..d059cfa 100644 (file)
@@ -617,6 +617,9 @@ produced, PDF schematics are easily found and it is easy to make.
 @* A JTAG driver acting as a client for the JTAG VPI server interface.
 @* Link: @url{http://github.com/fjullien/jtag_vpi}
 
+@item @b{xlnx_pcie_xvc}
+@* A JTAG driver exposing Xilinx Virtual Cable over PCI Express to OpenOCD as JTAG interface.
+
 @end itemize
 
 @node About Jim-Tcl
@@ -1571,7 +1574,7 @@ solution just avoids using that instruction with JTAG debuggers.
 If both the chip and the board support adaptive clocking,
 use the @command{jtag_rclk}
 command, in case your board is used with JTAG adapter which
-also supports it. Otherwise use @command{adapter_khz}.
+also supports it. Otherwise use @command{adapter speed}.
 Set the slow rate at the beginning of the reset sequence,
 and the faster rate as soon as the clocks are at full speed.
 
@@ -1611,12 +1614,12 @@ proc init_board @{@} @{
     reset_config trst_and_srst trst_pulls_srst
 
     $_TARGETNAME configure -event reset-start @{
-        adapter_khz 100
+        adapter speed 100
     @}
 
     $_TARGETNAME configure -event reset-init @{
         enable_fast_clock
-        adapter_khz 10000
+        adapter speed 10000
     @}
 @}
 @end example
@@ -2335,28 +2338,28 @@ A few cases are so simple that you only need to say what driver to use:
 
 @example
 # jlink interface
-interface jlink
+adapter driver jlink
 @end example
 
 Most adapters need a bit more configuration than that.
 
 
-@section Interface Configuration
+@section Adapter Configuration
 
-The interface command tells OpenOCD what type of debug adapter you are
+The @command{adapter driver} command tells OpenOCD what type of debug adapter you are
 using. Depending on the type of adapter, you may need to use one or
 more additional commands to further identify or configure the adapter.
 
-@deffn {Config Command} {interface} name
-Use the interface driver @var{name} to connect to the
+@deffn {Config Command} {adapter driver} name
+Use the adapter driver @var{name} to connect to the
 target.
 @end deffn
 
-@deffn Command {interface_list}
+@deffn Command {adapter list}
 List the debug adapter drivers that have been built into
 the running copy of OpenOCD.
 @end deffn
-@deffn Command {interface transports} transport_name+
+@deffn Command {adapter transports} transport_name+
 Specifies the transports supported by this debug adapter.
 The adapter driver builds-in similar knowledge; use this only
 when external configuration (such as jumpering) changes what
@@ -2365,7 +2368,7 @@ the hardware can support.
 
 
 
-@deffn Command {adapter_name}
+@deffn Command {adapter name}
 Returns the name of the debug adapter driver being used.
 @end deffn
 
@@ -2716,7 +2719,7 @@ For example, to connect remotely via TCP to the host foobar you might have
 something like:
 
 @example
-interface remote_bitbang
+adapter driver remote_bitbang
 remote_bitbang_port 3335
 remote_bitbang_host foobar
 @end example
@@ -2725,7 +2728,7 @@ To connect to another process running locally via UNIX sockets with socket
 named mysocket:
 
 @example
-interface remote_bitbang
+adapter driver remote_bitbang
 remote_bitbang_port 0
 remote_bitbang_host mysocket
 @end example
@@ -2990,7 +2993,7 @@ you may encounter a problem.
 @deffn Command {parport_toggling_time} [nanoseconds]
 Displays how many nanoseconds the hardware needs to toggle TCK;
 the parport driver uses this value to obey the
-@command{adapter_khz} configuration.
+@command{adapter speed} configuration.
 When the optional @var{nanoseconds} parameter is given,
 that setting is changed before displaying the current value.
 
@@ -3001,7 +3004,7 @@ To measure the toggling time with a logic analyzer or a digital storage
 oscilloscope, follow the procedure below:
 @example
 > parport_toggling_time 1000
-> adapter_khz 500
+> adapter speed 500
 @end example
 This sets the maximum JTAG clock speed of the hardware, but
 the actual speed probably deviates from the requested 500 kHz.
@@ -3012,14 +3015,15 @@ Update the setting to match your measurement:
 @example
 > parport_toggling_time <measured nanoseconds>
 @end example
-Now the clock speed will be a better match for @command{adapter_khz rate}
-commands given in OpenOCD scripts and event handlers.
+Now the clock speed will be a better match for @command{adapter speed}
+command given in OpenOCD scripts and event handlers.
 
 You can do something similar with many digital multimeters, but note
 that you'll probably need to run the clock continuously for several
 seconds before it decides what clock rate to show. Adjust the
 toggling time up or down until the measured clock rate is a good
-match for the adapter_khz rate you specified; be conservative.
+match with the rate you specified in the @command{adapter speed} command;
+be conservative.
 @end quotation
 @end deffn
 
@@ -3032,7 +3036,7 @@ For example, the interface configuration file for a
 classic ``Wiggler'' cable on LPT2 might look something like this:
 
 @example
-interface parport
+adapter driver parport
 parport_port 0x278
 parport_cable wiggler
 @end example
@@ -3127,6 +3131,25 @@ opendous-jtag is a freely programmable USB adapter.
 This is the Keil ULINK v1 JTAG debugger.
 @end deffn
 
+@deffn {Interface Driver} {xlnx_pcie_xvc}
+This driver supports the Xilinx Virtual Cable (XVC) over PCI Express.
+It is commonly found in Xilinx based PCI Express designs. It allows debugging
+fabric based JTAG devices such as Cortex-M1/M3 microcontrollers. Access to this is
+exposed via extended capability registers in the PCI Express configuration space.
+
+For more information see Xilinx PG245 (Section on From_PCIE_to_JTAG mode).
+
+@deffn {Config Command} {xlnx_pcie_xvc_config} device
+Specifies the PCI Express device via parameter @var{device} to use.
+
+The correct value for @var{device} can be obtained by looking at the output
+of lscpi -D (first column) for the corresponding device.
+
+The string will be of the format "DDDD:BB:SS.F" such as "0000:65:00.1".
+
+@end deffn
+@end deffn
+
 @deffn {Interface Driver} {ZY1000}
 This is the Zylin ZY1000 JTAG debugger.
 @end deffn
@@ -3307,10 +3330,10 @@ However, it introduces delays to synchronize clocks; so it
 may not be the fastest solution.
 
 @b{NOTE:} Script writers should consider using @command{jtag_rclk}
-instead of @command{adapter_khz}, but only for (ARM) cores and boards
+instead of @command{adapter speed}, but only for (ARM) cores and boards
 which support adaptive clocking.
 
-@deffn {Command} adapter_khz max_speed_kHz
+@deffn {Command} adapter speed max_speed_kHz
 A non-zero speed is in KHZ. Hence: 3000 is 3mhz.
 JTAG interfaces usually support a limited number of
 speeds. The speed actually used won't be faster
@@ -3440,7 +3463,7 @@ stops issuing the reset. For example, there may be chip or board
 requirements that all reset pulses last for at least a
 certain amount of time; and reset buttons commonly have
 hardware debouncing.
-Use the @command{adapter_nsrst_delay} and @command{jtag_ntrst_delay}
+Use the @command{adapter srst delay} and @command{jtag_ntrst_delay}
 commands to say when extra delays are needed.
 
 @item @emph{Drive type} ... Reset lines often have a pullup
@@ -3480,13 +3503,13 @@ needing to cope with both architecture and board specific constraints.
 
 @section Commands for Handling Resets
 
-@deffn {Command} adapter_nsrst_assert_width milliseconds
+@deffn {Command} adapter srst pulse_width milliseconds
 Minimum amount of time (in milliseconds) OpenOCD should wait
 after asserting nSRST (active-low system reset) before
 allowing it to be deasserted.
 @end deffn
 
-@deffn {Command} adapter_nsrst_delay milliseconds
+@deffn {Command} adapter srst delay milliseconds
 How long (in milliseconds) OpenOCD should wait after deasserting
 nSRST (active-low system reset) before starting new JTAG operations.
 When a board has a reset button connected to SRST line it will
@@ -4867,7 +4890,7 @@ the target clocks are fully set up.)
 before @command{reset-assert-pre} is called.
 
 This is the most robust place to use @command{jtag_rclk}
-or @command{adapter_khz} to switch to a low JTAG clock rate,
+or @command{adapter speed} to switch to a low JTAG clock rate,
 when reset disables PLLs needed to use a fast clock.
 @item @b{resume-start}
 @* Before any target is resumed
@@ -5051,10 +5074,11 @@ If @option{unlock} is specified, then the flash is unprotected
 before erase starts.
 @end deffn
 
-@deffn Command {flash fillw} address word length
+@deffn Command {flash filld} address double-word length
+@deffnx Command {flash fillw} address word length
 @deffnx Command {flash fillh} address halfword length
 @deffnx Command {flash fillb} address byte length
-Fills flash memory with the specified @var{word} (32 bits),
+Fills flash memory with the specified @var{double-word} (64 bits), @var{word} (32 bits),
 @var{halfword} (16 bits), or @var{byte} (8-bit) pattern,
 starting at @var{address} and continuing
 for @var{length} units (word/halfword/byte).
@@ -6829,7 +6853,7 @@ stm32h7x option_write 0 0x20 0x8000000 0x8000000
 @end deffn
 
 @deffn {Flash Driver} stm32lx
-All members of the STM32L microcontroller families from STMicroelectronics
+All members of the STM32L0 and STM32L1 microcontroller families from STMicroelectronics
 include internal flash and use ARM Cortex-M3 and Cortex-M0+ cores.
 The driver automatically recognizes a number of these chips using
 the chip identification register, and autoconfigures itself.
@@ -7767,9 +7791,9 @@ echo "Downloading kernel -- please wait"
 @end example
 @end deffn
 
-@deffn Command log_output [filename]
-Redirect logging to @var{filename};
-the initial log output channel is stderr.
+@deffn Command log_output [filename | "default"]
+Redirect logging to @var{filename} or set it back to default output;
+the default log output channel is stderr.
 @end deffn
 
 @deffn Command add_script_search_dir [directory]
@@ -10714,7 +10738,7 @@ To set the JTAG frequency use the command:
 
 @example
 # Example: 1.234MHz
-adapter_khz 1234
+adapter speed 1234
 @end example
 
 
index 34f91ce..18b3b85 100644 (file)
@@ -51,6 +51,8 @@ NOR_DRIVERS = \
        %D%/psoc4.c \
        %D%/psoc5lp.c \
        %D%/psoc6.c \
+       %D%/renesas_rpchf.c \
+       %D%/sh_qspi.c \
        %D%/sim3x.c \
        %D%/spi.c \
        %D%/stmsmi.c \
index b1e3e72..b41b15c 100644 (file)
@@ -253,8 +253,7 @@ static int ambiqmicro_read_part_info(struct flash_bank *bank)
 
        }
 
-       if (ambiqmicro_info->target_class <
-               (sizeof(ambiqmicroParts)/sizeof(ambiqmicroParts[0])))
+       if (ambiqmicro_info->target_class < ARRAY_SIZE(ambiqmicroParts))
                ambiqmicro_info->target_name =
                        ambiqmicroParts[ambiqmicro_info->target_class].partname;
        else
index bcb1f57..224f174 100644 (file)
@@ -34,9 +34,6 @@
 #include <helper/binarybuffer.h>
 #include <target/algorithm.h>
 
-#define CFI_MAX_BUS_WIDTH       4
-#define CFI_MAX_CHIP_WIDTH      4
-
 /* defines internal maximum size for code fragment in cfi_intel_write_block() */
 #define CFI_MAX_INTEL_CODESIZE 256
 
@@ -112,7 +109,7 @@ static void cfi_fixup(struct flash_bank *bank, const struct cfi_fixup *fixups)
        }
 }
 
-static inline uint32_t cfi_flash_address(struct flash_bank *bank, int sector, uint32_t offset)
+uint32_t cfi_flash_address(struct flash_bank *bank, int sector, uint32_t offset)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
 
@@ -143,8 +140,8 @@ static int cfi_target_write_memory(struct flash_bank *bank, target_addr_t addr,
        }
 }
 
-static int cfi_target_read_memory(struct flash_bank *bank, target_addr_t addr,
-                                 uint32_t count, uint8_t *buffer)
+int cfi_target_read_memory(struct flash_bank *bank, target_addr_t addr,
+                          uint32_t count, uint8_t *buffer)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
        if (cfi_info->read_mem) {
@@ -175,7 +172,7 @@ static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
        }
 }
 
-static int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t address)
+int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t address)
 {
        uint8_t command[CFI_MAX_BUS_WIDTH];
 
@@ -298,7 +295,7 @@ static int cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offset, u
        return ERROR_OK;
 }
 
-static int cfi_reset(struct flash_bank *bank)
+int cfi_reset(struct flash_bank *bank)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
        int retval = ERROR_OK;
@@ -379,7 +376,7 @@ static int cfi_intel_wait_status_busy(struct flash_bank *bank, int timeout, uint
        return retval;
 }
 
-static int cfi_spansion_wait_status_busy(struct flash_bank *bank, int timeout)
+int cfi_spansion_wait_status_busy(struct flash_bank *bank, int timeout)
 {
        uint8_t status, oldstatus;
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
@@ -819,14 +816,12 @@ static int cfi_intel_info(struct flash_bank *bank, char *buf, int buf_size)
        return ERROR_OK;
 }
 
-/* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#> [options]
- */
-FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command)
+int cfi_flash_bank_cmd(struct flash_bank *bank, unsigned int argc, const char **argv)
 {
        struct cfi_flash_bank *cfi_info;
        int bus_swap = 0;
 
-       if (CMD_ARGC < 6)
+       if (argc < 6)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        /* both widths must:
@@ -856,14 +851,14 @@ FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command)
        cfi_info->not_cfi = 0;
        cfi_info->data_swap = 0;
 
-       for (unsigned i = 6; i < CMD_ARGC; i++) {
-               if (strcmp(CMD_ARGV[i], "x16_as_x8") == 0)
+       for (unsigned i = 6; i < argc; i++) {
+               if (strcmp(argv[i], "x16_as_x8") == 0)
                        cfi_info->x16_as_x8 = 1;
-               else if (strcmp(CMD_ARGV[i], "data_swap") == 0)
+               else if (strcmp(argv[i], "data_swap") == 0)
                        cfi_info->data_swap = 1;
-               else if (strcmp(CMD_ARGV[i], "bus_swap") == 0)
+               else if (strcmp(argv[i], "bus_swap") == 0)
                        bus_swap = 1;
-               else if (strcmp(CMD_ARGV[i], "jedec_probe") == 0)
+               else if (strcmp(argv[i], "jedec_probe") == 0)
                        cfi_info->jedec_probe = 1;
        }
 
@@ -880,6 +875,13 @@ FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command)
        return ERROR_OK;
 }
 
+/* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#> [options]
+ */
+FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command)
+{
+       return cfi_flash_bank_cmd(bank, CMD_ARGC, CMD_ARGV);
+}
+
 static int cfi_intel_erase(struct flash_bank *bank, int first, int last)
 {
        int retval;
@@ -918,7 +920,7 @@ static int cfi_intel_erase(struct flash_bank *bank, int first, int last)
        return cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0));
 }
 
-static int cfi_spansion_unlock_seq(struct flash_bank *bank)
+int cfi_spansion_unlock_seq(struct flash_bank *bank)
 {
        int retval;
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
@@ -975,7 +977,7 @@ static int cfi_spansion_erase(struct flash_bank *bank, int first, int last)
        return cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0));
 }
 
-static int cfi_erase(struct flash_bank *bank, int first, int last)
+int cfi_erase(struct flash_bank *bank, int first, int last)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
 
@@ -1118,7 +1120,7 @@ static int cfi_intel_protect(struct flash_bank *bank, int set, int first, int la
        return cfi_send_command(bank, 0xff, cfi_flash_address(bank, 0, 0x0));
 }
 
-static int cfi_protect(struct flash_bank *bank, int set, int first, int last)
+int cfi_protect(struct flash_bank *bank, int set, int first, int last)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
 
@@ -2220,7 +2222,7 @@ static int cfi_spansion_write_words(struct flash_bank *bank, const uint8_t *word
        return ERROR_OK;
 }
 
-static int cfi_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address)
+int cfi_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
 
@@ -2591,7 +2593,7 @@ static int cfi_query_string(struct flash_bank *bank, int address)
        return ERROR_OK;
 }
 
-static int cfi_probe(struct flash_bank *bank)
+int cfi_probe(struct flash_bank *bank)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
        struct target *target = bank->target;
@@ -2927,7 +2929,7 @@ static int cfi_probe(struct flash_bank *bank)
        return ERROR_OK;
 }
 
-static int cfi_auto_probe(struct flash_bank *bank)
+int cfi_auto_probe(struct flash_bank *bank)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
        if (cfi_info->probed)
@@ -2995,7 +2997,7 @@ static int cfi_spansion_protect_check(struct flash_bank *bank)
        return cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0));
 }
 
-static int cfi_protect_check(struct flash_bank *bank)
+int cfi_protect_check(struct flash_bank *bank)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
 
@@ -3023,7 +3025,7 @@ static int cfi_protect_check(struct flash_bank *bank)
        return ERROR_OK;
 }
 
-static int cfi_get_info(struct flash_bank *bank, char *buf, int buf_size)
+int cfi_get_info(struct flash_bank *bank, char *buf, int buf_size)
 {
        int printed;
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
index 9451faa..aef7a04 100644 (file)
@@ -154,6 +154,24 @@ struct cfi_fixup {
        const void *param;
 };
 
+int cfi_erase(struct flash_bank *bank, int first, int last);
+int cfi_protect(struct flash_bank *bank, int set, int first, int last);
+int cfi_probe(struct flash_bank *bank);
+int cfi_auto_probe(struct flash_bank *bank);
+int cfi_protect_check(struct flash_bank *bank);
+int cfi_get_info(struct flash_bank *bank, char *buf, int buf_size);
+int cfi_flash_bank_cmd(struct flash_bank *bank, unsigned int argc, const char **argv);
+
+uint32_t cfi_flash_address(struct flash_bank *bank, int sector, uint32_t offset);
+int cfi_spansion_unlock_seq(struct flash_bank *bank);
+int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t address);
+int cfi_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address);
+int cfi_spansion_wait_status_busy(struct flash_bank *bank, int timeout);
+int cfi_reset(struct flash_bank *bank);
+
+int cfi_target_read_memory(struct flash_bank *bank, target_addr_t addr,
+                          uint32_t count, uint8_t *buffer);
+
 #define CFI_MFR_AMD            0x0001
 #define CFI_MFR_FUJITSU        0x0004
 #define CFI_MFR_ATMEL  0x001F
@@ -166,4 +184,7 @@ struct cfi_fixup {
 #define CFI_MFR_ANY            0xffff
 #define CFI_ID_ANY             0xffff
 
+#define CFI_MAX_BUS_WIDTH       4
+#define CFI_MAX_CHIP_WIDTH      4
+
 #endif /* OPENOCD_FLASH_NOR_CFI_H */
index 551f389..d52e072 100644 (file)
@@ -66,6 +66,8 @@ extern const struct flash_driver psoc5lp_flash;
 extern const struct flash_driver psoc5lp_eeprom_flash;
 extern const struct flash_driver psoc5lp_nvl_flash;
 extern const struct flash_driver psoc6_flash;
+extern const struct flash_driver renesas_rpchf_flash;
+extern const struct flash_driver sh_qspi_flash;
 extern const struct flash_driver sim3x_flash;
 extern const struct flash_driver stellaris_flash;
 extern const struct flash_driver stm32f1x_flash;
@@ -136,6 +138,8 @@ static const struct flash_driver * const flash_drivers[] = {
        &psoc5lp_eeprom_flash,
        &psoc5lp_nvl_flash,
        &psoc6_flash,
+       &renesas_rpchf_flash,
+       &sh_qspi_flash,
        &sim3x_flash,
        &stellaris_flash,
        &stm32f1x_flash,
index 37b60f0..da67585 100644 (file)
@@ -154,7 +154,7 @@ static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first,
  *
  * @return
  */
-static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_tbuffer,
+static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_t *buffer,
                                 uint32_t offset, uint32_t count)
 {
        int retval;
index 245f856..479e0d4 100644 (file)
@@ -140,6 +140,7 @@ static const struct efm32_family_data efm32_families[] = {
                { 43, "EFR32BG13P Blue", .series = 1 },
                { 44, "EFR32BG13B Blue", .series = 1 },
                { 45, "EFR32BG13V Blue", .series = 1 },
+               { 46, "EFR32ZG13P Zen", .series = 1 },
                { 49, "EFR32FG13P Flex", .series = 1 },
                { 50, "EFR32FG13B Flex", .series = 1 },
                { 51, "EFR32FG13V Flex", .series = 1 },
@@ -149,6 +150,7 @@ static const struct efm32_family_data efm32_families[] = {
                { 55, "EFR32BG14P Blue", .series = 1 },
                { 56, "EFR32BG14B Blue", .series = 1 },
                { 57, "EFR32BG14V Blue", .series = 1 },
+               { 58, "EFR32ZG14P Zen", .series = 1 },
                { 61, "EFR32FG14P Flex", .series = 1 },
                { 62, "EFR32FG14B Flex", .series = 1 },
                { 63, "EFR32FG14V Flex", .series = 1 },
index d923468..8422589 100644 (file)
@@ -609,7 +609,7 @@ static int nrf5_info(struct flash_bank *bank, char *buf, int buf_size)
                                variant, &variant[2]);
 
        } else {
-               res = snprintf(buf, buf_size, "nRF51xxx (HWID 0x%04" PRIx16 ")",
+               res = snprintf(buf, buf_size, "nRF51xxx (HWID 0x%08" PRIx32 ")",
                                chip->hwid);
        }
        if (res <= 0)
index c62af04..c6dbfb8 100644 (file)
@@ -1216,7 +1216,7 @@ static int numicro_init_isp(struct target *target)
        return ERROR_OK;
 }
 
-static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t addr, uint32_t wdata, uint32_trdata)
+static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t addr, uint32_t wdata, uint32_t *rdata)
 {
        uint32_t timeout, status;
        int retval = ERROR_OK;
@@ -1649,7 +1649,7 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
        return ERROR_OK;
 }
 
-static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type** cpu)
+static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type **cpu)
 {
        uint32_t part_id;
        int retval = ERROR_OK;
@@ -1663,7 +1663,7 @@ static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_
 
        LOG_INFO("Device ID: 0x%08" PRIx32 "", part_id);
        /* search part numbers */
-       for (size_t i = 0; i < sizeof(NuMicroParts)/sizeof(NuMicroParts[0]); i++) {
+       for (size_t i = 0; i < ARRAY_SIZE(NuMicroParts); i++) {
                if (part_id == NuMicroParts[i].partid) {
                        *cpu = &NuMicroParts[i];
                        LOG_INFO("Device Name: %s", (*cpu)->partname);
index 386075e..3cdfcc4 100644 (file)
@@ -108,7 +108,7 @@ static const struct row_region safe_sflash_regions[] = {
        {0x16007C00, 0x400},    /* SFLASH: TOC2 */
 };
 
-#define SFLASH_NUM_REGIONS (sizeof(safe_sflash_regions) / sizeof(safe_sflash_regions[0]))
+#define SFLASH_NUM_REGIONS ARRAY_SIZE(safe_sflash_regions)
 
 static struct working_area *g_stack_area;
 static struct armv7m_algorithm g_armv7m_info;
diff --git a/src/flash/nor/renesas_rpchf.c b/src/flash/nor/renesas_rpchf.c
new file mode 100644 (file)
index 0000000..3f03f92
--- /dev/null
@@ -0,0 +1,648 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Renesas RCar Gen3 RPC Hyperflash driver
+ * Based on U-Boot RPC Hyperflash driver
+ *
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ * Copyright (C) 2016 Cogent Embedded, Inc.
+ * Copyright (C) 2017-2019 Marek Vasut <marek.vasut@gmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imp.h"
+#include "cfi.h"
+#include "non_cfi.h"
+#include <helper/binarybuffer.h>
+#include <helper/bits.h>
+#include <helper/time_support.h>
+
+#define RPC_CMNCR              0x0000  /* R/W */
+#define RPC_CMNCR_MD           BIT(31)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO_HIZ    (RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+                                RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12)
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14)
+#define RPC_CMNCR_IOFV_HIZ     (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+                                RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val)     (((val) & 0x3) << 0)
+
+#define RPC_SSLDR              0x0004  /* R/W */
+#define RPC_SSLDR_SPNDL(d)     (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d)     (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d)     (((d) & 0x7) << 0)
+
+#define RPC_DRCR               0x000C  /* R/W */
+#define RPC_DRCR_SSLN          BIT(24)
+#define RPC_DRCR_RBURST(v)     (((v) & 0x1F) << 16)
+#define RPC_DRCR_RCF           BIT(9)
+#define RPC_DRCR_RBE           BIT(8)
+#define RPC_DRCR_SSLE          BIT(0)
+
+#define RPC_DRCMR              0x0010  /* R/W */
+#define RPC_DRCMR_CMD(c)       (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)      (((c) & 0xFF) << 0)
+
+#define RPC_DREAR              0x0014  /* R/W */
+#define RPC_DREAR_EAV(v)       (((v) & 0xFF) << 16)
+#define RPC_DREAR_EAC(v)       (((v) & 0x7) << 0)
+
+#define RPC_DROPR              0x0018  /* R/W */
+#define RPC_DROPR_OPD3(o)      (((o) & 0xFF) << 24)
+#define RPC_DROPR_OPD2(o)      (((o) & 0xFF) << 16)
+#define RPC_DROPR_OPD1(o)      (((o) & 0xFF) << 8)
+#define RPC_DROPR_OPD0(o)      (((o) & 0xFF) << 0)
+
+#define RPC_DRENR              0x001C  /* R/W */
+#define RPC_DRENR_CDB(o)       (uint32_t)((((o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)      (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)       (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)      (((o) & 0x3) << 20)
+#define RPC_DRENR_SPIDB(o)     (((o) & 0x3) << 16)
+#define RPC_DRENR_DME          BIT(15)
+#define RPC_DRENR_CDE          BIT(14)
+#define RPC_DRENR_OCDE         BIT(12)
+#define RPC_DRENR_ADE(v)       (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)      (((v) & 0xF) << 4)
+
+#define RPC_SMCR               0x0020  /* R/W */
+#define RPC_SMCR_SSLKP         BIT(8)
+#define RPC_SMCR_SPIRE         BIT(2)
+#define RPC_SMCR_SPIWE         BIT(1)
+#define RPC_SMCR_SPIE          BIT(0)
+
+#define RPC_SMCMR              0x0024  /* R/W */
+#define RPC_SMCMR_CMD(c)       (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)      (((c) & 0xFF) << 0)
+
+#define RPC_SMADR              0x0028  /* R/W */
+#define RPC_SMOPR              0x002C  /* R/W */
+#define RPC_SMOPR_OPD0(o)      (((o) & 0xFF) << 0)
+#define RPC_SMOPR_OPD1(o)      (((o) & 0xFF) << 8)
+#define RPC_SMOPR_OPD2(o)      (((o) & 0xFF) << 16)
+#define RPC_SMOPR_OPD3(o)      (((o) & 0xFF) << 24)
+
+#define RPC_SMENR              0x0030  /* R/W */
+#define RPC_SMENR_CDB(o)       (((o) & 0x3) << 30)
+#define RPC_SMENR_OCDB(o)      (((o) & 0x3) << 28)
+#define RPC_SMENR_ADB(o)       (((o) & 0x3) << 24)
+#define RPC_SMENR_OPDB(o)      (((o) & 0x3) << 20)
+#define RPC_SMENR_SPIDB(o)     (((o) & 0x3) << 16)
+#define RPC_SMENR_DME          BIT(15)
+#define RPC_SMENR_CDE          BIT(14)
+#define RPC_SMENR_OCDE         BIT(12)
+#define RPC_SMENR_ADE(v)       (((v) & 0xF) << 8)
+#define RPC_SMENR_OPDE(v)      (((v) & 0xF) << 4)
+#define RPC_SMENR_SPIDE(v)     (((v) & 0xF) << 0)
+
+#define RPC_SMRDR0             0x0038  /* R */
+#define RPC_SMRDR1             0x003C  /* R */
+#define RPC_SMWDR0             0x0040  /* R/W */
+#define RPC_SMWDR1             0x0044  /* R/W */
+#define RPC_CMNSR              0x0048  /* R */
+#define RPC_CMNSR_SSLF         BIT(1)
+#define        RPC_CMNSR_TEND          BIT(0)
+
+#define RPC_DRDMCR             0x0058  /* R/W */
+#define RPC_DRDMCR_DMCYC(v)    (((v) & 0xF) << 0)
+
+#define RPC_DRDRENR            0x005C  /* R/W */
+#define RPC_DRDRENR_HYPE       (0x5 << 12)
+#define RPC_DRDRENR_ADDRE      BIT(8)
+#define RPC_DRDRENR_OPDRE      BIT(4)
+#define RPC_DRDRENR_DRDRE      BIT(0)
+
+#define RPC_SMDMCR             0x0060  /* R/W */
+#define RPC_SMDMCR_DMCYC(v)    (((v) & 0xF) << 0)
+
+#define RPC_SMDRENR            0x0064  /* R/W */
+#define RPC_SMDRENR_HYPE       (0x5 << 12)
+#define RPC_SMDRENR_ADDRE      BIT(8)
+#define RPC_SMDRENR_OPDRE      BIT(4)
+#define RPC_SMDRENR_SPIDRE     BIT(0)
+
+#define RPC_PHYCNT             0x007C  /* R/W */
+#define RPC_PHYCNT_CAL         BIT(31)
+#define PRC_PHYCNT_OCTA_AA     BIT(22)
+#define PRC_PHYCNT_OCTA_SA     BIT(23)
+#define PRC_PHYCNT_EXDS                BIT(21)
+#define RPC_PHYCNT_OCT         BIT(20)
+#define RPC_PHYCNT_WBUF2       BIT(4)
+#define RPC_PHYCNT_WBUF                BIT(2)
+#define RPC_PHYCNT_MEM(v)      (((v) & 0x3) << 0)
+
+#define RPC_PHYINT             0x0088  /* R/W */
+#define RPC_PHYINT_RSTEN       BIT(18)
+#define RPC_PHYINT_WPEN                BIT(17)
+#define RPC_PHYINT_INTEN       BIT(16)
+#define RPC_PHYINT_RST         BIT(2)
+#define RPC_PHYINT_WP          BIT(1)
+#define RPC_PHYINT_INT         BIT(0)
+
+#define RPC_WBUF               0x8000  /* R/W size=4/8/16/32/64Bytes */
+#define RPC_WBUF_SIZE          0x100
+
+static uint32_t rpc_base = 0xee200000;
+static uint32_t mem_base = 0x08000000;
+
+enum rpc_hf_size {
+       RPC_HF_SIZE_16BIT = RPC_SMENR_SPIDE(0x8),
+       RPC_HF_SIZE_32BIT = RPC_SMENR_SPIDE(0xC),
+       RPC_HF_SIZE_64BIT = RPC_SMENR_SPIDE(0xF),
+};
+
+static int rpc_hf_wait_tend(struct target *target)
+{
+       uint32_t reg = rpc_base + RPC_CMNSR;
+       uint32_t val;
+       unsigned long timeout = 1000;
+       long long endtime;
+       int ret;
+
+       endtime = timeval_ms() + timeout;
+       do {
+               ret = target_read_u32(target, reg, &val);
+               if (ret != ERROR_OK)
+                       return ERROR_FAIL;
+
+               if (val & RPC_CMNSR_TEND)
+                       return ERROR_OK;
+
+               alive_sleep(1);
+       } while (timeval_ms() < endtime);
+
+       LOG_ERROR("timeout");
+       return ERROR_TIMEOUT_REACHED;
+}
+
+static int clrsetbits_u32(struct target *target, uint32_t reg,
+                          uint32_t clr, uint32_t set)
+{
+       uint32_t val;
+       int ret;
+
+       ret = target_read_u32(target, reg, &val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       val &= ~clr;
+       val |= set;
+
+       return target_write_u32(target, reg, val);
+}
+
+static int rpc_hf_mode(struct target *target, bool manual)
+{
+       uint32_t val;
+       int ret;
+
+       ret = rpc_hf_wait_tend(target);
+       if (ret != ERROR_OK) {
+               LOG_ERROR("Mode TEND timeout");
+               return ret;
+       }
+
+       ret = clrsetbits_u32(target, rpc_base + RPC_PHYCNT,
+                               RPC_PHYCNT_WBUF | RPC_PHYCNT_WBUF2 |
+                               RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3),
+                               RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3));
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = clrsetbits_u32(target, rpc_base + RPC_CMNCR,
+                               RPC_CMNCR_MD | RPC_CMNCR_BSZ(3),
+                               RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ |
+                               (manual ? RPC_CMNCR_MD : 0) | RPC_CMNCR_BSZ(1));
+       if (ret != ERROR_OK)
+               return ret;
+
+       if (manual)
+               return ERROR_OK;
+
+       ret = target_write_u32(target, rpc_base + RPC_DRCR,
+                              RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF |
+                              RPC_DRCR_RBE);
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = target_write_u32(target, rpc_base + RPC_DRCMR,
+                              RPC_DRCMR_CMD(0xA0));
+       if (ret != ERROR_OK)
+               return ret;
+       ret = target_write_u32(target, rpc_base + RPC_DRENR,
+                              RPC_DRENR_CDB(2) | RPC_DRENR_OCDB(2) |
+                              RPC_DRENR_ADB(2) | RPC_DRENR_SPIDB(2) |
+                              RPC_DRENR_CDE | RPC_DRENR_OCDE |
+                              RPC_DRENR_ADE(4));
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = target_write_u32(target, rpc_base + RPC_DRDMCR,
+                              RPC_DRDMCR_DMCYC(0xE));
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = target_write_u32(target, rpc_base + RPC_DRDRENR,
+                              RPC_DRDRENR_HYPE | RPC_DRDRENR_ADDRE |
+                              RPC_DRDRENR_DRDRE);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Dummy read */
+       return target_read_u32(target, rpc_base + RPC_DRCR, &val);
+}
+
+static int rpc_hf_xfer(struct target *target, target_addr_t addr,
+                      uint32_t wdata, uint32_t *rdata, enum rpc_hf_size size,
+                      bool write, const uint8_t *wbuf, unsigned int wbuf_size)
+{
+       int ret;
+       uint32_t val;
+
+       if (wbuf_size != 0) {
+               ret = rpc_hf_wait_tend(target);
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("Xfer TEND timeout");
+                       return ret;
+               }
+
+               /* Write calibration magic */
+               ret = target_write_u32(target, rpc_base + RPC_DRCR, 0x01FF0301);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = target_write_u32(target, rpc_base + RPC_PHYCNT, 0x80030277);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = target_write_memory(target, rpc_base | RPC_WBUF, 4,
+                                         wbuf_size / 4, wbuf);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = clrsetbits_u32(target, rpc_base + RPC_CMNCR,
+                                       RPC_CMNCR_MD | RPC_CMNCR_BSZ(3),
+                                       RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ |
+                                       RPC_CMNCR_MD | RPC_CMNCR_BSZ(1));
+               if (ret != ERROR_OK)
+                       return ret;
+       } else {
+               ret = rpc_hf_mode(target, 1);
+               if (ret != ERROR_OK)
+                       return ret;
+       }
+
+       /* Submit HF address, SMCMR CMD[7] ~= CA Bit# 47 (R/nW) */
+       ret = target_write_u32(target, rpc_base + RPC_SMCMR,
+                              write ? 0 : RPC_SMCMR_CMD(0x80));
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = target_write_u32(target, rpc_base + RPC_SMADR,
+                              addr >> 1);
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = target_write_u32(target, rpc_base + RPC_SMOPR, 0x0);
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = target_write_u32(target, rpc_base + RPC_SMDRENR,
+                              RPC_SMDRENR_HYPE | RPC_SMDRENR_ADDRE |
+                              RPC_SMDRENR_SPIDRE);
+       if (ret != ERROR_OK)
+               return ret;
+
+       val = RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) |
+             RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) |
+             (wbuf_size ? RPC_SMENR_OPDB(2) : 0) |
+             RPC_SMENR_CDE | RPC_SMENR_OCDE | RPC_SMENR_ADE(4) | size;
+
+       if (write) {
+               ret = target_write_u32(target, rpc_base + RPC_SMENR, val);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               if (wbuf_size == 0) {
+                       buf_bswap32((uint8_t *)&wdata, (uint8_t *)&wdata, 4);
+                       ret = target_write_u32(target, rpc_base + RPC_SMWDR0,
+                                              wdata);
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+
+               ret = target_write_u32(target, rpc_base + RPC_SMCR,
+                                      RPC_SMCR_SPIWE | RPC_SMCR_SPIE);
+               if (ret != ERROR_OK)
+                       return ret;
+       } else {
+               val |= RPC_SMENR_DME;
+
+               ret = target_write_u32(target, rpc_base + RPC_SMDMCR,
+                                      RPC_SMDMCR_DMCYC(0xE));
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = target_write_u32(target, rpc_base + RPC_SMENR, val);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = target_write_u32(target, rpc_base + RPC_SMCR,
+                                      RPC_SMCR_SPIRE | RPC_SMCR_SPIE);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = rpc_hf_wait_tend(target);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               uint32_t val32;
+               ret = target_read_u32(target, rpc_base + RPC_SMRDR0, &val32);
+               if (ret != ERROR_OK)
+                       return ret;
+               buf_bswap32((uint8_t *)&val32, (uint8_t *)&val32, 4);
+               *rdata = val32;
+       }
+
+       ret = rpc_hf_mode(target, 0);
+       if (ret != ERROR_OK)
+               LOG_ERROR("Xfer done TEND timeout");
+       return ret;
+}
+
+static int rpchf_target_write_memory(struct flash_bank *bank, target_addr_t addr,
+                                    uint32_t count, const uint8_t *buffer)
+{
+       struct target *target = bank->target;
+       uint32_t wdata;
+
+       if (count != 2)
+               return ERROR_FAIL;
+
+       wdata = buffer[0] | (buffer[1] << 8);
+
+       return rpc_hf_xfer(target, addr, wdata, NULL, RPC_HF_SIZE_16BIT,
+                          true, NULL, 0);
+}
+
+static int rpchf_target_read_memory(struct flash_bank *bank, target_addr_t addr,
+                                   uint32_t count, uint8_t *buffer)
+{
+       struct target *target = bank->target;
+       uint32_t i, rdata;
+       int ret;
+
+       for (i = 0; i < count; i++) {
+               ret = rpc_hf_xfer(target, addr + (2 * i), 0, &rdata,
+                                       RPC_HF_SIZE_16BIT, false, NULL, 0);
+               if (ret != ERROR_OK)
+                       return ret;
+               buffer[(2 * i) + 0] = rdata & 0xff;
+               buffer[(2 * i) + 1] = (rdata >> 8) & 0xff;
+       }
+
+       return ERROR_OK;
+}
+
+FLASH_BANK_COMMAND_HANDLER(rpchf_flash_bank_command)
+{
+       struct cfi_flash_bank *cfi_info;
+       int ret;
+
+       ret = cfi_flash_bank_cmd(bank, CMD_ARGC, CMD_ARGV);
+       if (ret != ERROR_OK)
+               return ret;
+
+       cfi_info = bank->driver_priv;
+       cfi_info->read_mem = rpchf_target_read_memory;
+       cfi_info->write_mem = rpchf_target_write_memory;
+
+       return ERROR_OK;
+}
+
+static int rpchf_spansion_write_words(struct flash_bank *bank, const uint8_t *word,
+       uint32_t wordcount, uint32_t address)
+{
+       int retval;
+       struct cfi_flash_bank *cfi_info = bank->driver_priv;
+       struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
+
+       /* Calculate buffer size and boundary mask
+        * buffersize is (buffer size per chip) * (number of chips)
+        * bufferwsize is buffersize in words */
+       uint32_t buffersize = RPC_WBUF_SIZE;
+       uint32_t buffermask = buffersize - 1;
+       uint32_t bufferwsize = buffersize / 2;
+
+       /* Check for valid range */
+       if (address & buffermask) {
+               LOG_ERROR("Write address at base " TARGET_ADDR_FMT
+                       ", address 0x%" PRIx32 " not aligned to 2^%d boundary",
+                       bank->base, address, cfi_info->max_buf_write_size);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       /* Check for valid size */
+       if (wordcount > bufferwsize) {
+               LOG_ERROR("Number of data words %" PRId32 " exceeds available buffersize %"
+                       PRId32, wordcount, buffersize);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       /* Unlock */
+       retval = cfi_spansion_unlock_seq(bank);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = cfi_send_command(bank, 0xa0, cfi_flash_address(bank, 0, pri_ext->_unlock1));
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = rpc_hf_xfer(bank->target, address, 0, NULL, RPC_HF_SIZE_64BIT, true, word, wordcount * 2);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (cfi_spansion_wait_status_busy(bank, cfi_info->word_write_timeout) != ERROR_OK) {
+               retval = cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0));
+               if (retval != ERROR_OK)
+                       return retval;
+
+               LOG_ERROR("couldn't write block at base " TARGET_ADDR_FMT
+                       ", address 0x%" PRIx32 ", size 0x%" PRIx32, bank->base, address,
+                       bufferwsize);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+static int rpchf_write_words(struct flash_bank *bank, const uint8_t *word,
+       uint32_t wordcount, uint32_t address)
+{
+       return rpchf_spansion_write_words(bank, word, wordcount, address);
+}
+
+static int rpchf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+       struct cfi_flash_bank *cfi_info = bank->driver_priv;
+       uint32_t address = bank->base + offset; /* address of first byte to be programmed */
+       uint32_t write_p;
+       int align;      /* number of unaligned bytes */
+       uint8_t current_word[CFI_MAX_BUS_WIDTH * 4];    /* word (bus_width size) currently being
+                                                        *programmed */
+       int i;
+       int retval;
+
+       if (bank->target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (offset + count > bank->size)
+               return ERROR_FLASH_DST_OUT_OF_BANK;
+
+       if (cfi_info->qry[0] != 'Q')
+               return ERROR_FLASH_BANK_NOT_PROBED;
+
+       /* start at the first byte of the first word (bus_width size) */
+       write_p = address & ~(bank->bus_width - 1);
+       align = address - write_p;
+       if (align != 0) {
+               LOG_INFO("Fixup %d unaligned head bytes", align);
+
+               /* read a complete word from flash */
+               retval = cfi_target_read_memory(bank, write_p, 1, current_word);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* replace only bytes that must be written */
+               for (i = align;
+                    (i < bank->bus_width) && (count > 0);
+                    i++, count--)
+                       if (cfi_info->data_swap)
+                               /* data bytes are swapped (reverse endianness) */
+                               current_word[bank->bus_width - i] = *buffer++;
+                       else
+                               current_word[i] = *buffer++;
+
+               retval = cfi_write_word(bank, current_word, write_p);
+               if (retval != ERROR_OK)
+                       return retval;
+               write_p += bank->bus_width;
+       }
+
+       /* Calculate buffer size and boundary mask
+        * buffersize is (buffer size per chip) * (number of chips)
+        * bufferwsize is buffersize in words */
+       uint32_t buffersize = RPC_WBUF_SIZE;
+       uint32_t buffermask = buffersize-1;
+       uint32_t bufferwsize = buffersize / bank->bus_width;
+
+       /* fall back to memory writes */
+       while (count >= (uint32_t)bank->bus_width) {
+               int fallback;
+               if ((write_p & 0xff) == 0) {
+                       LOG_INFO("Programming at 0x%08" PRIx32 ", count 0x%08"
+                               PRIx32 " bytes remaining", write_p, count);
+               }
+               fallback = 1;
+               if ((bufferwsize > 0) && (count >= buffersize) &&
+                               !(write_p & buffermask)) {
+                       retval = rpchf_write_words(bank, buffer, bufferwsize, write_p);
+                       if (retval == ERROR_OK) {
+                               buffer += buffersize;
+                               write_p += buffersize;
+                               count -= buffersize;
+                               fallback = 0;
+                       } else if (retval != ERROR_FLASH_OPER_UNSUPPORTED)
+                               return retval;
+               }
+               /* try the slow way? */
+               if (fallback) {
+                       for (i = 0; i < bank->bus_width; i++)
+                               current_word[i] = *buffer++;
+
+                       retval = cfi_write_word(bank, current_word, write_p);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       write_p += bank->bus_width;
+                       count -= bank->bus_width;
+               }
+       }
+
+       /* return to read array mode, so we can read from flash again for padding */
+       retval = cfi_reset(bank);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* handle unaligned tail bytes */
+       if (count > 0) {
+               LOG_INFO("Fixup %" PRId32 " unaligned tail bytes", count);
+
+               /* read a complete word from flash */
+               retval = cfi_target_read_memory(bank, write_p, 1, current_word);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* replace only bytes that must be written */
+               for (i = 0; (i < bank->bus_width) && (count > 0); i++, count--)
+                       if (cfi_info->data_swap)
+                               /* data bytes are swapped (reverse endianness) */
+                               current_word[bank->bus_width - i] = *buffer++;
+                       else
+                               current_word[i] = *buffer++;
+
+               retval = cfi_write_word(bank, current_word, write_p);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       /* return to read array mode */
+       return cfi_reset(bank);
+}
+
+static int rpchf_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+       struct cfi_flash_bank *cfi_info = bank->driver_priv;
+       struct target *target = bank->target;
+
+       LOG_DEBUG("reading buffer of %" PRIi32 " byte at 0x%8.8" PRIx32,
+                 count, offset);
+
+       if (bank->target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (offset + count > bank->size)
+               return ERROR_FLASH_DST_OUT_OF_BANK;
+
+       if (cfi_info->qry[0] != 'Q')
+               return ERROR_FLASH_BANK_NOT_PROBED;
+
+       return target_read_memory(target, offset | mem_base,
+                                 4, count / 4, buffer);
+}
+
+const struct flash_driver renesas_rpchf_flash = {
+       .name = "rpchf",
+       .flash_bank_command = rpchf_flash_bank_command,
+       .erase = cfi_erase,
+       .protect = cfi_protect,
+       .write = rpchf_write,
+       .read = rpchf_read,
+       .probe = cfi_probe,
+       .auto_probe = cfi_auto_probe,
+       .erase_check = default_flash_blank_check,
+       .protect_check = cfi_protect_check,
+       .info = cfi_get_info,
+       .free_driver_priv = default_flash_free_driver_priv,
+};
diff --git a/src/flash/nor/sh_qspi.c b/src/flash/nor/sh_qspi.c
new file mode 100644 (file)
index 0000000..931b0b1
--- /dev/null
@@ -0,0 +1,912 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * SH QSPI (Quad SPI) driver
+ * Copyright (C) 2019 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on U-Boot SH QSPI driver
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imp.h"
+#include "spi.h"
+#include <helper/binarybuffer.h>
+#include <helper/bits.h>
+#include <helper/time_support.h>
+#include <helper/types.h>
+#include <jtag/jtag.h>
+#include <target/algorithm.h>
+#include <target/arm.h>
+#include <target/arm_opcodes.h>
+#include <target/target.h>
+
+/* SH QSPI register bit masks <REG>_<BIT> */
+#define SPCR_MSTR      0x08
+#define SPCR_SPE       0x40
+#define SPSR_SPRFF     0x80
+#define SPSR_SPTEF     0x20
+#define SPPCR_IO3FV    0x04
+#define SPPCR_IO2FV    0x02
+#define SPPCR_IO1FV    0x01
+#define SPBDCR_RXBC0   BIT(0)
+#define SPCMD_SCKDEN   BIT(15)
+#define SPCMD_SLNDEN   BIT(14)
+#define SPCMD_SPNDEN   BIT(13)
+#define SPCMD_SSLKP    BIT(7)
+#define SPCMD_BRDV0    BIT(2)
+#define SPCMD_INIT1    (SPCMD_SCKDEN | SPCMD_SLNDEN | \
+                       SPCMD_SPNDEN | SPCMD_SSLKP | \
+                       SPCMD_BRDV0)
+#define SPCMD_INIT2    (SPCMD_SPNDEN | SPCMD_SSLKP | \
+                       SPCMD_BRDV0)
+#define SPBFCR_TXRST   BIT(7)
+#define SPBFCR_RXRST   BIT(6)
+#define SPBFCR_TXTRG   0x30
+#define SPBFCR_RXTRG   0x07
+
+/* SH QSPI register set */
+#define SH_QSPI_SPCR           0x00
+#define SH_QSPI_SSLP           0x01
+#define SH_QSPI_SPPCR          0x02
+#define SH_QSPI_SPSR           0x03
+#define SH_QSPI_SPDR           0x04
+#define SH_QSPI_SPSCR          0x08
+#define SH_QSPI_SPSSR          0x09
+#define SH_QSPI_SPBR           0x0a
+#define SH_QSPI_SPDCR          0x0b
+#define SH_QSPI_SPCKD          0x0c
+#define SH_QSPI_SSLND          0x0d
+#define SH_QSPI_SPND           0x0e
+#define SH_QSPI_DUMMY0         0x0f
+#define SH_QSPI_SPCMD0         0x10
+#define SH_QSPI_SPCMD1         0x12
+#define SH_QSPI_SPCMD2         0x14
+#define SH_QSPI_SPCMD3         0x16
+#define SH_QSPI_SPBFCR         0x18
+#define SH_QSPI_DUMMY1         0x19
+#define SH_QSPI_SPBDCR         0x1a
+#define SH_QSPI_SPBMUL0                0x1c
+#define SH_QSPI_SPBMUL1                0x20
+#define SH_QSPI_SPBMUL2                0x24
+#define SH_QSPI_SPBMUL3                0x28
+
+struct sh_qspi_flash_bank {
+       const struct flash_device *dev;
+       uint32_t                io_base;
+       int                     probed;
+       struct working_area     *io_algorithm;
+       struct working_area     *source;
+       unsigned int            buffer_size;
+};
+
+struct sh_qspi_target {
+       char            *name;
+       uint32_t        tap_idcode;
+       uint32_t        io_base;
+};
+
+static const struct sh_qspi_target target_devices[] = {
+       /* name,        tap_idcode,     io_base */
+       { "SH QSPI",    0x4ba00477,     0xe6b10000 },
+       { NULL,         0,              0 }
+};
+
+static int sh_qspi_init(struct flash_bank *bank)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       uint8_t val;
+       int ret;
+
+       /* QSPI initialize */
+       /* Set master mode only */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPCR, SPCR_MSTR);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set SSL signal level */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SSLP, 0x00);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set MOSI signal value when transfer is in idle state */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPPCR,
+                             SPPCR_IO3FV | SPPCR_IO2FV);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPBR, 0x01);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Disable Dummy Data Transmission */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPDCR, 0x00);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set clock delay value */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPCKD, 0x00);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set SSL negation delay value */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SSLND, 0x00);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set next-access delay value */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPND, 0x00);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set equence command */
+       ret = target_write_u16(target, info->io_base + SH_QSPI_SPCMD0,
+                              SPCMD_INIT2);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Reset transfer and receive Buffer */
+       ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       val |= SPBFCR_TXRST | SPBFCR_RXRST;
+
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Clear transfer and receive Buffer control bit */
+       ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       val &= ~(SPBFCR_TXRST | SPBFCR_RXRST);
+
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set equence control method. Use equence0 only */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPSCR, 0x00);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Enable SPI function */
+       ret = target_read_u8(target, info->io_base + SH_QSPI_SPCR, &val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       val |= SPCR_SPE;
+
+       return target_write_u8(target, info->io_base + SH_QSPI_SPCR, val);
+}
+
+static int sh_qspi_cs_activate(struct flash_bank *bank)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       uint8_t val;
+       int ret;
+
+       /* Set master mode only */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPCR, SPCR_MSTR);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set command */
+       ret = target_write_u16(target, info->io_base + SH_QSPI_SPCMD0,
+                              SPCMD_INIT1);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Reset transfer and receive Buffer */
+       ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       val |= SPBFCR_TXRST | SPBFCR_RXRST;
+
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Clear transfer and receive Buffer control bit */
+       ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       val &= ~(SPBFCR_TXRST | SPBFCR_RXRST);
+
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Set equence control method. Use equence0 only */
+       ret = target_write_u8(target, info->io_base + SH_QSPI_SPSCR, 0x00);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Enable SPI function */
+       ret = target_read_u8(target, info->io_base + SH_QSPI_SPCR, &val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       val |= SPCR_SPE;
+
+       return target_write_u8(target, info->io_base + SH_QSPI_SPCR, val);
+}
+
+static int sh_qspi_cs_deactivate(struct flash_bank *bank)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       uint8_t val;
+       int ret;
+
+       /* Disable SPI Function */
+       ret = target_read_u8(target, info->io_base + SH_QSPI_SPCR, &val);
+       if (ret != ERROR_OK)
+               return ret;
+
+       val &= ~SPCR_SPE;
+
+       return target_write_u8(target, info->io_base + SH_QSPI_SPCR, val);
+}
+
+static int sh_qspi_wait_for_bit(struct flash_bank *bank, uint8_t reg,
+                               uint32_t mask, bool set,
+                               unsigned long timeout)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       long long endtime;
+       uint8_t val;
+       int ret;
+
+       endtime = timeval_ms() + timeout;
+       do {
+               ret = target_read_u8(target, info->io_base + reg, &val);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               if (!set)
+                       val = ~val;
+
+               if ((val & mask) == mask)
+                       return ERROR_OK;
+
+               alive_sleep(1);
+       } while (timeval_ms() < endtime);
+
+       LOG_ERROR("timeout");
+       return ERROR_TIMEOUT_REACHED;
+}
+
+static int sh_qspi_xfer_common(struct flash_bank *bank,
+                              const uint8_t *dout, unsigned int outlen,
+                              uint8_t *din, unsigned int inlen,
+                              bool xfer_start, bool xfer_end)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       uint8_t tdata, rdata;
+       uint8_t val;
+       unsigned int nbyte = outlen + inlen;
+       int ret = 0;
+
+       if (xfer_start) {
+               ret = sh_qspi_cs_activate(bank);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = target_write_u32(target, info->io_base + SH_QSPI_SPBMUL0,
+                                      nbyte);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR,
+                                    &val);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               val &= ~(SPBFCR_TXTRG | SPBFCR_RXTRG);
+
+               ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR,
+                                     val);
+               if (ret != ERROR_OK)
+                       return ret;
+       }
+
+       while (nbyte > 0) {
+               ret = sh_qspi_wait_for_bit(bank, SH_QSPI_SPSR, SPSR_SPTEF,
+                                               true, 1000);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               tdata = outlen ? *dout++ : 0;
+               ret = target_write_u8(target, info->io_base + SH_QSPI_SPDR,
+                                     tdata);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = sh_qspi_wait_for_bit(bank, SH_QSPI_SPSR, SPSR_SPRFF,
+                                               true, 1000);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               ret = target_read_u8(target, info->io_base + SH_QSPI_SPDR,
+                                    &rdata);
+               if (ret != ERROR_OK)
+                       return ret;
+               if (!outlen && inlen) {
+                       *din++ = rdata;
+                       inlen--;
+               }
+
+               if (outlen)
+                       outlen--;
+
+               nbyte--;
+       }
+
+       if (xfer_end)
+               return sh_qspi_cs_deactivate(bank);
+       else
+               return ERROR_OK;
+}
+
+/* Send "write enable" command to SPI flash chip. */
+static int sh_qspi_write_enable(struct flash_bank *bank)
+{
+       uint8_t dout = SPIFLASH_WRITE_ENABLE;
+
+       return sh_qspi_xfer_common(bank, &dout, 1, NULL, 0, 1, 1);
+}
+
+/* Read the status register of the external SPI flash chip. */
+static int read_status_reg(struct flash_bank *bank, uint32_t *status)
+{
+       uint8_t dout = SPIFLASH_READ_STATUS;
+       uint8_t din;
+       int ret;
+
+       ret = sh_qspi_xfer_common(bank, &dout, 1, &din, 1, 1, 1);
+       if (ret != ERROR_OK)
+               return ret;
+
+       *status = din & 0xff;
+
+       return ERROR_OK;
+}
+
+/* check for WIP (write in progress) bit in status register */
+/* timeout in ms */
+static int wait_till_ready(struct flash_bank *bank, int timeout)
+{
+       long long endtime;
+       uint32_t status;
+       int ret;
+
+       endtime = timeval_ms() + timeout;
+       do {
+               /* read flash status register */
+               ret = read_status_reg(bank, &status);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               if ((status & SPIFLASH_BSY_BIT) == 0)
+                       return ERROR_OK;
+               alive_sleep(1);
+       } while (timeval_ms() < endtime);
+
+       LOG_ERROR("timeout");
+       return ERROR_TIMEOUT_REACHED;
+}
+
+static int sh_qspi_erase_sector(struct flash_bank *bank, int sector)
+{
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       bool addr4b = info->dev->size_in_bytes > (1UL << 24);
+       uint32_t address = (sector * info->dev->sectorsize) <<
+                          (addr4b ? 0 : 8);
+       uint8_t dout[5] = {
+               info->dev->erase_cmd,
+               (address >> 24) & 0xff, (address >> 16) & 0xff,
+               (address >> 8) & 0xff, (address >> 0) & 0xff
+       };
+       unsigned int doutlen = addr4b ? 5 : 4;
+       int ret;
+
+       /* Write Enable */
+       ret = sh_qspi_write_enable(bank);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Erase */
+       ret = sh_qspi_xfer_common(bank, dout, doutlen, NULL, 0, 1, 1);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* Poll status register */
+       return wait_till_ready(bank, 3000);
+}
+
+static int sh_qspi_erase(struct flash_bank *bank, int first, int last)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       int retval = ERROR_OK;
+       int sector;
+
+       LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
+               LOG_ERROR("Flash sector invalid");
+               return ERROR_FLASH_SECTOR_INVALID;
+       }
+
+       if (!info->probed) {
+               LOG_ERROR("Flash bank not probed");
+               return ERROR_FLASH_BANK_NOT_PROBED;
+       }
+
+       if (info->dev->erase_cmd == 0x00)
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+
+       for (sector = first; sector <= last; sector++) {
+               if (bank->sectors[sector].is_protected) {
+                       LOG_ERROR("Flash sector %d protected", sector);
+                       return ERROR_FAIL;
+               }
+       }
+
+       for (sector = first; sector <= last; sector++) {
+               retval = sh_qspi_erase_sector(bank, sector);
+               if (retval != ERROR_OK)
+                       break;
+               keep_alive();
+       }
+
+       return retval;
+}
+
+static int sh_qspi_write(struct flash_bank *bank, const uint8_t *buffer,
+                      uint32_t offset, uint32_t count)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       struct reg_param reg_params[4];
+       struct arm_algorithm arm_algo;
+       uint32_t io_base = (uint32_t)(info->io_base);
+       uint32_t src_base = (uint32_t)(info->source->address);
+       uint32_t chunk;
+       bool addr4b = !!(info->dev->size_in_bytes > (1UL << 24));
+       int ret = ERROR_OK;
+       int sector;
+
+       LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
+                 __func__, offset, count);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (offset + count > bank->size) {
+               LOG_WARNING("Write pasts end of flash. Extra data discarded.");
+               count = bank->size - offset;
+       }
+
+       if (offset & 0xff) {
+               LOG_ERROR("sh_qspi_write_page: unaligned write address: %08x",
+                         offset);
+               return ERROR_FAIL;
+       }
+
+       /* Check sector protection */
+       for (sector = 0; sector < bank->num_sectors; sector++) {
+               /* Start offset in or before this sector? */
+               /* End offset in or behind this sector? */
+               struct flash_sector *bs = &bank->sectors[sector];
+
+               if ((offset < (bs->offset + bs->size)) &&
+                   ((offset + count - 1) >= bs->offset) &&
+                   bs->is_protected) {
+                       LOG_ERROR("Flash sector %d protected", sector);
+                       return ERROR_FAIL;
+               }
+       }
+
+       LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
+                 __func__, offset, count);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (offset + count > bank->size) {
+               LOG_WARNING("Reads past end of flash. Extra data discarded.");
+               count = bank->size - offset;
+       }
+
+       arm_algo.common_magic = ARM_COMMON_MAGIC;
+       arm_algo.core_mode = ARM_MODE_SVC;
+       arm_algo.core_state = ARM_STATE_ARM;
+
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
+       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
+
+       while (count > 0) {
+               chunk = (count > info->buffer_size) ?
+                       info->buffer_size : count;
+
+               target_write_buffer(target, info->source->address,
+                                   chunk, buffer);
+
+               buf_set_u32(reg_params[0].value, 0, 32, io_base);
+               buf_set_u32(reg_params[1].value, 0, 32, src_base);
+               buf_set_u32(reg_params[2].value, 0, 32,
+                               (1 << 31) | (addr4b << 30) |
+                               (info->dev->pprog_cmd << 20) | chunk);
+               buf_set_u32(reg_params[3].value, 0, 32, offset);
+
+               ret = target_run_algorithm(target, 0, NULL, 4, reg_params,
+                               info->io_algorithm->address,
+                               0, 10000, &arm_algo);
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("error executing SH QSPI flash IO algorithm");
+                       ret = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+               }
+
+               buffer += chunk;
+               offset += chunk;
+               count -= chunk;
+       }
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_params[2]);
+       destroy_reg_param(&reg_params[3]);
+
+       return ret;
+}
+
+static int sh_qspi_read(struct flash_bank *bank, uint8_t *buffer,
+                       uint32_t offset, uint32_t count)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       struct reg_param reg_params[4];
+       struct arm_algorithm arm_algo;
+       uint32_t io_base = (uint32_t)(info->io_base);
+       uint32_t src_base = (uint32_t)(info->source->address);
+       uint32_t chunk;
+       bool addr4b = !!(info->dev->size_in_bytes > (1UL << 24));
+       int ret = ERROR_OK;
+
+       LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
+                 __func__, offset, count);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (offset + count > bank->size) {
+               LOG_WARNING("Reads past end of flash. Extra data discarded.");
+               count = bank->size - offset;
+       }
+
+       arm_algo.common_magic = ARM_COMMON_MAGIC;
+       arm_algo.core_mode = ARM_MODE_SVC;
+       arm_algo.core_state = ARM_STATE_ARM;
+
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
+       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
+
+       while (count > 0) {
+               chunk = (count > info->buffer_size) ?
+                       info->buffer_size : count;
+
+               buf_set_u32(reg_params[0].value, 0, 32, io_base);
+               buf_set_u32(reg_params[1].value, 0, 32, src_base);
+               buf_set_u32(reg_params[2].value, 0, 32,
+                               (addr4b << 30) | (info->dev->read_cmd << 20) |
+                               chunk);
+               buf_set_u32(reg_params[3].value, 0, 32, offset);
+
+               ret = target_run_algorithm(target, 0, NULL, 4, reg_params,
+                               info->io_algorithm->address,
+                               0, 10000, &arm_algo);
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("error executing SH QSPI flash IO algorithm");
+                       ret = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+               }
+
+               target_read_buffer(target, info->source->address,
+                                  chunk, buffer);
+
+               buffer += chunk;
+               offset += chunk;
+               count -= chunk;
+       }
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_params[2]);
+       destroy_reg_param(&reg_params[3]);
+
+       return ERROR_OK;
+}
+
+/* Return ID of flash device */
+static int read_flash_id(struct flash_bank *bank, uint32_t *id)
+{
+       struct target *target = bank->target;
+       uint8_t dout = SPIFLASH_READ_ID;
+       uint8_t din[3] = { 0, 0, 0 };
+       int ret;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       ret = sh_qspi_xfer_common(bank, &dout, 1, din, 3, 1, 1);
+       if (ret != ERROR_OK)
+               return ret;
+
+       *id = (din[0] << 0) | (din[1] << 8) | (din[2] << 16);
+
+       if (*id == 0xffffff) {
+               LOG_ERROR("No SPI flash found");
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int sh_qspi_protect(struct flash_bank *bank, int set,
+                        int first, int last)
+{
+       int sector;
+
+       for (sector = first; sector <= last; sector++)
+               bank->sectors[sector].is_protected = set;
+
+       return ERROR_OK;
+}
+
+static int sh_qspi_upload_helper(struct flash_bank *bank)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+
+       /* see contrib/loaders/flash/sh_qspi.s for src */
+       static const uint8_t sh_qspi_io_code[] = {
+#include "../../../contrib/loaders/flash/sh_qspi/sh_qspi.inc"
+       };
+       int ret;
+
+       if (info->source)
+               target_free_working_area(target, info->source);
+       if (info->io_algorithm)
+               target_free_working_area(target, info->io_algorithm);
+
+       /* flash write code */
+       if (target_alloc_working_area(target, sizeof(sh_qspi_io_code),
+                       &info->io_algorithm) != ERROR_OK) {
+               LOG_WARNING("no working area available, can't do block memory writes");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       target_write_buffer(target, info->io_algorithm->address,
+                           sizeof(sh_qspi_io_code), sh_qspi_io_code);
+
+       /*
+        * Try to allocate as big work area buffer as possible, start
+        * with 32 kiB and count down. If there is less than 256 Bytes
+        * of work area available, abort.
+        */
+       info->buffer_size = 32768;
+       while (true) {
+               ret = target_alloc_working_area_try(target, info->buffer_size,
+                                                   &info->source);
+               if (ret == ERROR_OK)
+                       return ret;
+
+               info->buffer_size /= 2;
+               if (info->buffer_size <= 256) {
+                       target_free_working_area(target, info->io_algorithm);
+
+                       LOG_WARNING("no large enough working area available, can't do block memory writes");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int sh_qspi_probe(struct flash_bank *bank)
+{
+       struct target *target = bank->target;
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+       struct flash_sector *sectors;
+       uint32_t id = 0; /* silence uninitialized warning */
+       uint32_t sectorsize;
+       const struct sh_qspi_target *target_device;
+       int ret;
+
+       if (info->probed)
+               free(bank->sectors);
+
+       info->probed = 0;
+
+       for (target_device = target_devices; target_device->name;
+               ++target_device)
+               if (target_device->tap_idcode == target->tap->idcode)
+                       break;
+       if (!target_device->name) {
+               LOG_ERROR("Device ID 0x%" PRIx32 " is not known",
+                         target->tap->idcode);
+               return ERROR_FAIL;
+       }
+
+       info->io_base = target_device->io_base;
+
+       LOG_DEBUG("Found device %s at address " TARGET_ADDR_FMT,
+                 target_device->name, bank->base);
+
+       ret = sh_qspi_upload_helper(bank);
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = sh_qspi_init(bank);
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = read_flash_id(bank, &id);
+       if (ret != ERROR_OK)
+               return ret;
+
+       info->dev = NULL;
+       for (const struct flash_device *p = flash_devices; p->name; p++)
+               if (p->device_id == id) {
+                       info->dev = p;
+                       break;
+               }
+
+       if (!info->dev) {
+               LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
+               return ERROR_FAIL;
+       }
+
+       LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
+                info->dev->name, info->dev->device_id);
+
+       /* Set correct size value */
+       bank->size = info->dev->size_in_bytes;
+       if (bank->size <= (1UL << 16))
+               LOG_WARNING("device needs 2-byte addresses - not implemented");
+
+       /* if no sectors, treat whole bank as single sector */
+       sectorsize = info->dev->sectorsize ?
+                    info->dev->sectorsize :
+                    info->dev->size_in_bytes;
+
+       /* create and fill sectors array */
+       bank->num_sectors = info->dev->size_in_bytes / sectorsize;
+       sectors = calloc(1, sizeof(*sectors) * bank->num_sectors);
+       if (!sectors) {
+               LOG_ERROR("not enough memory");
+               return ERROR_FAIL;
+       }
+
+       for (int sector = 0; sector < bank->num_sectors; sector++) {
+               sectors[sector].offset = sector * sectorsize;
+               sectors[sector].size = sectorsize;
+               sectors[sector].is_erased = 0;
+               sectors[sector].is_protected = 0;
+       }
+
+       bank->sectors = sectors;
+       info->probed = 1;
+       return ERROR_OK;
+}
+
+static int sh_qspi_auto_probe(struct flash_bank *bank)
+{
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+
+       if (info->probed)
+               return ERROR_OK;
+
+       return sh_qspi_probe(bank);
+}
+
+static int sh_qspi_flash_blank_check(struct flash_bank *bank)
+{
+       /* Not implemented */
+       return ERROR_OK;
+}
+
+static int sh_qspi_protect_check(struct flash_bank *bank)
+{
+       /* Not implemented */
+       return ERROR_OK;
+}
+
+static int sh_qspi_get_info(struct flash_bank *bank, char *buf, int buf_size)
+{
+       struct sh_qspi_flash_bank *info = bank->driver_priv;
+
+       if (!info->probed) {
+               snprintf(buf, buf_size,
+                        "\nSH QSPI flash bank not probed yet\n");
+               return ERROR_OK;
+       }
+
+       snprintf(buf, buf_size, "\nSH QSPI flash information:\n"
+               "  Device \'%s\' (ID 0x%08" PRIx32 ")\n",
+               info->dev->name, info->dev->device_id);
+
+       return ERROR_OK;
+}
+
+FLASH_BANK_COMMAND_HANDLER(sh_qspi_flash_bank_command)
+{
+       struct sh_qspi_flash_bank *info;
+
+       LOG_DEBUG("%s", __func__);
+
+       if (CMD_ARGC < 6 || CMD_ARGC > 7)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if ((CMD_ARGC == 7) && strcmp(CMD_ARGV[6], "cs0")) {
+               LOG_ERROR("Unknown arg: %s", CMD_ARGV[6]);
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       info = calloc(1, sizeof(struct sh_qspi_flash_bank));
+       if (!info) {
+               LOG_ERROR("not enough memory");
+               return ERROR_FAIL;
+       }
+
+       bank->driver_priv = info;
+
+       return ERROR_OK;
+}
+
+const struct flash_driver sh_qspi_flash = {
+       .name                   = "sh_qspi",
+       .flash_bank_command     = sh_qspi_flash_bank_command,
+       .erase                  = sh_qspi_erase,
+       .protect                = sh_qspi_protect,
+       .write                  = sh_qspi_write,
+       .read                   = sh_qspi_read,
+       .probe                  = sh_qspi_probe,
+       .auto_probe             = sh_qspi_auto_probe,
+       .erase_check            = sh_qspi_flash_blank_check,
+       .protect_check          = sh_qspi_protect_check,
+       .info                   = sh_qspi_get_info,
+       .free_driver_priv       = default_flash_free_driver_priv,
+};
index 7ccf56b..4e39705 100644 (file)
@@ -471,7 +471,7 @@ static int sim3x_write_block(struct flash_bank *bank, const uint8_t *buf,
        return ret;
 }
 
-static int sim3x_flash_write(struct flash_bank *bank, const uint8_t * buffer, uint32_t offset, uint32_t count)
+static int sim3x_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
 {
        int ret;
        struct target *target;
index 91fd541..ba0d54e 100644 (file)
@@ -116,7 +116,7 @@ struct stm32x_options {
 struct stm32x_flash_bank {
        struct stm32x_options option_bytes;
        int ppage_size;
-       int probed;
+       bool probed;
 
        bool has_dual_banks;
        /* used to access dual flash bank stm32xl */
@@ -145,7 +145,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
        stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
 
        bank->driver_priv = stm32x_info;
-       stm32x_info->probed = 0;
+       stm32x_info->probed = false;
        stm32x_info->has_dual_banks = false;
        stm32x_info->can_load_options = false;
        stm32x_info->register_base = FLASH_REG_BASE_B0;
@@ -368,7 +368,6 @@ static int stm32x_protect_check(struct flash_bank *bank)
 static int stm32x_erase(struct flash_bank *bank, int first, int last)
 {
        struct target *target = bank->target;
-       int i;
 
        if (bank->target->state != TARGET_HALTED) {
                LOG_ERROR("Target not halted");
@@ -386,7 +385,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
        if (retval != ERROR_OK)
                return retval;
 
-       for (i = first; i <= last; i++) {
+       for (int i = first; i <= last; i++) {
                retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER);
                if (retval != ERROR_OK)
                        return retval;
@@ -697,7 +696,7 @@ static int stm32x_probe(struct flash_bank *bank)
        int page_size;
        uint32_t base_address = 0x08000000;
 
-       stm32x_info->probed = 0;
+       stm32x_info->probed = false;
        stm32x_info->register_base = FLASH_REG_BASE_B0;
        stm32x_info->user_data_offset = 10;
        stm32x_info->option_offset = 0;
@@ -886,7 +885,7 @@ static int stm32x_probe(struct flash_bank *bank)
        if (num_prot_blocks == 32)
                bank->prot_blocks[31].size = (num_pages - (31 * stm32x_info->ppage_size)) * page_size;
 
-       stm32x_info->probed = 1;
+       stm32x_info->probed = true;
 
        return ERROR_OK;
 }
@@ -1474,8 +1473,6 @@ static int stm32x_mass_erase(struct flash_bank *bank)
 
 COMMAND_HANDLER(stm32x_handle_mass_erase_command)
 {
-       int i;
-
        if (CMD_ARGC < 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
@@ -1487,7 +1484,7 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
        retval = stm32x_mass_erase(bank);
        if (retval == ERROR_OK) {
                /* set all sectors as erased */
-               for (i = 0; i < bank->num_sectors; i++)
+               for (int i = 0; i < bank->num_sectors; i++)
                        bank->sectors[i].is_erased = 1;
 
                command_print(CMD, "stm32x mass erase complete");
index 0085729..d5b5daa 100644 (file)
@@ -83,6 +83,7 @@
 #define OPT_BSY        (1 << 0)
 #define OPT_RDP_POS    8
 #define OPT_RDP_MASK   (0xff << OPT_RDP_POS)
+#define OPT_OPTCHANGEERR (1 << 30)
 
 /* FLASH_OPTCCR register bits */
 #define OPT_CLR_OPTCHANGEERR (1 << 30)
@@ -122,7 +123,7 @@ struct stm32h7x_part_info {
 };
 
 struct stm32h7x_flash_bank {
-       int probed;
+       bool probed;
        uint32_t idcode;
        uint32_t user_bank_size;
        uint32_t flash_regs_base;    /* Address of flash reg controller */
@@ -166,9 +167,12 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
        stm32x_info = malloc(sizeof(struct stm32h7x_flash_bank));
        bank->driver_priv = stm32x_info;
 
-       stm32x_info->probed = 0;
+       stm32x_info->probed = false;
        stm32x_info->user_bank_size = bank->size;
 
+       bank->write_start_alignment = FLASH_BLOCK_SIZE;
+       bank->write_end_alignment = FLASH_BLOCK_SIZE;
+
        return ERROR_OK;
 }
 
@@ -343,8 +347,8 @@ static int stm32x_write_option(struct flash_bank *bank, uint32_t reg_offset, uin
 
        /* wait for completion */
        int timeout = FLASH_ERASE_TIMEOUT;
+       uint32_t status;
        for (;;) {
-               uint32_t status;
                retval = stm32x_read_flash_reg(bank, FLASH_OPTSR_CUR, &status);
                if (retval != ERROR_OK) {
                        LOG_ERROR("stm32x_options_program: failed to read FLASH_OPTSR_CUR");
@@ -361,6 +365,12 @@ static int stm32x_write_option(struct flash_bank *bank, uint32_t reg_offset, uin
                alive_sleep(1);
        }
 
+       /* check for failure */
+       if (status & OPT_OPTCHANGEERR) {
+               LOG_ERROR("error changing option bytes (OPTCHANGEERR=1)");
+               retval = ERROR_FLASH_OPERATION_FAILED;
+       }
+
 flash_options_lock:
        retval2 = stm32x_lock_option_reg(bank);
        if (retval2 != ERROR_OK)
@@ -603,17 +613,17 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       if (offset % FLASH_BLOCK_SIZE) {
-               LOG_WARNING("offset 0x%" PRIx32 " breaks required 32-byte alignment", offset);
-               return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
-       }
+       /* should be enforced via bank->write_start_alignment */
+       assert(!(offset % FLASH_BLOCK_SIZE));
+
+       /* should be enforced via bank->write_end_alignment */
+       assert(!(count % FLASH_BLOCK_SIZE));
 
        retval = stm32x_unlock_reg(bank);
        if (retval != ERROR_OK)
                goto flash_lock;
 
        uint32_t blocks_remaining = count / FLASH_BLOCK_SIZE;
-       uint32_t bytes_remaining = count % FLASH_BLOCK_SIZE;
 
        /* multiple words (32-bytes) to be programmed in block */
        if (blocks_remaining) {
@@ -660,25 +670,6 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
                blocks_remaining--;
        }
 
-       if (bytes_remaining) {
-               retval = stm32x_write_flash_reg(bank, FLASH_CR, FLASH_PG | FLASH_PSIZE_64);
-               if (retval != ERROR_OK)
-                       goto flash_lock;
-
-               retval = target_write_buffer(target, address, bytes_remaining, buffer);
-               if (retval != ERROR_OK)
-                       goto flash_lock;
-
-               /* Force Write buffer of FLASH_BLOCK_SIZE = 32 bytes */
-               retval = stm32x_write_flash_reg(bank, FLASH_CR, FLASH_PG | FLASH_PSIZE_64 | FLASH_FW);
-               if (retval != ERROR_OK)
-                       goto flash_lock;
-
-               retval = stm32x_wait_flash_op_queue(bank, FLASH_WRITE_TIMEOUT);
-               if (retval != ERROR_OK)
-                       goto flash_lock;
-       }
-
 flash_lock:
        retval2 = stm32x_lock_reg(bank);
        if (retval2 != ERROR_OK)
@@ -710,13 +701,12 @@ static int stm32x_probe(struct flash_bank *bank)
 {
        struct target *target = bank->target;
        struct stm32h7x_flash_bank *stm32x_info = bank->driver_priv;
-       int i;
        uint16_t flash_size_in_kb;
        uint32_t device_id;
        uint32_t base_address = FLASH_BANK0_ADDRESS;
        uint32_t second_bank_base;
 
-       stm32x_info->probed = 0;
+       stm32x_info->probed = false;
        stm32x_info->part_info = NULL;
 
        int retval = stm32x_read_id_code(bank, &stm32x_info->idcode);
@@ -812,12 +802,12 @@ static int stm32x_probe(struct flash_bank *bank)
        /* fixed memory */
        setup_sector(bank, 0, num_pages, stm32x_info->part_info->page_size * 1024);
 
-       for (i = 0; i < num_pages; i++) {
+       for (int i = 0; i < num_pages; i++) {
                bank->sectors[i].is_erased = -1;
                bank->sectors[i].is_protected = 0;
        }
 
-       stm32x_info->probed = 1;
+       stm32x_info->probed = true;
        return ERROR_OK;
 }
 
@@ -989,8 +979,6 @@ flash_lock:
 
 COMMAND_HANDLER(stm32x_handle_mass_erase_command)
 {
-       int i;
-
        if (CMD_ARGC < 1) {
                command_print(CMD, "stm32h7x mass_erase <bank>");
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1004,7 +992,7 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
        retval = stm32x_mass_erase(bank);
        if (retval == ERROR_OK) {
                /* set all sectors as erased */
-               for (i = 0; i < bank->num_sectors; i++)
+               for (int i = 0; i < bank->num_sectors; i++)
                        bank->sectors[i].is_erased = 1;
 
                command_print(CMD, "stm32h7x mass erase complete");
@@ -1057,7 +1045,7 @@ COMMAND_HANDLER(stm32x_handle_option_write_command)
        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], reg_offset);
        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
        if (CMD_ARGC > 3)
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], mask);
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], mask);
 
        return stm32x_modify_option(bank, reg_offset, value, mask);
 }
index 3d15377..abbb75b 100644 (file)
 #define FLASH_PROGERR  (1 << 3) /* Programming error */
 #define FLASH_OPERR    (1 << 1) /* Operation error */
 #define FLASH_EOP      (1 << 0) /* End of operation */
-#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGSERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR)
+#define FLASH_ERROR (FLASH_PGSERR | FLASH_SIZERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_PROGERR | FLASH_OPERR)
 
 /* register unlock keys */
 #define KEY1           0x45670123
@@ -142,7 +142,7 @@ struct stm32l4_part_info {
 };
 
 struct stm32l4_flash_bank {
-       int probed;
+       bool probed;
        uint32_t idcode;
        int bank1_sectors;
        bool dual_bank_mode;
@@ -278,7 +278,11 @@ FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command)
                return ERROR_FAIL; /* Checkme: What better error to use?*/
        bank->driver_priv = stm32l4_info;
 
-       stm32l4_info->probed = 0;
+       /* The flash write must be aligned to a double word (8-bytes) boundary.
+        * Ask the flash infrastructure to ensure required alignment */
+       bank->write_start_alignment = bank->write_end_alignment = 8;
+
+       stm32l4_info->probed = false;
 
        return ERROR_OK;
 }
@@ -408,34 +412,39 @@ static int stm32l4_unlock_option_reg(struct flash_bank *bank)
 static int stm32l4_write_option(struct flash_bank *bank, uint32_t reg_offset, uint32_t value, uint32_t mask)
 {
        uint32_t optiondata;
+       int retval, retval2;
 
-       int retval = stm32l4_read_flash_reg(bank, reg_offset, &optiondata);
+       retval = stm32l4_read_flash_reg(bank, reg_offset, &optiondata);
        if (retval != ERROR_OK)
                return retval;
 
        retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
 
        retval = stm32l4_unlock_option_reg(bank);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
 
        optiondata = (optiondata & ~mask) | (value & mask);
 
        retval = stm32l4_write_flash_reg(bank, reg_offset, optiondata);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
 
        retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_OPTSTRT);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
 
        retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
+
+err_lock:
+       retval2 = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK | FLASH_OPTLOCK);
+
        if (retval != ERROR_OK)
                return retval;
 
-       return retval;
+       return retval2;
 }
 
 static int stm32l4_protect_check(struct flash_bank *bank)
@@ -485,7 +494,7 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last)
 {
        struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
        int i;
-       int retval;
+       int retval, retval2;
 
        assert(first < bank->num_sectors);
        assert(last < bank->num_sectors);
@@ -497,7 +506,7 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last)
 
        retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
 
        /*
        Sector Erase
@@ -522,20 +531,22 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last)
                        erase_flags |= i << FLASH_PAGE_SHIFT;
                retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, erase_flags);
                if (retval != ERROR_OK)
-                       return retval;
+                       break;
 
                retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
                if (retval != ERROR_OK)
-                       return retval;
+                       break;
 
                bank->sectors[i].is_erased = 1;
        }
 
-       retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK);
+err_lock:
+       retval2 = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK);
+
        if (retval != ERROR_OK)
                return retval;
 
-       return ERROR_OK;
+       return retval2;
 }
 
 static int stm32l4_protect(struct flash_bank *bank, int set, int first, int last)
@@ -573,7 +584,7 @@ static int stm32l4_protect(struct flash_bank *bank, int set, int first, int last
        return ret;
 }
 
-/* Count is in halfwords */
+/* Count is in double-words */
 static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
                uint32_t offset, uint32_t count)
 {
@@ -626,15 +637,15 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
        init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);    /* buffer end */
        init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);    /* target address */
        init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* count (double word-64bit) */
-       init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);    /* flash base */
+       init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);    /* flash regs base */
 
        buf_set_u32(reg_params[0].value, 0, 32, source->address);
        buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
        buf_set_u32(reg_params[2].value, 0, 32, address);
-       buf_set_u32(reg_params[3].value, 0, 32, count / 4);
+       buf_set_u32(reg_params[3].value, 0, 32, count);
        buf_set_u32(reg_params[4].value, 0, 32, stm32l4_info->part_info->flash_regs_base);
 
-       retval = target_run_flash_async_algorithm(target, buffer, count, 2,
+       retval = target_run_flash_async_algorithm(target, buffer, count, 8,
                        0, NULL,
                        5, reg_params,
                        source->address, source->size,
@@ -672,45 +683,32 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
 static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer,
                uint32_t offset, uint32_t count)
 {
-       int retval;
+       int retval, retval2;
 
        if (bank->target->state != TARGET_HALTED) {
                LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       if (offset & 0x7) {
-               LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment",
-                                       offset);
-               return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
-       }
-
-       if (count & 0x7) {
-               LOG_WARNING("Padding %d bytes to keep 8-byte write size",
-                                       count & 7);
-               count = (count + 7) & ~7;
-               /* This pads the write chunk with random bytes by overrunning the
-                * write buffer. Padding with the erased pattern 0xff is purely
-                * cosmetical, as 8-byte flash words are ECC secured and the first
-                * write will program the ECC bits. A second write would need
-                * to reprogramm these ECC bits.
-                * But this can only be done after erase!
-                */
-       }
+       /* The flash write must be aligned to a double word (8-bytes) boundary.
+        * The flash infrastructure ensures it, do just a security check */
+       assert(offset % 8 == 0);
+       assert(count % 8 == 0);
 
        retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
+
+       retval = stm32l4_write_block(bank, buffer, offset, count / 8);
+
+err_lock:
+       retval2 = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK);
 
-       /* Only full double words (8-byte) can be programmed*/
-       retval = stm32l4_write_block(bank, buffer, offset, count / 2);
        if (retval != ERROR_OK) {
-               LOG_WARNING("block write failed");
+               LOG_ERROR("block write failed");
                return retval;
        }
-
-       LOG_WARNING("block write succeeded");
-       return stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK);
+       return retval2;
 }
 
 static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id)
@@ -727,12 +725,11 @@ static int stm32l4_probe(struct flash_bank *bank)
        struct target *target = bank->target;
        struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
        const struct stm32l4_part_info *part_info;
-       int i;
        uint16_t flash_size_in_kb = 0xffff;
        uint32_t device_id;
        uint32_t options;
 
-       stm32l4_info->probed = 0;
+       stm32l4_info->probed = false;
 
        /* read stm32 device id register */
        int retval = stm32l4_read_idcode(bank, &stm32l4_info->idcode);
@@ -877,7 +874,7 @@ static int stm32l4_probe(struct flash_bank *bank)
                return ERROR_FAIL;
        }
 
-       for (i = 0; i < bank->num_sectors; i++) {
+       for (int i = 0; i < bank->num_sectors; i++) {
                bank->sectors[i].offset = i * page_size;
                /* in dual bank configuration, if there is a gap between banks
                 * we fix up the sector offset to consider this gap */
@@ -888,7 +885,7 @@ static int stm32l4_probe(struct flash_bank *bank)
                bank->sectors[i].is_protected = 1;
        }
 
-       stm32l4_info->probed = 1;
+       stm32l4_info->probed = true;
        return ERROR_OK;
 }
 
@@ -934,7 +931,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
 
 static int stm32l4_mass_erase(struct flash_bank *bank)
 {
-       int retval;
+       int retval, retval2;
        struct target *target = bank->target;
        struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
 
@@ -950,35 +947,34 @@ static int stm32l4_mass_erase(struct flash_bank *bank)
 
        retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
 
        /* mass erase flash memory */
        retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT / 10);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
 
        retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, action);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
+
        retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, action | FLASH_STRT);
        if (retval != ERROR_OK)
-               return retval;
+               goto err_lock;
 
        retval = stm32l4_wait_status_busy(bank,  FLASH_ERASE_TIMEOUT);
-       if (retval != ERROR_OK)
-               return retval;
 
-       retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK);
+err_lock:
+       retval2 = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK);
+
        if (retval != ERROR_OK)
                return retval;
 
-       return ERROR_OK;
+       return retval2;
 }
 
 COMMAND_HANDLER(stm32l4_handle_mass_erase_command)
 {
-       int i;
-
        if (CMD_ARGC < 1) {
                command_print(CMD, "stm32l4x mass_erase <STM32L4 bank>");
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -992,7 +988,7 @@ COMMAND_HANDLER(stm32l4_handle_mass_erase_command)
        retval = stm32l4_mass_erase(bank);
        if (retval == ERROR_OK) {
                /* set all sectors as erased */
-               for (i = 0; i < bank->num_sectors; i++)
+               for (int i = 0; i < bank->num_sectors; i++)
                        bank->sectors[i].is_erased = 1;
 
                command_print(CMD, "stm32l4x mass erase complete");
index e6473f8..c3f9c72 100644 (file)
@@ -128,7 +128,7 @@ struct stm32lx_part_info {
 };
 
 struct stm32lx_flash_bank {
-       int probed;
+       bool probed;
        uint32_t idcode;
        uint32_t user_bank_size;
        uint32_t flash_base;
@@ -297,7 +297,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
 
        bank->driver_priv = stm32lx_info;
 
-       stm32lx_info->probed = 0;
+       stm32lx_info->probed = false;
        stm32lx_info->user_bank_size = bank->size;
 
        /* the stm32l erased value is 0x00 */
@@ -308,8 +308,6 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
 
 COMMAND_HANDLER(stm32lx_handle_mass_erase_command)
 {
-       int i;
-
        if (CMD_ARGC < 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
@@ -321,7 +319,7 @@ COMMAND_HANDLER(stm32lx_handle_mass_erase_command)
        retval = stm32lx_mass_erase(bank);
        if (retval == ERROR_OK) {
                /* set all sectors as erased */
-               for (i = 0; i < bank->num_sectors; i++)
+               for (int i = 0; i < bank->num_sectors; i++)
                        bank->sectors[i].is_erased = 1;
 
                command_print(CMD, "stm32lx mass erase complete");
@@ -731,14 +729,13 @@ static int stm32lx_probe(struct flash_bank *bank)
 {
        struct target *target = bank->target;
        struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
-       int i;
        uint16_t flash_size_in_kb;
        uint32_t device_id;
        uint32_t base_address = FLASH_BANK0_ADDRESS;
        uint32_t second_bank_base;
        unsigned int n;
 
-       stm32lx_info->probed = 0;
+       stm32lx_info->probed = false;
 
        int retval = stm32lx_read_id_code(bank->target, &device_id);
        if (retval != ERROR_OK)
@@ -756,7 +753,7 @@ static int stm32lx_probe(struct flash_bank *bank)
        }
 
        if (n == ARRAY_SIZE(stm32lx_parts)) {
-               LOG_WARNING("Cannot identify target as a STM32L family.");
+               LOG_ERROR("Cannot identify target as an STM32 L0 or L1 family device.");
                return ERROR_FAIL;
        } else {
                LOG_INFO("Device: %s", stm32lx_info->part_info.device_str);
@@ -852,14 +849,14 @@ static int stm32lx_probe(struct flash_bank *bank)
                return ERROR_FAIL;
        }
 
-       for (i = 0; i < num_sectors; i++) {
+       for (int i = 0; i < num_sectors; i++) {
                bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
                bank->sectors[i].size = FLASH_SECTOR_SIZE;
                bank->sectors[i].is_erased = -1;
                bank->sectors[i].is_protected = -1;
        }
 
-       stm32lx_info->probed = 1;
+       stm32lx_info->probed = true;
 
        return ERROR_OK;
 }
index bd313a0..3287dd9 100644 (file)
@@ -476,7 +476,7 @@ COMMAND_HANDLER(handle_flash_write_image_command)
 COMMAND_HANDLER(handle_flash_fill_command)
 {
        target_addr_t address;
-       uint32_t pattern;
+       uint64_t pattern;
        uint32_t count;
        struct target *target = get_current_target(CMD_CTX);
        unsigned i;
@@ -487,7 +487,7 @@ COMMAND_HANDLER(handle_flash_fill_command)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
+       COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], pattern);
        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
 
        struct flash_bank *bank;
@@ -496,6 +496,9 @@ COMMAND_HANDLER(handle_flash_fill_command)
                return retval;
 
        switch (CMD_NAME[4]) {
+               case 'd':
+                       wordsize = 8;
+                       break;
                case 'w':
                        wordsize = 4;
                        break;
@@ -541,6 +544,10 @@ COMMAND_HANDLER(handle_flash_fill_command)
        uint8_t *ptr = buffer + padding_at_start;
 
        switch (wordsize) {
+               case 8:
+                       for (i = 0; i < count; i++, ptr += wordsize)
+                               target_buffer_set_u64(target, ptr, pattern);
+                       break;
                case 4:
                        for (i = 0; i < count; i++, ptr += wordsize)
                                target_buffer_set_u32(target, ptr, pattern);
@@ -577,9 +584,12 @@ COMMAND_HANDLER(handle_flash_fill_command)
                goto done;
 
        for (i = 0, ptr = buffer; i < count; i++) {
-               uint32_t readback = 0;
+               uint64_t readback = 0;
 
                switch (wordsize) {
+                       case 8:
+                               readback = target_buffer_get_u64(target, ptr);
+                               break;
                        case 4:
                                readback = target_buffer_get_u32(target, ptr);
                                break;
@@ -593,7 +603,7 @@ COMMAND_HANDLER(handle_flash_fill_command)
                if (readback != pattern) {
                        LOG_ERROR(
                                "Verification error address " TARGET_ADDR_FMT
-                               ", read back 0x%02" PRIx32 ", expected 0x%02" PRIx32,
+                               ", read back 0x%02" PRIx64 ", expected 0x%02" PRIx64,
                                address + i * wordsize, readback, pattern);
                        retval = ERROR_FAIL;
                        goto done;
@@ -1003,6 +1013,14 @@ static const struct command_registration flash_exec_command_handlers[] = {
 
        },
        {
+               .name = "filld",
+               .handler = handle_flash_fill_command,
+               .mode = COMMAND_EXEC,
+               .usage = "address value n",
+               .help = "Fill n double-words with 64-bit value, starting at "
+                       "word address.  (No autoerase.)",
+       },
+       {
                .name = "fillw",
                .handler = handle_flash_fill_command,
                .mode = COMMAND_EXEC,
index de52e20..7259534 100644 (file)
@@ -101,23 +101,20 @@ proc program {filename args} {
 add_help_text program "write an image to flash, address is only required for binary images. verify, reset, exit are optional"
 add_usage_text program "<filename> \[address\] \[pre-verify\] \[verify\] \[reset\] \[exit\]"
 
-# stm32f0x uses the same flash driver as the stm32f1x
-# this alias enables the use of either name.
-proc stm32f0x args {
-       eval stm32f1x $args
-}
+# stm32[f0x|f3x] uses the same flash driver as the stm32f1x
+proc stm32f0x args { eval stm32f1x $args }
+proc stm32f3x args { eval stm32f1x $args }
 
-# stm32f3x uses the same flash driver as the stm32f1x
-# this alias enables the use of either name.
-proc stm32f3x args {
-       eval stm32f1x $args
-}
+# stm32[f4x|f7x] uses the same flash driver as the stm32f2x
+proc stm32f4x args { eval stm32f2x $args }
+proc stm32f7x args { eval stm32f2x $args }
 
-# stm32f4x uses the same flash driver as the stm32f2x
-# this alias enables the use of either name.
-proc stm32f4x args {
-       eval stm32f2x $args
-}
+# stm32lx driver supports both STM32 L0 and L1 devices
+proc stm32l0x args { eval stm32lx $args }
+proc stm32l1x args { eval stm32lx $args }
+
+# stm32wb uses the same flash driver as the stm32l4x
+proc stm32wbx args { eval stm32l4x $args }
 
 # ease migration to updated flash driver
 proc stm32x args {
index 8f48b92..ae26df5 100644 (file)
@@ -220,6 +220,15 @@ COMMAND_HANDLER(handle_debug_level_command)
 
 COMMAND_HANDLER(handle_log_output_command)
 {
+       if (CMD_ARGC == 0 || (CMD_ARGC == 1 && strcmp(CMD_ARGV[0], "default") == 0)) {
+               if (log_output != stderr && log_output != NULL) {
+                       /* Close previous log file, if it was open and wasn't stderr. */
+                       fclose(log_output);
+               }
+               log_output = stderr;
+               LOG_DEBUG("set log_output to default");
+               return ERROR_OK;
+       }
        if (CMD_ARGC == 1) {
                FILE *file = fopen(CMD_ARGV[0], "w");
                if (file == NULL) {
@@ -231,9 +240,11 @@ COMMAND_HANDLER(handle_log_output_command)
                        fclose(log_output);
                }
                log_output = file;
+               LOG_DEBUG("set log_output to \"%s\"", CMD_ARGV[0]);
+               return ERROR_OK;
        }
 
-       return ERROR_OK;
+       return ERROR_COMMAND_SYNTAX_ERROR;
 }
 
 static const struct command_registration log_command_handlers[] = {
@@ -242,7 +253,7 @@ static const struct command_registration log_command_handlers[] = {
                .handler = handle_log_output_command,
                .mode = COMMAND_ANY,
                .help = "redirect logging to a file (default: stderr)",
-               .usage = "file_name",
+               .usage = "[file_name | \"default\"]",
        },
        {
                .name = "debug_level",
index 5e35c13..b6747f8 100644 (file)
@@ -126,17 +126,17 @@ static inline uint64_t le_to_h_u64(const uint8_t *buf)
                          (uint64_t)buf[7] << 56);
 }
 
-static inline uint32_t le_to_h_u32(const uint8_tbuf)
+static inline uint32_t le_to_h_u32(const uint8_t *buf)
 {
        return (uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24);
 }
 
-static inline uint32_t le_to_h_u24(const uint8_tbuf)
+static inline uint32_t le_to_h_u24(const uint8_t *buf)
 {
        return (uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16);
 }
 
-static inline uint16_t le_to_h_u16(const uint8_tbuf)
+static inline uint16_t le_to_h_u16(const uint8_t *buf)
 {
        return (uint16_t)((uint16_t)buf[0] | (uint16_t)buf[1] << 8);
 }
@@ -153,17 +153,17 @@ static inline uint64_t be_to_h_u64(const uint8_t *buf)
                          (uint64_t)buf[0] << 56);
 }
 
-static inline uint32_t be_to_h_u32(const uint8_tbuf)
+static inline uint32_t be_to_h_u32(const uint8_t *buf)
 {
        return (uint32_t)((uint32_t)buf[3] | (uint32_t)buf[2] << 8 | (uint32_t)buf[1] << 16 | (uint32_t)buf[0] << 24);
 }
 
-static inline uint32_t be_to_h_u24(const uint8_tbuf)
+static inline uint32_t be_to_h_u24(const uint8_t *buf)
 {
        return (uint32_t)((uint32_t)buf[2] | (uint32_t)buf[1] << 8 | (uint32_t)buf[0] << 16);
 }
 
-static inline uint16_t be_to_h_u16(const uint8_tbuf)
+static inline uint16_t be_to_h_u16(const uint8_t *buf)
 {
        return (uint16_t)((uint16_t)buf[1] | (uint16_t)buf[0] << 8);
 }
@@ -192,7 +192,7 @@ static inline void h_u64_to_be(uint8_t *buf, int64_t val)
        buf[7] = (uint8_t) (val >> 0);
 }
 
-static inline void h_u32_to_le(uint8_tbuf, int val)
+static inline void h_u32_to_le(uint8_t *buf, int val)
 {
        buf[3] = (uint8_t) (val >> 24);
        buf[2] = (uint8_t) (val >> 16);
@@ -200,7 +200,7 @@ static inline void h_u32_to_le(uint8_t* buf, int val)
        buf[0] = (uint8_t) (val >> 0);
 }
 
-static inline void h_u32_to_be(uint8_tbuf, int val)
+static inline void h_u32_to_be(uint8_t *buf, int val)
 {
        buf[0] = (uint8_t) (val >> 24);
        buf[1] = (uint8_t) (val >> 16);
@@ -208,27 +208,27 @@ static inline void h_u32_to_be(uint8_t* buf, int val)
        buf[3] = (uint8_t) (val >> 0);
 }
 
-static inline void h_u24_to_le(uint8_tbuf, int val)
+static inline void h_u24_to_le(uint8_t *buf, int val)
 {
        buf[2] = (uint8_t) (val >> 16);
        buf[1] = (uint8_t) (val >> 8);
        buf[0] = (uint8_t) (val >> 0);
 }
 
-static inline void h_u24_to_be(uint8_tbuf, int val)
+static inline void h_u24_to_be(uint8_t *buf, int val)
 {
        buf[0] = (uint8_t) (val >> 16);
        buf[1] = (uint8_t) (val >> 8);
        buf[2] = (uint8_t) (val >> 0);
 }
 
-static inline void h_u16_to_le(uint8_tbuf, int val)
+static inline void h_u16_to_le(uint8_t *buf, int val)
 {
        buf[1] = (uint8_t) (val >> 8);
        buf[0] = (uint8_t) (val >> 0);
 }
 
-static inline void h_u16_to_be(uint8_tbuf, int val)
+static inline void h_u16_to_be(uint8_t *buf, int val)
 {
        buf[0] = (uint8_t) (val >> 8);
        buf[1] = (uint8_t) (val >> 0);
index e2782a7..af75917 100644 (file)
@@ -66,7 +66,7 @@ static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
        return JIM_OK;
 }
 
-COMMAND_HANDLER(interface_transport_command)
+COMMAND_HANDLER(adapter_transports_command)
 {
        char **transports;
        int retval;
@@ -85,12 +85,12 @@ COMMAND_HANDLER(interface_transport_command)
        return retval;
 }
 
-COMMAND_HANDLER(handle_interface_list_command)
+COMMAND_HANDLER(handle_adapter_list_command)
 {
-       if (strcmp(CMD_NAME, "interface_list") == 0 && CMD_ARGC > 0)
+       if (strcmp(CMD_NAME, "list") == 0 && CMD_ARGC > 0)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       command_print(CMD, "The following debug interfaces are available:");
+       command_print(CMD, "The following debug adapters are available:");
        for (unsigned i = 0; NULL != adapter_drivers[i]; i++) {
                const char *name = adapter_drivers[i]->name;
                command_print(CMD, "%u: %s", i + 1, name);
@@ -99,7 +99,7 @@ COMMAND_HANDLER(handle_interface_list_command)
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(handle_interface_command)
+COMMAND_HANDLER(handle_adapter_driver_command)
 {
        int retval;
 
@@ -134,7 +134,7 @@ COMMAND_HANDLER(handle_interface_command)
         */
        LOG_ERROR("The specified debug interface was not found (%s)",
                                CMD_ARGV[0]);
-       CALL_COMMAND_HANDLER(handle_interface_list_command);
+       CALL_COMMAND_HANDLER(handle_adapter_list_command);
        return ERROR_JTAG_INVALID_INTERFACE;
 }
 
@@ -355,7 +355,7 @@ next:
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(handle_adapter_nsrst_delay_command)
+COMMAND_HANDLER(handle_adapter_srst_delay_command)
 {
        if (CMD_ARGC > 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -365,11 +365,11 @@ COMMAND_HANDLER(handle_adapter_nsrst_delay_command)
 
                jtag_set_nsrst_delay(delay);
        }
-       command_print(CMD, "adapter_nsrst_delay: %u", jtag_get_nsrst_delay());
+       command_print(CMD, "adapter srst delay: %u", jtag_get_nsrst_delay());
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command)
+COMMAND_HANDLER(handle_adapter_srst_pulse_width_command)
 {
        if (CMD_ARGC > 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -379,11 +379,11 @@ COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command)
 
                jtag_set_nsrst_assert_width(width);
        }
-       command_print(CMD, "adapter_nsrst_assert_width: %u", jtag_get_nsrst_assert_width());
+       command_print(CMD, "adapter srst pulse_width: %u", jtag_get_nsrst_assert_width());
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(handle_adapter_khz_command)
+COMMAND_HANDLER(handle_adapter_speed_command)
 {
        if (CMD_ARGC > 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -524,92 +524,103 @@ static const struct command_registration adapter_usb_command_handlers[] = {
 };
 #endif /* MINIDRIVER */
 
-static const struct command_registration adapter_command_handlers[] = {
-#ifndef HAVE_JTAG_MINIDRIVER_H
+static const struct command_registration adapter_srst_command_handlers[] = {
        {
-               .name = "usb",
+               .name = "delay",
+               .handler = handle_adapter_srst_delay_command,
                .mode = COMMAND_ANY,
-               .help = "usb adapter command group",
-               .usage = "",
-               .chain = adapter_usb_command_handlers,
-       },
-#endif /* MINIDRIVER */
-       {
-               .name = "assert",
-               .handler = handle_adapter_reset_de_assert,
-               .mode = COMMAND_EXEC,
-               .help = "Controls SRST and TRST lines.",
-               .usage = "|deassert [srst|trst [assert|deassert srst|trst]]",
+               .help = "delay after deasserting SRST in ms",
+               .usage = "[milliseconds]",
        },
        {
-               .name = "deassert",
-               .handler = handle_adapter_reset_de_assert,
-               .mode = COMMAND_EXEC,
-               .help = "Controls SRST and TRST lines.",
-               .usage = "|assert [srst|trst [deassert|assert srst|trst]]",
+               .name = "pulse_width",
+               .handler = handle_adapter_srst_pulse_width_command,
+               .mode = COMMAND_ANY,
+               .help = "SRST assertion pulse width in ms",
+               .usage = "[milliseconds]",
        },
        COMMAND_REGISTRATION_DONE
 };
 
-static const struct command_registration interface_command_handlers[] = {
+static const struct command_registration adapter_command_handlers[] = {
        {
-               .name = "adapter",
-               .mode = COMMAND_ANY,
-               .help = "adapter command group",
-               .usage = "",
-               .chain = adapter_command_handlers,
+               .name = "driver",
+               .handler = handle_adapter_driver_command,
+               .mode = COMMAND_CONFIG,
+               .help = "Select a debug adapter driver",
+               .usage = "driver_name",
        },
        {
-               .name = "adapter_khz",
-               .handler = handle_adapter_khz_command,
+               .name = "speed",
+               .handler = handle_adapter_speed_command,
                .mode = COMMAND_ANY,
                .help = "With an argument, change to the specified maximum "
                        "jtag speed.  For JTAG, 0 KHz signifies adaptive "
-                       " clocking. "
+                       "clocking. "
                        "With or without argument, display current setting.",
                .usage = "[khz]",
        },
        {
-               .name = "adapter_name",
+               .name = "list",
+               .handler = handle_adapter_list_command,
+               .mode = COMMAND_ANY,
+               .help = "List all built-in debug adapter drivers",
+               .usage = "",
+       },
+       {
+               .name = "name",
                .mode = COMMAND_ANY,
                .jim_handler = jim_adapter_name,
                .help = "Returns the name of the currently "
                        "selected adapter (driver)",
        },
        {
-               .name = "adapter_nsrst_delay",
-               .handler = handle_adapter_nsrst_delay_command,
+               .name = "srst",
                .mode = COMMAND_ANY,
-               .help = "delay after deasserting SRST in ms",
-               .usage = "[milliseconds]",
+               .help = "srst adapter command group",
+               .usage = "",
+               .chain = adapter_srst_command_handlers,
        },
        {
-               .name = "adapter_nsrst_assert_width",
-               .handler = handle_adapter_nsrst_assert_width_command,
+               .name = "transports",
+               .handler = adapter_transports_command,
+               .mode = COMMAND_CONFIG,
+               .help = "Declare transports the adapter supports.",
+               .usage = "transport ... ",
+       },
+#ifndef HAVE_JTAG_MINIDRIVER_H
+       {
+               .name = "usb",
                .mode = COMMAND_ANY,
-               .help = "delay after asserting SRST in ms",
-               .usage = "[milliseconds]",
+               .help = "usb adapter command group",
+               .usage = "",
+               .chain = adapter_usb_command_handlers,
        },
+#endif /* MINIDRIVER */
        {
-               .name = "interface",
-               .handler = handle_interface_command,
-               .mode = COMMAND_CONFIG,
-               .help = "Select a debug adapter interface (driver)",
-               .usage = "driver_name",
+               .name = "assert",
+               .handler = handle_adapter_reset_de_assert,
+               .mode = COMMAND_EXEC,
+               .help = "Controls SRST and TRST lines.",
+               .usage = "|deassert [srst|trst [assert|deassert srst|trst]]",
        },
        {
-               .name = "interface_transports",
-               .handler = interface_transport_command,
-               .mode = COMMAND_CONFIG,
-               .help = "Declare transports the interface supports.",
-               .usage = "transport ... ",
+               .name = "deassert",
+               .handler = handle_adapter_reset_de_assert,
+               .mode = COMMAND_EXEC,
+               .help = "Controls SRST and TRST lines.",
+               .usage = "|assert [srst|trst [deassert|assert srst|trst]]",
        },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration interface_command_handlers[] = {
        {
-               .name = "interface_list",
-               .handler = handle_interface_list_command,
+               .name = "adapter",
                .mode = COMMAND_ANY,
-               .help = "List all built-in debug adapter interfaces (drivers)",
+               .help = "adapter command group",
                .usage = "",
+               .chain = adapter_command_handlers,
        },
        {
                .name = "reset_config",
index 324ec7c..9e47413 100644 (file)
@@ -349,41 +349,53 @@ static void aice_unpack_dthmb(uint8_t *cmd_ack_code, uint8_t *target_id,
 /* calls the given usb_bulk_* function, allowing for the data to
  * trickle in with some timeouts  */
 static int usb_bulk_with_retries(
-                       int (*f)(jtag_libusb_device_handle *, int, char *, int, int),
+                       int (*f)(jtag_libusb_device_handle *, int, char *, int, int, int *),
                        jtag_libusb_device_handle *dev, int ep,
-                       char *bytes, int size, int timeout)
+                       char *bytes, int size, int timeout, int *transferred)
 {
        int tries = 3, count = 0;
 
        while (tries && (count < size)) {
-               int result = f(dev, ep, bytes + count, size - count, timeout);
-               if (result > 0)
+               int result, ret;
+
+               ret = f(dev, ep, bytes + count, size - count, timeout, &result);
+               if (ERROR_OK == ret)
                        count += result;
-               else if ((-ETIMEDOUT != result) || !--tries)
-                       return result;
+               else if ((ERROR_TIMEOUT_REACHED != ret) || !--tries)
+                       return ret;
        }
-       return count;
+
+       *transferred = count;
+       return ERROR_OK;
 }
 
 static int wrap_usb_bulk_write(jtag_libusb_device_handle *dev, int ep,
-               char *buff, int size, int timeout)
+               char *buff, int size, int timeout, int *transferred)
 {
+
        /* usb_bulk_write() takes const char *buff */
-       return jtag_libusb_bulk_write(dev, ep, buff, size, timeout);
+       jtag_libusb_bulk_write(dev, ep, buff, size, timeout, transferred);
+
+       return 0;
 }
 
 static inline int usb_bulk_write_ex(jtag_libusb_device_handle *dev, int ep,
                char *bytes, int size, int timeout)
 {
-       return usb_bulk_with_retries(&wrap_usb_bulk_write,
-                       dev, ep, bytes, size, timeout);
+       int tr = 0;
+
+       usb_bulk_with_retries(&wrap_usb_bulk_write,
+                       dev, ep, bytes, size, timeout, &tr);
+       return tr;
 }
 
 static inline int usb_bulk_read_ex(jtag_libusb_device_handle *dev, int ep,
                char *bytes, int size, int timeout)
 {
-       return usb_bulk_with_retries(&jtag_libusb_bulk_read,
-                       dev, ep, bytes, size, timeout);
+       int tr = 0;
+       usb_bulk_with_retries(&jtag_libusb_bulk_read,
+                       dev, ep, bytes, size, timeout, &tr);
+       return tr;
 }
 
 /* Write data from out_buffer to USB. */
index 111b122..1d59712 100644 (file)
@@ -842,6 +842,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        if (trst_with_tlr) {
                LOG_DEBUG("JTAG reset with TLR instead of TRST");
                jtag_add_tlr();
+               jtag_execute_queue();
 
        } else if (jtag_trst != new_trst) {
                jtag_trst = new_trst;
@@ -1519,9 +1520,9 @@ int adapter_init(struct command_context *cmd_ctx)
                return ERROR_OK;
 
        if (!adapter_driver) {
-               /* nothing was previously specified by "interface" command */
+               /* nothing was previously specified by "adapter driver" command */
                LOG_ERROR("Debug Adapter has to be specified, "
-                       "see \"interface\" command");
+                       "see \"adapter driver\" command");
                return ERROR_JTAG_INVALID_INTERFACE;
        }
 
@@ -1538,7 +1539,7 @@ int adapter_init(struct command_context *cmd_ctx)
 
        if (CLOCK_MODE_UNSELECTED == clock_mode) {
                LOG_ERROR("An adapter speed is not selected in the init script."
-                       " Insert a call to adapter_khz or jtag_rclk to proceed.");
+                       " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed.");
                return ERROR_JTAG_INIT_FAILED;
        }
 
index 572cd24..7fbcd58 100644 (file)
@@ -145,6 +145,9 @@ endif
 if SYSFSGPIO
 DRIVERFILES += %D%/sysfsgpio.c
 endif
+if XLNX_PCIE_XVC
+DRIVERFILES += %D%/xlnx-pcie-xvc.c
+endif
 if BCM2835GPIO
 DRIVERFILES += %D%/bcm2835gpio.c
 endif
index c072821..3d2693c 100644 (file)
@@ -1628,10 +1628,10 @@ static int cmsis_dap_execute_queue(void)
 static int cmsis_dap_speed(int speed)
 {
        if (speed > DAP_MAX_CLOCK)
-               LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed);
+               LOG_INFO("High speed (adapter speed %d) may be limited by adapter firmware.", speed);
 
        if (speed == 0) {
-               LOG_ERROR("RTCK not supported. Set nonzero adapter_khz.");
+               LOG_ERROR("RTCK not supported. Set nonzero \"adapter speed\".");
                return ERROR_JTAG_NOT_IMPLEMENTED;
        }
 
index 1ef0c57..c20367f 100644 (file)
@@ -132,11 +132,11 @@ static int ft232r_send_recv(void)
                        bytes_to_write = rxfifo_free;
 
                if (bytes_to_write) {
-                       int n = jtag_libusb_bulk_write(adapter, IN_EP,
-                               (char *) ft232r_output + total_written,
-                               bytes_to_write, 1000);
+                       int n;
 
-                       if (n == 0) {
+                       if (jtag_libusb_bulk_write(adapter, IN_EP,
+                                                  (char *) ft232r_output + total_written,
+                                                  bytes_to_write, 1000, &n) != ERROR_OK) {
                                LOG_ERROR("usb bulk write failed");
                                return ERROR_JTAG_DEVICE_ERROR;
                        }
@@ -147,12 +147,10 @@ static int ft232r_send_recv(void)
 
                /* Read */
                uint8_t reply[64];
+               int n;
 
-               int n = jtag_libusb_bulk_read(adapter, OUT_EP,
-                       (char *) reply,
-                       sizeof(reply), 1000);
-
-               if (n == 0) {
+               if (jtag_libusb_bulk_read(adapter, OUT_EP, (char *) reply,
+                                         sizeof(reply), 1000, &n) != ERROR_OK) {
                        LOG_ERROR("usb bulk read failed");
                        return ERROR_JTAG_DEVICE_ERROR;
                }
index 40d076e..a9cdbbe 100644 (file)
@@ -213,7 +213,7 @@ static int ftdi_set_signal(const struct signal *s, char value)
        return ERROR_OK;
 }
 
-static int ftdi_get_signal(const struct signal *s, uint16_t * value_out)
+static int ftdi_get_signal(const struct signal *s, uint16_t *value_out)
 {
        uint8_t data_low = 0;
        uint8_t data_high = 0;
index e5124b5..a5a95a5 100644 (file)
 #define CMD_SCAN_CHAIN_FLIP_TMS        3
 #define CMD_STOP_SIMU          4
 
-int server_port = SERVER_PORT;
-char *server_address;
+/* jtag_vpi server port and address to connect to */
+static int server_port = SERVER_PORT;
+static char *server_address;
 
-int sockfd;
-struct sockaddr_in serv_addr;
+/* Send CMD_STOP_SIMU to server when OpenOCD exits? */
+static bool stop_sim_on_exit;
+
+static int sockfd;
+static struct sockaddr_in serv_addr;
 
 /* One jtag_vpi "packet" as sent over a TCP channel. */
 struct vpi_cmd {
@@ -576,10 +580,28 @@ static int jtag_vpi_init(void)
        return ERROR_OK;
 }
 
+static int jtag_vpi_stop_simulation(void)
+{
+       struct vpi_cmd cmd;
+       memset(&cmd, 0, sizeof(struct vpi_cmd));
+       cmd.length = 0;
+       cmd.nb_bits = 0;
+       cmd.cmd = CMD_STOP_SIMU;
+       return jtag_vpi_send_cmd(&cmd);
+}
+
 static int jtag_vpi_quit(void)
 {
+       if (stop_sim_on_exit) {
+               if (jtag_vpi_stop_simulation() != ERROR_OK)
+                       LOG_WARNING("jtag_vpi: failed to send \"stop simulation\" command");
+       }
+       if (close_socket(sockfd) != 0) {
+               LOG_WARNING("jtag_vpi: could not close jtag_vpi client socket");
+               log_socket_error("jtag_vpi");
+       }
        free(server_address);
-       return close_socket(sockfd);
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(jtag_vpi_set_port)
@@ -609,6 +631,17 @@ COMMAND_HANDLER(jtag_vpi_set_address)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler)
+{
+       if (CMD_ARGC != 1) {
+               LOG_ERROR("jtag_vpi_stop_sim_on_exit expects 1 argument (on|off)");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       } else {
+               COMMAND_PARSE_ON_OFF(CMD_ARGV[0], stop_sim_on_exit);
+       }
+       return ERROR_OK;
+}
+
 static const struct command_registration jtag_vpi_command_handlers[] = {
        {
                .name = "jtag_vpi_set_port",
@@ -624,6 +657,14 @@ static const struct command_registration jtag_vpi_command_handlers[] = {
                .help = "set the address of the VPI server",
                .usage = "ipv4_addr",
        },
+       {
+               .name = "jtag_vpi_stop_sim_on_exit",
+               .handler = &jtag_vpi_stop_sim_on_exit_handler,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure if simulation stop command shall be sent "
+                       "before OpenOCD exits (default: off)",
+               .usage = "<on|off>",
+       },
        COMMAND_REGISTRATION_DONE
 };
 
index 4894411..7b339aa 100644 (file)
@@ -731,14 +731,14 @@ static int kitprog_swd_run_queue(void)
                        }
                }
 
-               ret = jtag_libusb_bulk_write(kitprog_handle->usb_handle,
-                               BULK_EP_OUT, (char *)buffer, write_count, 0);
-               if (ret > 0) {
-                       queued_retval = ERROR_OK;
-               } else {
+               if (jtag_libusb_bulk_write(kitprog_handle->usb_handle,
+                                          BULK_EP_OUT, (char *)buffer,
+                                          write_count, 0, &ret)) {
                        LOG_ERROR("Bulk write failed");
                        queued_retval = ERROR_FAIL;
                        break;
+               } else {
+                       queued_retval = ERROR_OK;
                }
 
                /* KitProg firmware does not send a zero length packet
@@ -754,18 +754,17 @@ static int kitprog_swd_run_queue(void)
                if (read_count % 64 == 0)
                        read_count_workaround = read_count;
 
-               ret = jtag_libusb_bulk_read(kitprog_handle->usb_handle,
+               if (jtag_libusb_bulk_read(kitprog_handle->usb_handle,
                                BULK_EP_IN | LIBUSB_ENDPOINT_IN, (char *)buffer,
-                               read_count_workaround, 1000);
-               if (ret > 0) {
+                               read_count_workaround, 1000, &ret)) {
+                       LOG_ERROR("Bulk read failed");
+                       queued_retval = ERROR_FAIL;
+                       break;
+               } else {
                        /* Handle garbage data by offsetting the initial read index */
                        if ((unsigned int)ret > read_count)
                                read_index = ret - read_count;
                        queued_retval = ERROR_OK;
-               } else {
-                       LOG_ERROR("Bulk read failed");
-                       queued_retval = ERROR_FAIL;
-                       break;
                }
 
                for (int i = 0; i < pending_transfer_count; i++) {
index 14a8b61..0e78589 100644 (file)
 #include "log.h"
 #include "libusb0_common.h"
 
+static int jtag_libusb_error(int err)
+{
+       switch (err) {
+       case 0:
+               return ERROR_OK;
+       case -ETIMEDOUT:
+               return ERROR_TIMEOUT_REACHED;
+       default:
+               return ERROR_FAIL;
+       }
+}
+
 static bool jtag_libusb_match(struct jtag_libusb_device *dev,
                const uint16_t vids[], const uint16_t pids[])
 {
@@ -130,15 +142,37 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t request
 }
 
 int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes,
-               int size, int timeout)
+               int size, int timeout, int *transferred)
 {
-       return usb_bulk_write(dev, ep, bytes, size, timeout);
+       int ret;
+
+       *transferred = 0;
+
+       ret = usb_bulk_write(dev, ep, bytes, size, timeout);
+
+       if (ret < 0) {
+               LOG_ERROR("usb_bulk_write error: %i", ret);
+               return jtag_libusb_error(ret);
+       }
+
+       return ERROR_OK;
 }
 
 int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes,
-               int size, int timeout)
+               int size, int timeout, int *transferred)
 {
-       return usb_bulk_read(dev, ep, bytes, size, timeout);
+       int ret;
+
+       *transferred = 0;
+
+       ret = usb_bulk_read(dev, ep, bytes, size, timeout);
+
+       if (ret < 0) {
+               LOG_ERROR("usb_bulk_read error: %i", ret);
+               return jtag_libusb_error(ret);
+       }
+
+       return ERROR_OK;
 }
 
 int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
index 676f43a..6f632c4 100644 (file)
@@ -60,9 +60,9 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
                uint8_t requestType, uint8_t request, uint16_t wValue,
                uint16_t wIndex, char *bytes,   uint16_t size, unsigned int timeout);
 int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep,
-               char *bytes, int size, int timeout);
+               char *bytes, int size, int timeout, int *transferred);
 int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep,
-               char *bytes, int size, int timeout);
+               char *bytes, int size, int timeout, int *transferred);
 int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
                int configuration);
 int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
index d96ac76..0d4bcba 100644 (file)
 static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
 static libusb_device **devs; /**< The usb device list **/
 
+static int jtag_libusb_error(int err)
+{
+       switch (err) {
+       case LIBUSB_SUCCESS:
+               return ERROR_OK;
+       case LIBUSB_ERROR_TIMEOUT:
+               return ERROR_TIMEOUT_REACHED;
+       case LIBUSB_ERROR_IO:
+       case LIBUSB_ERROR_INVALID_PARAM:
+       case LIBUSB_ERROR_ACCESS:
+       case LIBUSB_ERROR_NO_DEVICE:
+       case LIBUSB_ERROR_NOT_FOUND:
+       case LIBUSB_ERROR_BUSY:
+       case LIBUSB_ERROR_OVERFLOW:
+       case LIBUSB_ERROR_PIPE:
+       case LIBUSB_ERROR_INTERRUPTED:
+       case LIBUSB_ERROR_NO_MEM:
+       case LIBUSB_ERROR_NOT_SUPPORTED:
+       case LIBUSB_ERROR_OTHER:
+               return ERROR_FAIL;
+       default:
+               return ERROR_FAIL;
+       }
+}
+
 static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc,
                const uint16_t vids[], const uint16_t pids[])
 {
@@ -179,23 +204,37 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t request
 }
 
 int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes,
-               int size, int timeout)
+                          int size, int timeout, int *transferred)
 {
-       int transferred = 0;
+       int ret;
 
-       libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
-                            &transferred, timeout);
-       return transferred;
+       *transferred = 0;
+
+       ret = libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
+                                  transferred, timeout);
+       if (ret != LIBUSB_SUCCESS) {
+               LOG_ERROR("libusb_bulk_write error: %s", libusb_error_name(ret));
+               return jtag_libusb_error(ret);
+       }
+
+       return ERROR_OK;
 }
 
 int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes,
-               int size, int timeout)
+                         int size, int timeout, int *transferred)
 {
-       int transferred = 0;
+       int ret;
 
-       libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
-                            &transferred, timeout);
-       return transferred;
+       *transferred = 0;
+
+       ret = libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
+                                  transferred, timeout);
+       if (ret != LIBUSB_SUCCESS) {
+               LOG_ERROR("libusb_bulk_read error: %s", libusb_error_name(ret));
+               return jtag_libusb_error(ret);
+       }
+
+       return ERROR_OK;
 }
 
 int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
index 7c73d29..34be691 100644 (file)
@@ -53,9 +53,9 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
                uint8_t requestType, uint8_t request, uint16_t wValue,
                uint16_t wIndex, char *bytes,   uint16_t size, unsigned int timeout);
 int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep,
-               char *bytes,    int size, int timeout);
+               char *bytes, int size, int timeout, int *transferred);
 int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep,
-               char *bytes, int size, int timeout);
+               char *bytes, int size, int timeout, int *transferred);
 int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
                int configuration);
 /**
index 539f475..d5c279b 100644 (file)
@@ -770,8 +770,8 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
                        LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
                        FUNC_WRITE_DATA, 0, 0, (char *) usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
        } else {
-               result = jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT, \
-                       (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
+               jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT, \
+                       (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT, &result);
        }
 #ifdef _DEBUG_USB_COMMS_
        LOG_DEBUG("USB write end: %d bytes", result);
@@ -797,8 +797,8 @@ int opendous_usb_read(struct opendous_jtag *opendous_jtag)
                        LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
                        FUNC_READ_DATA, 0, 0, (char *) usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
        } else {
-               result = jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
-                       (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
+               jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
+                       (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT, &result);
        }
 #ifdef _DEBUG_USB_COMMS_
        LOG_DEBUG("USB read end: %d bytes", result);
index 24960a8..c42b620 100644 (file)
@@ -256,10 +256,9 @@ static int openjtag_buf_write_cy7c65215(
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
-       ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
-                                                                CY7C65215_USB_TIMEOUT);
-       if (ret < 0) {
-               LOG_ERROR("bulk write failed, error %d", ret);
+       if (jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
+                                  CY7C65215_USB_TIMEOUT, &ret)) {
+               LOG_ERROR("bulk write failed, error");
                return ERROR_JTAG_DEVICE_ERROR;
        }
        *bytes_written = ret;
@@ -324,10 +323,9 @@ static int openjtag_buf_read_cy7c65215(
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
-       ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
-                                                               CY7C65215_USB_TIMEOUT);
-       if (ret < 0) {
-               LOG_ERROR("bulk read failed, error %d", ret);
+       if (jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
+                                 CY7C65215_USB_TIMEOUT, &ret)) {
+               LOG_ERROR("bulk read failed, error");
                return ERROR_JTAG_DEVICE_ERROR;
        }
        *bytes_read = ret;
index ed89a79..3323557 100644 (file)
@@ -144,10 +144,12 @@ static struct osbdm osbdm_context;
 static int osbdm_send_and_recv(struct osbdm *osbdm)
 {
        /* Send request */
-       int count = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE,
-               (char *)osbdm->buffer, osbdm->count, OSBDM_USB_TIMEOUT);
+       int count, ret;
 
-       if (count != osbdm->count) {
+       ret = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE,
+                                    (char *)osbdm->buffer, osbdm->count,
+                                    OSBDM_USB_TIMEOUT, &count);
+       if (ret || count != osbdm->count) {
                LOG_ERROR("OSBDM communication error: can't write");
                return ERROR_FAIL;
        }
@@ -156,13 +158,12 @@ static int osbdm_send_and_recv(struct osbdm *osbdm)
        uint8_t cmd_saved = osbdm->buffer[0];
 
        /* Reading answer */
-       osbdm->count = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ,
-               (char *)osbdm->buffer, OSBDM_USB_BUFSIZE, OSBDM_USB_TIMEOUT);
-
+       ret = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ,
+                                   (char *)osbdm->buffer, OSBDM_USB_BUFSIZE,
+                                   OSBDM_USB_TIMEOUT, &osbdm->count);
        /* Now perform basic checks for data sent by BDM device
         */
-
-       if (osbdm->count < 0) {
+       if (ret) {
                LOG_ERROR("OSBDM communication error: can't read");
                return ERROR_FAIL;
        }
@@ -296,7 +297,7 @@ static int osbdm_swap(struct osbdm *osbdm, void *tms, void *tdi,
        return ERROR_OK;
 }
 
-static int osbdm_flush(struct osbdm *osbdm, struct queuequeue)
+static int osbdm_flush(struct osbdm *osbdm, struct queue *queue)
 {
        uint8_t tms[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
        uint8_t tdi[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
index 5c904d4..da1d1b5 100644 (file)
@@ -78,7 +78,7 @@
 /*
  * ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and
  * this limits the bulk packet size and the 8bit read/writes to max 64 bytes.
- * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes.
+ * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes from FW V3J6.
  */
 #define STLINK_MAX_RW8         (64)
 #define STLINKV3_MAX_RW8       (512)
@@ -317,6 +317,7 @@ enum stlink_mode {
 #define STLINK_F_QUIRK_JTAG_DP_READ     BIT(6)
 #define STLINK_F_HAS_AP_INIT            BIT(7)
 #define STLINK_F_HAS_DPBANKSEL          BIT(8)
+#define STLINK_F_HAS_RW8_512BYTES       BIT(9)
 
 /* aliases */
 #define STLINK_F_HAS_TARGET_VOLT        STLINK_F_HAS_TRACE
@@ -367,7 +368,7 @@ static unsigned int stlink_usb_block(void *handle)
 
        assert(handle != NULL);
 
-       if (h->version.stlink == 3)
+       if (h->version.flags & STLINK_F_HAS_RW8_512BYTES)
                return STLINKV3_MAX_RW8;
        else
                return STLINK_MAX_RW8;
@@ -531,14 +532,16 @@ static int jtag_libusb_bulk_transfer_n(
 static int stlink_usb_xfer_v1_get_status(void *handle)
 {
        struct stlink_usb_handle_s *h = handle;
+       int tr, ret;
 
        assert(handle != NULL);
 
        /* read status */
        memset(h->cmdbuf, 0, STLINK_SG_SIZE);
 
-       if (jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)h->cmdbuf,
-                       13, STLINK_READ_TIMEOUT) != 13)
+       ret = jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)h->cmdbuf, 13,
+                                   STLINK_READ_TIMEOUT, &tr);
+       if (ret || tr != 13)
                return ERROR_FAIL;
 
        uint32_t t1;
@@ -602,23 +605,26 @@ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int
 static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int size)
 {
        struct stlink_usb_handle_s *h = handle;
+       int tr, ret;
 
        assert(handle != NULL);
 
-       if (jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf, cmdsize,
-                       STLINK_WRITE_TIMEOUT) != cmdsize) {
+       ret = jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf,
+                                    cmdsize, STLINK_WRITE_TIMEOUT, &tr);
+       if (ret || tr != cmdsize)
                return ERROR_FAIL;
-       }
 
        if (h->direction == h->tx_ep && size) {
-               if (jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)buf,
-                               size, STLINK_WRITE_TIMEOUT) != size) {
+               ret = jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)buf,
+                                            size, STLINK_WRITE_TIMEOUT, &tr);
+               if (ret || tr != size) {
                        LOG_DEBUG("bulk write failed");
                        return ERROR_FAIL;
                }
        } else if (h->direction == h->rx_ep && size) {
-               if (jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)buf,
-                               size, STLINK_READ_TIMEOUT) != size) {
+               ret = jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)buf,
+                                           size, STLINK_READ_TIMEOUT, &tr);
+               if (ret || tr != size) {
                        LOG_DEBUG("bulk read failed");
                        return ERROR_FAIL;
                }
@@ -840,13 +846,15 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size)
 static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size)
 {
        struct stlink_usb_handle_s *h = handle;
+       int tr, ret;
 
        assert(handle != NULL);
 
        assert(h->version.flags & STLINK_F_HAS_TRACE);
 
-       if (jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf,
-                       size, STLINK_READ_TIMEOUT) != size) {
+       ret = jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf, size,
+                                   STLINK_READ_TIMEOUT, &tr);
+       if (ret || tr != size) {
                LOG_ERROR("bulk trace read failed");
                return ERROR_FAIL;
        }
@@ -1053,6 +1061,10 @@ static int stlink_usb_version(void *handle)
                if (h->version.jtag >= 2)
                        flags |= STLINK_F_HAS_DPBANKSEL;
 
+               /* 8bit read/write max packet size 512 bytes from V3J6 */
+               if (h->version.jtag >= 6)
+                       flags |= STLINK_F_HAS_RW8_512BYTES;
+
                break;
        default:
                break;
@@ -3450,6 +3462,21 @@ static void stlink_dap_op_quit(struct adiv5_dap *dap)
                LOG_ERROR("Error closing APs");
 }
 
+static int stlink_dap_config_trace(bool enabled,
+               enum tpiu_pin_protocol pin_protocol, uint32_t port_size,
+               unsigned int *trace_freq, unsigned int traceclkin_freq,
+               uint16_t *prescaler)
+{
+       return stlink_config_trace(stlink_dap_handle, enabled, pin_protocol,
+                                                          port_size, trace_freq, traceclkin_freq,
+                                                          prescaler);
+}
+
+static int stlink_dap_trace_read(uint8_t *buf, size_t *size)
+{
+       return stlink_usb_trace_read(stlink_dap_handle, buf, size);
+}
+
 /** */
 COMMAND_HANDLER(stlink_dap_serial_command)
 {
@@ -3633,6 +3660,8 @@ struct adapter_driver stlink_dap_adapter_driver = {
        .speed = stlink_dap_speed,
        .khz = stlink_dap_khz,
        .speed_div = stlink_dap_speed_div,
+       .config_trace = stlink_dap_config_trace,
+       .poll_trace = stlink_dap_trace_read,
 
        .dap_jtag_ops = &stlink_dap_ops,
        .dap_swd_ops = &stlink_dap_ops,
index d991733..fb1e444 100644 (file)
 static int ublast2_libusb_read(struct ublast_lowlevel *low, uint8_t *buf,
                              unsigned size, uint32_t *bytes_read)
 {
-       *bytes_read = jtag_libusb_bulk_read(low->libusb_dev,
+       int ret, tmp = 0;
+
+       ret = jtag_libusb_bulk_read(low->libusb_dev,
                                            USBBLASTER_EPIN | \
                                            LIBUSB_ENDPOINT_IN,
                                            (char *)buf,
                                            size,
-                                           100);
-       return ERROR_OK;
+                                           100, &tmp);
+       *bytes_read = tmp;
+
+       return ret;
 }
 
 static int ublast2_libusb_write(struct ublast_lowlevel *low, uint8_t *buf,
                               int size, uint32_t *bytes_written)
 {
-       *bytes_written = jtag_libusb_bulk_write(low->libusb_dev,
+       int ret, tmp = 0;
+
+       ret = jtag_libusb_bulk_write(low->libusb_dev,
                                                USBBLASTER_EPOUT | \
                                                LIBUSB_ENDPOINT_OUT,
                                                (char *)buf,
                                                size,
-                                               100);
-       return ERROR_OK;
+                                               100, &tmp);
+       *bytes_written = tmp;
+
+       return ret;
+
 }
 
 static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libusb_dev,
index 53a7e98..678b097 100644 (file)
@@ -48,7 +48,7 @@ uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
 
 #define usbtoxxx_get_type_name(type)   \
        types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \
-                  % (sizeof(types_name) / sizeof(types_name[0]))]
+                  % ARRAY_SIZE(types_name)]
 
 static uint8_t type_pre;
 static uint16_t usbtoxxx_buffer_index;
diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c
new file mode 100644 (file)
index 0000000..1743859
--- /dev/null
@@ -0,0 +1,487 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2019 Google, LLC.
+ * Author: Moritz Fischer <moritzf@google.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+#include <linux/pci.h>
+
+#include <jtag/interface.h>
+#include <jtag/swd.h>
+#include <jtag/commands.h>
+#include <helper/replacements.h>
+#include <helper/bits.h>
+
+/* Available only from kernel v4.10 */
+#ifndef PCI_CFG_SPACE_EXP_SIZE
+#define PCI_CFG_SPACE_EXP_SIZE 4096
+#endif
+
+#define PCIE_EXT_CAP_LST       0x100
+
+#define XLNX_XVC_EXT_CAP       0x00
+#define XLNX_XVC_VSEC_HDR      0x04
+#define XLNX_XVC_LEN_REG       0x0C
+#define XLNX_XVC_TMS_REG       0x10
+#define XLNX_XVC_TDx_REG       0x14
+
+#define XLNX_XVC_CAP_SIZE      0x20
+#define XLNX_XVC_VSEC_ID       0x8
+#define XLNX_XVC_MAX_BITS      0x20
+
+struct xlnx_pcie_xvc {
+       int fd;
+       unsigned offset;
+       char *device;
+};
+
+static struct xlnx_pcie_xvc xlnx_pcie_xvc_state;
+static struct xlnx_pcie_xvc *xlnx_pcie_xvc = &xlnx_pcie_xvc_state;
+
+static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val)
+{
+       uint32_t res;
+       int err;
+
+       /* Note: This should be ok endianess-wise because by going
+        * through sysfs the kernel does the conversion in the config
+        * space accessor functions
+        */
+       err = pread(xlnx_pcie_xvc->fd, &res, sizeof(res),
+                   xlnx_pcie_xvc->offset + offset);
+       if (err != sizeof(res)) {
+               LOG_ERROR("Failed to read offset %x", offset);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       if (val)
+               *val = res;
+
+       return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val)
+{
+       int err;
+
+       /* Note: This should be ok endianess-wise because by going
+        * through sysfs the kernel does the conversion in the config
+        * space accessor functions
+        */
+       err = pwrite(xlnx_pcie_xvc->fd, &val, sizeof(val),
+                    xlnx_pcie_xvc->offset + offset);
+       if (err != sizeof(val)) {
+               LOG_ERROR("Failed to write offset: %x with value: %x",
+                         offset, val);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi,
+                                 uint32_t *tdo)
+{
+       int err;
+
+       err = xlnx_pcie_xvc_write_reg(XLNX_XVC_LEN_REG, num_bits);
+       if (err != ERROR_OK)
+               return err;
+
+       err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TMS_REG, tms);
+       if (err != ERROR_OK)
+               return err;
+
+       err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TDx_REG, tdi);
+       if (err != ERROR_OK)
+               return err;
+
+       err = xlnx_pcie_xvc_read_reg(XLNX_XVC_TDx_REG, tdo);
+       if (err != ERROR_OK)
+               return err;
+
+       if (tdo)
+               LOG_DEBUG_IO("Transact num_bits: %zu, tms: %x, tdi: %x, tdo: %x",
+                            num_bits, tms, tdi, *tdo);
+       else
+               LOG_DEBUG_IO("Transact num_bits: %zu, tms: %x, tdi: %x, tdo: <null>",
+                            num_bits, tms, tdi);
+       return ERROR_OK;
+}
+
+int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
+{
+       int tms = tap_get_state() == TAP_RESET ? 1 : 0;
+       size_t left = cmd->cmd.stableclocks->num_cycles;
+       size_t write;
+       int err;
+
+       LOG_DEBUG("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
+
+       while (left) {
+               write = MIN(XLNX_XVC_MAX_BITS, left);
+               err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
+               if (err != ERROR_OK)
+                       return err;
+               left -= write;
+       };
+
+       return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_statemove(size_t skip)
+{
+       uint8_t tms_scan = tap_get_tms_path(tap_get_state(),
+                                           tap_get_end_state());
+       int tms_count = tap_get_tms_path_len(tap_get_state(),
+                                            tap_get_end_state());
+       int err;
+
+       LOG_DEBUG("statemove starting at (skip: %zu) %s end in %s", skip,
+                 tap_state_name(tap_get_state()),
+                 tap_state_name(tap_get_end_state()));
+
+
+       err = xlnx_pcie_xvc_transact(tms_count - skip, tms_scan >> skip, 0, NULL);
+       if (err != ERROR_OK)
+               return err;
+
+       tap_set_state(tap_get_end_state());
+
+       return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
+{
+       int err = ERROR_OK;
+
+       LOG_DEBUG("runtest %i cycles, end in %i",
+                 cmd->cmd.runtest->num_cycles,
+                 cmd->cmd.runtest->end_state);
+
+       tap_state_t tmp_state = tap_get_end_state();
+
+       if (tap_get_state() != TAP_IDLE) {
+               tap_set_end_state(TAP_IDLE);
+               err = xlnx_pcie_xvc_execute_statemove(0);
+               if (err != ERROR_OK)
+                       return err;
+       };
+
+       size_t left = cmd->cmd.runtest->num_cycles;
+       size_t write;
+
+       while (left) {
+               write = MIN(XLNX_XVC_MAX_BITS, left);
+               err = xlnx_pcie_xvc_transact(write, 0, 0, NULL);
+               if (err != ERROR_OK)
+                       return err;
+               left -= write;
+       };
+
+       tap_set_end_state(tmp_state);
+       if (tap_get_state() != tap_get_end_state())
+               err = xlnx_pcie_xvc_execute_statemove(0);
+
+       return err;
+}
+
+static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
+{
+       size_t num_states = cmd->cmd.pathmove->num_states;
+       tap_state_t *path = cmd->cmd.pathmove->path;
+       int err = ERROR_OK;
+       size_t i;
+
+       LOG_DEBUG("pathmove: %i states, end in %i",
+                 cmd->cmd.pathmove->num_states,
+                 cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+
+       for (i = 0; i < num_states; i++) {
+               if (path[i] == tap_state_transition(tap_get_state(), false)) {
+                       err = xlnx_pcie_xvc_transact(1, 1, 0, NULL);
+               } else if (path[i] == tap_state_transition(tap_get_state(), true)) {
+                       err = xlnx_pcie_xvc_transact(1, 0, 0, NULL);
+               } else {
+                       LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.",
+                                 tap_state_name(tap_get_state()),
+                                 tap_state_name(path[i]));
+                       err = ERROR_JTAG_QUEUE_FAILED;
+               }
+               if (err != ERROR_OK)
+                       return err;
+               tap_set_state(path[i]);
+       }
+
+       tap_set_end_state(tap_get_state());
+
+       return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
+{
+       enum scan_type type = jtag_scan_type(cmd->cmd.scan);
+       tap_state_t saved_end_state = cmd->cmd.scan->end_state;
+       bool ir_scan = cmd->cmd.scan->ir_scan;
+       uint32_t tdi, tms, tdo;
+       uint8_t *buf, *rd_ptr;
+       int err, scan_size;
+       size_t write;
+       size_t left;
+
+       scan_size = jtag_build_buffer(cmd->cmd.scan, &buf);
+       rd_ptr = buf;
+       LOG_DEBUG("%s scan type %d %d bits; starts in %s end in %s",
+                 (cmd->cmd.scan->ir_scan) ? "IR" : "DR", type, scan_size,
+                 tap_state_name(tap_get_state()),
+                 tap_state_name(cmd->cmd.scan->end_state));
+
+       /* If we're in TAP_DR_SHIFT state but need to do a IR_SCAN or
+        * vice-versa, do a statemove to corresponding other state, then restore
+        * end state
+        */
+       if (ir_scan && tap_get_state() != TAP_IRSHIFT) {
+               tap_set_end_state(TAP_IRSHIFT);
+               err = xlnx_pcie_xvc_execute_statemove(0);
+               if (err != ERROR_OK)
+                       goto out_err;
+               tap_set_end_state(saved_end_state);
+       } else if (!ir_scan && (tap_get_state() != TAP_DRSHIFT)) {
+               tap_set_end_state(TAP_DRSHIFT);
+               err = xlnx_pcie_xvc_execute_statemove(0);
+               if (err != ERROR_OK)
+                       goto out_err;
+               tap_set_end_state(saved_end_state);
+       }
+
+       left = scan_size;
+       while (left) {
+               write = MIN(XLNX_XVC_MAX_BITS, left);
+               /* the last TMS should be a 1, to leave the state */
+               tms = left <= XLNX_XVC_MAX_BITS ? BIT(write - 1) : 0;
+               tdi = (type != SCAN_IN) ? buf_get_u32(rd_ptr, 0, write) : 0;
+               err = xlnx_pcie_xvc_transact(write, tms, tdi, type != SCAN_OUT ?
+                                            &tdo : NULL);
+               if (err != ERROR_OK)
+                       goto out_err;
+               left -= write;
+               if (type != SCAN_OUT)
+                       buf_set_u32(rd_ptr, 0, write, tdo);
+               rd_ptr += sizeof(uint32_t);
+       };
+
+       err = jtag_read_buffer(buf, cmd->cmd.scan);
+       if (buf)
+               free(buf);
+
+       if (tap_get_state() != tap_get_end_state())
+               err = xlnx_pcie_xvc_execute_statemove(1);
+
+       return err;
+
+out_err:
+       if (buf)
+               free(buf);
+       return err;
+}
+
+static void xlnx_pcie_xvc_execute_reset(struct jtag_command *cmd)
+{
+       LOG_DEBUG("reset trst: %i srst: %i", cmd->cmd.reset->trst,
+                 cmd->cmd.reset->srst);
+}
+
+static void xlnx_pcie_xvc_execute_sleep(struct jtag_command *cmd)
+{
+       LOG_DEBUG("sleep %" PRIi32 "", cmd->cmd.sleep->us);
+       usleep(cmd->cmd.sleep->us);
+}
+
+static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd)
+{
+       const size_t num_bits = cmd->cmd.tms->num_bits;
+       const uint8_t *bits = cmd->cmd.tms->bits;
+       size_t left, write;
+       uint32_t tms;
+       int err;
+
+       LOG_DEBUG("execute tms %zu", num_bits);
+
+       left = num_bits;
+       while (left) {
+               write = MIN(XLNX_XVC_MAX_BITS, left);
+               tms = buf_get_u32(bits, 0, write);
+               err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
+               if (err != ERROR_OK)
+                       return err;
+               left -= write;
+               bits += 4;
+       };
+
+       return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_command(struct jtag_command *cmd)
+{
+       LOG_DEBUG("%s: cmd->type: %u", __func__, cmd->type);
+       switch (cmd->type) {
+       case JTAG_STABLECLOCKS:
+               return xlnx_pcie_xvc_execute_stableclocks(cmd);
+       case JTAG_RUNTEST:
+               return xlnx_pcie_xvc_execute_runtest(cmd);
+       case JTAG_TLR_RESET:
+               tap_set_end_state(cmd->cmd.statemove->end_state);
+               return xlnx_pcie_xvc_execute_statemove(0);
+       case JTAG_PATHMOVE:
+               return xlnx_pcie_xvc_execute_pathmove(cmd);
+       case JTAG_SCAN:
+               return xlnx_pcie_xvc_execute_scan(cmd);
+       case JTAG_RESET:
+               xlnx_pcie_xvc_execute_reset(cmd);
+               break;
+       case JTAG_SLEEP:
+               xlnx_pcie_xvc_execute_sleep(cmd);
+               break;
+       case JTAG_TMS:
+               return xlnx_pcie_xvc_execute_tms(cmd);
+       default:
+               LOG_ERROR("BUG: Unknown JTAG command type encountered.");
+               return ERROR_JTAG_QUEUE_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_queue(void)
+{
+       struct jtag_command *cmd = jtag_command_queue;
+       int ret;
+
+       while (cmd) {
+               ret = xlnx_pcie_xvc_execute_command(cmd);
+
+               if (ret != ERROR_OK)
+                       return ret;
+
+               cmd = cmd->next;
+       }
+
+       return ERROR_OK;
+}
+
+
+static int xlnx_pcie_xvc_init(void)
+{
+       char filename[PATH_MAX];
+       uint32_t cap, vh;
+       int err;
+
+       snprintf(filename, PATH_MAX, "/sys/bus/pci/devices/%s/config",
+                xlnx_pcie_xvc->device);
+       xlnx_pcie_xvc->fd = open(filename, O_RDWR | O_SYNC);
+       if (xlnx_pcie_xvc->fd < 0) {
+               LOG_ERROR("Failed to open device: %s", filename);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       LOG_INFO("Scanning PCIe device %s's for Xilinx XVC/PCIe ...",
+                xlnx_pcie_xvc->device);
+       /* Parse the PCIe extended capability list and try to find
+        * vendor specific header */
+       xlnx_pcie_xvc->offset = PCIE_EXT_CAP_LST;
+       while (xlnx_pcie_xvc->offset <= PCI_CFG_SPACE_EXP_SIZE - sizeof(cap) &&
+              xlnx_pcie_xvc->offset >= PCIE_EXT_CAP_LST) {
+               err = xlnx_pcie_xvc_read_reg(XLNX_XVC_EXT_CAP, &cap);
+               if (err != ERROR_OK)
+                       return err;
+               LOG_DEBUG("Checking capability at 0x%x; id=0x%04x version=0x%x next=0x%x",
+                        xlnx_pcie_xvc->offset,
+                        PCI_EXT_CAP_ID(cap),
+                        PCI_EXT_CAP_VER(cap),
+                        PCI_EXT_CAP_NEXT(cap));
+               if (PCI_EXT_CAP_ID(cap) == PCI_EXT_CAP_ID_VNDR) {
+                       err = xlnx_pcie_xvc_read_reg(XLNX_XVC_VSEC_HDR, &vh);
+                       if (err != ERROR_OK)
+                               return err;
+                       LOG_DEBUG("Checking possible match at 0x%x; id: 0x%x; rev: 0x%x; length: 0x%x",
+                                xlnx_pcie_xvc->offset,
+                                PCI_VNDR_HEADER_ID(vh),
+                                PCI_VNDR_HEADER_REV(vh),
+                                PCI_VNDR_HEADER_LEN(vh));
+                       if ((PCI_VNDR_HEADER_ID(vh) == XLNX_XVC_VSEC_ID) &&
+                           (PCI_VNDR_HEADER_LEN(vh) == XLNX_XVC_CAP_SIZE))
+                               break;
+               }
+               xlnx_pcie_xvc->offset = PCI_EXT_CAP_NEXT(cap);
+       }
+       if ((xlnx_pcie_xvc->offset > PCI_CFG_SPACE_EXP_SIZE - XLNX_XVC_CAP_SIZE) ||
+            xlnx_pcie_xvc->offset < PCIE_EXT_CAP_LST) {
+               close(xlnx_pcie_xvc->fd);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       LOG_INFO("Found Xilinx XVC/PCIe capability at offset: 0x%x", xlnx_pcie_xvc->offset);
+
+       return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_quit(void)
+{
+       int err;
+
+       err = close(xlnx_pcie_xvc->fd);
+       if (err)
+               return err;
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(xlnx_pcie_xvc_handle_config_command)
+{
+       if (CMD_ARGC < 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       /* we can't really free this in a safe manner, so at least
+        * limit the memory we're leaking by freeing the old one first
+        * before allocating a new one ...
+        */
+       if (xlnx_pcie_xvc->device)
+               free(xlnx_pcie_xvc->device);
+
+       xlnx_pcie_xvc->device = strdup(CMD_ARGV[0]);
+       return ERROR_OK;
+}
+
+static const struct command_registration xlnx_pcie_xvc_command_handlers[] = {
+       {
+               .name = "xlnx_pcie_xvc_config",
+               .handler = xlnx_pcie_xvc_handle_config_command,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure XVC/PCIe JTAG adapter",
+               .usage = "device",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static struct jtag_interface xlnx_pcie_xvc_interface = {
+       .execute_queue = &xlnx_pcie_xvc_execute_queue,
+};
+
+struct adapter_driver xlnx_pcie_xvc_adapter_driver = {
+       .name = "xlnx_pcie_xvc",
+       .transports = jtag_only,
+       .commands = xlnx_pcie_xvc_command_handlers,
+
+       .init = &xlnx_pcie_xvc_init,
+       .quit = &xlnx_pcie_xvc_quit,
+
+       .jtag_ops = &xlnx_pcie_xvc_interface,
+};
index 17d4541..00b3bb5 100644 (file)
@@ -117,6 +117,9 @@ extern struct adapter_driver opendous_adapter_driver;
 #if BUILD_SYSFSGPIO == 1
 extern struct adapter_driver sysfsgpio_adapter_driver;
 #endif
+#if BUILD_XLNX_PCIE_XVC == 1
+extern struct adapter_driver xlnx_pcie_xvc_adapter_driver;
+#endif
 #if BUILD_AICE == 1
 extern struct adapter_driver aice_adapter_driver;
 #endif
@@ -225,6 +228,9 @@ struct adapter_driver *adapter_drivers[] = {
 #if BUILD_SYSFSGPIO == 1
                &sysfsgpio_adapter_driver,
 #endif
+#if BUILD_XLNX_PCIE_XVC == 1
+               &xlnx_pcie_xvc_adapter_driver,
+#endif
 #if BUILD_AICE == 1
                &aice_adapter_driver,
 #endif
index ff17831..7f033e0 100644 (file)
@@ -162,8 +162,8 @@ void jtag_tap_free(struct jtag_tap *tap);
 
 struct jtag_tap *jtag_all_taps(void);
 const char *jtag_tap_name(const struct jtag_tap *tap);
-struct jtag_tap *jtag_tap_by_string(const chardotted_name);
-struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interpinterp, Jim_Obj *obj);
+struct jtag_tap *jtag_tap_by_string(const char *dotted_name);
+struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *obj);
 struct jtag_tap *jtag_tap_by_position(unsigned abs_position);
 struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p);
 unsigned jtag_tap_count_enabled(void);
index 3551521..8fc3ad5 100644 (file)
@@ -34,16 +34,16 @@ proc init_reset { mode } {
 proc power_restore {} {
        echo "Sensed power restore, running reset init and halting GDB."
        reset init
-       
+
        # Halt GDB so user can deal with a detected power restore.
        #
        # After GDB is halted, then output is no longer forwarded
        # to the GDB console.
-       set targets [target names]      
+       set targets [target names]
        foreach t $targets {
                # New event script.
                $t invoke-event arp_halt_gdb
-       }       
+       }
 }
 
 add_help_text power_restore "Overridable procedure run when power restore is detected. Runs 'reset init' by default."
@@ -65,11 +65,11 @@ proc srst_deasserted {} {
        #
        # After GDB is halted, then output is no longer forwarded
        # to the GDB console.
-       set targets [target names]      
+       set targets [target names]
        foreach t $targets {
                # New event script.
                $t invoke-event arp_halt_gdb
-       }               
+       }
 }
 
 add_help_text srst_deasserted "Overridable procedure run when srst deassert is detected. Runs 'reset init' by default."
@@ -120,22 +120,22 @@ proc jtag_ntrst_assert_width args {
 # FIXME phase these aids out after about April 2011
 #
 proc jtag_khz args {
-       echo "DEPRECATED! use 'adapter_khz' not 'jtag_khz'"
-       eval adapter_khz $args
+       echo "DEPRECATED! use 'adapter speed' not 'jtag_khz'"
+       eval adapter speed $args
 }
 
 proc jtag_nsrst_delay args {
-       echo "DEPRECATED! use 'adapter_nsrst_delay' not 'jtag_nsrst_delay'"
-       eval adapter_nsrst_delay $args
+       echo "DEPRECATED! use 'adapter srst delay' not 'jtag_nsrst_delay'"
+       eval adapter srst delay $args
 }
 
 proc jtag_nsrst_assert_width args {
-       echo "DEPRECATED! use 'adapter_nsrst_assert_width' not 'jtag_nsrst_assert_width'"
-       eval adapter_nsrst_assert_width $args
+       echo "DEPRECATED! use 'adapter srst pulse_width' not 'jtag_nsrst_assert_width'"
+       eval adapter srst pulse_width $args
 }
 
 proc jtag_reset args {
-       echo "DEPRECATED! use 'adapter [de]assert' not 'jtag_reset'"
+       echo "DEPRECATED! use 'adapter \[de\]assert' not 'jtag_reset'"
        switch $args {
                "0 0"
                        {eval adapter deassert trst deassert srst}
@@ -176,4 +176,44 @@ proc stlink args {
        eval hla $args
 }
 
+proc adapter_khz args {
+       echo "DEPRECATED! use 'adapter speed' not 'adapter_khz'"
+       eval adapter speed $args
+}
+
+proc adapter_name args {
+       echo "DEPRECATED! use 'adapter name' not 'adapter_name'"
+       eval adapter name $args
+}
+
+proc adapter_nsrst_delay args {
+       echo "DEPRECATED! use 'adapter srst delay' not 'adapter_nsrst_delay'"
+       eval adapter srst delay $args
+}
+
+proc adapter_nsrst_assert_width args {
+       echo "DEPRECATED! use 'adapter srst pulse_width' not 'adapter_nsrst_assert_width'"
+       eval adapter srst pulse_width $args
+}
+
+proc interface args {
+       echo "DEPRECATED! use 'adapter driver' not 'interface'"
+       eval adapter driver $args
+}
+
+proc  interface_transports args {
+       echo "DEPRECATED! use 'adapter transports' not 'interface_transports'"
+       eval adapter transports $args
+}
+
+proc  interface_list args {
+       echo "DEPRECATED! use 'adapter list' not 'interface_list'"
+       eval adapter list $args
+}
+
+proc ftdi_location args {
+       echo "DEPRECATED! use 'adapter usb location' not 'ftdi_location'"
+       eval adapter usb location $args
+}
+
 # END MIGRATION AIDS
index ef0cd3f..ba0cb1d 100644 (file)
@@ -1314,7 +1314,7 @@ static const struct command_registration jtag_command_handlers[] = {
                .name = "irscan",
                .handler = handle_irscan_command,
                .mode = COMMAND_EXEC,
-               .help = "Execute Instruction Register (DR) scan.  The "
+               .help = "Execute Instruction Register (IR) scan.  The "
                        "specified opcodes are put into each TAP's IR, "
                        "and other TAPs are put in BYPASS.",
                .usage = "[tap_name instruction]* ['-endstate' state_name]",
index 8a307f1..42d2a8c 100644 (file)
@@ -135,7 +135,7 @@ static int embKernel_create(struct target *target)
 }
 
 static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embKernel_params *param,
-               struct thread_detail *details, const charstate_str)
+               struct thread_detail *details, const char *state_str)
 {
        int64_t task = 0;
        int retval = target_read_buffer(rtos->target, iterable + param->iterable_task_owner_offset, param->pointer_width,
index 6646ad4..f45c15d 100644 (file)
@@ -106,7 +106,7 @@ static int mqx_valid_address_check(
 )
 {
        enum mqx_arch arch_type = ((struct mqx_params *)rtos->rtos_specific_params)->target_arch;
-       const char * targetname = ((struct mqx_params *)rtos->rtos_specific_params)->target_name;
+       const char *targetname = ((struct mqx_params *)rtos->rtos_specific_params)->target_name;
 
        /* Cortex-M address range */
        if (arch_type == mqx_arch_cortexm) {
index 9f1cb7b..0ca4fa4 100644 (file)
@@ -2031,7 +2031,7 @@ static int lookup_add_arch_defined_types(char const **arch_defined_types_list[],
 
 static int gdb_generate_reg_type_description(struct target *target,
                char **tdesc, int *pos, int *size, struct reg_data_type *type,
-               char const **arch_defined_types_list[], int * num_arch_defined_types)
+               char const **arch_defined_types_list[], int *num_arch_defined_types)
 {
        int retval = ERROR_OK;
 
index 759ba52..5d87c89 100644 (file)
@@ -990,7 +990,7 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
                                /* TODO: set jtag speed to */
                                if (svf_para.frequency > 0) {
                                        command_run_linef(cmd_ctx,
-                                                       "adapter_khz %d",
+                                                       "adapter speed %d",
                                                        (int)svf_para.frequency / 1000);
                                        LOG_DEBUG("\tfrequency = %f", svf_para.frequency);
                                }
index f120151..c0deee1 100644 (file)
@@ -179,9 +179,18 @@ static int dapdirect_swd_select(struct command_context *ctx)
 
 static int dapdirect_init(struct command_context *ctx)
 {
+       enum reset_types jtag_reset_config = jtag_get_reset_config();
+
        LOG_DEBUG("dapdirect_init()");
 
-       adapter_deassert_reset();
+       if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
+               if (jtag_reset_config & RESET_SRST_NO_GATING)
+                       adapter_assert_reset();
+               else
+                       LOG_WARNING("\'srst_nogate\' reset_config option is required");
+       } else
+               adapter_deassert_reset();
+
        return ERROR_OK;
 }
 
index 8d11537..ee30ff7 100644 (file)
@@ -96,7 +96,7 @@ static int swd_run_inner(struct adiv5_dap *dap)
 static int swd_connect(struct adiv5_dap *dap)
 {
        const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
-       uint32_t dpidr;
+       uint32_t dpidr = 0xdeadbeef;
        int status;
 
        /* FIXME validate transport config ... is the
index d415eb3..1662c7e 100644 (file)
--- a/